Repository navigation
CI-001D4 — Configure and verify no-billing staging App Check #676
Description
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
daliu commentedon Aug 26, 2026
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.
daliu commentedon Aug 26, 2026
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.
daliu commentedon Aug 26, 2026
Monitoring checkpoint merged and reverified — issue remains open
PR #678 merged exact reviewed head
654b36ab24f4bcb243c92656e0ed75047a0ac315tomainas merge14286c9c6e8c65ed39343ad2c1e6ee93e6af296d. 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.comand exact projectrun-mprc-stagingmatched the merged record: one web app; one restricted score-based key; exactlyrun-mprc-staging.firebaseapp.comandrun-mprc-staging.web.app; one-hour token TTL; Authentication and Firestore bothUNENFORCEDwith replay protection off; Hosting version8556fc51210bdc66; 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, anddocs/officers/SYSTEM_MAPS.md, merged in PR #678.Deployment evidence: Website — exact source
bce911a7083201cfe2141edaa9660f210287bf57remains Hosting version8556fc51210bdc66; 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
ENFORCEDreadback; 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.daliu commentedon Aug 27, 2026
Final enforcement evidence
Completion PR #679 merged exact reviewed head
98a980d1d75c701abb63e947c9032cabb2910244as merge667a4dc7bb4672bf63165f67ab0149e18692da5f; #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 head39d017249143784af53da22259fe832c715c59c2as final-main merge1f27b0619c494cd3fc5e4c75dff521cffc584aae.All five jobs passed for that exact final
mainin 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.comand exact projectrun-mprc-staging. They matched every expected value:run-mprc-staging.firebaseapp.comandrun-mprc-staging.web.app;ENFORCEDwith replay protectionOFF;8556fc51210bdc66from exact sourcebce911a7083201cfe2141edaa9660f210287bf57.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, anddocs/officers/SYSTEM_MAPS.md; matching root state is recorded inREADME.md,SYSTEM_DESIGN.md,SECURITY.md,IMPLEMENTATION_PLAN.md,OPERATIONS_RUNBOOK.md, andGITHUB_ISSUES.md.Deployment evidence: Website — exact source
bce911a7083201cfe2141edaa9660f210287bf57remains staging Hosting version8556fc51210bdc66, 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.