Skip to content

BACKEND-001 — Audit the Firebase cutover and approve legacy data disposition #113

Open

Description

@daliu

Problem

Commit 1a160da repointed four configuration paths from the inaccessible Firebase project runmprc-97922 to the club-controlled mid-peninsula-running-club project. It did not export or import Firebase Auth users, Firestore documents, Storage objects, Functions state, provider configuration, or Google Forms/Sheets data.

The old Firebase project has existed in source since December 2023 and returned 403 PERMISSION_DENIED to the two accounts available during the June cutover. Its emptiness was inferred from the club's historical use of Google Forms/Sheets, not verified by an authorized inventory. The new project is active and has Firestore indexes, but current checks show no deployed Cloud Function endpoints; deployment evidence, recovery settings, and the disposition of legacy data remain incomplete.

daliu.github.io was only the Claude session's shell working directory. It is not a source database and is not being migrated into MPRC.

Architecture decision under review

Retain Firebase Auth + Cloud Firestore + Cloud Functions as MPRC's operational backend for accounts, membership authorization, private content, registrations, commerce state, provider links, and audited administration. This issue validates the estate cutover and data disposition; it does not select or build another database.

Atomic outcome

Authorized primary owner Dave Liu (backup appointment waived for backend work under #697) produces a private, read-only inventory of the legacy Firebase estate, the club-owned Firebase estate, and the active Google Forms/Sheets sources. Publish only redacted counts/configuration conclusions and an approved disposition matrix. Make no production changes.

For each system/data category, record:

  • verified owner, backup, access state, MFA/recovery state, environment, region, and intended authority;
  • redacted counts and schema/configuration variants, without record contents;
  • source date range and whether the source is active, archival, test-only, unknown, or inaccessible;
  • disposition: migrate, recreate, retire, reauthorize, bootstrap, or unknown/blocked;
  • collision/reconciliation rule, owner, dependency, rollback/stop condition, and approval date.

Required inventory

Firebase estates

  • Auth user counts by provider and verification state; custom-claim categories; duplicate/collision risk. Do not list emails or provider identifiers.
  • Firestore collection names, redacted document counts, schema variants, TTL state, and obvious orphan relationships. Do not export documents into the repository, an issue, AI context, or a local workspace.
  • Deployed Rules/index revision evidence; Function names, regions, and deployment revisions; extensions; Storage buckets; App Check; Secret Manager existence only; billing; IAM; delete protection; PITR/backups; and deployment authority.
  • Attempt recovery/read-only access to runmprc-97922 through authorized former maintainers/officers. If access cannot be recovered, record the uncertainty and preserve the project; do not call it empty or delete it.
  • Confirm the observed mid-peninsula-running-club baseline, including the absence/presence of live Functions and the exact source commit whose Rules/indexes are deployed.

Legacy operational sources

  • Privately inventory the active and historical Google Forms/Sheets used for membership, dues, event signup, waivers, volunteers, communications, and other club operations.
  • Record owner, purpose, date range, redacted row count, field/category list, consent/notice state, duplicate semantics, renewal/lapse meaning, and retention-decision status.
  • Identify any additional authoritative sources such as Stripe, Google Site/Groups, manual officer records, or provider dashboards without copying credentials, discount codes, invite links, payment data, or member records.

Authority/disposition map

Cover accounts/UIDs, membership/dues state, member-role claims, profiles, events/registrations, waivers, payments/refunds, merchandise, discounts, Google content access, Strava, WhatsApp, Instagram, mail, audit, and backups.

Acceptance criteria

  • The report distinguishes verified evidence, owner assertion, inference, and unknown/blocked state.
  • Both Firebase estates and every known Google Form/Sheet have an owner/access status and redacted category/count inventory or an explicit inaccessible result.
  • No Auth UID is recreated, provider identity linked, custom claim granted, or membership inferred merely by matching email.
  • Every category has one intended authority and a disposition; dual-write/dual-authority is either prohibited or time-bounded with a reconciliation owner.
  • The report explicitly records that the June change was a configuration cutover, not a completed data migration.
  • The new project's live state is truthful: deployed Functions, Rules/index revision, IAM/deploy authority, protection/recovery settings, and hosting consumer are evidenced rather than inferred from source.
  • An owner approves one of two outcomes:
  • The old project and legacy sources remain preserved until the disposition decision and required retention/hold review are complete.
  • Public GitHub evidence contains no real PII, secrets, tokens, private URLs, member rosters, Forms/Sheets locators, discounts, or payment records.

Dependencies and coordination

Current evidence to verify, not overclaim

  • mid-peninsula-running-club is an active Firebase project with one web app and a Firestore Native database in us-west2.
  • Four composite indexes and four registration field overrides are visible in the new project.
  • Known Cloud Function endpoints currently return 404, and the deployment workflow has skipped Firebase when backend credentials are absent.
  • Firestore currently reports delete protection and PITR disabled and no backup schedule; closure belongs to the resilience/owner program after retention decisions.
  • The legacy Apps Script is not a migration tool: it is hardcoded to an old Sheet tab, contains a placeholder key, uses a request contract that no longer matches the server, and only attempts role updates for existing Auth users.

Explicitly out of scope

  • Production writes, exports, imports, account creation/linking, role grants, provider-token copying, data deletion, DNS/hosting changes, IAM changes, deployments, billing changes, or recovery-setting changes.
  • Copying production Firebase/Sheets data into local emulators or test fixtures.
  • Choosing retention/legal/insurance/accounting policy or declaring inaccessible data empty.
  • Implementing BACKEND-002, AUTH-002, membership schemas, Rules, Functions, backup, or provider migrations.

Claim protocol

Creation is not a claim. Engineering coordination must be assigned and begin only after a timestamped CLAIMED by <canonical agent> at <UTC>; branch <branch> comment is posted and re-read. Earliest valid claim wins. All account access, former-maintainer outreach, console inspection, and private evidence handling require a named authorized owner even after an engineering claim.

Superseding backend ownership decision — October 11, 2026

Direct human owner instruction: continue without a backup owner. #697 records Dave Liu (daliu) as sole backend release/recovery owner. Backup-appointment/two-owner requirements in this ticket no longer gate backend setup; backup coverage remains absent. Existing staging read-only reviewers gain no broader authority. All other scope, data/policy, protected-release, least-privilege, staging, exact-source and rollback requirements remain unchanged. This amendment does not complete this issue or authorize a skipped/partial release.

Activity

  1. added
    priority:P0Launch blocker or urgent security risk
    area:membershipMembership lifecycle and reconciliation
    area:authAuthentication and authorization
    area:firebaseFirebase services and data
    size:SSmall focused issue
    needs-external-configRequires provider console or external configuration
    area:privacyPersonal data, consent, minimization, retention, and privacy operations
    on Jul 12, 2026
  2. daliu commented on Jul 12, 2026

    @daliu
    ContributorAuthor

    Dependency status update: #104 / PR #108 merged at 0e03ac145f410b210419efdc9026a52205e110f1 while this audit was underway. The architecture/playbook is now source-merged and deployed on the frontend host; Firebase deployment still skipped for missing backend authority. #113 remains owner-blocked and unclaimed, and it does not authorize edits or external inventory access without the claim plus named owners.

  3. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    OWNER DIRECTION (2026-07-12): Firebase/the website is the going-forward authoritative membership system. Historical membership import is intentionally deferred; initial activation will be one-at-a-time through #115 as people create accounts or an officer explicitly associates an existing verified account. Continue #113's read-only legacy inventory/disposition work, but do not create or execute BACKEND-002 now and do not delay the target #81/#114 contract merely to bulk-import historical rows.

  4. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    CUTOVER AUDIT ADDENDUM (2026-07-12; no production data inspected): a current signed-in user reports profile save permission-denied. Source shows profile creation normally comes from the Auth on-create Function, while the browser update is update-only and the UI hides initial profile-read failure. Repository deployment evidence does not prove that trigger or source Rules reached mid-peninsula-running-club; known Functions are 404.

    Please add private, read-only verification of: deployed profile trigger existence/revision, deployed Firestore Rules revision/time, Firestore App Check enforcement state, and aggregate existence/count/disposition of member-profile categories without reading or exporting member fields. Do not create Dave's record, alter a role, copy a document, or migrate/backfill here. #118 owns the future idempotent self-bootstrap/recovery behavior; #100/#105 own safe Rules/deployment.

    For events, the referenced Google Site is not a structured event feed. Its separate Forms/Sheets/Docs remain inventory sources here; do not open/copy them into a public issue or create EVENTS-001B until the owner approves one structured source and disposition. #121 defines the public event/source contract only.

  5. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    LEGACY SOURCE INVENTORY ADDENDUM (2026-07-13) — NOT CLAIMED; no response destination, submission, member data, or provider configuration was opened.

    The owner has now identified three current discount-related surfaces for the private inventory:

    • a public Google Form used to request race/product/service discounts;
    • the publicly readable legacy MPRC discount Site, which contains protected redemption material;
    • RaceGrader, a public third-party directory linked as a non-exclusive external resource.

    Record the exact Google locators only in approved private evidence. For the Form, verify owner/backup, linked response destination, access list, redacted count/date range, field categories, active/archival status, notice/consent state, and approved retain/migrate/retire/recreate disposition without reading or exporting response rows. Classify the Form as request intake, not membership evidence, an approved-offer authority, an event feed, or a migration tool.

    For the Site, #80 owns containment and exposed-offer response; #83 owns the eventual protected replacement. For RaceGrader, record only that it is an external public discovery resource unless an owner later approves a bounded link-out policy; do not scrape it or treat changing third-party deals as MPRC data. #110 retains all purpose/minimization/retention decisions for requester and contact data.

  6. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    Tracking correction: PR #694 used a negated closing-keyword sentence, which GitHub interpreted as a completion reference during merge. The audit was marked closed at the same merge timestamp without new audit evidence. That PR wording is corrected and this issue is restored to OPEN. COST-002 #693 is complete; estate/data disposition, owners, inventory and approval requirements in this audit are unchanged. No provider or member-data action occurred in this correction.

  7. reopened this on Oct 11, 2026
  8. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    CLAIMED by Codex at 2026-10-11T18:57:04.198Z; branch codex/113-estate-metadata

    Bounded work: configuration-only read-only Firebase estate metadata under Dave Liu's authorization for runmprc@gmail.com. No member records, exports, secrets, IAM/API/billing changes, deployments, or outreach. This is a partial inventory, not the primary/backup approval or disposition decision required to complete this issue. Backup release/recovery owner remains unconfirmed.

    Officer impact: identify remaining setup and recovery gaps without changing club operations.
    Officer documentation: current access-continuity guide remains unchanged; a dated private redacted handoff will record this audit.
    Deployment evidence: none; no website or Firebase deployment is part of this audit.

  9. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    Partial configuration-only estate readback — 2026-10-11 UTC

    Club account authorization: Dave Liu directed work under runmprc@gmail.com. Claimed/read back on branch codex/113-estate-metadata, based on main 81ea6d9. This is verified metadata, not a completed data inventory or approved disposition.

    • Legacy runmprc-97922: project identity read denied. Contents and ownership remain unknown; preserved, not declared empty.
    • Production: active; billing disabled/unlinked; Functions, Build, Artifact Registry, Secret Manager and App Check APIs disabled. Function inventory and App Check configuration reads return API-disabled; no endpoint-count or enforcement conclusion inferred.
    • Staging: active; billing linked/enabled; Functions, Build, Artifact Registry and Secret Manager APIs disabled. Auth and Firestore App Check enforcement remain ENFORCED. No Function revision can be verified through the disabled API.
    • Both databases: Native/Standard/us-west2, PITR disabled, zero backup schedules, four READY composite indexes matching current main definitions, no TTL configuration in listed field metadata. Production delete protection disabled; staging enabled.
    • Production deployed Rules differ from main: SHA-256 ecf30f940747dcc3c5ba4993093e9a11ac9fc5df7e14b2a1512d2446923d84eb; release updated June 13. Four explicit field-index entries, versus 28 source overrides. Staging Rules match main/historical CI-001D1 — Provision empty staging Firestore and deploy exact Rules/indexes #669 source: fe3f53302db76df5febf7e9d242d82a6b6bec0c0b574ecc8253f1034f1a77dba; release updated August 26. Staging has 28 explicit field-index entries. Default wildcard metadata excluded from these counts; count agreement alone is not field-definition proof.
    • Password-required email/password Auth and improved email privacy enabled in both; anonymous/phone disabled. Authorized domain counts: production 4, staging 2. Federated-provider inventory not performed.
    • Direct project IAM: club account Owner in both; no other individual user principal and no public principal in either policy. This is not inherited-access, MFA, recovery, or backup-approval proof. Production has one service account and staging two; all listed key inventories read successfully, zero user-managed keys. No identities/keys changed.

    Unknowns remain: Auth aggregates/claims, document/category inventory, Forms/Sheets, backup owner and sign-in drills, legacy access, storage/extensions/secret existence, intended authority/disposition and owner approval. Disabled Secret Manager API is not proof that secrets never existed. No member-record reads, exports, credentials, payment operations, API enablement, IAM/billing/protection changes or deployment occurred. All acceptance boxes remain unchanged.

    Officer impact: identifies current configuration and recovery gaps before membership/race launch; current operations unchanged.
    Officer documentation: ACCESS_CONTINUITY.md and LOW_COST_COMMUNITY.md remain current; dated redacted private Obsidian handoff records this partial audit, without private locators or records.
    Deployment evidence: website unchanged; no Firebase deployment; provider configuration metadata read only. #113, #133 and #136 remain open.

  10. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    Configuration inventory addendum — 2026-10-11 UTC

    Further read-only checks on current main 81ea6d9:

    • Storage bucket list returns zero buckets in both club production and staging. No objects or member records read.
    • Firebase Extensions API disabled in both: extension inventory remains unknown, not an asserted zero.
    • Compared actual explicit field-index definitions, not just counts: staging's 28 definitions exactly match normalized current source; production's four do not match the 28 source definitions. Default wildcard metadata excluded. Composite index definitions already matched in both.

    No API enablement, provider settings change, data operation, deployment or paid upgrade occurred. #113 remains a partial inventory: backup-owner approval, source/category aggregates and disposition are still missing. Disabled Secret Manager/Extensions/Functions APIs do not prove historical absence. Production differences require reviewed work after approvals, not a Console repair.

    Officer impact: adds exact staged index proof and identifies remaining production parity gaps without changing club operations.
    Officer documentation: dated private redacted backend-launch handoff; current operational guides unchanged because no workflow became available.
    Deployment evidence: configuration-only reads; no website or Firebase deployment, provider mutation, or production-behavior test.

  11. daliu commented on Oct 11, 2026

    @daliu
    ContributorAuthor

    October 11 count-only isolation checkpoint

    The official Auth query used returnUserInfo:false, so only recordsCount was requested. Production has 4 Auth accounts; engineering staging has 0. No account list, UID, email, claims, or user record was requested or returned. Staging Firestore root-collection metadata is empty; no document was read. The separate read-only service-account review found no first-generation default runtime identity in staging and no direct service-account Owner/Editor binding. Runtime identity must therefore be explicitly reviewed; do not fall back to a broad default.

    #697 / merged PR #698 remove only the backup-appointment gate. Dave remains the named sole backend release/recovery owner. This partial inventory does not complete #113 or authorize production account/data migration, role reassignment, import, deletion, or legacy-project disposition. Preserve the four production accounts and stable UIDs.

    Officer impact: No officer action or member-data handling is required for this read-only checkpoint.
    Officer documentation: ACCESS_CONTINUITY.md and PUBLISH_AND_CHECK.md explain the scoped owner exception; current member behavior is unchanged.
    Deployment evidence: Aggregate/metadata-only provider readback; no Firebase deployment, API/IAM/billing change, website publication or payment action.

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:authAuthentication and authorizationarea:firebaseFirebase services and dataarea:membershipMembership lifecycle and reconciliationarea:privacyPersonal data, consent, minimization, retention, and privacy operationsneeds-external-configRequires provider console or external configurationpriority:P0Launch blocker or urgent security risksize:SSmall focused issuestatus:blocked-ownerRequires an owner or external decisiontype:architectureArchitecture and contract designtype:operationsOperational setup or runbook

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions