Skip to content

AUTH-006H — Restore focus to an unconfirmed profile-name Save result #653

Description

@daliu

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

  1. 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.
  2. 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.
  3. Current null and rejected confirmation rereads each focus the same alert; one update and one confirmation reread; no success result or private canary.
  4. Restore from body, null active element, document root, and disconnected active element.
  5. Preserve a connected deliberate outside target while update or reread is pending; leave an already-focused alert alone.
  6. Unfocused/programmatic Save shows the alert but does not move focus, including after its outside origin disappears; no delayed focus on rerender.
  7. 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.
  8. UID-only, Firebase-app-only, Firestore-only, identity-service-only, unavailable-to-same-context generation, newer-attempt, stale-read, and unmount races are inert.
  9. CSS guard proves width/min/max containment, overflow-wrap:anywhere, and a 3-pixel #005bd8 focus outline/offset without broad selectors.
  10. 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.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

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:authAuthentication and authorizationarea:membershipMembership lifecycle and reconciliationarea:webWeb application and hostingpriority: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