Skip to content

AUTH-PROFILE-001 — Restore safe profile setup and editing after the Firebase cutover #118

Closed

Description

@daliu

Officer impact: Members can save their own name and phone number after sign-in. Officers do not create member records by hand or grant membership to repair an account.

Officer documentation: Update docs/officers/EVENTS_SHOP_MEMBERS.md, docs/officers/EMERGENCY_AND_RECOVERY.md, and the account/profile path in docs/officers/SYSTEM_MAPS.md. Keep the repair path marked NOT AVAILABLE YET until both the website and Firebase backend are proven live.

Deployment evidence: None at issue creation. Closure requires exact source/test revisions, a protected staging Firebase deployment, synthetic account proof, website publication, Firebase Rules and Function deployment proof, rollback proof, and a final production state report that does not expose a real member record.

User-reported symptom

On 2026-07-12, a signed-in user could open the profile screen but saving profile information returned Missing or insufficient permissions.

Email verification is not required by the source rule for this edit. The Firebase email spam report is tracked separately and must not be treated as the cause of this permission error.

Read-only diagnosis

The current browser targets Firebase project mid-peninsula-running-club. The Firebase cutover changed the browser/project configuration, but repository deployment evidence does not prove that the matching profile-creation Function or Firestore Rules were deployed to that project.

The current account screen also hides profile-read failures and still shows the Edit action. Saving then performs an update-only write to members/{signed-in UID}. If the profile document is missing, the profile Function is absent, or deployed Rules differ from the tested source, the user sees the reported generic permission error.

Do not repair this by widening browser Rules, creating a production document by hand, changing a role, or deleting/recreating the account.

Atomic outcome

Make profile setup idempotent and make service failures clear:

  1. Add an authenticated server operation that ensures only the caller's minimal pending profile exists.
  2. Derive identity fields from verified Firebase Auth state on the server.
  3. Create a missing record with role: unverified; never infer membership, dues, discounts, or admin access.
  4. Never overwrite an existing profile or user-entered fields.
  5. Call the operation before the first profile read, then read the profile.
  6. Disable editing and show a plain recovery message when profile setup/read is unavailable.
  7. Keep profile edits restricted to the current small field allowlist.

Security and reliability invariants

  • Anonymous callers are rejected without account enumeration.
  • A caller cannot choose another UID, initial role, membership state, payment state, claims, timestamps, or extra fields.
  • Duplicate, concurrent, and retried calls return the same safe result and never overwrite an existing record.
  • Browser clients still cannot create arbitrary members documents directly.
  • Existing member/admin profiles and custom claims are not changed.
  • No name, email, phone, token, request body, or raw Firebase error is logged or returned.
  • App Check, authentication, input limits, and generic error handling follow the shared server boundary.
  • No production member data or production write is used for development or testing.

Acceptance criteria

  • A synthetic signed-in user with no profile receives one exact minimal pending profile through the server operation.
  • Repeating or racing the same operation leaves one unchanged profile.
  • An existing profile is returned/recognized without any field or role change.
  • Injected UID, email, role, membership, payment, or extra-field inputs are ignored or rejected.
  • Anonymous, wrong-project, App Check failure, backend unavailable, and Rules mismatch cases show a safe, understandable UI state and keep Edit disabled.
  • The current exact self-edit of name and phone succeeds against the staged Rules; cross-user and disallowed-field writes fail.
  • Name and phone limits are enforced consistently in the form and Rules.
  • A profile-read failure is no longer silently swallowed and raw Firebase wording is not shown to members.
  • Focused frontend/Function/Rules tests plus the relevant full suites pass without network or production access.
  • A staged synthetic account proves sign-up, idempotent profile setup, read, edit, sign-out, and retry.
  • Deployment evidence distinguishes source merged, tests passed, Rules deployed, Function deployed, website published, runmprc.com verified, and production behavior verified.

Dependencies and coordination

This issue may be implemented in source after its code-test dependencies are complete, but production deployment remains blocked until #100 and the applicable #105 deployment child are proven.

Explicitly out of scope

  • Email sender reputation or template delivery.
  • Google sign-in/account linking, membership approval, dues, role grants, roster import, or bulk migration.
  • Manual production Firestore edits, deleting/recreating accounts, or loosening the admin/member Rules boundary.

Claim protocol

Creation is not a claim. Before editing, confirm dependencies, assign the issue, post CLAIMED by <canonical agent> at <UTC>; branch <branch>, and re-read all comments. Split again if implementation cannot remain one reviewable outcome.

Activity

  1. added
    bugSomething isn't working
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    area:authAuthentication and authorization
    area:firebaseFirebase services and data
    area:webWeb application and hosting
    size:MMedium multi-file issue
    status:proposedDesigned but dependencies or decisions remain
    on Jul 13, 2026
  2. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    DEPENDENCY UPDATE at 2026-07-13T07:13:30Z (not a claim): #100 is source-complete and merged to main at a7fc301 with 295/295 Rules tests and two independent approvals.\n\nImportant live-state boundary: deploy run 29231224213 explicitly skipped Firebase because FIREBASE_SERVICE_ACCOUNT is absent. The reported profile-save failure is therefore not fixed or safely retested in production. This issue still waits for its remaining source dependencies and the protected staging/backend-first deployment path under #105. Do not create or modify a real member document as a workaround.

  3. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    Dependency update after #99 (2026-07-13): safe synthetic local Auth/Firestore/Functions development and fail-closed startup are now merged on final main f6e86be. This makes an isolated #118 implementation possible, but it does not repair or prove the live profile path. Firebase deployment still skipped for lack of FIREBASE_SERVICE_ACCOUNT, and no real member/profile action was tested. #118 remains a separate unclaimed outcome with its own profile bootstrap/recovery tests and deployment evidence.

  4. added
    status:in-progressClaimed and actively being implemented
    and removed
    status:proposedDesigned but dependencies or decisions remain
    on Jul 13, 2026
  5. self-assigned this
    on Jul 13, 2026
  6. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    CLAIMED by /root at 2026-07-13T08:10:06Z; branch codex/issue-118-profile-bootstrap. Source-only implementation and emulator verification begin from f6e86be. I will not use real member data or production writes. Firebase production deployment remains a separately proven #105 gate; I will split the source slice before editing if inspection shows this cannot remain one reviewable outcome.

  7. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    EXTRACTION FINISHED by /root at 2026-07-13T08:45:36Z on branch codex/issue-118-profile-bootstrap.

    Reviewable draft PR: #132

    • Exact base: e86a0f702cff6495f50630c5de3337290db8b8cb
    • Exact head: c982bcd752ed9b6eb1d443103d09996ac2541ea7
    • Scope: create-once signup/recovery Functions, fail-closed account UI, focused frontend/Function/emulator/Rules tests, and the required system/officer/security/runbook truth.
    • Node 20 local proof: frontend 62/62; Functions 36 pass + 1 emulator-only skip; Functions with demo-only Auth/Firestore emulators 37/37; Firestore Rules 298/298; SPA 10/10; lint and diagnostic production build pass.
    • Independent review: two read-only reviews approved authorization, claim preservation, concurrency/idempotency, redacted errors/logs, officer steps, and the exact release order.
    • Production data/providers: not accessed or changed. No real member record, secret, payment, email, Strava, or production write was used.

    Deployment is deliberately blocked, not complete. The current workflow publishes the website before Firebase and lacks FIREBASE_SERVICE_ACCOUNT. Merging this frontend-bearing branch now would call an absent Function and intentionally hide account features. #105 must first provide protected staging and target deployment of the exact #100 Rules plus both revised createMemberOnSignUp and ensureMemberProfile, with configured App Check proof and rehearsed rollback/safe roll-forward. The website may publish only after that exact backend is verified.

    Keep #118 open and claimed through PR review. Do not treat a preview or green workflow as Firebase/live proof, and do not manually repair a member profile or role.

  8. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    DEPLOYMENT DEPENDENCIES PUBLISHED at 2026-07-13T08:49:30Z (not claims):

    #105 now links the three atomic children. PR #132 remains draft and must not merge until that path is proven. No provider setting, Firebase resource, website, or production data changed while publishing these tickets.

  9. added and removed
    status:in-progressClaimed and actively being implemented
    on Jul 13, 2026
  10. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    COORDINATION at 2026-07-13T09:02:44Z: #135 temporarily owns only the release-status hunks in SECURITY.md and OPERATIONS_RUNBOOK.md, plus the repository/officer deployment truth listed in its scope amendment. PR #132 keeps all profile/App Check/runtime/Rules/test content. After #135 merges, #132 must refresh onto that exact main and preserve the protected-release/Netlify-containment wording; do not merge #132 before then. No #118 runtime file ownership changed.

  11. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    REFRESH STARTED by /root at 2026-07-13T09:57:23Z; branch codex/issue-118-profile-bootstrap.

    #135 is complete at main 9eafab1217aff7058c42240aaba72d7b93f8ed24, so the old frontend-first merge blocker is removed: a merge now runs CI only and publishes nothing. I am rebasing the already-reviewed #118 source onto that exact main, preserving every protected-release/Netlify-containment hunk, correcting the PR release sequence, and rerunning the full relevant suites.

    The #118 runtime/Rules/profile scope is unchanged. This is source merge preparation only. Firebase, Pages, Netlify production, providers, and real member records remain untouched; #133/#136 still own protected authority and the actual staged/live backend-first release.

  12. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    SOURCE MERGED / FILE CLAIM RELEASED at 2026-07-13T10:08Z

    • PR AUTH-PROFILE-001: recover missing member profiles safely #132 merged as 13ccc1b67dd57f69091e808b12e1287a1bc05b2f; exact reviewed source head was 6381907a6e243335094cb25122ef773943f7f19d.
    • Two independent exact-head reviews approved authorization, App Check/request ordering, create-once concurrency, claim preservation, Rules boundaries, UI failure/redaction, and officer procedures.
    • Local Node 20/Java 17 proof: frontend 62/62; Functions 36/36 unit plus 37/37 Auth/Firestore emulator; Rules 298/298; SPA 10/10; lint/build/diff checks passed.
    • Exact PR CI run 29241330054 and exact main-push CI run 29241524287 passed Frontend/build, Functions, and Rules.
    • The merge triggered CI only. No protected release workflow, GitHub deployment, or new Pages build ran. Latest Pages build remains the earlier commit 68b823a5f2a42e0490859dc74e5188d89fd5181c.
    • Firebase Rules and Functions were not deployed. The website and runmprc.com were not published or live-tested. No real member record, provider setting, secret, payment, email, or production write was used.

    The source-file claim, including SECURITY.md and OPERATIONS_RUNBOOK.md, is released after a controlled refresh to 13ccc1b67dd57f69091e808b12e1287a1bc05b2f. Preserve both #135 release-gate truth and #118 profile-recovery truth.

    #118 stays open with status:blocked-owner / needs-external-config. #113/#133, the protected WEB-001 child, and #136 still own isolated staging, protected OIDC/WIF authority, exact backend-first deployment/readback, website publication, synthetic proof, rollback, and live verification.

    Officer impact: source is ready, but automatic profile repair is still NOT AVAILABLE YET. Officers must use a new redacted incident and must not edit a member record, role, or account manually.

    Officer documentation: merged in the three #118 officer guides and system/security/runbook maps.

    Deployment evidence: source merge and tests only; no application/provider deployment claimed.

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

Metadata

Metadata

Assignees

Labels

area:authAuthentication and authorizationarea:firebaseFirebase services and dataarea:webWeb application and hostingbugSomething isn't workingneeds-external-configRequires provider console or external configurationpriority:P0Launch blocker or urgent security risksize:MMedium multi-file issuestatus:blocked-ownerRequires an owner or external decisiontype:reliabilityReliability and recoverytype:securitySecurity or privacy boundary

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions