You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(plugin-security): walled elevation requires a verified owner-email match, and the bootstrap replays on the verifying update (#11639)
* fix(plugin-security): walled elevation requires a verified owner-email match, and the bootstrap replays on the verifying update
Closes the remainder #11211 left open (issue #11343): under walled postures
the platform-admin elevation matched the env-declared owner email as a raw
string, and email verification is off by default — so an account created
with the owner's address before the owner registered would be elevated.
Both halves land together, deliberately:
1. bootstrapPlatformAdmin: the walled owner-email match must be VERIFIED
(fail-closed allow-list over email_verified representations; absent
reads unverified). Unverified holder => refused with the new reason
walled_owner_not_verified, logged loudly with the unblock in the line,
never falling back — the same direction as the undeclared-owner refusal.
2. security-plugin bootstrap-replay middleware: also fires on sys_user
updates touching email_verified / email (trigger set extracted as
shouldReplayBootstrapFor, consumed by middleware and pins alike).
Verification is an UPDATE; with the old insert-only replay, half 1
alone would refuse the genuine owner at sign-up and never look again,
leaving the platform without any administrator.
single posture is untouched in both directions. Pins cover both invariant
directions: the unverified holder is refused AND the verified owner is
elevated, including across the refuse-then-verify-then-re-run sequence.
Fixes#11343
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
* test(plugin-security): route the wiring fake's update() through assertEngineUpdateDispatch; record the pinned double
check:engine-double-contract named the new fake's bare update(); pin it to
the producer's dispatch predicate and let the RETAINED ledger learn the
new pinned coverage (--write; 0 lost, coverage grew).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
* fix(plugin-auth): seed the dev admin with a verified email — operator-provisioned, not a self-registrant
The Dogfood Regression Gate caught #11343's invariant end-to-end: two
walled-posture fixtures (automation-toggle-tenant-scope :189,
federated-rls-injectors :135) build their platform admin through the
shared dev-admin seed, which drives the real sign-up pipeline and so
left the account unverified — correctly refused by the restored
invariant, i.e. the fixtures modeled a deployment state the platform no
longer considers valid.
The repair is the shared seed path, not the fixtures: maybeSeedDevAdmin
now stamps email_verified on the account it just provisioned. The seeded
dev admin is created by the deployment's own boot command with
operator-known credentials — the same trust shape as a trusted-SSO
insert — not an unknown self-registrant, which is the class the
invariant refuses. Dev-only by the existing NODE_ENV gate; the generic
sign-up factory is untouched, so unverified-user flows keep testing what
they name. Fail-open on the stamp, fail-closed on elevation.
Part of #11343
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
* chore(changeset): cover @objectstack/plugin-auth — the dev-seed verified stamp ships under the same card
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments