Skip to content

WEB-001 — Controlled Firebase Hosting and automatic web releases #460

Open

Description

@daliu

Outcome

Replace the split Netlify/GitHub Pages website path with controlled Firebase Hosting and make a reviewed merge into a protected web-production branch automatically publish the exact merged commit. Keep main as the integration branch until production has safely caught up.

Verified current state (2026-07-22)

  • runmprc.com is still served by Netlify deploy 6a54a3c93db9d300082e1f5f from source e86a0f702cff6495f50630c5de3337290db8b8cb.
  • Current main is 176 commits and 247 files ahead of live and contains frontend, Functions, Rules, workflow, and dependency changes. It must not be connected directly to production hosting.
  • Netlify receives main and pull-request events, but repository logic intentionally stops production builds. The current signed-in runmprc@gmail.com account can view deploys but is denied project deployment settings.
  • .github/workflows/deploy.yml is manual and deploys a fixed backend plan plus a separate GitHub Pages artifact. It does not publish the live website.
  • firebase.json has no Hosting configuration. Optimized browser builds still select the production Firebase project, so a staging Hosting preview would contact production.
  • No protected web-production branch exists. main has no required status checks and administrators can bypass its review rule. The GitHub production environment has no reviewer or branch policy.
  • The available Google identity cannot access mid-peninsula-running-club. BACKEND-001 — Audit the Firebase cutover and approve legacy data disposition #113, CI-001C — Configure protected short-lived Firebase deployment identity #133, and CI-001D — Prove backend-first staging and deploy the profile repair #136 still own staging inventory, short-lived deployment authority/environment protection, and staged release evidence.

Release contract

feature PR -> main (integration and CI)
approved promotion PR -> protected production-web
merge -> automatic exact-SHA Firebase Hosting deploy -> readback and smoke checks

The promotion merge is production approval. There is no separate deploy button or laptop CLI publication. A release tag is written only after successful verification and is an audit marker, not the authorization trigger.

Scope

  1. Make browser Firebase configuration explicit and fail closed for local, isolated staging, and production. Prove an optimized staging build cannot reach production Firebase resources.
  2. Add Firebase Hosting configuration for SPA rewrites, canonical/SEO behavior, assets, callback routes, cache policy, release identification, and preview/live channels.
  3. Add exact-commit CI for promotion pull requests and pushes to production-web, including frontend tests, SPA tests, non-mutating lint, build, artifact safety, and a release-scope gate.
  4. Create and protect production-web. Require reviewed pull requests, exact required checks, current head, stale-review dismissal, last-push approval, conversation resolution, no direct/force pushes or deletion, and no administrator bypass.
  5. Restrict the production environment and short-lived WIF/ADC identity to the protected branch. Do not use a service-account JSON key or legacy Firebase token.
  6. Automatically deploy a successful main commit only to isolated staging/preview Hosting after BACKEND-001 — Audit the Firebase cutover and approve legacy data disposition #113/CI-001C — Configure protected short-lived Firebase deployment identity #133. Automatically deploy production only after the protected promotion merge.
  7. Add a deployment concurrency lock, exact SHA/release marker readback, public deep-route/callback smoke checks, and a rehearsed previous-release rollback.
  8. Stage CSP and the approved browser-security headers, then perform an owner-approved DNS/TLS cutover. Remove the GitHub Pages custom-domain claim and retire Netlify only after observation and rollback proof.

Backend-dependent releases remain explicit backend-first release plans. This website lane must never broaden into an all-Functions, Rules, Stripe, email, or provider deployment.

Acceptance criteria

  • An optimized staging artifact is proven unable to call production Firebase resources.
  • A promotion pull request cannot merge without all exact-head required checks and an authorized independent approval.
  • Direct pushes, force pushes, branch deletion, and administrator bypass are disabled for production-web.
  • Merging the promotion pull request automatically deploys that exact commit to Firebase Hosting without a second manual deploy action.
  • Deployment authority is short lived, environment restricted, and unavailable to pull-request code or the build job.
  • Concurrent or superseded production deployments cannot race.
  • Provider readback and a public release marker identify the exact published commit; skipped or partial work fails red.
  • SPA deep links, static assets, OAuth/payment callback routes, canonical domain behavior, TLS, headers, and caching pass on staging and production.
  • The previous known-good release can be restored and the rollback drill is recorded.
  • Netlify and the GitHub Pages custom-domain claim are retired only after the Firebase site is verified and the rollback observation period completes.

Stop conditions

  • Production hosting is pointed at current main.
  • Staging can reach production Firebase, or the Firebase estate/project ownership is still ambiguous.
  • Required checks, protected-branch rules, environment restrictions, short-lived authority, exact-SHA readback, or rollback proof are missing.
  • An unreviewed backend, Rules, dependency, provider, or production-data change enters the website release.
  • DNS, TLS, callback, or custom-domain ownership cannot be verified by an authorized owner.

Officer impact: Officers approve a promotion pull request in GitHub; merging it publishes the reviewed website automatically. Officers do not run terminal commands, handle secrets, or use provider dashboards as the normal release path.

Officer documentation: Update OFFICER_START_HERE.md, docs/officers/PUBLISH_AND_CHECK.md, docs/officers/SYSTEM_MAPS.md, docs/officers/ACCESS_CONTINUITY.md, docs/officers/EMERGENCY_AND_RECOVERY.md, the glossary, SYSTEM_DESIGN.md, SECURITY.md, and OPERATIONS_RUNBOOK.md in the implementation pull requests.

Deployment evidence: None at creation. Record source, tests, staging Hosting URL, exact commit/release marker, protected-environment run, Firebase provider readback, DNS/TLS/deep-route checks, Netlify/Pages retirement, and rollback rehearsal as separate dated evidence.

Activity

  1. added
    priority:P1High-priority follow-up
    type:securitySecurity or privacy boundary
    area:webWeb application and hosting
    size:LLarge cross-boundary issue
    needs-external-configRequires provider console or external configuration
    on Jul 23, 2026
  2. daliu commented on Aug 1, 2026

    @daliu
    ContributorAuthor

    COORDINATION / CURRENT HOSTING AUDIT — 2026-08-01T18:41Z

    The owner recalled a planned move away from Netlify and automatic publication after a reviewed branch merge. This issue is that plan: controlled Firebase Hosting through production-web, not CloudWatch. It remains open, unassigned, and unimplemented.

    Current evidence:

    • runmprc.com is still served by Netlify deploy 6a6dc9ea588b0c0008036312, control commit 9ad6837756cdd409d296009fde5082eeeae5c059.
    • Current integration main is 5e23f66fe6f246e0a4950dd836451dd8eb88edfb; ordinary main merges automatically create Netlify attempts, but the inactive one-use manifest makes production publication fail closed.
    • firebase.json still has no Hosting configuration, no production-web branch exists, and no automatic Firebase Hosting workflow exists.
    • No staging GitHub environment exists. production exists but has zero protection rules, no branch policy, administrator bypass enabled, and no visible variables or secrets.
    • The existing manual backend-first workflow publishes only a GitHub Pages copy and cannot update the live Netlify host.

    #507 needs either this controlled Hosting lane completed or a separately reviewed bounded Netlify publication path after its directory backend is deployed and read back. Merging #529 correctly did not make the directory live.

    No branch, environment, provider, DNS, website, Firebase resource, or production data was changed by this audit.

    Officer impact: Automatic reviewed-merge publication is still not available; officers must not interpret a main merge or red Netlify attempt as a live release.

    Officer documentation: None changed; current publishing guides already describe the unavailable target path and paused Netlify state.

    Deployment evidence: Netlify/public marker read only; Firebase Hosting absent in source; GitHub configuration read only; live website and providers unchanged.

  3. daliu commented on Aug 13, 2026

    @daliu
    ContributorAuthor

    Coordination from new unclaimed #623 WEB-002C: this is a one-time exact-artifact Netlify exception using the existing fail-closed manifest, valid marker, exact rollback, and immediate repause. It does not create reusable automatic deployment or close/replace WEB-001/#460, #133, or #136. Current production remains #473 deploy 6a6dc9ea... until every #623 gate passes.

  4. daliu commented on Aug 14, 2026

    @daliu
    ContributorAuthor

    PRE-CLAIM disjointness notice for #657, WEB-UX-004 — Move focus to main content after SPA path navigation.

    Exact proposed base is main 3265a55cb92df1ebb5401f2647ff81e4ca3af0b8, tree 322468cc75a57f7ea392eb9f57a201fb11c4b35a. Proposed ownership is exactly four paths: src/components/ScrollToTop.jsx only a pathname-bound, cancelable, one-shot main-focus settlement while preserving its scroll effect; src/App.jsx only the existing main landmark's stable target relationship and tabIndex={-1}; existing src/App.test.jsx only one separately named WEB-UX-004 generated focus/race matrix and real-shell proof; and docs/officers/PUBLISH_AND_CHECK.md only one separately named no-terminal route-focus verification procedure adjacent to the historical #291 keyboard procedure.

    There is no new test file, lint-baseline change, CSS change, root-document change, Navbar/Footer/route-page change, backend/service/Rules/Functions/index/package/workflow change, provider/account/sign-in/data action, deployment/publication action, or live claim. Released #291 visible-focus/skip-link behavior and #490 mobile disclosure/close behavior remain immutable. #504 stays the disconnected directory coordinator, #507 retains every future connection/release gate, and availability stays byte-for-byte literal false. #616 retains both Strava Function paths and its separate OAUTH/RISK-024 SECURITY hunk. #133/#136/#460 retain their separate future publication procedures; this new guide hunk is separately named.

    Issue creation is not a claim. No source or documentation edit has been made. Send STOP only for an exact path/hunk collision or dependency; otherwise no reply is required. The exact issue/claim/open-PR state will be reread immediately before editing.

  5. daliu commented on Aug 14, 2026

    @daliu
    ContributorAuthor

    PRE-CLAIM coordination for #659 / WEB-002D. This issue uses the existing reviewed one-shot Netlify manifest/build control to publish one exact frozen web artifact, with rollback and immediate repause. It does not generalize reusable hosting, alter .github/workflows/deploy.yml, Firebase deployment, GitHub Pages authority, DNS, secrets, provider configuration, or close #460/#133/#136. Those issues retain their automation/ownership outcomes. Send STOP for an exact release-control collision.

  6. daliu commented on Aug 23, 2026

    @daliu
    ContributorAuthor

    CLAIM COORDINATION — child #663 (WEB-001A1) is assigned and claimed on branch codex/issue-460-firebase-hosting-foundation from exact base 230d73894a69c3f5f5fda05e319fb7b9d63e3d69.

    #663 owns only the source-side fail-closed environment selector, synthetic staging artifact proof, fail-safe local Firebase CLI default, inert build/ Hosting SPA rewrite, minimum existing build-lane wiring, and separately named current-truth documentation. It changes no provider, project, Hosting channel, branch/environment protection, WIF/IAM, release marker/readback, rollback, header/CSP, DNS/custom domain, Netlify/Pages state, account, data, deployment, or live behavior.

    The authenticated Google identity still cannot access MPRC production, so #113/#133 remain hard owner prerequisites. Parent #460 retains automatic production-web promotion and all live cutover work. Send STOP only for an exact path/hunk collision or a newer ownership decision.

  7. daliu commented on Aug 23, 2026

    @daliu
    ContributorAuthor

    CHILD PR READY — WEB-001A1 #663 is implemented at commit e0c459f in PR #664: #664

    This remains the bounded source foundation only: explicit staging/production browser builds, artifact identity checks, demo-only unqualified CLI default, and inert Hosting SPA/predeploy configuration. Local Node 20 / Java 21 suites and synthetic staging/production artifact checks pass. No Firebase project/site/channel, cloud authority, protected environment, release marker, headers, DNS, provider, website, account, production data, deployment, or live behavior changed.

    The current Google identity still cannot see the MPRC production project or an approved staging project. #113/#133 remain the owner gate; parent #460 remains open for automatic promotion, headers, readback/rollback, and cutover.

  8. daliu commented on Aug 24, 2026

    @daliu
    ContributorAuthor

    2026-08-23/24 progress: WEB-001A1 merged; provider deployment remains stopped

    • WEB-001A1: add fail-closed Firebase Hosting foundation #664 merged to main as a614c68d9a1a2be631a3be874a686d61e5d170a0.
    • Exact merged-commit CI run 32695600148 passed all five jobs, including the synthetic staging artifact verifier.
    • Hosted UI evidence: preview / and direct /events rendered without broken images, overflow, or console errors; the only preview warning was the expected App Check-disabled signal for the synthetic configuration. The unchanged live site also passed root-to-/events SPA navigation and 390x844 responsive checks.
    • Netlify containment passed: automatic production build main@a614c68 failed closed. The published site remains main@46e2364; public release-marker readback still identifies control commit 46e23647d8e0bf9fa3a574ea5c5f993be10a419d.
    • Firebase provider readback failed closed: both signed-in Google identities are explicitly denied access to mid-peninsula-running-club; Firebase CLI lists only an unrelated disposable test project; active gcloud identity also has no project visibility. No Firebase project, Hosting channel, IAM, DNS, TLS, backend, or production data was changed.

    Stop condition remains active: the approved production/staging Firebase estate and short-lived deployment authority are not available. Do not deploy through the unrelated test project or create a parallel estate. Resume provider deployment only through the private owner evidence and approvals in #113/#133.

    Officer impact: Source support is merged, but the live officer procedure is unchanged and Firebase publishing remains NOT AVAILABLE YET.

    Officer documentation: merged paths listed in #664.

    Deployment evidence: source/CI/preview/Netlify containment/live readback verified; Firebase Hosting, provider configuration, DNS/TLS cutover, and production behavior not deployed or verified.

  9. daliu commented on Aug 26, 2026

    @daliu
    ContributorAuthor

    WEB-001A2 staging milestone — 2026-08-26

    Child #665 and PR #666 are complete. The club account now owns run-mprc-staging, one Firebase web app, and the first static Hosting release at https://run-mprc-staging.web.app. Finalized version 3ffadcf2ac8cc760 was built from exact merged source a614c68d9a1a2be631a3be874a686d61e5d170a0; direct-route, desktop, phone, empty-data, and provider readback passed. The evidence documentation merged as b115433542329f4ec8f0bbe242b461a5f7ea9b64.

    This closes only static engineering staging. Do not sign in or use real data. Backend/provider isolation, App Check, protected WIF authority and reviewers, exact release marker, predecessor rollback, security headers, production-web, custom domain/DNS/TLS, production Firebase publication, and Netlify/Pages retirement remain open. Production Firebase Hosting still returns 404 and runmprc.com remains unchanged.

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:webWeb application and hostingneeds-external-configRequires provider console or external configurationpriority:P1High-priority follow-upsize:LLarge cross-boundary issuetype:securitySecurity or privacy boundary

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions