# 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).