These notes describe local and production-like setup knowledge. They do not claim that this repository is production ready, externally deployed, or operating live tenants.
What this proof covers:
- Local Docker Compose dependencies, health checks, and migration verification.
- Required vs optional environment variables for a production-like local run.
- Backup and restore commands for Postgres state.
- Redis state classification and recovery guidance.
- Known limitations that would need work before production readiness.
What this proof does not cover:
- Cloud networking, TLS termination, WAF rules, VPC/firewall controls, managed Redis ACLs, managed database backups, incident response staffing, or real tenant operations.
- Provider-side per-tenant LLM credentials. Tenant spend is controlled locally
through
cost_ledger. - A production SLA. Current SLOs and load evidence are local operating targets.
| Variable | Required | Purpose | Local review value |
|---|---|---|---|
DATABASE_URL |
Required outside Compose | Per-process async Postgres URL: gdev_app for request traffic, gdev_owner only for migrations/seed/restore |
Compose injects distinct owner and app URLs; never reuse the owner URL in the agent process |
GDEV_OWNER_PASSWORD |
Required for Compose | Password for bootstrap/migration owner gdev_owner; never use for request traffic |
Local-only example in .env.example; replace outside an isolated workstation |
GDEV_APP_PASSWORD |
Required for Compose | Password for non-owner NOSUPERUSER NOBYPASSRLS request role gdev_app |
Local-only example in .env.example; replace outside an isolated workstation |
REDIS_URL |
Required outside Compose | Redis for dedup, approvals, rate limits, JWT blocklist, tenant config cache | Compose injects redis://redis:6379 |
JWT_SECRET |
Required | Signs HS256 JWTs for protected REST APIs | Use a 32+ byte random value outside demo |
WEBHOOK_SECRET_ENCRYPTION_KEY |
Required for signed webhooks | Fernet key used to decrypt per-tenant webhook HMAC secrets from Postgres | Compose uses a committed demo key only for local fixtures |
APPROVE_SECRET |
Recommended | Optional approval endpoint defense in depth in addition to JWT role checks | approve-secret in demo fixtures |
ANTHROPIC_API_KEY |
Required for LLM_MODE=live |
Live provider calls | Empty for deterministic LLM_MODE=demo |
TELEGRAM_BOT_TOKEN / TELEGRAM_APPROVAL_CHAT_ID |
Optional | Approval notifications | Empty unless testing Telegram |
GOOGLE_SHEETS_CREDENTIALS_JSON / GOOGLE_SHEETS_ID |
Optional | External audit export | Empty for local proof |
OTLP_ENDPOINT |
Optional | Trace export | Compose points to local Tempo |
Never commit real provider keys, bot tokens, approval secrets, JWT secrets, or webhook encryption keys. Rotate local demo values before any shared environment that is reachable by other people.
Use this shape for a local run that is closer to a real deployment while still remaining non-production:
APP_ENV=staging-like
LLM_MODE=demo
GDEV_OWNER_PASSWORD=$(openssl rand -hex 24)
GDEV_APP_PASSWORD=$(openssl rand -hex 24)
DATABASE_URL=postgresql+asyncpg://gdev_app:${GDEV_APP_PASSWORD}@postgres:5432/gdev
REDIS_URL=redis://redis:6379
JWT_SECRET=$(openssl rand -hex 32)
WEBHOOK_SECRET_ENCRYPTION_KEY=$(python - <<'PY'
from cryptography.fernet import Fernet
print(Fernet.generate_key().decode())
PY
)
APPROVE_SECRET=$(openssl rand -hex 24)
OTLP_ENDPOINT=http://tempo:4318/v1/tracesFor live LLM testing, set LLM_MODE=live, provide ANTHROPIC_API_KEY, and
keep tenant daily_budget_usd low. Live mode can spend real money.
The Compose migrate service runs:
alembic upgrade head
python scripts/cli.py migrations check
python scripts/seed_db.pyThat service receives the gdev_owner URL. The long-running agent service
receives only the gdev_app URL.
Manual verification against a running local stack:
docker compose exec agent python scripts/cli.py migrations check
curl -i http://localhost:8000/health
bash scripts/verify_compose_rls.sh
docker compose exec -T agent \
python scripts/demo.py --url http://localhost:8000 --llm-mode demoGET /health is application liveness only. Compose readiness additionally
depends on Postgres and Redis health checks plus successful migration
verification and seed data.
Back up the local Compose database:
mkdir -p ./backups
docker compose exec -T postgres pg_dump -U gdev_owner -d gdev \
--format=custom --file=/tmp/gdev.dump
docker compose cp postgres:/tmp/gdev.dump ./backups/gdev.dumpRestore into a fresh local database:
docker compose cp ./backups/gdev.dump postgres:/tmp/gdev.dump
docker compose exec -T postgres pg_restore -U gdev_owner -d gdev \
--clean --if-exists /tmp/gdev.dump
docker compose exec agent python scripts/cli.py migrations checkProduction would need managed backups, point-in-time recovery, encryption, restore drills, retention policy, and access controls. Those are not proven by this repository.
Redis stores ephemeral coordination state:
- Dedup cache:
{tenant_id}:dedup:{message_id}. - Pending approvals:
{tenant_id}:pending:{pending_id}. - Rate-limit counters.
- JWT blocklist entries.
- Tenant config cache.
For local recovery, prefer restarting Redis and letting TTL state rebuild. If a pending approval is lost, re-run the webhook to create a fresh pending decision rather than manually recreating Redis keys. Production would need an explicit decision on Redis persistence, ACLs, encryption, and whether pending approvals should be restored or invalidated after outage.
- The stack is local/pilot evidence, not production readiness.
- Compose secrets are visible to local Docker users and are not a secret manager.
.env.examplecontains workstation-only sample database passwords; Compose requires the environment variables and has no password fallback./metricsis JWT-exempt for Prometheus and must be network-restricted in a real deployment.GET /healthdoes not check downstream dependencies.- Redis isolation is key namespace isolation, not per-tenant Redis ACLs.
- There is no external deployment, live tenant traffic, production backup policy, or restore drill evidence.
- Read API service extraction remains open architecture debt.