Repository navigation
fix(plugin-auth): settle membership under the auto policy at user creation (ADR-0093 D7) - #21813
Conversation
…ll ledger Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…fill ledger Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…eation Also adds the plugin-auth changeset and tightens comments. Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…he new ledger write Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…mbership-create-time
📓 Docs Drift CheckThis PR changes 3 package(s): 30 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 11 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 2a800159759cab12a8abd8faf01528c74b4be097 && git checkout 2a800159759cab12a8abd8faf01528c74b4be097
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9f9510f25e6aa65aa61ce3effb42706fabcab92e 5c52ad32f1ce53f9985a4a7107c6270751596ce0 && git checkout -B drift-repro 9f9510f25e6aa65aa61ce3effb42706fabcab92e && git merge --no-ff 5c52ad32f1ce53f9985a4a7107c6270751596ce0
node scripts/docs-audit/affected-docs.mjs --json 9f9510f25e6aa65aa61ce3effb42706fabcab92e
|
…i-org refusals; scan the backfill in full Also stages the created user from the adapter's create result, so the session seam recognises the creating request without a store read. Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…cabulary copy Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…nators it does not implement Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…mbership-create-time
…org wirings; latch one-time decisions in-process Also: the showcase seed writes its personas' membership at creation, and the keyset walk judges a stalled cursor by equality instead of JS string order. Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
… on an undecided pass Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…s organization Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
…mbership-create-time
…gated bootstrap; declare the widened surface Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6 Co-Authored-By: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs read: card #21791 (body and all 5 comments, including the ① Derived judgmentsMeasured against the ruling: under
② Semver level
③ Boundary flags
Required to flip to PASS: add the Implemented-by: VERDICT: FAIL |
…s ungated direct call Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018zT8d8NpiQ1ExhuNd5TxY6
Contract reviewServed-tier: Inputs read: card #21791 (body and all 6 comments: the triage, the claim with its ① Derived judgmentsMeasured against the ruling: under
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #21791
Clause-②: yes (widening)
What
Under the
automembership policy, membership is now decided when the user is created (ADR-0093 D7), per the maintainer ruling recorded on the card. Packages:@objectstack/plugin-auth,@objectstack/organizations,@objectstack/types.sys_migrationledger.adr-0093-membership-backfill) scans the user and member tables in full with keyset pages, with no row cap. An incomplete scan binds nobody and records nothing. A multi-org deployment with no default target is recorded as such. A deployment with no organization at all defers, and the pass runs when the default organization is first created.adr-0093-default-org-owner-bind) runs once. One shared gate (createEnsureDefaultOrganizationOnce) is used by both the single-organization wiring and the walled@objectstack/organizationswiring. Once decided, a missing default organization is recreated with nobody bound and no seed-ownership handoff. On a kernel without the ledger, the owner is bound only when the bootstrap creates the organization; if the ledger exists but cannot be read, that call binds nobody and the next trigger decides.error).keysetWalk(@objectstack/types) detects a stalled cursor by key equality or a repeated page, never by string order.@objectstack/plugin-auth(additive,minor):createEnsureDefaultOrganizationOnceandEnsureDefaultOrganizationOnceOptions;ObjectQLAdapterFactoryOptions.onRecordCreatedvia the new optional second argument ofcreateObjectQLAdapterFactory;bindOnlyOnCreate/bindOwneronEnsureDefaultOrganizationOptions; reason members'owner_bind_decided'and'scan-incomplete'.@objectstack/organizationsand@objectstack/typesadd no public export (patch).ensureDefaultOrganization(plugin-auth helper and the organizations wrapper), in favour of the gated factory.invite-onlybinds nobody; multi-org has no automatic binding; the creation paths (sign-up, admin create, import, SSO JIT) still bind underauto.persistLedgerDecisionRow) and its swallow-census copy.Tests
Measured at
3ed15b1836:@objectstack/plugin-auth: typecheck green; 121 files, 2541 passed, 10 skipped.@objectstack/organizations: typecheck green; 9 files, 131 passed.@objectstack/types: typecheck green; 23 files, 706 passed (--project local).scripts/ablation-replace.mjs, each restored to HEAD: the request-scoped creation check, the in-process latches (owner bind, backfill), the keyset equality check, and the persona membership write each turned their test red.pnpmgates viadispatch-gates: 121 derived, 121 run, all exit 0 (including the changeset gates againstorigin/main); CI-environment jobs (shards, test completeness, workspace type-check lanes) left to CI.Acceptance notes
app:seededre-run; amending it is a governed (Tier H) edit left to the maintainer.Generated by Claude Code