Quantago Dev Environment
Isolated dev stack for active coding & testing. Provisioned 2026-04-28.
URLs
| Surface | Prod | Dev |
|---|---|---|
| Frontend | https://app.quantago.co | https://dev.quantago.co |
| API | https://api.quantago.co | https://dev-api.quantago.co |
| Pages | quantago-app.pages.dev | quantago-dev-app.pages.dev |
| Worker | quantago-api | quantago-dev-api |
| Database | Neon ep-patient-glade-akbt9n8k | Neon ep-calm-truth-ak38uzzc (project quantago-dev, id flat-bonus-34310933) |
Login (dev)
- email:
[email protected] - password:
QuantagoDev!1b5c2b5c(from the provisioning secret blob) - role:
admin
What is isolated
- Database — separate Neon project, separate
neondbschema, ran all 12 migrations cleanly. - Worker —
quantago-dev-apiis a distinct Worker script. Separate Durable Objects, separate Workflows (named*-dev). - Auth — fresh
BETTER_AUTH_SECRET, freshINGESTION_ADMIN_SECRET. Sessions don't cross between envs. - Cron — disabled on dev (
triggers.crons = []) so dev never auto-mutates ClickHouse / Finnhub. - Pages project —
quantago-dev-app, separate deploys from prod.
What is shared (intentional)
- 3rd-party API keys: Google OAuth, cTrader, Alpaca, Finnhub, Twelve Data — these are vendor-side credentials, no risk in sharing read-only or sandbox keys.
- Cloudflare account, R2 buckets (none configured yet), AI binding.
How dev was provisioned
- Neon project created via REST:
POST https://console.neon.tech/api/v2/projectswith orgorg-frosty-salad-83675640. Returned projectflat-bonus-34310933. - Migrations applied:
DATABASE_URL=<dev pooler> bash scripts/migrate-neon.sh. - Wrangler
[env.dev]block added toservices/backend/wrangler.jsonc— duplicates the workflows / DOs / migrations / AI bindings under the new namequantago-dev-api, overridesvarswith dev URLs andENABLE_DEFAULT_ADMIN_SEED=true, disables cron. - First deploy:
wrangler deploy --env dev(creates the Worker). - Secrets:
bash scripts/provision-dev-env.sh secretsgenerates fresh BETTER_AUTH_SECRET + INGESTION_ADMIN_SECRET, setsDATABASE_URL=<dev>,PROD_DATABASE_URL=<prod>, copies vendor API keys, uploads viawrangler secret bulk. - Custom domain for dev API:
bash scripts/provision-dev-env.sh dnscalls the Workers Custom Domains API. Uses the legacy CF global key for the DNS CNAME because the scoped API token doesn't have Zone:DNS:Edit. - Dev Pages project:
wrangler pages project create quantago-dev-app, then build withVITE_API_URL=https://dev-api.quantago.coandwrangler pages deploy dist. - Pages custom domain:
dev.quantago.coCNAME →quantago-dev-app.pages.dev, plusPOST /pages/projects/quantago-dev-app/domainsto bind it.
Re-provisioning / refreshing dev
cd projects/quantago
# Push secrets only (idempotent)
bash scripts/provision-dev-env.sh secrets
# Push DNS / domain bindings only (idempotent)
bash scripts/provision-dev-env.sh dns
# Both
bash scripts/provision-dev-env.sh all
Deploying
# Backend dev
cd services/backend
pnpm exec wrangler deploy --env dev
# Frontend dev
cd ../..
VITE_API_URL=https://dev-api.quantago.co \
pnpm --filter @quantago/frontend build
cd services/frontend
pnpm exec wrangler pages deploy dist \
--project-name=quantago-dev-app \
--branch=main --commit-dirty=true
Frontend API target switcher
The dev frontend renders a small env selector in the header (only on dev.quantago.co and localhost). Choices:
auto— uses dev API ondev.*host, local API on localhostdev— forcehttps://dev-api.quantago.coprod— forcehttps://api.quantago.co(⚠ red banner — talks to prod data)local— forcehttp://localhost:8787
Selection is persisted in localStorage['quantago.apiTarget'] and triggers a reload.
Known follow-up
- Per-request prod-DB override (an admin-only header
X-Db-Override: prodon the dev backend that swapsDATABASE_URLfor one request) is not yet implemented. ThePROD_DATABASE_URLsecret andALLOW_PROD_DB_DEBUGvar are already provisioned on the dev worker so it can be added in a follow-up without re-provisioning. For now use the frontend "prod API" target switcher to talk to the prod backend instead. - Pulumi:
Pulumi.dev.yamlis not yet authored. Today the dev env is encoded inwrangler.jsonc[env.dev]and the provisioning script. Promoting that to Pulumi is a follow-up. - Admin pages project for dev (
dev-admin.quantago.co) — referenced invars.ADMIN_ORIGINbut not deployed. - Admin password rotation — current value
QuantagoDev!1b5c2b5cwas generated by the script. To rotate, editscripts/.dev-env.localto setDEV_ADMIN_PASSWORD=...and re-runprovision-dev-env.sh secrets, then update theuserrow directly via psql or use the Better Auth password change flow.
Files added/changed
services/backend/wrangler.jsonc—env.devblock.services/backend/src/auth/auth-env.ts— addeddev.quantago.coandquantago-dev-app.pages.devto allowed origins.services/frontend/src/lib/runtime-config/index.ts— runtime API target switcher +dev.<domain>→dev-api.<domain>host inference.services/frontend/src/components/layout/header/DevApiTargetSwitcher.tsx— new component.services/frontend/src/components/layout/header/Header.tsx— mounts the switcher.scripts/provision-dev-env.sh— secrets bulk-upload + DNS/domain binding.scripts/.dev-env.local— gitignored local override (DEV_DATABASE_URL)..gitignore— ignoresscripts/.dev-env.local.