Skip to content

AUTH-MAIL-002 — Make account-email delivery states honest and recoverable #120

Open

Description

@daliu

Officer impact: Members receive clear, accurate instructions when verification or password-recovery email is sent, delayed, or unavailable. Officers can point members to a safe recovery path without requesting passwords, codes, screenshots, or private links.

Officer documentation: Update docs/officers/EVENTS_SHOP_MEMBERS.md and docs/officers/EMERGENCY_AND_RECOVERY.md with the member-facing recovery wording, stop conditions, proof, undo, and escalation. Mark the revised behavior NOT AVAILABLE YET until the website publication is verified.

Deployment evidence: None at issue creation. Closure requires deterministic frontend tests, no-network provider mocks/emulators, merged source, website publication, runmprc.com verification, and a staged Auth-flow walkthrough using synthetic accounts. It does not require or authorize real email delivery from production.

Problem

Account registration currently catches a Firebase verification-email error, writes only a console warning, and can still tell the member to check the inbox. That makes account created and verification message sent look like the same successful state.

The resend path has no visible cooldown. Raw or inconsistent provider errors can confuse members, while detailed password-reset errors can reveal whether an account exists.

Atomic outcome

Represent identity and email-delivery outcomes separately and provide one simple recovery path:

  • Account created.
  • Verification message accepted for sending.
  • Delivery request failed or is temporarily unavailable.
  • Resend is available after a visible cooldown.
  • Already verified, link expired/used, and wrong-account states have plain next steps.

The UI may suggest checking Spam and marking the approved sender as not spam, but must explain that this does not fix delivery for everyone.

Security and usability invariants

  • Never claim a message was sent after the Firebase call failed.
  • Password reset and public recovery responses remain generic and do not confirm whether an email/account exists.
  • Do not display raw Firebase error codes, stack traces, email addresses, action links, or tokens.
  • Do not log names, emails, request bodies, action links, or raw provider errors.
  • Resend has a client-visible cooldown and must also tolerate provider throttling; it is not an authorization control.
  • A retry cannot create another account, change membership, grant access, or lose the task the member was trying to complete.
  • Controls and copy use large, clear actions and ordinary language suitable for elderly/nontechnical members.
  • All tests use mocks/emulators and synthetic data; no production inbox or action link is used.

Acceptance criteria

  • Registration distinguishes account created from verification request accepted and verification request failed.
  • A failed verification request shows a generic recovery action and never says to check the inbox as if success were proven.
  • Resend shows a visible countdown, blocks accidental repeat clicks, and recovers after success, failure, refresh, and sign-in changes.
  • Password-reset UI returns the same public result for existing, missing, malformed, throttled, and provider-failure cases where enumeration resistance requires it.
  • Verification success, already verified, expired/used link, wrong account, offline, and provider-unavailable states have one clear next action.
  • Spam guidance names the currently configured sender generically and can be updated after AUTH-MAIL-001 without a code fork.
  • Screen-reader labels, focus movement, keyboard flow, readable control sizes, and loading/disabled states are tested.
  • Unit/integration tests prove success, send failure, resend cooldown, retry, navigation preservation, and generic-error behavior without any network call.
  • No logs, analytics, screenshots, fixtures, or errors contain an email address, action URL, code, or token.
  • Officer guidance states what can be checked, what must never be requested from a member, and when to escalate.

Dependencies and coordination

The implementation becomes claimable after #103 and the required no-network test boundary are merged. Provider configuration may proceed separately under #119.

Explicitly out of scope

  • Custom sender-domain DNS, SMTP/provider delivery, template administration, Google sign-in, membership approval, dues, discounts, or role grants.
  • Reading a member mailbox, sending production test mail, or collecting message headers/action links in public systems.

Claim protocol

Creation is not a claim. Before editing, confirm dependencies, assign the issue, post CLAIMED by <canonical agent> at <UTC>; branch <branch>, and re-read all comments. Keep this as one tested UI/recovery outcome.

Activity

  1. 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:proposedDesigned but dependencies or decisions remain
    type:testingTest infrastructure and quality gates
    on Jul 13, 2026
  2. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    #145 / AUTH-MAIL-002A child update

    The registration/email-request truth slice is source-complete and merged through PR #148 as 46557c7. Exact PR and post-merge CI passed, and two independent exact-diff reviews approved.

    This completes the source behavior for the first two parent acceptance outcomes: account creation is distinct from verification-request acceptance/failure, and a failed request never falsely says to check Inbox. The member keeps the account and receives a safe stop/escalation path.

    Production remains NOT LIVE. Protected release run 29247125844 failed closed before build/cloud access because required public App Check configuration is absent; Firebase and Pages were skipped, and runmprc.com still serves the prior asset. Keep this parent open.

    Remaining atomic work:

    • #120B: truthful My Account resend result plus visible cooldown/session-reset behavior. Publish and claim as a focused child before editing Account paths.
    • #120C: generic password-reset and action-code recovery states. Publish and claim separately.
    • AUTH-MAIL-001 — Brand and authenticate Firebase Authentication email #119: sender/provider configuration remains parallel owner work.

    Do not advertise Resend as a verified recovery procedure until #118 backend/profile behavior, #120B source, staged behavior, and live publication are all proven.

  3. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    AUTH-MAIL-002B is now published and claimed as #153 for the My Account resend request result, 60-second visible client cooldown, double-click guard, accessibility, and no-network tests. It explicitly treats provider resolution as request acceptance, not delivery; refresh may reset the usability cooldown and does not bypass provider throttling. #119 and AUTH-MAIL-002C remain separate.

  4. added
    status:in-progressClaimed and actively being implemented
    and removed
    status:proposedDesigned but dependencies or decisions remain
    on Jul 13, 2026
  5. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Status correction: parent AUTH-MAIL-002 is now status:in-progress while claimed child #153 is active. #145 is source-merged but not published; #153 owns resend truth/cooldown; AUTH-MAIL-002C remains proposed. Parent closure still requires all child and deployment/live evidence.

  6. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    AUTH-MAIL-002 progress at 2026-07-13T13:08:36Z: child #153 completed and merged through PR #154 as 23bca8c. The first three parent acceptance boxes now reflect merged #145 registration truth plus merged #153 resend truth.

    The parent stays OPEN and status:in-progress. Remaining work includes AUTH-MAIL-002C password-reset/action-code recovery states, #119 sender/provider configuration, and protected publication/live verification.

    Deployment is not complete: release run 29252492614 stopped before build because the production environment lacks the public App Check site key. Firebase and Pages were skipped, so no website, Firebase, provider, mailbox, or production-behavior claim is made.

  7. 1 remaining item

  8. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    COORDINATION — #178 is validly claimed at 2026-07-13T20:29:16Z on codex/issue-178-pause-profile-phone. It owns the My Account/profile-service phone-control hunks listed in #178 and preserves all merged AUTH-MAIL resend behavior. AUTH-MAIL-002C2 must not edit those exact hunks until #178 releases them; email/action-code behavior remains outside #178.

  9. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Coordination release — #178 merged as 6017493f3366790eefba5d00baf3df7211dfc380; post-merge CI passed and its ten-path claim is released. Future work should refresh from that SHA and preserve the source-only My Account phone pause and name-only owner update boundary. Firebase deploy/readback and production verification remain unproven; #178 did not change Functions, providers, or production data.

  10. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    AUTH-MAIL-002C2 is now published/assigned/CLAIMED as #194 at 2026-07-13T23:38:15Z on codex/issue-194-verify-email-action, exact base aafd15c04fbcd09341092a78f23d513b09cca5d2.

    This is one verification-only source/test outcome: a deliberate-click /account/verify-email page, closed Identity result projection, query/fragment scrub, capability telemetry/App Check guard, no-network tests, and minimum officer/status docs. It excludes My Account/profile/phone, password reset completion, recover-email mutation, providers/templates/DNS, Functions, Rules, packages, workflows, and live publication.

    Important release boundary: Firebase uses one configured custom action handler across verification, reset-password, and recover-email templates. #194 must remain SOURCE ONLY and must not be wired as the global handler until every enabled mode has separately reviewed safe coverage, or #119 retains Firebase's default multi-mode handler. Parent #120 remains in progress while this child is active; provider/live acceptance remains open.

  11. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Pre-edit #194 route correction: the source path is /auth/action, not /account/verify-email. Firebase configures one generic handler URL, so the generic route is the truthful future dispatcher shape. C2 still supports verification only and remains forbidden for global provider activation until every enabled mode is safely covered.

  12. daliu commented on Jul 14, 2026

    @daliu
    ContributorAuthor

    AUTH-MAIL-002C2 source update — 2026-07-14T00:17:06Z

    Focused child #194 completed through PR #195 and merged as e76b1ee01a0f0ce9951fdcc6e454b66288394b93. It adds the deliberate verification-only action, native/router capability scrub, strict syntax and provider-operation checks, fixed accessible results, telemetry startup suppression, and officer guidance. Exact-head and post-merge hosted CI passed.

    Parent #120 remains open. The source is not published on runmprc.com; Firebase's global handler, templates, sender/DNS, Spam/delivery, enumeration protection, Firestore verification mirror, and live behavior remain unproven. Never configure the verification-only route as the project-wide handler while reset-password or recover-email modes would reach it.

  13. daliu commented on Jul 17, 2026

    @daliu
    ContributorAuthor

    C6 landed in PR #344 (f98b62c).

    Verification and password-reset anti-spam copy now flows through a single getSpamGuidance() seam that names the configured sender via REACT_APP_ACCOUNT_EMAIL_SENDER (blank → generic "the club's account email"). This satisfies acceptance criterion C6 — "Spam guidance names the currently configured sender generically and can be updated after AUTH-MAIL-001 without a code fork." The guidance still refuses to over-promise (never "sent"/"delivered"; states that marking Not-spam does not fix delivery for everyone).

    Kept open intentionally. The remaining criteria are already honest in source but gated on work I can't complete autonomously:

    Once #119 publishes the approved sender and it's set in the build config, this issue can be verified live and closed.

  14. daliu commented on Jul 18, 2026

    @daliu
    ContributorAuthor

    Coordination only — AUTH-UX-001A #368 was published/assigned/CLAIMED at 2026-07-18T23:20:55Z on codex/issue-368-account-signout, exact base 73b46cbf37e204bd1e69000c396e0736d500cb07.

    #368 owns only the existing My Account sign-out control/state in Account.tsx, an additive named sign-out test block in Account.test.tsx, additive .account-sign-out* CSS, one separately named sign-out procedure in EVENTS_SHOP_MEMBERS.md, and only the profile symptom/missing-profile sign-out wording in EMERGENCY_AND_RECOVERY.md.

    Every merged #120 resend, account-email, password-reset, verification/action-handler, sender/Spam, and live/provider hunk is immutable. #368 does not alter parent acceptance or claim provider/live completion.

  15. daliu commented on Jul 18, 2026

    @daliu
    ContributorAuthor

    Coordination release — 2026-07-18T23:52:30Z: child #368 is complete/closed via PR #371 at exact main df91460. Pull-request CI 29665823878 and exact-main CI 29665891927 passed all five jobs. Its exact five-path claim is released. This is source/test/merge evidence only: no protected release, website/runmprc.com verification, Firebase/Auth provider action, production account/session action, or live sign-out proof occurred. Parent #120 provider/live-email work remains separate.

  16. daliu commented on Jul 19, 2026

    @daliu
    ContributorAuthor

    Coordination claim — 2026-07-19T00:00:48Z: #374 owns only the upcoming-registration empty-state hunk in Account.tsx, one named empty-state test block in Account.test.tsx, listMyRegistrations source/new tests, a named officer-guide section, and one SECURITY ledger row. All #120 verification-email/resend/action-handler/sign-out/profile/provider/live hunks are immutable. No current #120 source claim was found; please stop and coordinate before touching these exact #374 hunks.

  17. daliu commented on Jul 19, 2026

    @daliu
    ContributorAuthor

    COORDINATION RELEASE — 2026-07-19T00:30:02Z

    DATA-001A3/#374 merged as exact main e414c828c3171f212737a5026d04aac05e61e1d1; exact-main CI 29666951610 passed. The slice removes email-based My Account registration ownership and keeps registration-load failure separate from empty success. It changes no verification-email, resend, action-handler, sender, profile, sign-out, or other #120 behavior. No deployment/live proof exists. The Account/list-registration/docs claims are released.

  18. added and removed
    status:in-progressClaimed and actively being implemented
    on Jul 22, 2026
  19. daliu commented on Jul 22, 2026

    @daliu
    ContributorAuthor

    STATUS CORRECTION — 2026-07-22

    The status:in-progress label was stale. All named source children (#145, #153, #155, #194, and the C6 source change in #344) are merged and their claims are released. The 2026-07-19 coordination comment also records that no current #120 source claim exists.

    The remaining closure work is owner/release-gated: #119 must supply the approved sender/provider configuration, and #105/#133/#136 must provide protected publication plus exact live-site verification. No new #120 engineering child is dependency-clear.

    The issue is therefore relabeled status:blocked-owner. This tracking correction changes no source, website, Firebase/Auth configuration, mailbox, production data, or live behavior.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:authAuthentication and authorizationarea:firebaseFirebase services and dataarea:webWeb application and hostingbugSomething isn't workingpriority:P1High-priority follow-upsize:SSmall focused issuestatus:blocked-ownerRequires an owner or external decisiontype: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