Repository navigation
AUTH-006H — Restore focus to an unconfirmed profile-name Save result #653
Description
Foundation: released #651 / PR #652 and the existing AUTH-006F lifecycle fences.
Officer impact: No live workflow change is claimed at issue creation. In reviewed My Account source, a keyboard user whose focused full-name Save reaches the existing unconfirmed state will receive that fixed alert as the one otherwise-lost focus destination before the existing Try profile again action.
Officer documentation: Update SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, SECURITY.md, and the existing My Account Mermaid/text alternative plus one no-terminal source-evidence procedure in docs/officers/EVENTS_SHOP_MEMBERS.md.
Deployment evidence: None at issue creation. Source/test review only. No website publication, Firebase deployment, provider configuration, account/sign-in action, production-data action, or live behavior is authorized or claimed.
Atomic outcome
A keyboard user who activates the exact current My Account full-name Save must not be left on body when the Save/editor disappears because the update rejects or the required authoritative reread is missing or rejected. Keep the existing fixed unconfirmed message and Try profile again action; move otherwise-lost focus once to that alert only when the admitted Save owned focus.
Current defect
On exact released main cfe03c66b8f443cb4e160a80d335d966ba268e27, handleSave captures #651's generation/attempt-only focus token while the connected Save owns focus. Its current catch then clears that token, clears profile/editor state, and renders the existing role=alert plus Try profile again. The removed focused Save commonly leaves focus on body; there is no failure-result handoff. Existing tests prove the truthful failure paths and call counts but do not assert recovery focus.
Invariants and acceptance criteria
- Arm only after validation and synchronous one-attempt admission, and only if the exact connected Save owns focus; retain only opaque
{generation, attemptId}. - On the exact current catch for update rejection, null confirmation reread, or rejected confirmation reread, transfer only the matching pending intent. Do not infer whether the write persisted.
- Keep the message byte-exact:
We could not confirm your profile change. Try the profile again before making another change.Never expose caught, member, or provider detail. - Reuse the existing alert and existing Try profile again control. Give the alert programmatic-focus, atomic assertive-alert, bounded/wrapping, and scoped visible-focus semantics. Focus the alert rather than the retry button so the uncertainty is announced before action; DOM order keeps the retry button as the next Tab stop.
- One layout effect consumes the intent before target checks. Require exact current generation/attempt, unavailable state, no profile/editor/confirmation, the exact unconfirmed result, and a connected alert.
- Leave an already-focused alert alone. Restore focus only from null,
body, document root, or a disconnected element. Preserve every other connected deliberate focus. - A valid unfocused/programmatic Save still shows the alert without moving focus, including after its outside origin disappears. Initial profile setup/read failure never moves focus.
- Validation failure, context/generation change, newer attempt, stale update/reread settlement, reload, unmount, and later same-context rerender cannot focus a stale result. Reload clears the intent before loading.
- The handoff adds no read, write, request, retry, provider call, log, or stored value; preserve exact update/reread counts and AUTH-006G — Announce a confirmed profile-name save and preserve focus #651 success behavior.
Required trustworthy tests
- RED on unchanged runtime: focused Save plus deferred rejected update plus modeled native focus eviction renders the exact alert/retry but does not focus the alert.
- Current update rejection: exact alert,
role=alert, atomic/assertive,tabIndex=-1, scoped class, connected and focused; caught canary absent; one update and no confirmation reread. - Current null and rejected confirmation rereads each focus the same alert; one update and one confirmation reread; no success result or private canary.
- Restore from body, null active element, document root, and disconnected active element.
- Preserve a connected deliberate outside target while update or reread is pending; leave an already-focused alert alone.
- Unfocused/programmatic Save shows the alert but does not move focus, including after its outside origin disappears; no delayed focus on rerender.
- Initial setup/read failure remains unfocused; validation failure remains local with Save focused and no write; clicking Try profile again clears the old save intent and cannot reuse it.
- UID-only, Firebase-app-only, Firestore-only, identity-service-only, unavailable-to-same-context generation, newer-attempt, stale-read, and unmount races are inert.
- CSS guard proves width/min/max containment,
overflow-wrap:anywhere, and a 3-pixel#005bd8focus outline/offset without broad selectors. - Existing AUTH-006G, AUTH-006F, and full Account suites remain green with exact service counts; then run the full frontend, repository Node, type-check, scoped lint, unchanged lint baseline, diagnostic build, workflow/security checks, and diff-check.
Exact ownership
src/pages/account/Account.tsxsrc/pages/account/Account.test.tsxsrc/pages/account/Account.cssSYSTEM_DESIGN.mdIMPLEMENTATION_PLAN.mdSECURITY.mddocs/officers/EVENTS_SHOP_MEMBERS.md
Update a separate AUTH-006H design/plan/security boundary, the existing My Account Mermaid failure branch and text alternative, and one no-terminal backup-officer source-review procedure. Keep #651 historical evidence intact while changing its open-outcome references to AUTH-006H where current truth requires it.
Explicit exclusions
- Focus settlement for the later Try profile again outcome; that needs its own load-intent/result destinations.
- Initial-load focus, validation association/
aria-invalid, Edit-to-input focus, Cancel-to-Edit focus, changed success truth, or changed AUTH-006G — Announce a confirmed profile-name save and preserve focus #651 semantics. - Profile payloads, validation, service contracts, reads/writes/call counts, Functions, Rules, schema, indexes, packages, workflows, directory runtime/availability/connection, Strava, provider configuration, Firebase deployment, accounts, sign-in, production data, publication, or live action.
- Membership, dues, role, payment, entitlement, roster, photo query, facial recognition, matching, embeddings, similarity, or biometrics.
- Active OAUTH-001A2L — Bound Strava activity/statistics JSON and cancel the unread statistics body #616 Strava files and its separate OAUTH-001A2L/RISK-024 hunk.
Migration and residual risk
No migration. The fixed alert still means only that the browser could not confirm the change; it does not prove rejection, persistence, provider acknowledgement, deployment, identity ownership beyond existing authentication, membership, directory eligibility, or live behavior. The later Try-profile-again settlement, validation association, Edit-to-input focus, and Cancel-to-Edit focus remain separate follow-ups.
Coordination and claim protocol
#651 is closed and released. #504 coordinates the optional directory; #507 retains every connection/release gate. #616 owns only both Strava Function files and its separate SECURITY hunk. Preclaim notices were posted to #531, #504, #507, and #616 from the exact base before issue creation; no STOP or exact collision was found.
Creation is not a claim. Before editing, create a unique branch/worktree from exact current main, assign this issue, post and reread a timestamped CLAIMED by /root at <UTC>; branch <branch>; base <SHA>; exact seven paths, and change status:ready to status:in-progress. The claim remains active through reviewed merge, exact-main/provider audit, closure, and explicit release.
Activity
daliu commentedon Aug 14, 2026
CLAIMED by /root at 2026-08-14T04:15:02Z; branch
codex/issue-653-profile-save-unconfirmed-focus; basecfe03c66b8f443cb4e160a80d335d966ba268e27; base treecd8c32d73021b026e145325d968f0a3cedf9bbff; exact paths:src/pages/account/Account.tsx,src/pages/account/Account.test.tsx,src/pages/account/Account.css,SYSTEM_DESIGN.md,IMPLEMENTATION_PLAN.md,SECURITY.md,docs/officers/EVENTS_SHOP_MEMBERS.md. No source edit preceded this marker. The claim remains active through reviewed merge, exact-main/provider audit, closure, and explicit release.daliu commentedon Aug 14, 2026
COMPLETED / RELEASED by /root at 2026-08-14T04:41:50Z. PR #654 merged as exact main
75a4f1ee3b20f61d375ed6d786e67e056a2206ef; tree6036ac48fd2c28f0cc0c05d5b1be09a7d812783eequals the reviewed candidate tree; parents are basecfe03c66b8f443cb4e160a80d335d966ba268e27and candidatebfd36ab08661d5ee67f59b2e2b78d13527a64b2e; base-to-main remains the exact seven paths with binary diff SHA-2565b691113b00f02571021be3395375e2188d41c021d811b7f33a7372c82276cf7.Exact-head CI run
31770307722passed 5/5, exact-main CI run31770479770passed 5/5, and Netlify preview6a7e9af0dd5db60008769decwas ready at the exact head, unpublished/noindex, with no Functions or edge Functions. The automatic main attempt6a7e9bb766c9050008e0253bended error withpublished_at:nulland did not move production. Published production remains inert #623 deploy6a7e072f8f346b0008510d29, control9d5cc8612b4321172370bd949d307e7e4ac0ec7d, and the public release marker remains issue 623/sourcec2d87d1f69f15e128a0bc9b1b9f915b7c8417aec/tree411aa6ec9a9459f5d923030533ffc7c007fe6908.Directory availability remains byte-for-byte false; active #616 Strava files and RISK-024 documentation remain unchanged. No Firebase deployment, provider configuration, account/sign-in action, production-data action, or connected-live behavior occurred. The AUTH-006H claim is now released and its seven paths are free, subject only to new coordination.