Repository navigation
AUTH-MAIL-002B — Make verification resend honest and rate-conscious #153
Description
Officer impact: Members see whether Firebase accepted a verification-email request, without a promise that delivery succeeded. A visible countdown prevents accidental repeat clicks. Officers never need passwords, codes, screenshots, email addresses, action links, or mailbox access.
Officer documentation: Update docs/officers/EVENTS_SHOP_MEMBERS.md and docs/officers/EMERGENCY_AND_RECOVERY.md. Keep this 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 verification, Firebase/provider configuration, and observed behavior. No production email may be sent as a test.
Parent and dependencies
Focused AUTH-MAIL-002B child of #120. #145 completed registration/send truth. #118 completed the profile recovery source used by My Account. #99, #103, and #111 supply isolated tests and redacted diagnostics. #119 owns sender/domain/provider configuration. #105/#133/#136 own protected publication.
Problem
My Account currently says Verification email sent after the provider call resolves, although that proves only request acceptance. It has no visible cooldown and can make repeated provider calls. A provider failure gives only a vague line and no predictable retry state.
Atomic outcome
Replace the current resend control with one simple state machine:
- Idle: Request another verification email.
- Sending: one disabled large action.
- Accepted: explain that the request was accepted, delivery can take time, and Inbox/Spam may be checked.
- Unavailable: fixed generic wording with no provider detail.
- Cooldown: after every completed attempt, show the seconds until another try and block repeat calls.
The cooldown is a browser usability guard, not an authorization or abuse-control boundary. A page refresh or signed-in UID change may reset it; Firebase throttling can still apply. State this truth in tests/docs rather than claiming a durable server limit.
Invariants
- Never say an email was sent or delivered; say the request was accepted.
- A synchronous in-flight guard prevents rapid double-click provider calls.
- Success and failure use the same visible cooldown and recover to one retry action.
- Refresh, unmount, and signed-in UID change do not leave the control stuck or apply a stale result to another account.
- Raw provider errors, email addresses, UIDs, action links, codes, and tokens never enter UI, logs, analytics, screenshots, or test output.
- Resend does not create an account, change membership/roles/dues/discounts, navigate away, or edit Firestore.
- Password reset/action-code handling remains the separate AUTH-MAIL-002C child.
- Tests use synthetic mocks only and make no network or production-mail request.
Exact source boundary
- src/pages/account/Account.tsx
- src/pages/account/Account.test.tsx
- new src/pages/account/Account.css only if needed for a verified large/focus-visible action
- docs/officers/EVENTS_SHOP_MEMBERS.md
- docs/officers/EMERGENCY_AND_RECOVERY.md
- minimum exact status hunks in SECURITY.md, OPERATIONS_RUNBOOK.md, GITHUB_ISSUES.md, and GITHUB_ISSUE_SLICES.md
Post a scope amendment before editing Identity runtime, Firebase config, workflows, packages, Functions, Rules, provider settings, password/action-code screens, or any other file.
Acceptance criteria
- Accepted result uses request-accepted wording and never says sent or delivered.
- Failure result is fixed/generic and contains no caught provider detail.
- A visible 60-second countdown follows both accepted and unavailable attempts.
- Disabled state plus an immediate in-flight guard proves one provider call under rapid repeat activation.
- The action becomes available after the countdown, and remount/UID-change tests prove no stuck or cross-account result state.
- Accessible status/alert announcements, keyboard activation, focus visibility, and at least a 44px action target are tested.
- No-network tests cover idle, sending, accepted, unavailable, duplicate click, countdown, retry, remount, and UID change.
- Officer guidance gives purpose, approver, prerequisites, steps, expected result, stop conditions, proof, undo, and escalation.
- Full frontend, SPA, lint/build, diff/link/sensitive-pattern checks pass.
Excluded
- DNS, sender branding, Firebase templates, SMTP/mail provider, production delivery tests (AUTH-MAIL-001 — Brand and authenticate Firebase Authentication email #119).
- Password reset and Firebase action-code states (future AUTH-MAIL-002C).
- Google sign-in/linking (AUTH-006 — Offer simple email/password and Google sign-in #109/AUTH-004 — Link a Google identity to an existing Firebase member account #82), membership/role/payment state, Firebase Rules/Functions, workflows, or production data.
Claim protocol
Creation is not a claim. Assign one agent and post CLAIMED with canonical agent, UTC timestamp, unique branch, and exact base before editing.
Activity
daliu commentedon Jul 13, 2026
CLAIMED by Codex agent /root at 2026-07-13T12:47:38Z; branch codex/issue-153-verification-resend; exact base 7c7a41c. Ownership is limited to the issue source/docs paths. No provider setting, real email, production mailbox, Firebase backend, membership/payment state, workflow, secret, or production record will be used.
daliu commentedon Jul 13, 2026
IMPLEMENTATION / REVIEW READY — 2026-07-13T13:02:49Z
Exact base: 7c7a41c
Exact staged diff SHA-256: e379783f3c4bf57b51139608b55721553918c23bf91a1e3c2141ff27efefc686
Independent review: two exact-hash reviews APPROVED with no findings.
Node 20 verification:
Officer impact: My Account now reports request acceptance or generic unavailability, never delivery. Rapid repeats are blocked and both completed results show the same 60-second browser wait. The display may reset on refresh/account change and is not server abuse protection.
Officer documentation: docs/officers/EVENTS_SHOP_MEMBERS.md and docs/officers/EMERGENCY_AND_RECOVERY.md.
Deployment evidence: Source/tests only. No website publication, runmprc.com verification, Firebase/provider configuration, production mailbox, real email, member record, or live behavior was used or verified. Exact #118 backend deployment/readback must precede #153 website publication.
daliu commentedon Jul 13, 2026
COMPLETED source outcome by /root at 2026-07-13T13:08:36Z.
Acceptance boxes reflect the completed source/test outcome. The #153 claim is released. External configuration and backend-first publication remain with #105/#133/#136; sender/provider work remains #119.