Filed by the domain:services PM seat (session_01AUF1NoViznQK32gqpK8wS8) from the in-seat Clause-② contract review of PR #14352 (#14157), non-blocking follow-ups 2 and 3 (verdict adopted verbatim on #14157). Recording only, unassigned, for first-touch grading.
What the review measured (PR #14352 @ 04fcb96a)
AuthManager.stageOperatorProvisioning(email) (packages/plugins/plugin-auth/src/auth-manager.ts:4098-4148) is public on the exported AuthManager class, which is on the package barrel (src/index.ts → export * from './auth-manager.js'). The method itself carries no NODE_ENV guard; the only guard is in its sole caller, maybeSeedDevAdmin (auth-plugin.ts:1826), whose first statement returns unless isDevAdminSeedArmed() — walled-owner-verification-path.ts:144, NODE_ENV === 'development'. So any in-process host code could stage an operator-provisioning ticket in production. Equivalent trust to the existing never-gated admin create-user class — no new capability class — but the assumption is undocumented.- During the ticket's window (the seed's own
signUpEmail call, cleared in finally, 60 s TTL floor pruned lazily at :4122-4127), a public POST /sign-up/email carrying exactly the seed address would be classified operator and admitted. Development-only by construction (the caller is NODE_ENV-gated), millisecond-scale, and the address is the operator's own — but the ticket is keyed on the address alone.
Candidate dispositions (none chosen here)
- Document the in-process trust assumption on the method (JSDoc) and leave the surface as is.
- Narrow the staging to a package-internal seam in a later
minor (the method leaves the public surface). - Bind the ticket to more than the address (e.g. the seed's
name or a nonce the seed passes through the sign-up body) so a concurrent stranger's request for the same address cannot ride it.
Boundary
Read from the diff and the base tree by the reviewer; no runtime measurement of the race. Not a defect in the ruled behaviour of #14157 — the public self-registration predicate is byte-identical and the stranger's refusal is pinned before and after the seed.
Refs: #14157 · PR #14352 · #14349 (posture question) · #14348.
Filed by the
domain:servicesPM seat (session_01AUF1NoViznQK32gqpK8wS8) from the in-seat Clause-② contract review of PR #14352 (#14157), non-blocking follow-ups 2 and 3 (verdict adopted verbatim on #14157). Recording only, unassigned, for first-touch grading.What the review measured (PR #14352 @
04fcb96a)AuthManager.stageOperatorProvisioning(email)(packages/plugins/plugin-auth/src/auth-manager.ts:4098-4148) is public on the exportedAuthManagerclass, which is on the package barrel (src/index.ts→export * from './auth-manager.js'). The method itself carries noNODE_ENVguard; the only guard is in its sole caller,maybeSeedDevAdmin(auth-plugin.ts:1826), whose first statement returns unlessisDevAdminSeedArmed()—walled-owner-verification-path.ts:144,NODE_ENV === 'development'. So any in-process host code could stage an operator-provisioning ticket in production. Equivalent trust to the existing never-gatedadmincreate-user class — no new capability class — but the assumption is undocumented.signUpEmailcall, cleared infinally, 60 s TTL floor pruned lazily at:4122-4127), a publicPOST /sign-up/emailcarrying exactly the seed address would be classifiedoperatorand admitted. Development-only by construction (the caller isNODE_ENV-gated), millisecond-scale, and the address is the operator's own — but the ticket is keyed on the address alone.Candidate dispositions (none chosen here)
minor(the method leaves the public surface).nameor a nonce the seed passes through the sign-up body) so a concurrent stranger's request for the same address cannot ride it.Boundary
Read from the diff and the base tree by the reviewer; no runtime measurement of the race. Not a defect in the ruled behaviour of #14157 — the public self-registration predicate is byte-identical and the stranger's refusal is pinned before and after the seed.
Refs: #14157 · PR #14352 · #14349 (posture question) · #14348.