Snapshots

Everything runs in one Google Cloud project, with Cloudflare handling DNS

Being built
  • Production, staging and demo are separate Cloud Run services behind one load balancer.
  • Production stores in Cloud SQL brew-prod, regional HA, plus the gs://brew-prod bucket.
  • Each site has its own release tool; use only that one.
  • The handbook has been public with no sign in since 26 Oct, at Param's call.
  • Handbook comments are not deployed, so comments on pages do nothing for now.
10Max production web instances
Your call

Who besides Param gets into the handbook, and when do we clean old buckets?

Ops and infrastructure · 8.12

Hosting map

DraftLast checked Mon Oct 26Owner Param

Answer

Everything runs in one Google Cloud project, squareup-492617 in asia-south1, with Cloudflare in front for DNS; this page maps each site and service to where it runs, what it stores in and how it is released, including the docs and this handbook.

Today

Sites

Site Address Runs on Stores in Released by Source
Production feed.joinsquareup.com Cloud Run brew-web, 2 to 10 instances, and brew-worker, exactly 1, behind load balancer squareup-urlmap, Cloud Armor brew-prod-armor Cloud SQL brew-prod, Postgres 17, regional HA; gs://brew-prod tools/promote.sh brew/.wt-prod/docs/production.md:9-15
Staging brew.joinsquareup.com Cloud Run shopos-feed, one instance, both roles Cloud SQL brew-staging; gs://brew-prototype, mirrored ./deploy.sh brew/.wt-prod/docs/production.md:9-14 brew/deploy.sh:39-41
Demo demo.joinsquareup.com Cloud Run brew-demo, one instance, DEMO_MODE=1 gs://brew-prototype-demo only tools/deploy-demo.sh brew/tools/deploy-demo.sh:14-16
Shared docs docs.joinsquareup.com Firebase Hosting site squareup-docs static files brand-directions/_tools/deploy-docs.py brand-directions/_tools/deploy-docs.py:1-9 memory brand-directions-2026-10-25
Handbook handbook.joinsquareup.com Firebase Hosting site squareup-handbook, public with no sign in since 26 Oct at Param's call; pages send X-Robots-Tag: noindex so search engines skip them; DNS is a DNS-only Cloudflare CNAME to squareup-handbook.web.app static build of handbook/out brand-directions/_tools/deploy-handbook.py --public, domain by brand-directions/_tools/handbook-domain.py brand-directions/_tools/deploy-handbook.py:57-63 Param, 26 Oct, "host it without any auth"
Handbook comments none while the handbook is public Cloud Run handbook-comments needs the Cloudflare Access identity, so it stays undeployed; comments on pages do nothing for now Firestore collection handbook_comments not deployed brand-directions/_tools/deploy-handbook.py:10, 22 handbook/comments/server.mjs:1-4

The handbook deploy refuses to upload unless check.mjs has 0 errors, a signed-out request to handbook.joinsquareup.com is sent to Cloudflare Access or refused, and the build exists. The pages are never uploaded to Hosting as files, because Hosting also serves every site at squareup-handbook.web.app, which Access does not cover. After release the script checks that the web.app, firebaseapp.com and run.app addresses all refuse a signed-out request, and stops with LEAK if one does not. --skip-gate is only for a first upload Param has approved. brand-directions/_tools/deploy-handbook.py:4-9 brand-directions/_tools/deploy-handbook.py:51-59

Next's first build step is switching on that gate and sending Claude the Access team domain and audience tag. handbook/tools/next-build.json

Cloud Run jobs

Job Does Runs as Source
brew-prod-migrate db/migrate.js on production, during a promote brew-prod-runtime brew/tools/promote.sh:65-67
brew-prod-clean Smoke test and clean gate, inside the VPC brew-prod-runtime brew/tools/promote.sh:85-89
brew-partner-copy Partner copy from staging to production brew-partner-copy brew/tools/partner-copy.sh:13
brew-ops Staging status, jam reset, parity brew-runtime memory brew-prod-backend
brew-import Bucket to Postgres import on staging memory brew-storage
brew-prod-ping, brew-staging-ping Read-only connector ping memory brew-prod-backend

Shared pieces

Piece Detail Source
Network Direct VPC egress on subnet default; databases have private IPs only, 172.30.0.4 and 172.30.0.3 brew/.wt-prod/docs/production.md:11 brew/tools/prod-env.sh:13
Ingress brew-web takes only load balancer traffic; brew-worker is internal brew/tools/promote.sh:74 brew/tools/promote.sh:94
CDN Off on production; session affinity made it useless memory brew-prod-backend
Backups bucket gs://brew-prod-backups: nightly export and the promote lock brew/.wt-prod/docs/production.md:40
Service accounts brew-prod-runtime, brew-runtime, brew-partner-copy, brew-backup brew/tools/prod-env.sh:5-6 memory brew-prod-backend
Source code private GitHub repo wulfor24/brew, branch main memory brew-prototype-repo

Retired

Cloud Run arata-feed, arata-feed-v1 and shopos-feed-demo with their routes were removed on 15 Oct; the buckets gs://squareup-feed and gs://squareup-feed-demo were kept. memory brew-prototype-repo

Tomorrow

Item Version Tag
Production, staging and demo as above v1 Stays
Staging's bucket mirror v2 Goes
The demo on its own Postgres v2 New
Handbook comments service deployed v1 New, after the gate is on
Production on the product's own domain v2 Changes, waits on the name

How we do it

  1. Release each site only with its own tool from the table.
  2. Publish the handbook:
cd /Users/param/Documents/ChatGPT/handbook && node check.mjs && node build.mjs && node tools/snapshot.mjs build
python3 ../brand-directions/_tools/deploy-handbook.py
  1. Publish the shared docs:
cd /Users/param/Documents/ChatGPT/brand-directions && node _tools/bundle.mjs && python3 _tools/deploy-docs.py
  1. The deploy script builds and deploys the service itself; set CF_TEAM_DOMAIN, CF_ACCESS_AUD and ALLOWED_EMAILS before running it. handbook/comments/server.mjs:9-13
  2. A new service gets a row in this map the day it is created.

Numbers

Metric Definition Where measured
Services running Cloud Run services and jobs in squareup-492617 gcloud run services list, Proposed monthly check against this map
Unmapped services Services running that this page does not list Proposed; target 0

Open

  1. When does the handbook go live? The deploy script already keeps the pages off public hosting and refuses a release if squareup-handbook.web.app, firebaseapp.com or run.app answer a signed-out request, but nothing is uploaded until Cloudflare Access is on. Proposal: Param switches on Access for handbook.joinsquareup.com this week and sends the team domain and audience tag, then the first release runs with the gate, never with --skip-gate.
  2. Who besides Param gets into the handbook? Proposal: Access allows Param, Sai and Arvind by email; the comments service's ALLOWED_EMAILS holds the same three.
  3. Should we clean up the old buckets gs://squareup-feed and gs://squareup-feed-demo? Proposal: export a copy to cold storage, then delete them after Param confirms nothing reads them.
Sources
  • brew/.wt-prod/docs/production.md:1-21
  • brew origin/main a559de6: deploy.sh:39-41, tools/promote.sh:65-105, tools/prod-env.sh:4-9, tools/deploy-demo.sh:14-16, tools/partner-copy.sh:13
  • brand-directions/_tools/deploy-handbook.py:1-115, brand-directions/_tools/deploy-docs.py:1-28
  • handbook/comments/server.mjs:1-15, handbook/comments/Dockerfile, handbook/tools/next-build.json
  • memory brew-prod-backend, brew-storage, brew-demo-mode, brew-prototype-repo, brand-directions-2026-10-25, brew-handbook

Source file content/ops-and-infrastructure/hosting-map.md · For agents: Markdown · JSON