Deployment
Four independently deployable pieces: API (Workers), Web (Pages), Docs (Pages), and Mobile (EAS Build). All triggered from the same GitHub repo.
What deploys where
API — Cloudflare Workers
-
Workflow:
.github/workflows/cd.yml→deploy-apijob. -
Order per deploy: run migrations → build →
wrangler deploy. -
Config:
apps/api/wrangler.toml(bindings, compat date, vars). -
Secrets (Cloudflare secret store, set with
wrangler secret put <NAME>— see secrets):SESSION_SECRET,PII_ENCRYPTION_KEY,INFINIA_API_USERNAME,INFINIA_API_PASSWORD,INFINIA_WEBHOOK_SECRET,NEON_DB_URL. -
Public vars (in
wrangler.toml[vars]):APPLE_BUNDLE_ID,GOOGLE_OAUTH_CLIENT_ID,INFINIA_COMPANY_ID,INFINIA_BASE_URL. -
Bindings:
HYPERDRIVE(id inwrangler.toml). -
Neon region: pinned to an EU region — see privacy for the why.
-
Manual deploy from your machine:
pnpm --filter @gringo-pay/api exec wrangler deploy
Web — Cloudflare Pages
- Workflow:
.github/workflows/cd.yml→deploy-webjob. - Project name:
gringo-pay-web(must match Cloudflare Pages project). - Build output:
apps/web/dist.
Docs — Cloudflare Pages
- Workflow:
.github/workflows/docs.yml. - Project name:
gringo-pay-docs(must match a Cloudflare Pages project). - URL: gringo-pay-docs.pages.dev (default; add a custom domain via the Cloudflare dashboard when ready).
- One-time setup: create the Pages project in the Cloudflare dashboard (Pages → Create → Direct Upload → name it
gringo-pay-docs). No repo settings to change.
Mobile — EAS
- Workflow:
.github/workflows/cd.yml→build-mobilejob. - Currently only iOS preview builds. Android is not wired up yet.
- Requires
EXPO_TOKEN(Expo access token). - Distribution is via internal preview channel — no app store submission automated yet.
Mobile-specific config to set at build time:
EXPO_PUBLIC_API_BASE_URL— deployed API URL.EXPO_PUBLIC_APPLE_BUNDLE_ID— must match theAPPLE_BUNDLE_IDon the API side (used asaudwhen verifying Apple ID tokens).EXPO_PUBLIC_GOOGLE_OAUTH_CLIENT_ID— same for Google.
Required GitHub secrets
| Secret | Used by | Purpose |
|---|---|---|
CLOUDFLARE_API_TOKEN | CD (api + web) | Deploy to Workers + Pages |
CLOUDFLARE_ACCOUNT_ID | CD (api + web) | Cloudflare account |
DATABASE_URL | CD (api migrations) | Neon Postgres for drizzle-kit migrate |
EXPO_TOKEN | CD (mobile) | EAS Build authentication |
TURBO_TOKEN | CI + CD (optional) | Turborepo remote cache |
TURBO_TEAM | CI + CD (optional) | Turborepo team slug |
First production deploy — pre-flight
Before the API can serve real users, all of these must be true (see also privacy pre-production checklist):
- Infinia production credentials issued;
INFINIA_BASE_URLset to Infinia's production hostname - Infinia HOSTED KYC widget branding option confirmed
- Infinia UK / EU custodial licensing confirmed for our user population
- DPAs signed with Infinia, Cloudflare, Neon
- Apple + Google OAuth client IDs created; bundle id / client id set as env vars
-
SESSION_SECRETandPII_ENCRYPTION_KEYgenerated (32+ bytes each) and set viawrangler secret put -
pgcryptoextension enabled on the production Neon database - Nightly reconciliation cron and retention cron scheduled
- Privacy policy published on the marketing site
-
INFINIA_WEBHOOK_SECRETregistered as thecallback_urlon every Infinia resource type we create - Observability tooling picked and wired up (architecture/observability) — edge SLIs emitting, page-worthy alerts firing to on-call, runbooks landed for each alert (ops/runbooks)
-
GET /healthliveness probe monitored externally from ≥ 2 regions
Rollback
- API:
wrangler rollback— Cloudflare keeps recent versions. - Web: re-deploy a previous git SHA via
workflow_dispatch. - Docs: re-deploy a previous git SHA via
workflow_dispatchondocs.yml, or roll back via the Cloudflare Pages dashboard. - Mobile: re-run EAS Build on a prior SHA. Users need to install the new build.
Environments
Currently one environment: production. Infinia sandbox credentials + a dev Neon branch are used for local dev; there is no separately-deployed staging tier. Staging is a candidate for Phase 1.5 once we have real user volume to protect.