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
- Release each site only with its own tool from the table.
- 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
- Publish the shared docs:
cd /Users/param/Documents/ChatGPT/brand-directions && node _tools/bundle.mjs && python3 _tools/deploy-docs.py
- 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
- 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
- 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.
- 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.
- 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.