fix(plugin-auth): ensureDefaultOrganization resolves the L4 config-derived owner when no grant row exists (#13514 follow-through) - #13708
Conversation
…rived owner when no grant row exists (#13514 follow-through) #13514 (L4) retired the walled grant row: bootstrapPlatformAdmin writes no sys_user_permission_set row under walled postures, standing is config-derived at the one derivation site. The ADR-0081 D1 default-org bootstrap still resolved the admin BY THE ROW (admin_full_access set → oldest cross-tenant grant) — so on every walled deployment it dead-ended on `no_admin` forever. The open AuthPlugin never hits this (its runner is gated on non-walled postures), but the enterprise organizations package invokes this same helper under walled postures by design ("every WALLED posture keeps its existing owner: the enterprise organizations package" — the runner comment); cloud's EE guided-path suite caught the dead end on its pin bump (signup-membership-policy.e2e: "the platform admin never received their default-organization owner row"). The fallback asks the same public predicates the derivation site asks — resolvePlatformAdminEmails() + isConfiguredPlatformAdminEmail from core, the #11343 verified-email allow-list from types — oldest verified owner wins (the bootstrap's own tiebreak), and the grant row stays PRIMARY where it exists. Fail-closed in every other shape: no declared owner, unverified match, or no row all still answer `no_admin`. Four new pins in the package suite (16/16 green): the walled L4 shape resolves the owner; unverified stays no_admin; undeclared stays no_admin; a grant row wins over the config fallback. Gates: plugin-auth build + check-dts-emitted green, full-repo lint green, changeset (patch) present. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 11 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 6633d21062a22200e236175dcbcfc17bba5810ca && git checkout 6633d21062a22200e236175dcbcfc17bba5810ca
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 76fa3553208777f2eb8caf360cf36e37be84cd0d d6af213b5b001315b92f7ad6b0ccde073f4ddda0 && git checkout -B drift-repro 76fa3553208777f2eb8caf360cf36e37be84cd0d && git merge --no-ff d6af213b5b001315b92f7ad6b0ccde073f4ddda0
node scripts/docs-audit/affected-docs.mjs --json 76fa3553208777f2eb8caf360cf36e37be84cd0d
|
|
Superseded by #13685 (L3 re-anchor), which landed while this was in the queue — and landed the better shape. I filed this after cloud's pin bump took the EE guided-path suite red on the walled dead end (
Verified against #13685's implementation on cloud's rig rather than mine: EE guided-path 5/5. Closing with no residue; the four pins I wrote here are subsumed by that PR's own coverage. |
What
The ADR-0081 D1 default-org bootstrap still resolved the platform admin by the grant row (
admin_full_accessset → oldest cross-tenant grant). #13514 (L4) retired that row under walled postures — standing is config-derived at the one derivation site — so on every walled deployment the helper dead-ends onno_adminforever. The open AuthPlugin never hits this (its runner is gated on non-walled postures), but the enterprise organizations package invokes this same helper under walled postures by design (the runner comment: "every WALLED posture keeps its existing owner: the enterprise organizations package").How it surfaced: cloud's pin bump to current main took its EE guided-path suite red —
signup-membership-policy.e2e: "the platform admin never received their default-organization owner row" — the walled founder signs up, verifies, and no default org ever appears.The fix
When the grant lookup answers nothing, fall back to the declared verified owner, asked with the same public predicates the derivation site asks:
resolvePlatformAdminEmails()+isConfiguredPlatformAdminEmail(@objectstack/core) + the #11343 verified-email allow-list (@objectstack/types); oldest verified owner wins — the bootstrap's own tiebreak. The grant row stays primary where it exists. Fail-closed everywhere else: no declared owner, unverified match, or no matching row all still answerno_admin.Pins
Four new cases in the package suite (16/16 green): the walled L4 shape resolves the owner · unverified stays
no_admin· undeclared staysno_admin· a grant row wins over the config fallback.Consumer chain verified end-to-end on cloud's rig with this exact patch: the EE guided-path suite goes 5/5, full EE pass 156/156, full cloud pass 285/285 (cloud pairs this with a trigger widening in its organizations plugin — re-run ensure on the verifying
sys_userwrite, since no permission-set insert exists to listen to any more).Gates
plugin-auth build + check-dts-emitted green · full-repo lint green · changeset (patch).
🤖 Generated with Claude Code