Repository navigation
AUTH-MAIL-002C2A — Bind verification results to the current identity service #571
Description
Outcome
Bind every deliberate email-verification attempt and displayed result to the exact ready identity service that started it. If that identity context changes after a provider request begins, retire the private link instead of reusing its code.
This is browser source, synthetic tests, and an officer source-review update only. It is NOT LIVE until the exact website revision is published and verified separately.
Why this matters
The verification page correctly makes a visitor click before applying a Firebase action code. It also ignores results after the page unmounts or the capability route changes.
It does not currently invalidate an in-flight request when Firebase readiness is lost or when the app replaces identity service A with identity service B. A late completion from A can therefore show a terminal result while the page belongs to B. Reusing the same one-time code through B would also cross an identity-service authority boundary that this browser cannot prove safe.
Invariant
- Derive one effective identity service only while the Firebase service locator is ready.
- Before any provider request starts, a readiness or service-object change may select the current ready service. No automatic request occurs.
- Once
verifyEmailActionis invoked, bind that attempt and capability to the exact committed service object and context generation. - A later readiness loss, missing service, or service-object replacement retires the code for this page, immediately hides its pending or displayed result, and shows only the fixed unusable outcome. The replacement service receives no call. The member must request one new verification email.
- A late obsolete resolve, rejection, or cleanup must not:
- set or focus a provider result;
- change the current fixed state;
- inspect, format, log, or serialize a rejection;
- navigate or start another provider request.
- Temporary A → unavailable → A after a request began is a new generation and remains unusable. The first request may already have consumed the code.
- Replacing a service-locator wrapper around the same identity-service object does not reset a valid current result and does not start a request.
- A → B → A is a new context generation. The first A completion remains obsolete.
- Within one unchanged service generation, preserve the existing offline behavior and fixed temporary retry. A click rejected locally while offline makes no provider request and does not bind the code.
- Preserve capability scrubbing, rapid-repeat protection, fixed public states, Identity-service provider-operation validation, same-route invalidation, and unmount behavior.
A provider request already sent through an obsolete service cannot be cancelled by this browser change. This slice makes browser truth fail closed; it does not undo or prove any provider-side mutation.
Exact scope
src/pages/login/VerifyEmailAction.tsx- Only the effective ready identity-service context, committed generation/fence, attempt token, capability retirement, and result display gates.
- Existing
src/pages/login/VerifyEmailAction.test.tsx- One separately named
AUTH-MAIL-002C2Ablock plus the minimum controllable service helpers. - No new test file and no lint-ledger change.
- One separately named
docs/officers/EMERGENCY_AND_RECOVERY.md- Only the existing
Verification link page — SOURCE ONLY, NOT LIVEsection, diagram, source-review steps, stop conditions, and proof needed to describe current-service invalidation.
- Only the existing
Required tests
- Attempt on A, then readiness becomes false before A succeeds; returning to A does not reuse the code.
- Attempt on A, then services become unavailable before A succeeds.
- Attempt on A, switch to B, and prove B receives no call while late A success remains inert.
- Late hostile A rejection remains inert without property reads, logging, or serialization.
- A → B → A after a provider request remains unusable and makes no second call.
- Terminal A result followed by readiness loss or service replacement is hidden and exposes no enabled retry.
- A wrapper-only change with the same identity-service object preserves current state and starts no second request.
- Service replacement before the first provider request permits one deliberate call through the current service.
- An offline click makes no provider request and does not prevent a later current-service call.
- Current-service success and fixed same-context unavailable/retry behavior remain correct.
- Existing route scrub, rapid-repeat, provider-operation, and unmount tests remain green.
Use synthetic action codes and service doubles only. Do not call Firebase or an email provider.
Explicit exclusions
src/services/identity/Identity.tsand its tests.- Login form, password reset, Google sign-in, account linking, roles, or membership authority.
- App routes, Firebase configuration, App Check, Sentry, Analytics, CSS, or storage.
- Firebase email templates, global action-handler configuration, DNS, sender authentication, spam/delivery, provider consoles, or live email.
- Functions, Firestore Rules, packages, locks, workflows, deployment, production data, or live verification.
- Active dependency-security paths and
SECURITY.md. - Coordinating parent MEMBERS-DIRECTORY-001 — Add a private opt-in officer photo directory #504 and draft rollback PR Rollback: prepare exact pre-header Netlify artifact #462.
Dependencies and residuals
- Follow-up to merged verification-action source child AUTH-MAIL-002C2 — Handle verification links safely without exposing action codes #194.
- Uses the merged current-context pattern established by AUTH-006E — Bind browser auth projection to the current identity service #519; it does not change that hook.
- Source containment does not depend on blocked provider configuration under AUTH-MAIL-001 — Brand and authenticate Firebase Authentication email #119/AUTH-MAIL-002 — Make account-email delivery states honest and recoverable #120.
- Firebase's project-wide action handler still must not point to a verification-only page while password-reset or recover-email modes need another handler.
- Provider delivery, global-handler configuration, exact website publication, Firebase behavior, and live email verification remain separate.
Acceptance evidence
- Trustworthy RED against the old component.
- Focused GREEN tests and relevant full frontend checks.
- TypeScript, lint ledger, SPA/repository safety checks, and diagnostic build.
- Exact path/diff review plus independent privacy/lifecycle, test/mutation, and backup-officer reviews.
- Hosted PR CI and exact-main CI.
- Separate evidence for source changed, tests passed, merged, website published,
runmprc.comverified, Firebase/provider configured, and production behavior verified.
Officer impact: No live procedure changes. The source-review guide explains that losing or changing the identity service after Checking verification... begins makes the private link unusable and requires one new verification email.
Officer documentation: docs/officers/EMERGENCY_AND_RECOVERY.md — only the existing verification-link source-review section and diagram.
Deployment evidence: None at issue creation. Source or CI must not be described as website publication, Firebase configuration, provider delivery, or live verification.
Activity
daliu commentedon Aug 1, 2026
CLAIMED by
/rootat2026-08-01T22:21:47Zon branchcodex/issue-571-verification-context, exact released base7a9f7647d40c6846015605d25e43f9e87c4653d0.Exact ownership:
src/pages/login/VerifyEmailAction.tsxsrc/pages/login/VerifyEmailAction.test.tsxAUTH-MAIL-002C2A current identity-service boundaryblock plus minimum controllable service helpers;docs/officers/EMERGENCY_AND_RECOVERY.mdVerification link page — SOURCE ONLY, NOT LIVEsection, diagram, steps, stop conditions, proof, and text alternative needed for current-service loss/change truth.Invariant: an attempt and its visible result belong only to the exact ready identity-service object and generation that started it. Readiness/service loss or service identity change invalidates the prior browser result synchronously. A late obsolete completion cannot change/focus UI, clear the capability, unlock/overwrite a newer attempt, inspect/log a rejection, navigate, or start provider work. A same-service wrapper change is not a new context. A → B → A is a new generation. The visitor must deliberately retry on the current service.
Immutable exclusions:
Identity.tsand its tests; LoginForm/password reset/Google/account linking; App/routes/Firebase config/App Check/Sentry/Analytics/CSS/storage; Functions/Rules/packages/locks/workflows; provider templates/configuration/delivery; membership/roles; deployment/data/live work; every #566 listMyRegistrations/SECURITY path; coordinating #504; draft #462.The empty remote branch was pushed before this marker. Live issue/PR/branch/path searches found no competing claim. No source, test, or documentation edit preceded this claim. Claim remains active through RED, implementation, independent exact-head review, hosted CI, merge, exact-main/deployment audit, closure, and explicit release.
Officer impact: source-review clarity only; no live officer procedure or provider step.
Officer documentation: only the named section in
docs/officers/EMERGENCY_AND_RECOVERY.md.Deployment evidence: none at claim time; source/CI will not be described as website publication, Firebase/provider configuration, delivery, or live behavior.
daliu commentedon Aug 1, 2026
TRUSTWORTHY RED — before runtime or officer-guide edits
7a9f7647d40c6846015605d25e43f9e87c4653d0.src/pages/login/VerifyEmailAction.test.tsx.0a57c1daf082ff7d050d8452eef29295cc229eec8ff2680355db63ec90c95e48.v20.20.2with its binary directory pinned inPATH.AUTH-MAIL-002C2Ablock.Expected RED observed: 6 failed / 1 passed / 27 skipped.
The six intended failures prove exact current source:
Checking verification...after readiness is lost;Email verified.result after service replacement.The same-identity-service wrapper control passed, proving the tests do not require every service-locator wrapper change to reset valid state.
No runtime, officer documentation, Firebase/provider configuration, email, account, data, website, deployment, or live behavior changed. All values and services are synthetic; no network call occurred.
daliu commentedon Aug 1, 2026
SECURITY/SCOPE AMENDMENT —
2026-08-01T22:38:42Z, before the corrective runtime/test/guide editsIndependent privacy review found that the original retry invariant was too permissive. A change from identity service A to a distinct service B is an authority boundary. This source slice has no proof that both objects represent the same Firebase project or trust context. Sending the same private one-time action code through B after it was already sent through A would therefore reuse a bearer capability across unproven authorities.
The safer amended invariant is:
verifyEmailActionhas been invoked through one service, the capability is bound to that committed service generation.useMemotoken identity are not security guarantees.finallynot unlocking B are superseded. Late obsolete resolve/reject/finally paths still must not alter UI, clear current state, inspect/log rejection values, navigate, or start provider work.Required test corrections within the already claimed test block:
The already claimed officer-guide section will replace its same-link retry instructions with plain observable steps: if
Preparing verificationor the fixed unusable result appears after a click, do not reuse the link; request one new verification email. It will also keep one action per numbered step.Exact three-file ownership and every exclusion remain unchanged. This amendment narrows provider calls and capability use; it adds no provider configuration, deployment, data, or live action.
Officer impact: source-review wording becomes safer and simpler; no live procedure changes.
Officer documentation: the already claimed
Verification link page — SOURCE ONLY, NOT LIVEsection only.Deployment evidence: none; this is an issue-contract correction before final implementation.
daliu commentedon Aug 1, 2026
AMENDED TRUSTWORTHY RED —
2026-08-01T22:49:43ZThis supersedes the earlier 6-failure/1-control RED because the
2026-08-01T22:38:42Zsecurity amendment removed unsafe cross-context capability reuse and added the offline/no-provider boundary.7a9f7647d40c6846015605d25e43f9e87c4653d0.src/pages/login/VerifyEmailAction.test.tsx.12fe6d7023e58260e16ec9614c64491160a9c94e985ef27031c43500c71da000.Independent old-source reproduction: 8 intended failures / 2 controls passed / 27 skipped in the named
AUTH-MAIL-002C2Ablock.The failures prove current main does not yet:
The controls prove the test does not reset a same-service wrapper and still permits a service replacement before the first provider attempt.
No runtime, officer documentation, website, Firebase/provider configuration, deployment, production data, or live behavior changed during RED.
daliu commentedon Aug 13, 2026
RECOVERY / BRANCH AMENDMENT —
2026-08-13T05:05:37Z, before reconstructed editsThe original uncommitted candidate worktree under
/private/tmpwas removed by external temporary-file cleanup. No #571 source commit or pull request existed; the original remote branch still contains only the old base.I recovered the exact reviewed patch sequence and final diff hash from the durable Codex session log. Recovery now continues on empty branch
codex/issue-571-verification-context-v2, published before edits from exact current mainb94622bd42775d84704d5fc05ee87da81f5a76e0.The three claimed file blobs on current main are byte-identical to the original base
7a9f7647d40c6846015605d25e43f9e87c4653d0:VerifyEmailAction.tsx:227b8dde853dc3fc843e6d8841ec183bca22839dVerifyEmailAction.test.tsx:900896be5312001df103c2178049fa2e9434eb94EMERGENCY_AND_RECOVERY.md:d76187ffbd459996c7e2464546b050f4d6d7a889The recovered old-base exact three-file binary diff was
ab79ef9ca2809a1d65e71d9ceae525af7274896a9ece28677a9efb24f65448ce. I will reconstruct it with the same amended fail-closed invariant, then require a fresh exact-current-main diff review and all current gates. I will not treat the deleted candidate's prior green checks as current acceptance evidence.Exact ownership and exclusions are unchanged. Active #616, #617, coordinating #504, and draft #462 remain immutable and path-disjoint.
Officer impact: source-review clarity only; no live procedure or provider step.
Officer documentation: only the already claimed verification-link section in
docs/officers/EMERGENCY_AND_RECOVERY.md.Deployment evidence: none. Branch publication is not website publication, Firebase/provider configuration, email delivery, account/data action, or live proof.
daliu commentedon Aug 13, 2026
EXACT REVIEWED CANDIDATE / PR
PR #619 is open from exact current-main parent
b94622bd42775d84704d5fc05ee87da81f5a76e0at exact reviewed head5ecdbf4c08097921399031f861711d3cfd926148, treeb3b6bf5999bf5bb96f4071fc822306472e6daa6a.Exact three-file binary diff SHA-256:
deb47b0a8451ec4b07c0c6498fbfe7252b83ca3dfa824f6156da9e5703798025.Current Node 20 evidence:
The initial reconstructed diff exactly matched the prior recovered hash; one independent mutation review then found and drove two additional provider-unavailable/context-retirement tests before this final commit. The exact runtime and officer-guide blobs remain the reviewed recovered versions.
Claim remains active through exact-head hosted CI, base-fresh merge, exact-main CI/deployment audit, issue closure, and explicit release.
PR: #619
Deployment evidence: source/test/PR only. No website publication,
runmprc.comverification, Firebase/provider configuration, email, account/data action, or live behavior proof.daliu commentedon Aug 13, 2026
FINAL COMPLETE / CLOSED / CLAIM RELEASED
#571 AUTH-MAIL-002C2A is complete. All exact claims are released.
PR #619 admin-squash-merged exact independently reviewed head
5ecdbf4c08097921399031f861711d3cfd926148as exact main3af585077d665d7720b35b5b89505b1d90d9a007. Head and merge tree are identical:b3b6bf5999bf5bb96f4071fc822306472e6daa6a. Exact merged three-file patch SHA-256:deb47b0a8451ec4b07c0c6498fbfe7252b83ca3dfa824f6156da9e5703798025.Evidence:
31669859505passed all five required jobs;31670041767passed all five required jobs;[].Netlify truth: PR preview
6a7d5390868d870008a6dc36is an isolated ready preview withpublished_at: null. Exact-main attempt6a7d5456776e57000898dc05iserrorwithpublished_at: null. Publicrunmprc.comstill reports the separate #473 containment marker (control9ad6837, source39ab864, treed76b496, 60 files, digest07b10c7d…). Therefore #571 is merged but not published/live.No protected release, Firebase deployment/configuration, email-provider action, account/data action, migration, or live verification occurred. A provider request already sent through an obsolete service remains outside browser cancellation and proof.
Released paths/hunks:
src/pages/login/VerifyEmailAction.tsx;AUTH-MAIL-002C2Ablock/support insrc/pages/login/VerifyEmailAction.test.tsx;docs/officers/EMERGENCY_AND_RECOVERY.md.Future work may refresh from exact released main
3af585077d665d7720b35b5b89505b1d90d9a007or later and must preserve #571 behavior.