# TODO: Secret Management Overhaul + Deploy Migration

> Status: **Deferred — created 2026-05-29**
> Owner: infra / nick
> Trigger: discovered while wiring Telegram startup notifications (2026-05-29)

A dedicated pass to (a) rotate every secret that has lived in git, (b) move secrets out of committed files into the right injection layer, and (c) collapse the two-stack deploy split. All dev data is disposable (no data-migration concern).

## 1. Rotate secrets (all have been committed in git → treat as compromised)

Rotate at the provider, then place per the build-vs-runtime split (decided 2026-05-29).

**→ Runtime (live-stack env injection):**
- `JWT_SECRET` (rotation logs everyone out — fine)
- `MONGODB_URI` password + `MONGO_INITDB_ROOT_PASSWORD` (same value)
- `REDIS_URI` password
- `ADMIN_PASSWORD`
- `GOOGLE_CLIENT_SECRET` (Google Cloud Console)
- `SMTP_PASS` (Resend dashboard — revoke + new API key)
- `REQUEST_NETWORK_API_KEY` (RN dashboard)
- `REQUEST_NETWORK_WEBHOOK_SECRET` (+ update RN webhook config)
- `TELEGRAM_BOT_TOKEN` (Mini App bot — @BotFather /revoke)
- `TELEGRAM_WEBHOOK_SECRET_TOKEN` (+ re-set on Telegram setWebhook)
- `TG_NOTIFY_BOT_TOKEN` (amnGG_MonitorBot — already a dedicated bot; rotate if desired)

**→ Build-time (frontend Woodpecker secret, baked into image):**
- `NEXT_PUBLIC_ALCHEMY_API_KEY_*` (one secret `alchemy_api_key` feeds all 3 args) — rotate in Alchemy **and domain-restrict to dev.amn.gg** (it ships in the browser bundle, so the origin allowlist is the real protection).

**Public by design — no rotation:** Google client IDs, `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` (domain-restrict instead), `NEXT_PUBLIC_TELEGRAM_BOT_ID`, wallet addresses, `REQUEST_NETWORK_MERCHANT_REFERENCE`, URLs/flags.

## 2. Strip secrets from committed files
- `backend/.env.example` — currently holds live values; reduce to reference-only (keys + non-secret defaults). Safe: it is **docs-only**, not read at runtime.
- `frontend/.env.production` — same; not copied into the runtime image by the Dockerfile.
- Remove the gitleaks token allowlists once tokens are gone.

## 3. Collapse the two-stack deploy split
See [[deploy_architecture_two_stacks]] (memory). Make `escrow-deploy` (gitops from `nick/deploy`) the canonical live stack; retire `devEscrow`; point the Woodpecker redeploy step at `escrow-deploy` (`8cbe7b2a…`) so sync + redeploy target the same project. This also fixes the cosmetic redeploy **400**.
- Pending local edits already staged for this in `~/CascadeProjects/escrow/deployment` (uncommitted): `TG_NOTIFY_BOT_TOKEN` + `TG_NOTIFY_CHATS` added to `.env` and wired into both service `environment:` blocks in `docker-compose.yml`.
- Container names are identical across both stacks → cutover has a brief collision/downtime window (acceptable; test data).

## Injection model (decided)
- Build-time `NEXT_PUBLIC_*` → Woodpecker secrets (frontend `build_args`).
- Runtime secrets → live-stack env (deploy-repo `.env` once `escrow-deploy` is canonical).
