Skip to content

CI-001D4 — Configure and verify no-billing staging App Check #676

Closed

Description

@daliu

Officer impact: Officers get a staging site whose Firebase Authentication and Firestore traffic is protected by App Check. The public site and production Firebase project do not change.

Officer documentation: Update OFFICER_START_HERE.md, docs/officers/README.md, docs/officers/PUBLISH_AND_CHECK.md, and docs/officers/SYSTEM_MAPS.md with the current verified staging state, purpose, success proof, stop conditions, rollback, and escalation role.

Deployment evidence: Closure must separately record exact source and CI, provider API/key/app registration, exact Hosting revision, browser token behavior, Authentication and Firestore enforcement/readback, synthetic missing-token denial, cleanup, billing state, Functions state, production website, and production Firebase state. Public evidence must contain no token, credential, key locator, provider response body, user identifier, or production data.

Parent: #136. Security program: ABUSE-001A. Dependencies: #159, #443, #665, #667, #669, #671, and #674 are complete.

Problem

Staging Hosting, Firestore, and email/password Authentication are available, but staging has no App Check provider. The existing browser source initializes reCAPTCHA Enterprise only when a site key is supplied, while the Hosting deploy contract does not require that key or prove that the built artifact contains it. Authentication and Firestore therefore accept traffic without App Check. No Functions are deployed because billing is not authorized.

Atomic outcome

Protect only the empty synthetic run-mprc-staging web path without billing:

  • Add a staging-deploy source contract that requires one bounded, non-placeholder public reCAPTCHA Enterprise site key and proves it is present in the executable Hosting artifact. Ordinary local/test builds and credential-free preview builds remain unchanged.
  • Merge and verify that source before provider mutation.
  • Reconfirm the exact club account, project, one staging web app, two approved staging domains, zero users/root documents, billing disabled, no visible billing account, and no Functions/APIs/deployments.
  • Enable only the Firebase App Check and reCAPTCHA Enterprise APIs needed for this staging outcome.
  • Create one score-based reCAPTCHA Essentials key restricted exactly to run-mprc-staging.web.app and run-mprc-staging.firebaseapp.com. Do not allow all domains, localhost, AMP, WAF, a testing score, or mobile settings.
  • Register that key only to the existing staging Firebase web app with a one-hour token TTL.
  • Set Authentication and Firestore to monitoring-only, publish exact merged main to staging Hosting with the public key, and prove a real browser obtains App Check-backed service behavior.
  • Because staging is empty and has no old clients, atomically move only Authentication and Firestore to enforced after the positive proof; wait for propagation and prove missing-token requests are rejected while the browser path still works.
  • Remove every disposable Auth identity and Firestore record, then prove final counts are zero.

Safety invariants

  • Use only runmprc@gmail.com and name run-mprc-staging explicitly for every provider command.
  • Mint any access token only inside a child process, never print/store/journal it, and remove it from the child environment after use.
  • Do not link or create billing, enable a Functions API, deploy a Function, modify IAM, use ADC, create a debug token, or contact an outside business provider.
  • Do not change production Firebase, runmprc.com, Netlify, DNS, GitHub Pages, or production data.
  • App Check complements Auth and Rules; it grants no membership, role, payment, or administrative authority.
  • Missing/invalid App Check denial must be tested only with made-up data in staging. Never test production denial or a real account.
  • Stop and roll service enforcement back to monitoring-only if the staged browser cannot obtain a valid token or a required service fails.

Acceptance criteria

  • Exact source guard rejects missing, empty, whitespace, overlong, placeholder, malformed, production-equal, or artifact-absent staging site keys and accepts a synthetic valid shape.
  • Node 20 focused tests, release/source suites, frontend Jest, SPA tests, Functions lint/Jest, Rules tests, diagnostic build, artifact verification, audits, sensitive-pattern review, hosted CI, and independent review pass.
  • Exact source commit is merged before provider work and exact post-merge CI is green.
  • Staging has one restricted score-based key and one matching web-app Enterprise config with one-hour TTL; readback is verified without exposing locators.
  • Exact merged main is published to staging Hosting and its version/source relation is recorded.
  • Browser proof succeeds for App Check initialization, a Firestore read, disposable email/password sign-up/sign-in/sign-out, and cleanup.
  • Authentication and Firestore read back ENFORCED after propagation; missing-token synthetic requests fail and the token-bearing browser path still succeeds.
  • Final staging users and root collections are zero; billing remains disabled; Functions-related APIs and deployed Functions remain absent.
  • Production hosting and Firebase surfaces are unchanged and truthfully recorded.
  • Root and officer documentation distinguishes source changed, tests passed, merged, website published, provider configured, enforcement enabled, production unchanged, and live Functions unavailable.

Rollback

If browser verification fails after enforcement, atomically return Authentication and Firestore to UNENFORCED, read both settings back, preserve the restricted provider configuration for diagnosis, and redeploy the last verified staging Hosting version if needed. Do not weaken domains, use a debug token, or enable billing as a workaround.

Excluded

Native callable enforcement and any Function deployment remain the billing-gated ABUSE-001A2/#136 follow-up. Production App Check, provider callbacks, Stripe/Strava/email, member/admin flows, Storage, production publication, DNS, billing, IAM, legal/retention decisions, and real data are excluded.

Activity

  1. self-assigned this
    on Aug 26, 2026
  2. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    CLAIMED by daliu at 2026-08-26T21:46:49Z; branch codex/issue-676-staging-app-check; exact base 4b8ed83. The user authorized provider work with runmprc@gmail.com; this claim excludes billing, Functions, IAM, production, and real data.

  3. added
    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
    needs-external-configRequires provider console or external configuration
    status:in-progressClaimed and actively being implemented
    on Aug 26, 2026
  4. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    Source PR opened: #677 at exact commit 6393e95. Local Node 20/Java 21 verification is green; this PR performs no provider, deployment, billing, IAM, user, record, or production mutation. Provider work remains stopped until the exact source is merged and exact-main CI passes.

  5. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    Monitoring checkpoint merged and reverified — issue remains open

    PR #678 merged exact reviewed head 654b36ab24f4bcb243c92656e0ed75047a0ac315 to main as merge 14286c9c6e8c65ed39343ad2c1e6ee93e6af296d. All five jobs passed in exact-main CI run https://github.com/Run-MPRC/Run-MPRC.github.io/actions/runs/33020694806. Both exact-head PR CI runs also passed all five jobs, and the Netlify preview/header/redirect checks were green.

    Fresh redacted readback using only runmprc@gmail.com and exact project run-mprc-staging matched the merged record: one web app; one restricted score-based key; exactly run-mprc-staging.firebaseapp.com and run-mprc-staging.web.app; one-hour token TTL; Authentication and Firestore both UNENFORCED with replay protection off; Hosting version 8556fc51210bdc66; zero Auth users; zero Firestore root collections; billing disabled; and no enabled Functions-related API. No key, provider locator, token, user identifier, or provider response body is included.

    Officer impact: Backup officers now have a merged no-terminal procedure for distinguishing configured monitoring from enforcement. They must not sign in, enter information, run commands, configure providers, attach billing, or call this a usable member backend.

    Officer documentation: OFFICER_START_HERE.md, docs/officers/README.md, docs/officers/PUBLISH_AND_CHECK.md, and docs/officers/SYSTEM_MAPS.md, merged in PR #678.

    Deployment evidence: Website — exact source bce911a7083201cfe2141edaa9660f210287bf57 remains Hosting version 8556fc51210bdc66; the previously recorded public root/direct Events/UI/browser checks passed. Firebase — the restricted registration, monitoring settings, zero counts, billing state, and absent Functions-related APIs were freshly re-read after the evidence merge. Provider/production — no provider mutation occurred during this recheck, and production remains unchanged.

    Still pending before #676 may close: explicit approval for submitting one made-up disposable email/password in the staging browser; new sign-up/sign-in/sign-out and empty-Firestore proof; atomic Auth/Firestore ENFORCED readback; missing-token denial; token-bearing browser replay; cleanup; and final zero-count/provider/production evidence. Functions remain separately billing-gated and were not enabled or deployed.

  6. daliu commented on Aug 27, 2026

    @daliu
    ContributorAuthor

    Final enforcement evidence

    Completion PR #679 merged exact reviewed head 98a980d1d75c701abb63e947c9032cabb2910244 as merge 667a4dc7bb4672bf63165f67ab0149e18692da5f; #676 closed automatically. A post-merge consistency audit found four pre-#676 current-state sentences, corrected them in independently reviewed PR #680, and merged exact head 39d017249143784af53da22259fe832c715c59c2 as final-main merge 1f27b0619c494cd3fc5e4c75dff521cffc584aae.

    All five jobs passed for that exact final main in CI run https://github.com/Run-MPRC/Run-MPRC.github.io/actions/runs/33037066118. Both PR heads also passed all five hosted jobs; Netlify preview, header, and redirect checks passed, with the docs-only Pages check neutral as expected. Local Node 20 focused staging contracts passed 34/34 on each completion diff.

    Fresh redacted provider assertions after the final merge used only runmprc@gmail.com and exact project run-mprc-staging. They matched every expected value:

    • exactly one staging web app, one restricted score-based key, and one matching App Check registration;
    • allowed domains exactly run-mprc-staging.firebaseapp.com and run-mprc-staging.web.app;
    • one-hour token lifetime; all-domain, AMP, testing, and WAF options absent/disabled;
    • Authentication and Firestore both ENFORCED with replay protection OFF;
    • zero Auth users and zero Firestore root collections;
    • billing unlinked and disabled;
    • no enabled Function deployment API and no deployed Function;
    • Hosting remains version 8556fc51210bdc66 from exact source bce911a7083201cfe2141edaa9660f210287bf57.

    The approved reserved-domain disposable browser identity passed account creation, sign-out, fresh sign-in, post-enforcement sign-in, and signed-in/signed-out token-bearing empty Events reads. Tokenless valid-credential Auth and Firestore probes were rejected with HTTP 401 and 403 after propagation. The account profile failed closed because its two profile Functions are intentionally absent. Browser warnings/errors were absent. The disposable identity was deleted, and final provider counts are zero.

    Public checks after the final merge returned 200 for staging root, direct Events, and runmprc.com; the latter still identifies Netlify as its server. Production Firebase, production data, DNS, GitHub Pages, Netlify configuration, and live website behavior were not mutated.

    No token, credential, site key, key/provider locator, provider response body, disposable email, local user identifier, or production data is included.

    Officer impact: Backup officers can now verify one consistent current state: staging Authentication and Firestore enforce App Check, but Functions and a usable member backend remain unavailable. Officers do not sign in, run commands, configure providers, attach billing, or handle credentials.

    Officer documentation: OFFICER_START_HERE.md, docs/officers/README.md, docs/officers/PUBLISH_AND_CHECK.md, and docs/officers/SYSTEM_MAPS.md; matching root state is recorded in README.md, SYSTEM_DESIGN.md, SECURITY.md, IMPLEMENTATION_PLAN.md, OPERATIONS_RUNBOOK.md, and GITHUB_ISSUES.md.

    Deployment evidence: Website — exact source bce911a7083201cfe2141edaa9660f210287bf57 remains staging Hosting version 8556fc51210bdc66, with browser/public checks passed. Firebase — Auth/Firestore enforcement, tokenless denial, token-bearing browser behavior, and zero-count cleanup passed. Provider — one restricted matching one-hour registration remains configured. Functions/billing — absent/unlinked/disabled. Production — unchanged.

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 hostingneeds-external-configRequires provider console or external configurationpriority:P0Launch blocker or urgent security risksize:MMedium multi-file issuetype:operationsOperational setup or runbooktype:securitySecurity or privacy boundary

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions