Publish the Firebase Hosting mirror, keyless - #51
Merged
Conversation
added 2 commits
August 3, 2026 18:42
firebase.json and .firebaserc were written weeks ago and nothing ever deployed them, so upgradegr-claimscene.web.app served nothing. This adds the workflow that publishes it. It authenticates with the SAME Workload Identity Federation the Cloud Run deploy already uses. The obvious alternative, a long-lived FIREBASE_SERVICE_ACCOUNT key in repository secrets, would add a second and weaker credential path into the same project, and this repository is public. The deploy identity gained exactly one role, roles/firebasehosting.admin. The client is built with no VITE_* env, which is how the container builds it too, so both origins serve the same bundle: relative API paths, same origin, no CORS. The verification step drives the mirror rather than trusting the CLI's exit code, and checks the app shell, /health, /scenarios and a scenario image through the rewrite. It deliberately does not assert a commit match: this runs beside the Cloud Run deploy, which may still be rolling.
test_live_failure_returns_a_plain_kind_and_hides_the_upstream_text asserts that no part of the upstream provider error reaches the caller, and searched the sealed response for the bare digits "402". The response is mostly SHA-256 hex, so "402" turns up inside a digest by chance roughly one run in seven, and the case id carries a random suffix, so which run is red is a coin toss. It failed on a workflow-only PR that touches nothing it tests. The status code is now searched for as it actually appears in the upstream message, "(402)". Parentheses cannot occur in hex, so the needle only fires on a real leak. The other three needles were already leak-specific.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
firebase.jsonand.firebaserchave been in this repo for weeks and nothing ever ran a deploy, sohttps://upgradegr-claimscene.web.app/served nothing at all. This adds the workflow that publishes it.Why not the sibling repo's pattern. Cinemory deploys hosting with a long-lived
FIREBASE_SERVICE_ACCOUNTJSON key in repository secrets. This repo already has keyless Workload Identity Federation wired for the Cloud Run deploy, and adding a second, weaker credential path into the same Google project — in a public repository — would be a step backwards. This reuses the existing identity (github-deployer@upgradegr-claimscene, provider pinned toupgradedev/claimsceneon the Google side) and it gained exactly one role:roles/firebasehosting.admin. Nothing else was widened, and there is no key to leak or rotate.One product, two front doors.
firebase.jsonrewrites/health,/scenarios,/casesand/meto the same Cloud Run service, so the mirror is a CDN for the client plus a proxy for the API, not a second deployment. Every backend route lives under those four prefixes, so nothing falls through toindex.htmland gets HTML where it expects JSON. The client is built with noVITE_*env, exactly as the container builds it, so both origins serve the same bundle.Verified by driving it, not by trusting the CLI. The last step fetches the app shell,
/health,/scenariosand a scenario image through the rewrite, and fails the run if any of them does not answer. It deliberately does not assert a commit match, because it runs beside the Cloud Run deploy which may still be rolling.README gains a short section pointing at the second origin and the command to check it.