Skip to content

AUTH-MAIL-002A — Tell the truth when account creation succeeds but verification sending fails #145

Closed

Description

@daliu

Officer impact: Members will see whether the account exists and whether Firebase accepted the verification-email request as two separate facts. Officers get a safe recovery message and never need a password, code, screenshot, email address, action link, or mailbox access.

Officer documentation: Update docs/officers/EVENTS_SHOP_MEMBERS.md and docs/officers/EMERGENCY_AND_RECOVERY.md. Keep behavior NOT AVAILABLE YET until the exact website revision is published and verified.

Deployment evidence: None at issue creation. Closure must separate source/tests, merge, website publication, runmprc.com, Firebase/provider configuration, and observed behavior. No production email may be sent as a test.

Parent

Focused child of #120. The parent must remain open for resend cooldown/session reset and password-reset/action-code recovery children.

Problem

Firebase can create the account and then reject the verification-email request. Current code catches that second failure but the page still says “Check your inbox,” falsely presenting email delivery as proven. The reported Firebase sender also landed in Spam; sender branding/authentication remains owner work under #119.

Atomic outcome

Return and display two explicit results after registration:

  1. Account created.
  2. Verification-email request accepted or temporarily unavailable.

A failed send request preserves the signed-in account and provides one generic recovery action. It never claims that a message was sent.

Invariants

  • Account creation success is never rolled back or hidden because the later email request failed.
  • The UI never says to check Inbox or Spam unless Firebase accepted the send request.
  • Failure copy contains no raw Firebase code/message, email address, action URL, token, or account-enumeration detail.
  • No caught error object or member value reaches console, Sentry, Analytics, test output, or screenshots.
  • Registration return navigation, membership, roles, dues, discounts, and admin access do not change.
  • Tests use Firebase mocks and synthetic .example identities; no network or production mailbox.

Exact source boundary

  • src/services/identity/Identity.ts
  • new src/services/identity/Identity.test.ts
  • src/pages/login/LoginForm.jsx
  • src/pages/login/LoginForm.test.jsx
  • docs/officers/EVENTS_SHOP_MEMBERS.md
  • docs/officers/EMERGENCY_AND_RECOVERY.md
  • minimum #120A status hunks in SECURITY.md and OPERATIONS_RUNBOOK.md

Acceptance criteria

  • Identity registration returns an explicit verification-request outcome without exposing the caught provider error.
  • Create failure remains a generic authentication failure and never shows an email-success state.
  • Create success plus send acceptance says the account exists and that the request was accepted; it may suggest checking Inbox and Spam without promising delivery.
  • Create success plus send rejection says the account exists, the request was not completed, and the member can check My Account for the next available step. If My Account is unavailable, the member keeps the account and stops for identity-owner help. Resend is not advertised by this child.
  • The failure state preserves the signed-in user and does not retry, create another account, navigate away, or grant any access.
  • Status messages use an accessible live region/focus behavior and large clear actions suitable for nontechnical members.
  • Focused tests cover all three outcomes, provider-detail redaction, no false “check inbox,” and preserved return path with no network.
  • Officer guidance names purpose, approver, prerequisites, expected result, stop conditions, success proof, undo, and escalation.

Excluded

Dependencies

#99, #103, #111, #142, and #146 are complete. #119 is parallel provider work, not a source prerequisite. My Account can be unavailable when its profile cannot load, and its current Resend result overclaims delivery. #118 plus #120’s truthful resend/cooldown child must be verified before anyone advertises that recovery path. Preserve #143’s fixed diagnostic identifier and no-raw-console contract.

Claim protocol

Assign one agent and post CLAIMED by <canonical agent> at <UTC>; branch <branch> before editing. Keep this child one registration/send-truth outcome.

Activity

  1. self-assigned this
    on Jul 13, 2026
  2. added
    bugSomething isn't working
    priority:P1High-priority follow-up
    area:authAuthentication and authorization
    area:firebaseFirebase services and data
    area:webWeb application and hosting
    size:SSmall focused issue
    status:readyDependencies complete and ready to claim
    type:testingTest infrastructure and quality gates
    status:in-progressClaimed and actively being implemented
    and removed
    status:readyDependencies complete and ready to claim
    on Jul 13, 2026
  3. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    CLAIMED by Codex agent /root at 2026-07-13T11:14:15Z; branch codex/issue-145-registration-email-truth; exact base f2caaae3b3f25adfd4fc552008871408f18e5931.

    Ownership is limited to the eight paths named in the issue. Account.tsx, resend cooldown, password reset/action codes, provider/DNS/template settings, Firebase Rules/Functions, Google sign-in/linking, membership/payment state, workflows, and production email/data are excluded. Tests use synthetic Firebase mocks and no network. Any overlapping newer claim is a stop-and-coordinate condition.

  4. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    SCOPE AMENDMENT by Codex agent /root at 2026-07-13T11:15:40Z: add only src/services/monitoring/clientDiagnostics.test.ts to the test boundary.

    Reason: merged #142 added a regression assertion in that file that directly fixes the old Identity.register() return contract. #145 must update only that assertion while preserving the fixed-identifier/no-provider-data proof. src/services/monitoring/clientDiagnostics.ts and all other #142 runtime/documentation behavior remain immutable. No other scope changes.

  5. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    COORDINATION CORRECTION from #111 at 2026-07-13T11:18Z — no #145 ownership change.

    An independent acceptance audit found that #111 had been closed before signup's fixed failure log had a hostile-canary console regression. #111 is reopened, and test-only child #146 is claimed on codex/issue-146-signup-log-test; it owns only functions/ensureMemberProfile.test.js and does not touch any #145 path or runtime file.

    #145 may continue because it depends on merged #142's diagnostic contract, not on this Functions-only proof. In its final dependency/deployment wording, treat #111 as reopened until #146 merges and the parent re-audit closes. Preserve #142 and #145's current claimed paths; any discovered overlap remains a stop-and-coordinate condition.

  6. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    SCOPE AMENDMENT by Codex agent /root at 2026-07-13T11:22:44Z: add new src/pages/login/LoginForm.css.

    Reason: isolated browser verification proved the repository does not compile its Tailwind-style utility names, leaving the new outcome panel transparent and its recovery action visually indistinct. The new file will contain only scoped registration-outcome* styles for contrast, focus visibility, and a large action. No site-wide stylesheet, Tailwind dependency/configuration, or unrelated login styling is included.

  7. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    SCOPE AMENDMENT by Codex agent /root at 2026-07-13T11:32:30Z: add only src/services/hooks/useAuth.ts.

    Reason: independent review found its exported register(): Promise<void> wrapper discards the new explicit verification-request outcome. There are no current runtime callers, but retaining that contract would let a future screen silently recreate the false-success defect. This amendment changes only the return type/value; it does not change auth state, routes, providers, resend behavior, or any other hook method.

  8. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    IMPLEMENTATION / REVIEW READY

    Status: in review.

    Exact base: 8d25007
    Exact staged diff SHA-256: d5c4abca4793af3cedd94a58a02f24be61e9bb21018488133e64ccd80f616025

    Independent review:

    • Security/correctness: APPROVED exact hash; no findings.
    • Officer/usability/accessibility: APPROVED exact hash; no findings.

    Verification on Node 20:

    • Focused identity, login, and diagnostic tests: 44/44 passed.
    • Full frontend tests: 9 suites, 113/113 passed.
    • SPA navigation tests: 10/10 passed.
    • Strict changed-file lint: passed.
    • Optimized diagnostic build: passed.
    • Relative links, sensitive-pattern scan, and git diff check: passed.
    • Synthetic browser check: desktop and 390px layouts passed; action is 48px; no production mailbox or provider was used.

    Officer impact: Members see account creation and verification-email request acceptance as separate facts. If the request fails, the account is kept and the member gets a safe stop/escalation path.

    Officer documentation: docs/officers/EVENTS_SHOP_MEMBERS.md and docs/officers/EMERGENCY_AND_RECOVERY.md.

    Deployment evidence: Source and local tests only at this point. Website publication, runmprc.com, Firebase/provider configuration, and live behavior are not yet proven. No production email was sent.

  9. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    COMPLETED — source, review, merge, and release-gate evidence

    Deployment result:

    • Protected production release run 29247125844 validated exact current main and exact successful CI.
    • It then failed closed because the required public App Check site-key variable is absent.
    • Website build, Firebase authentication/deployment/readback, and GitHub Pages publication did not run.
    • No cloud credential, production email, provider setting, member data, or production record was used or changed.
    • On 2026-07-13, runmprc.com returned HTTP 200 with main.58ede287.js; it did not contain the new copy. The preview and live asset hashes differ, so production behavior is not claimed.

    Officer impact: the merged source gives members separate account-created and email-request outcomes, preserves the account after email-request failure, and gives a safe stop/escalation path.

    Officer documentation: docs/officers/EVENTS_SHOP_MEMBERS.md and docs/officers/EMERGENCY_AND_RECOVERY.md.

    #120 remains open for truthful resend/cooldown and password/action-code recovery. #133/#105 own the protected release configuration blocker. The #145 file claim and status label are released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:authAuthentication and authorizationarea:firebaseFirebase services and dataarea:webWeb application and hostingbugSomething isn't workingpriority:P1High-priority follow-upsize:SSmall focused issuetype:reliabilityReliability and recoverytype:testingTest infrastructure and quality gates

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions