Skip to content

MEMBERS-DIRECTORY-001F — Review and confirm a profile photo before upload #629

Closed

Description

@daliu

Parent: #504. Follows released frontend-hardening child #627. This is a source-only interface child; #507 retains backend connection and release.

Officer impact: No live officer duty changes. In the preserved future My Account flow, a person will review a locally held centered-square photo preview and explicitly choose Save or Cancel before any photo bytes are sent. The officer People finder behavior does not change.

Officer documentation: Update docs/officers/EVENTS_SHOP_MEMBERS.md with source-only review steps plus the matching Mermaid diagram/text alternative. Update the separately named current-source boundaries in SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, and SECURITY.md.

Deployment evidence: None at issue creation. The source-controlled availability value remains false; production remains the inert #623 deploy. This issue authorizes no website publication, Firebase/Rules/index/Function deployment, provider configuration, account/sign-in action, or production-data action.

Atomic outcome

Replace the preserved connected Account branch's immediate-on-selection photo upload with an explicit local review step:

  1. Validate and read a selected JPG, PNG, or WebP locally.
  2. Show a centered-square draft preview labeled not uploaded yet.
  3. Create a request ID and call the existing upload service only after Save profile photo.
  4. Let Cancel selected photo discard the local draft and send nothing.
  5. Refetch and display only the authoritative processed thumbnail after confirmed Save.

The default unavailable branch stays inert and makes zero directory calls. This issue changes no server contract and does not connect the backend.

Invariants

  • Selecting or previewing a file sends nothing and creates no request ID.
  • The local filename is not copied into React state, logs, analytics, errors, documentation evidence, or tests.
  • The draft bytes remain component-memory only and are discarded on Cancel, successful confirmation, unmount, app/account change, or unknown outcome.
  • A stale FileReader completion after reselection, Cancel, unmount, app change, or account change cannot render or upload.
  • Unsupported, empty, oversized, unreadable, or browser-unrenderable selections get fixed control-associated errors and cannot be saved.
  • The current processed thumbnail/no-photo state remains visibly distinct and authoritative until Save succeeds and the profile is refetched.
  • Uploading/replacing never changes finder visibility. The independent default-off finder choice and officer name search are unchanged.
  • Save and Cancel are keyboard-operable, screen-reader-described, at least 44 pixels high, and contained at 320 pixels.
  • No photo-as-query, face recognition, embedding, similarity, biometric processing, result-count, membership, or authorization behavior is added.
  • memberDirectoryAvailability.ts remains byte-for-byte false.

Exact ownership

  • src/pages/account/MemberDirectoryProfile.tsx: connected-branch local draft/read/render/Save/Cancel/fencing only; truthful unavailable-preview copy only if needed.
  • src/pages/account/MemberDirectoryProfile.test.tsx: separately named 001F local review, explicit Save, Cancel, invalid/unrenderable, stale-read, accessibility, and narrow-layout coverage.
  • src/pages/account/Account.css: only scoped draft-preview/action/320px styles.
  • SYSTEM_DESIGN.md: one separately named MEMBERS-DIRECTORY-001F source-only boundary.
  • IMPLEMENTATION_PLAN.md: one separately named MEMBERS-DIRECTORY-001F current-source boundary.
  • SECURITY.md: one separately named MEMBERS-DIRECTORY-001F/RISK-042 source ledger row.
  • docs/officers/EVENTS_SHOP_MEMBERS.md: one separately named 001F source-review procedure and the existing optional-directory diagram/text-alternative hunk.

Acceptance criteria

  • A valid generated synthetic file produces a local unsaved preview and no request-ID/service call.
  • Save sends the exact selected content type/bytes once with the current revision, refetches authoritative state, and leaves visibility unchanged.
  • Cancel discards the draft, sends nothing, and leaves the saved thumbnail/no-photo state unchanged.
  • Selecting a replacement leaves the current saved thumbnail authoritative until Save.
  • Unsupported, empty, oversized, unreadable, and unrenderable selections expose fixed associated errors and cannot be saved.
  • Older reads after reselection, Cancel, unmount, app change, or UID change are inert.
  • Definitive rejection refetches current state without losing a retryable local draft; unknown outcome hides controls and discards the draft.
  • Default unavailable rendering remains disabled and zero-read/zero-upload/zero-request-ID.
  • Keyboard, semantic status/error, 44px interaction, explicit contrast, and actual/synthetic 320px containment evidence pass.
  • Focused and full frontend tests, TypeScript, diagnostic build, lint baseline, workflow checks, diff-check, and independent security/frontend/backup-officer reviews pass.

Explicit exclusions

Claim protocol

Assign and post a UTC timestamped CLAIMED marker naming the branch and exact base before any edit. The claim remains active through reviewed merge, exact-main CI/deployment audit, closure, and explicit release.

Activity

  1. added
    priority:P1High-priority follow-up
    type:securitySecurity or privacy boundary
    area:membershipMembership lifecycle and reconciliation
    area:webWeb application and hosting
    size:MMedium multi-file issue
    status:readyDependencies complete and ready to claim
    type:testingTest infrastructure and quality gates
    area:privacyPersonal data, consent, minimization, retention, and privacy operations
    status:in-progressClaimed and actively being implemented
    and removed
    status:readyDependencies complete and ready to claim
    on Aug 13, 2026
  2. self-assigned this
    on Aug 13, 2026
  3. daliu commented on Aug 13, 2026

    @daliu
    ContributorAuthor

    CLAIMED by /root at 2026-08-13T19:46:14Z on branch codex/issue-629-photo-review, exact released base 1e8fa00987dd8b7113362135513eb7f20834c080.

    Exact ownership is the seven paths/hunks listed in the issue body:

    • connected-branch local selection/read/centered draft-preview/explicit Save/Cancel/fencing and saved-thumbnail fallback in MemberDirectoryProfile.tsx
    • separately named 001F tests in MemberDirectoryProfile.test.tsx
    • scoped draft styles in Account.css
    • one separately named 001F source-only hunk each in SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, SECURITY.md, and the existing optional-directory diagram/text/procedure section in docs/officers/EVENTS_SHOP_MEMBERS.md

    No edit preceded this marker. memberDirectoryAvailability.ts remains byte-for-byte false. Account parent wiring, admin finder, client services, Functions, Rules, indexes, packages, workflows, release controls, Privacy policy, provider/deployment/data/live work, #507 gates, active #616 Strava files, and its separately named SECURITY OAUTH/RISK-024 hunk are immutable.

    Claim remains active through reviewed merge, exact-main CI/deployment audit, closure, and explicit release.

  4. daliu commented on Aug 13, 2026

    @daliu
    ContributorAuthor

    Invariant clarification at 2026-08-13T20:07:00Z, before final test implementation/review: the browser File API requires every synthetic File fixture to receive an opaque generated filename. The no-filename invariant means production code must never read file.name, copy it into React state, render it, log it, send it, or include a user-derived filename in evidence. Tests may construct only generated non-face fixtures with opaque synthetic names and must prove the application never accesses or exposes that property. Exact seven-path ownership and every deployment/backend exclusion remain unchanged.

  5. daliu commented on Aug 13, 2026

    @daliu
    ContributorAuthor

    CANDIDATE READY — exact source-only head 916cae5, tree fa646f3772ddd462c730ea3c01f88d7327c0103f, sole parent/released main 1e8fa00. Exact seven-path binary diff SHA-256: 4c57a9d7fa5266dbdbb8675a95736aa603a368f5da042cf2154cf597f1a913d5.

    RED on the old runtime proved selection immediately uploaded and exposed no local review/Save/Cancel. GREEN on the exact candidate: full frontend 18 suites / 1,109 tests; focused photo suite 71/71; TypeScript; targeted ESLint; frontend lint baseline 120 files / 113 reviewed legacy errors / 6 reviewed warnings; production build; 35 workflow/release checks; and diff-check all pass under Node 20. Independent security/privacy, code-quality, frontend/accessibility/mobile, and backup-officer reviews are GO.

    The source-controlled availability value remains byte-identical false. Active #616 Strava files and its SECURITY OAUTH/RISK-024 hunk are preserved. No website publication, Firebase/Rules/index/Function, provider, account/sign-in, production-data, or connected-behavior action occurred. Production remains inert #623 deploy 6a7e072f8f346b0008510d29. Claim stays active through PR CI, merge, exact-main/deployment audit, closure, and explicit release.

  6. removed their assignment
    on Aug 13, 2026
  7. daliu commented on Aug 13, 2026

    @daliu
    ContributorAuthor

    FINAL RELEASE — COMPLETE/CLOSED/CLAIM RELEASED.

    PR #630 squash-merged exact reviewed head 916cae5 as exact main 03d197a. Reviewed and merged trees are identical: fa646f3772ddd462c730ea3c01f88d7327c0103f. Exact seven-path binary diff SHA-256: 4c57a9d7fa5266dbdbb8675a95736aa603a368f5da042cf2154cf597f1a913d5.

    PR CI 31741032670 and exact-main CI 31741319462 each passed all five required jobs. Three independent exact-head reviews returned GO. Netlify deploy preview 6a7e28e931e2b50008c622d1 passed. The exact-main production attempt 6a7e29b9b00a4600094d92fa is state=error, published_at=null, with no Netlify Functions or Edge Functions; it did not publish.

    Netlify still reports both production deploy pointers at inert #623 deploy 6a7e072f8f346b0008510d29 / control 9d5cc86. The public marker is unchanged and valid, SHA-256 b74498854585346aa66c0341e29c829245445ce986806c3864cad526b267876f, source c2d87d1, tree 411aa6ec9a9459f5d923030533ffc7c007fe6908, 62 files, digest d837272a1e5efc1575809e87f532276b38d1a63f1dd79ec1aef0533f6da8afb1.

    Availability remains false. No Firebase, Rules, index, Function, provider, account/sign-in, production-data, or connected-live action occurred. #507 retains every connection/release gate. The status/assignee are cleared and the remote branch is absent. All seven #629 claims are released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:membershipMembership lifecycle and reconciliationarea:privacyPersonal data, consent, minimization, retention, and privacy operationsarea:webWeb application and hostingpriority:P1High-priority follow-upsize:MMedium multi-file issuetype:featureProduct capabilitytype:securitySecurity or privacy boundarytype: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