Environment Isolation & Verification
This runbook documents how all 6 Factory apps prevent environment mixups using layered configuration and runtime verification.The Problem: Environment Mixups
Environment mixups happen when:- Developer deploys staging code to production
- Production secrets leak into staging logs
- Staging database hits production data
- Wrong rate limiter namespace causes staging to block production users
- Hyperdrive binding connects to wrong database
The Solution: Layered Isolation
All 6 Factory apps use three layers of isolation to prevent mixups:Layer 1: Build-Time — wrangler.jsonc Isolation
Each app has a uniquewrangler.jsonc with environment-specific overrides:
WORKER_NAMEis hardcoded per environment (no typos, no .env fetch)- Hyperdrive ID is per-app (staging can’t accidentally query production DB)
- Rate limiter namespace is unique per app (staging can’t block production users)
Layer 2: Deploy-Time — GitHub Actions Environment Secrets
Each environment (production, staging) has separate GitHub Actions environment with approval gates:- Production secrets have approval gate (must explicitly authorize)
- Staging secrets cannot access production database URL
- If someone tries to deploy staging code to production, it gets staging secrets (still wrong, but caught at runtime)
Layer 3: Runtime — TypeScript Type Validation + Health Endpoint
- Any missing secret = compile error (caught in CI before deploy)
- ENVIRONMENT is literal type (only ‘staging’ | ‘production’, no typos)
/healthendpoint reveals current environment (can verify post-deploy)
Verification Workflow
After Deploy: Check /health Endpoint
Pre-Deploy: Verify wrangler env
CI/CD: Automated Environment Checks
Add this to.github/workflows/deploy.yml:
Anti-Pattern: What NOT to Do
❌ Environment Variable in wrangler.jsonc vars
❌ Optional Environment Fields
❌ Environment Variables Read from .env at Runtime
❌ Secrets in wrangler.jsonc
Isolation Checklist
Before deploying any app, verify:Configuration
-
wrangler.jsonchas"name": "{app-name}"or"{app-name}-staging"(not generic) -
WORKER_NAMEinvarsmatches the worker name (no typos) - Rate limiter
namespace_idis unique per app (1001–1006) - Hyperdrive
idis unique per app (verify in wrangler.jsonc) -
env.stagingoverrides exist:ENVIRONMENT: "staging",WORKER_NAME: "{app}-staging"
Secrets
- All required fields in
src/env.tsare non-optional - No secrets in
wrangler.jsoncvarssection - All secrets set in GitHub Actions environment secrets (not repo secrets)
- GitHub Actions workflow targets correct environment (
environment: productionorstaging)
Deployment
- Ran
wrangler deploy --dry-run --env {env}and verified worker name - Confirmed correct branch (
main= production,staging= staging branch) - Checked
/healthendpoint post-deploy to verify environment
Monitoring
- Sentry is reporting errors to correct project (staging vs. production DSN)
- PostHog is tracking events to correct workspace (staging vs. production key)
- Logs show correct
workerandenvironmentvalues
Real-World Scenario: Staging → Production Mixup
Scenario: Developer merges staging code to main by mistake. Layer 1 Protection (Build-Time):- CI/CD runs on
mainbranch wrangler deployreadswrangler.jsonc(which specifiesname: wordis-bond, notwordis-bond-staging)- Code deploys to
wordis-bond.adrper79.workers.dev(production URL) - Layer 1 failed → Staged code goes to production ❌
- GitHub Actions workflow checks
environment: production - Secrets are from production environment (correct DB, correct Sentry)
- Layer 2 passed → Code has production secrets ✓
- App starts with
c.env.ENVIRONMENT = 'production' c.env.WORKER_NAME = 'wordis-bond'/healthendpoint returnsworker: wordis-bond, environment: production- Layer 3 passed → No obvious sign of mixup ✓
- Monitor Sentry for surge in errors (staging code hitting production data)
- Check PostHog for unexpected events (staging logic in production)
- Developers immediately see via
/healththat production URL has production env
main. Fix: use branch protection rules requiring PR review.
Environment Verification Script
Add this to each app’sscripts section in package.json:
scripts/verify-env.js:
Summary
Result: Staging code can reach production, but:
- ✅ It uses production secrets (not staging)
- ✅ It’s visible at runtime (
/healthshows production env) - ✅ Errors/events flow to correct monitoring (Sentry/PostHog)
See Also
- GitHub Secrets & Tokens Runbook — Where to set environment secrets
- Deployment Runbook — How to deploy with proper environment gates
- Lessons Learned Runbook — Common environment mixup errors