Skip to content

Membership backfill binds all 80 job seekers and both platform staff to the Default Organization: the auth membership policy is left at auto, which DESIGN.md §03 forbids #38

Description

@os-sam

Found while verifying #27 on claude/issue-27-signable-personas at 48568f9 (memory driver and the default sqlite driver both show it). Not touched by that PR — the seed's member set is unchanged since #19 and the rule is runtime-side.

Observed

Every fresh boot logs, at info level:

[auth] membership backfill (kernel:ready) bound 82 member-less user(s) to the default organization (ADR-0093 D6) {"scanned":113,"bound":82,"skipped":31}

The 31 skipped are the 30 seeded employer staff (who hold a seeded sys_member row in their employer's organization) plus the platform owner (bound to the default organization by the default-org bootstrap). The 82 bound are the 80 job seekers and the 2 platform staff — everyone the seed deliberately leaves without a membership.

Why it matters

DESIGN.md §03, section 自助入驻的现状与到期条件, rules the membership policy explicitly:

membershipPolicy 必须是 invite-only(不自动绑组织)。⛔ 不要用 auto:那会把所有求职者绑进同一个默认组织,等于给他们一个共同的组织身份,而组织在这个平台里是隔离边界。求职者不属于任何组织是正确状态,不是待修的缺陷。

Nothing in the app declares that policy, so the platform default (auto) applies and the backfill does exactly what §03 says must not happen: all seekers now share one organization identity. Today it is inert for reads because accessible_org_ids never resolves in RLS (#18), but every readScope: 'org' grant on a seeker-side object widens the owner match to that shared organization the day #18 lifts, and the two platform staff become members of a tenant they do not belong to.

What is needed

Someone has to decide where the app states the policy — it is an auth-plugin setting (auth.membership_policy per ADR-0093 D1, read live through getMembershipPolicy()), not a defineStack() key. Options I can see:

  • A. Declare it in the platform settings the deployment ships with (if defineStack or the package manifest can carry a settings default) so a fresh boot starts at invite-only.
  • B. Set it operationally (Setup → auth settings) and document it as a required step in the README next to the demo path.
  • C. Ask upstream for an app-declarable default.

Recommendation: A if the surface exists, otherwise B with a loud README note, because the boot log line is the only place the deviation shows today.

Filed without a label for triage.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions