You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent: #504. Connected release remains owned by #507.
Officer impact: In the preserved future My Account interface, a keyboard or screen-reader user whose focused Remove action disappears after a rejected removal and authoritative profile refresh will be returned to the closest surviving photo action. The connected interface remains unavailable on production.
Officer documentation: Update SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, SECURITY.md, and only the optional-directory one-sentence text alternative plus one no-terminal source-evidence procedure in docs/officers/EVENTS_SHOP_MEMBERS.md. No Mermaid change is needed because page topology, permissions, and data movement do not change.
Deployment evidence: None at issue creation. This is source-only accessibility hardening. memberDirectoryAvailability.ts must remain byte-for-byte false; no website, Firebase, provider, account, sign-in, production-data, deployment, or connected-live action is authorized.
Atomic outcome
Restore keyboard focus to the correct surviving photo control after a focused Remove current saved photo receives a definitive rejection and a successful authoritative profile readback.
Defect
On exact released main f3da2f3, a Remove mutation disables the focused Remove action while pending. A definitive rejection then performs an authoritative profile read. If that current read says hasPhoto:false, Remove disappears. Unlike confirmed removal, the definitive-rejection path records no ready-state focus handoff. Browser-disabled or removed-control focus can therefore remain on the document body.
The existing rejection test returns a profile that still has a saved photo and does not assert focus, so it does not exercise the missing-control branch.
Invariants and transitions
Create a rejection-focus intent only after request-ID creation and startMutation('remove') admit the exact current operation into pending.
Create it only when Remove current saved photo owns focus at that point.
Store only the current mounted application/account lifetime and exact mutation-operation identity. Store no photo bytes, profile value, request ID, revision, provider value, or error.
Programmatic or outside-focused Remove invocation, request-ID failure, and rejected mutation start create no intent.
After definitive Remove rejection and successful current authoritative readback, consume the matching intent after ready controls render.
Choose the current rendered destination: surviving Remove; otherwise current enabled Save profile photo when the exact local draft is ready; otherwise the persistent Add/Replace file input, including no draft, reading, or not-yet-ready draft.
If the target already owns focus, leave it alone. Restore only from body, the document root element, absent, or disconnected focus. Preserve any other connected focus deliberately selected during pending.
Keep the fixed rejection role=alert. If Remove survives, retain its error description. If Remove disappears, leave the alert standalone; do not associate it with Save or the file input.
Clear/fence the intent on confirmed success, unknown outcome, failed confirming read, application change, UID change, unmount, or obsolete operation.
Focus creates no request ID, callable, retry, automatic mutation, draft, data URL, confirmation, audit, or provider/data action.
Availability stays false; the default branch remains inert and zero-context/zero-ID/zero-call.
No photo query, facial recognition, matching, embedding, similarity, biometric processing, roster authority, or membership proof is added.
Exact ownership
src/pages/account/MemberDirectoryProfile.tsx: only the exact-operation focused-Remove rejection intent, cleanup guards, and guarded current-state focus handoff.
src/pages/account/MemberDirectoryProfile.test.tsx: one separately named MEMBERS-DIRECTORY-001M block plus minimum directly affected helpers/assertions.
SYSTEM_DESIGN.md: one separately named 001M source-only paragraph.
IMPLEMENTATION_PLAN.md: one separately named 001M current-source paragraph.
docs/officers/EVENTS_SHOP_MEMBERS.md: only the optional-directory one-sentence text alternative and one no-terminal 001M source-evidence procedure; no Mermaid or unrelated procedure change.
No CSS change: the same native controls and existing focus styles are used.
Trustworthy RED and required tests
On unchanged runtime, focus Remove, begin a deferred valid removal, assert disabled, explicitly blur to model native focus eviction, reject definitively, resolve confirming read with hasPhoto:false, and prove focus remains off the surviving file input.
Repeat with a current ready replacement and prove old source does not focus Save profile photo.
Corrected behavior restores surviving Remove, ready Save, or file input for no/reading/not-ready draft.
Surviving Remove retains aria-describedby to the fixed error; vanished Remove leaves a standalone alert and does not attach it to Save/input.
Programmatic/outside-focused invocation creates no intent; deliberate outside focus during pending is preserved; already-retained Remove is not redundantly focused.
Request-ID failure remains enabled/focused with zero removal call.
Existing profile, draft, rejection, uncertainty, recovery-focus, response-boundary, accessibility, privacy, race, and mobile suites remain green.
Explicit exclusions
No Account.tsx/test, CSS, service adapter, availability, inbound WebP validation, admin finder, AdminGuard, routes, backend Function/Rule/index/schema/repair/package/lock/workflow/release control, privacy/capability policy, Firebase/provider configuration, deployment, account/sign-in, production data, real name/photo, connected/live action, or #616 path/hunk.
Migration and residual risk
No migration. This focus handoff is accessibility state, not server acknowledgement, deletion proof, reconciliation, authorization, provider evidence, or proof that removal succeeded. A definitive rejection and a concurrent authoritative state with no photo may both be true; the rejection alert therefore remains separate from the current surviving action.
Availability stays false and live #623 remains inert. #507 retains every connection and release gate.
Claim protocol
Assign the issue and post a timestamped CLAIMED marker naming the exact branch and released base before any edit. The claim remains active through reviewed merge, exact-main/deployment audit, closure, and explicit release.
Parent: #504. Connected release remains owned by #507.
Officer impact: In the preserved future My Account interface, a keyboard or screen-reader user whose focused Remove action disappears after a rejected removal and authoritative profile refresh will be returned to the closest surviving photo action. The connected interface remains unavailable on production.
Officer documentation: Update SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, SECURITY.md, and only the optional-directory one-sentence text alternative plus one no-terminal source-evidence procedure in docs/officers/EVENTS_SHOP_MEMBERS.md. No Mermaid change is needed because page topology, permissions, and data movement do not change.
Deployment evidence: None at issue creation. This is source-only accessibility hardening. memberDirectoryAvailability.ts must remain byte-for-byte false; no website, Firebase, provider, account, sign-in, production-data, deployment, or connected-live action is authorized.
Atomic outcome
Restore keyboard focus to the correct surviving photo control after a focused Remove current saved photo receives a definitive rejection and a successful authoritative profile readback.
Defect
On exact released main f3da2f3, a Remove mutation disables the focused Remove action while pending. A definitive rejection then performs an authoritative profile read. If that current read says hasPhoto:false, Remove disappears. Unlike confirmed removal, the definitive-rejection path records no ready-state focus handoff. Browser-disabled or removed-control focus can therefore remain on the document body.
The existing rejection test returns a profile that still has a saved photo and does not assert focus, so it does not exercise the missing-control branch.
Invariants and transitions
Exact ownership
No CSS change: the same native controls and existing focus styles are used.
Trustworthy RED and required tests
Explicit exclusions
No Account.tsx/test, CSS, service adapter, availability, inbound WebP validation, admin finder, AdminGuard, routes, backend Function/Rule/index/schema/repair/package/lock/workflow/release control, privacy/capability policy, Firebase/provider configuration, deployment, account/sign-in, production data, real name/photo, connected/live action, or #616 path/hunk.
Migration and residual risk
No migration. This focus handoff is accessibility state, not server acknowledgement, deletion proof, reconciliation, authorization, provider evidence, or proof that removal succeeded. A definitive rejection and a concurrent authoritative state with no photo may both be true; the rejection alert therefore remains separate from the current surviving action.
Availability stays false and live #623 remains inert. #507 retains every connection and release gate.
Claim protocol
Assign the issue and post a timestamped CLAIMED marker naming the exact branch and released base before any edit. The claim remains active through reviewed merge, exact-main/deployment audit, closure, and explicit release.