---
id: "5.4"
title: "Environments"
dept: engineering
status: draft
owner: Param
branded: false
last_verified: 2026-10-26
sources:
  - "brew/.wt-prod/docs/production.md"
  - "brew origin/main: deploy.sh:20-55, tools/prod-env.sh, tools/deploy-demo.sh, tools/promote.sh, moved.js:1-15, server.js:1119-1124, db/prod-clean.mjs:1-30"
  - "brew origin/main: README.md 'Run it locally', DUMMY.md rows 1, 5, 6, 8"
  - "brew origin/main git log: deb7d90, 119dc8a, 41b0258 (25 Oct, which site is home)"
  - "memory brew-prod-backend, prod-clean-only, brew-live-stores, brew-demo-mode, always-deploy-to-test, brew-setup-v2"
---

# Environments

## Answer

Brew runs in four places, production, staging, the demo and a laptop, and this page settles who uses each, what may run there and how code and brands move between them.

## Today

| | Production | Staging | Demo | Local |
|---|---|---|---|---|
| Address | feed.joinsquareup.com | brew.joinsquareup.com | demo.joinsquareup.com | http://localhost:4200 |
| Cloud Run | `brew-web` + `brew-worker` | `shopos-feed` | `brew-demo` | none |
| Storage | Cloud SQL `brew-prod` + `gs://brew-prod` | Cloud SQL `brew-staging` + `gs://brew-prototype` (mirrored) | `gs://brew-prototype-demo` only | `.brands/`, `.tenants/` folders |
| Who uses it | The five design partners and our team | Our team, testing | Prospects, a sandbox per visitor | One developer |
| AI | Gemini: Pro for Plays, Flash for the rest | same | all Flash | `AI_MOCK=1` |
| Released by | `tools/promote.sh` only | `./deploy.sh` | `tools/deploy-demo.sh` | `node server.js` |
| Admins | `param@joinsquareup.com` only, plus full-access domains joinsquareup.com and shopos.ai | three admin emails | same as staging | `DEV_MEMBER=1` |

Sources: [src: brew/.wt-prod/docs/production.md] [src: brew/deploy.sh:39] [src: brew/tools/prod-env.sh:9] [src: brew/tools/deploy-demo.sh] [src: brew/README.md]

### Which site is a brand's home

- Since 25 Oct (evening) every design partner's home is production: Arata, Nutrova, Mana, PUMA India and Scrubroom. [src: git 119dc8a] [src: memory brew-prod-backend]
- Staging lists them in `MOVED_TO_PROD`: their own people get a 302 (pages) or 409 (API) to production; staff stay. [src: brew/deploy.sh:39] [src: brew/server.js:1119-1124]
- Production's `STAGING_HOME` does the reverse and is empty. [src: brew/tools/prod-env.sh:9]
- A brand at home on one site gets no background work, outgoing email or Slack, or sign-in renewal from the other. Connector reads keep running on both, so Arata stays connected on both. [src: brew/moved.js:1-8] [src: brew/.wt-prod/docs/production.md]
- Two code comments still say Arata's home is staging again (deploy.sh's smoke list and moved.js's header). They date from commit deb7d90, which 119dc8a reversed 30 minutes later. [src: brew/deploy.sh:51] [src: brew/moved.js:5-6] [src: git deb7d90, 119dc8a]
- Cozy Snugglet and Zenant are our own test brands. Other slugs on staging are leftovers. [src: memory brew-live-stores]

### What may run where

| Rule | Production | Staging | Demo | Source |
|---|---|---|---|---|
| `DEMO_MODE`, `AI_MOCK`, `/auth/dev`, `OPEN_SITE`, simulated connectors | never (clean gate refuses) | never on purpose | `DEMO_MODE=1` | [src: brew/db/prod-clean.mjs:1-6] [src: memory prod-clean-only] |
| Test brands and test keys | never | yes | prepared brands only | [src: brew/db/prod-clean.mjs:12] |
| Sloosh finals | off (Gemini fallback) | connected | simulated, Dummy | [src: git 0fc7cfc] [src: brew/DUMMY.md] |
| Simulated teammate replies | no | no | yes, tagged | [src: brew/DUMMY.md] |
| Outgoing email | yes | staff and non-moved brands | blocked | [src: brew/DUMMY.md] [src: brew/moved.js:1-6] |
| Kept exceptions in production | Pro plan sheet (no billing), Marketplaces "Coming soon", catalog-photo fallback, Delete my data as an email request | | | [src: memory prod-clean-only] |

### What moves between them

| From → to | What moves | How | Source |
|---|---|---|---|
| main → staging | code | `./deploy.sh` from a clean tree of origin/main | [src: brew/deploy.sh:7] |
| staging → production | the exact image staging runs, by digest | `tools/promote.sh` | [src: brew/tools/promote.sh:1-20] |
| staging → production | a partner's data, once | `tools/partner-copy.sh` (job `brew-partner-copy`): rows, parts, vault re-encrypted, binaries; never jams, finals, `raw/`, spend or test data | [src: memory brew-prod-backend] |
| staging → demo | a prepared brand's public pack | `tools/demo-sync.sh <slug>` then `tools/demo-strip.mjs` and a canary | [src: memory brew-meta-connector-qa] |
| production → anywhere | nothing | | |

Work kept on staging on purpose: the Set-up v2 composer was not promoted as of 25 Oct by Param's choice. [src: memory brew-setup-v2]

### Local

```bash
npm ci
AI_MOCK=1 BUILD_RESUME_OFF=1 RESEARCH_OFF=1 LIVE_OFF=1 TREG_OFF=1 FEED_SIGNIN=0 node server.js
```

Keys come from `../ugc-factory/.env` (override with `ENV_FILE`). Only test brands serve locally; partners live on production. [src: brew/README.md] [src: memory brew-jam-rca-2026-10-26]

## Tomorrow

| Item | Version | Tag |
|---|---|---|
| Production as the only home for real brands | v1 | Stays |
| A new production domain to replace feed.joinsquareup.com | v2 | Changes (domain open) |
| Staging bucket mirror | v2 | Goes |
| Demo on its own Postgres | v2 | New |
| Shopify public app pointed at production after review | v1 | Changes, once Shopify approves |
| Sloosh connected on production | v2 | Open, Param's call |

## How we do it

1. Test on staging. Deploy right after a change is tested; Param tests on the live staging URL. [src: memory always-deploy-to-test]
2. Release to production only with `tools/promote.sh`, from a clean checkout of origin/main. See Release and promote.
3. Run risky tests (disconnects, resets) only on Cozy or Zenant on staging. [src: memory brew-live-stores]
4. Never wipe or reset the five partners. [src: memory brew-live-stores]

## Numbers

| Metric | Definition | Where measured |
|---|---|---|
| Brands per site | Brands whose home is each site | `MOVED_TO_PROD` and `STAGING_HOME` |
| Staging to production lag | Commits on origin/main not yet promoted | `git log <prod git-sha>..origin/main` (Proposed) |
| Clean gate findings | Findings per promote run | `brew-prod-clean` job logs |

## Open

1. **Is Arata's home production or staging?** The settings say production; two comments say staging. Proposal: production, and fix the two comments.
2. **When does production get its own domain?** Proposal: keep feed.joinsquareup.com until the brand name is picked, then move with a redirect.
3. **Should Sloosh finals run on production?** Proposal: no until the Sloosh workspace has paid credits and Param approves the first quote there.
