Repository navigation
MEMBERS-DIRECTORY-001H — Preserve a reviewed replacement across saved-photo removal #633
Description
Parent: #504. Connected release remains owned by #507.
Officer impact: In the preserved future My Account interface, removing the current saved photo will no longer silently discard a replacement photo the person is still reviewing, and keyboard focus will move to the next relevant photo action. This connected interface source remains unavailable on production.
Officer documentation: Update SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, SECURITY.md, and the existing optional-directory diagram, one-sentence text alternative, and source-review procedure in docs/officers/EVENTS_SHOP_MEMBERS.md.
Deployment evidence: None at issue creation. This is source-only interface hardening. memberDirectoryAvailability.ts must remain byte-for-byte false; no Firebase, provider, account, production-data, sign-in, or live website action is authorized. Closure must distinguish source/test/merge evidence from the unchanged inert #623 production preview.
Atomic outcome
Preserve a local selected-photo review across a confirmed removal of the current saved photo, and restore keyboard focus to a useful persistent or next-step control.
Invariants and transitions
- Rename the destructive action to Remove current saved photo so it cannot be confused with the selected local replacement.
- Selecting/reading/reviewing a replacement remains local and creates no request ID or service call until explicit Save profile photo.
- A confirmed remove with authoritative readback preserves the current local reading or ready draft and its identity. It updates only the current saved-photo state and revision.
- A later explicit Save of the preserved ready draft creates one new request ID, sends the preserved bytes once, and uses the authoritative revision returned after removal.
- A confirmed remove does not change the officer-finder visibility setting.
- A definitive rejected remove with successful authoritative readback keeps the local draft available for review/retry and associates the fixed error with the remove control.
- An unknown remove outcome or any post-mutation authoritative readback failure clears the local draft/data URL, hides connected controls, and exposes the existing unknown/unavailable recovery state. It must not invite a duplicate mutation.
- After confirmed removal, focus moves to Save profile photo when the preserved draft is ready; otherwise it moves to the persistent Add/Replace file input. If authoritative readback says a current saved photo still exists, the visible remove action remains a valid focus target.
- App, UID, unmount, reselection, Cancel, FileReader, image-render, mutation, and readback generations remain fenced. A stale completion cannot restore bytes, focus, state, or a service call into another context.
- The source-controlled availability boundary stays
false. The default My Account branch remains an inert zero-context, zero-request-ID, zero-call preview. - Photo upload remains independent of visibility. Do not add photo-as-query, recognition, matching, embeddings, similarity, biometrics, roster authority, or membership proof.
Exact ownership
src/pages/account/MemberDirectoryProfile.tsx- preserve only the current local draft/read identity across a confirmed remove;
- rename the remove action and add bounded post-remove focus intent.
src/pages/account/MemberDirectoryProfile.test.tsx- one separately named MEMBERS-DIRECTORY-001H block and the minimum expectation updates for the renamed action.
SYSTEM_DESIGN.md- one separately named MEMBERS-DIRECTORY-001H source-only paragraph.
IMPLEMENTATION_PLAN.md- one separately named MEMBERS-DIRECTORY-001H current-source paragraph.
SECURITY.md- one separately named MEMBERS-DIRECTORY-001H/RISK-042 source-ledger row immediately after released 001G; preserve active OAUTH-001A2L — Bound Strava activity/statistics JSON and cancel the unread statistics body #616's OAUTH-001A2L/RISK-024 hunk byte-for-byte.
docs/officers/EVENTS_SHOP_MEMBERS.md- only the existing optional-directory Mermaid/one-sentence text alternative and one separately named source-review procedure for this change.
Required tests
- Capture trustworthy RED on the old runtime for draft loss and/or focus loss.
- A ready reviewed draft survives one successful remove; no upload happens before Save.
- The subsequent Save sends the exact preserved content once with the refetched revision.
- A FileReader completion that remains current across a confirmed remove can finish locally; stale/reselected/context completions remain inert.
- A definitive rejected remove with successful readback preserves the draft and fixed remove error.
- Unknown remove outcome and post-success readback failure discard the draft/data URL and expose no Save retry.
- Confirmed remove restores focus correctly with a ready draft, a reading/no-ready draft, no draft, and authoritative readback that still has a saved photo.
- Visibility and saved-thumbnail fallback behavior remain unchanged.
- The default unavailable branch still obtains no directory context and creates no request ID or service call.
- Existing profile races, upload review, accessibility, mobile, privacy, and error tests remain green.
Explicit exclusions
Account.tsx,Account.test.tsx, admin People finder, Account CSS, and all client service adapters.- The separate inbound WebP-magic contract hardening identified after MEMBERS-DIRECTORY-001G — Clear People-finder results and distinguish unavailable photos #631.
- Functions, Rules, indexes, schemas, repair/backfill, packages, workflows, or release controls.
- Privacy-notice approval, AUTH-003 capability design, role/MFA changes, or MEMBERS-DIRECTORY-001C — Release and verify the opt-in officer photo directory #507 activation work.
- Firebase/provider configuration, deployment, sign-in, accounts, production data, real names/photos, or live connected behavior.
- Both active OAUTH-001A2L — Bound Strava activity/statistics JSON and cancel the unread statistics body #616 Strava files and its separately named SECURITY OAUTH-001A2L/RISK-024 hunk.
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 audit, closure, and explicit release.
Activity
daliu commentedon Aug 13, 2026
CLAIMED by
/rootat 2026-08-13T21:33:15Z on branchcodex/issue-633-preserve-photo-draft, exact released based5a218a3ceebdfa758067ae7510803c75564c3c0.Exact ownership is limited to:
src/pages/account/MemberDirectoryProfile.tsx: reviewed/reviewing draft preservation across confirmed saved-photo removal, the exact remove label, and bounded post-remove focus intent only.src/pages/account/MemberDirectoryProfile.test.tsx: one separately named MEMBERS-DIRECTORY-001H block plus minimum exact-label expectation updates.SYSTEM_DESIGN.md,IMPLEMENTATION_PLAN.md, andSECURITY.md;docs/officers/EVENTS_SHOP_MEMBERS.md.Everything else is immutable: Account wiring/tests/CSS, admin finder, client services including the separate inbound-WebP finding, availability, Functions, Rules, indexes, packages, workflows, release controls, providers, data, sign-in, production/live behavior, #507 gates, and both #616 Strava files plus its OAUTH-001A2L/RISK-024 SECURITY hunk. No source edit preceded this marker. The claim remains active through reviewed merge, exact-main audit, closure, and explicit release.
daliu commentedon Aug 13, 2026
RED/GREEN implementation evidence on exact base
d5a218a3ceebdfa758067ae7510803c75564c3c0:Remove current saved photo; one-shot focus resolves to current Remove, current ready Save, or the persistent file input.--noEmit, scoped ESLint, lint baseline (120 files / 113 reviewed legacy errors / 6 warnings), diagnostic production build, diff-check, and repository workflow/security/SPA Node suites (105/105) passed.Availability remains byte-identical literal
false; production remains the inert #623 release. No Firebase, provider, account, sign-in, production-data, deployment, or live connected action occurred.daliu commentedon Aug 13, 2026
CANDIDATE / PR MARKER: PR #634 is open at exact three-review-approved head
38fb2b79665510317aa8ab889627f6b89ece7ea4, tree2cbc73167092d83a3d81155e9d3f520cc32b41e0, sole parent/based5a218a3ceebdfa758067ae7510803c75564c3c0.Exact six-path binary diff SHA-256:
e57f4962c73851f10f4a3e813e76fe6c8136e09fcfb958e0c15e055bfb7454e9.Local focused/full/type/lint/build/workflow gates are green. Independent security/privacy, frontend/accessibility, and backup-officer/operations reviews are GO with no findings. Hosted exact-head CI and preview checks are now pending.
Availability remains hard
false; live remains inert #623. No Firebase/provider/account/sign-in/data/deployment/connected action. #616 protected files/hunk are byte-identical. Claim remains active through exact-head CI, reviewed merge, exact-main/production-boundary audit, closure, and explicit release.PR: #634
Preserve reviewed photo after removal (#633) (#634)
daliu commentedon Aug 13, 2026
COMPLETE/CLOSED/CLAIM RELEASED.
PR #634 was admin squash-merged from exact reviewed head
38fb2b79665510317aa8ab889627f6b89ece7ea4as exact mainfd0988afc8f55869db3bd8e5f0a391de83b8c816. The reviewed and merged trees are identical at2cbc73167092d83a3d81155e9d3f520cc32b41e0; the exact six-path binary diff SHA-256 remainse57f4962c73851f10f4a3e813e76fe6c8136e09fcfb958e0c15e055bfb7454e9.PR CI
31748099236and exact-main CI31748394119passed all five required jobs. Netlify preview6a7e3e66f69c0b00083c3301is ready and unpublished; the exact-main production attempt6a7e3f53a5cd00000855ffc6errored unpublished. Netlify site readback still reports both deploy pointers at inert #623 deploy6a7e072f8f346b0008510d29/ control9d5cc8612b4321172370bd949d307e7e4ac0ec7d. The public #623 marker remains valid JSON with no-store/nosniff/HSTS and byte SHA-256b74498854585346aa66c0341e29c829245445ce986806c3864cad526b267876f. GitHub deployment records contain no #633 deployment.The source-controlled availability boundary remains byte-identical and literal
false. No Firebase, Functions, Rules, indexes, provider, account, sign-in, production-data, website publication, or connected/live member-directory action occurred. #507 retains every connection/release gate. Active #616 Strava blobs and its separate SECURITY OAUTH-001A2L/RISK-024 hunk remain byte-identical.All six #633 claims are released. The remote feature branch is absent.