CANCRIDOCS · v0.4
DOCS --:--:-- ET

Deploy to Firebase

The codebase is complete and emulator-verified. Bringing it up against real infrastructure is a one-time provisioning pass. There are two ways to push it — a manual one-shot from your machine, and a keyless CI pipeline on every push to main.

A deploy workflow already exists: .github/workflows/deploy.yml. It deploys Hosting + Functions + rules via Workload Identity Federation (no stored key) and rolls the Cloud Run feed-engine. It's gated by a repo variable until you've provisioned the GCP side — the runway below walks you through arming it.

Two paths

manual one-shot, from your machine

scripts/deploy.sh — containerised, builds web + functions and pushes Hosting, Functions, and rules. Best for a first deploy, a hotfix, or a project without WIF yet.

automated keyless CI

deploy.yml — on push to main (and workflow_dispatch). Authenticates via WIF, deploys the Firebase surfaces, and builds + deploys the Cloud Run feed-engine.

Manual one-shot deploy

The hands-on counterpart to the CI pipeline. Everything runs in a node:26 container — the host only needs Docker. It builds the web app and functions, then runs firebase deploy.

  1. Pick your auth

    Non-interactive (CI token) or interactive login inside the container:

    bash · auth options
    # option A — token (non-interactive)
    export FIREBASE_TOKEN="$(firebase login:ci)"
    
    # option B — leave it unset; the script runs `firebase login` in-container
  2. Deploy

    Point it at your project id. It builds, then deploys Hosting + Functions + Firestore/RTDB rules.

    bash
    FIREBASE_PROJECT=your-project-id scripts/deploy.sh
  3. Narrow the scope (optional)

    Deploy just one surface — e.g. a Hosting-only push for a UI change:

    bash
    CANCRI_DEPLOY_ONLY=hosting FIREBASE_PROJECT=your-project-id scripts/deploy.sh

The manual script deploys the Firebase surfaces (Hosting, Functions, rules). It does not build the Cloud Run feed-engine image — that's the always-on price source. Without it the terminal authenticates and onboards, but no live ticks flow. Roll the feed-engine via the CI pipeline or the runway.

Keyless CI deploy

On push to main, deploy.yml authenticates to GCP with a short-lived OIDC token (no JSON key in the repo), then:

  • builds the web app + functions;
  • firebase-tools deploy --only hosting,functions,firestore:rules,database;
  • builds + pushes the feed-engine image and gcloud run deploys it (always-on, single instance, internal ingress).

The split — firebase-tools for the Firebase surfaces, gcloud for the long-running Cloud Run deploy — keeps the container build off the firebase-tools ADC timeout path.

The workflow is gated by vars.CANCRI_DEPLOY_ENABLED == 'true'. It stays inert until you've set up WIF + the deployer service account and flip that variable on — exactly the runway below.

Going-live runway

None of this is needed to run locally (scripts/quickstart.sh). It's the one-time provisioning to arm the CI deploy. The canonical checklist is SETUP.md §4; the shape of it:

1 · Firebase project irreversible region

  1. Create a Blaze-plan project

    Spark blocks the outbound egress to ls-tc.de / Yahoo / Vertex, and Cloud Run / Scheduler / Secret Manager need Blaze.

  2. Firestore + RTDB in europe-west1

    ADR-0001. Firestore's location is permanent — get it right before any data exists. RTDB is offered only in us-central1, europe-west1, asia-southeast1 — not europe-west3.

  3. Enable Auth providers

    Email/Password + Google; configure the consent screen and authorized domains. Decide your invite-allowlist policy — this is an access-gated product.

2 · Gemini via Vertex AI no API key

  • Enable the Vertex AI API; grant the Functions runtime SA roles/aiplatform.user.
  • Confirm gemini-3.5-flash availability/quota in europe-west1.
  • Set CANCRI_USE_VERTEX=true for the deployed functions. There is no Gemini API key — access is via IAM.

3 · Workload Identity Federation keyless deploy

deploy.yml authenticates via WIF — no stored JSON key. One-time setup:

  1. WIF pool + provider

    With an attribute-condition pinning assertion.repository == 't11z/cancri'.

  2. A dedicated deployer service account

    Granted roles/iam.workloadIdentityUser for your repo's principalSet, plus least-privilege deploy roles (firebasehosting.admin, cloudfunctions.admin, run.admin, artifactregistry.writer, …).

  3. An Artifact Registry Docker repo

    Named cancri in your region.

  4. Enable the APIs

    Cloud Run, Cloud Build, Artifact Registry, Secret Manager, Cloud Scheduler.

  5. Set repo Variables, then arm it

    Set GCP_PROJECT_ID, GCP_REGION (default europe-west1), WIF_PROVIDER, DEPLOYER_SA — and finally:

    arm the CI deploy
    gh variable set CANCRI_DEPLOY_ENABLED --body true

4 · The remaining live fills flagged in code

  • Secret Manager entries for the L&S handshake config (LS_cid, magic/idle/polling params, origin) — never in the repo.
  • The first L&S capture (the self-heal Job, during trading hours) fills packages/ls-protocol/protocol.config.v1 with the real handshake bytes / frame offsets — exactly what the replay gate verifies.
  • A Playwright Dockerfile for services/selfheal, then gcloud run jobs deploy.
  • A logo provider behind resolveLogo's fetcher (monogram-only until then).
  • Branch-protect main to require the replay-regression check + ≥1 human review for self-heal PRs.

Deploy the docs site

This documentation site is hand-authored static HTML/CSS in site/ — no build step. It ships to GitHub Pages via its own workflow, .github/workflows/pages.yml, on any push to main that touches site/.

  1. Turn Pages on (one time)

    Repo Settings → Pages → Build and deployment → Source = “GitHub Actions.”

  2. Push a change under site/

    The workflow uploads the folder and deploys it. The site lives at https://t11z.github.io/cancri/ — all links are relative, so it works under the /cancri/ subpath.

  3. Preview locally (optional)

    Any static server works, e.g.:

    bash · preview the docs
    cd site && python3 -m http.server 8080   # → http://localhost:8080