Environments & Infrastructure
Three environments — Dev, Test, Prod (plus local). Each maps to a branch in both repos. Verified against commit history on 2026-06-24.
| Environment | Frontend — branch → host | Backend — branch → API | LangGraph |
|---|---|---|---|
| Dev | dev → dev.consumr.ai |
dev → dev-api.consumr.ai |
pw-dev-maven |
| Test | test → test.consumr.ai |
test → test-api.consumr.ai |
pw-dev-maven |
| Prod | main → app.consumr.ai |
app → app-api.consumr.ai (api.consumr.ai = legacy) |
pw-prod-maven |
| Local | feature branch → localhost | dev-api / 127.0.0.1:5001 | pw-dev-maven |
📎 Evidence
- Dev FE branch is
dev—pw-enterprise-frontendgit —git branch -ashowsremotes/origin/dev; aDevworkflow exists in.github/workflows/dev.yml. ✅ - Dev FE host
dev.consumr.ai—pw-enterprise-frontend/src/api/config.js:144-152— hostname branch setsurl = dev,environment = 'dev'. ✅ - Dev BE branch is
dev—pw-enterprisegit —remotes/origin/devexists; backend.github/workflows/dev.ymlnameddev. ✅ - Dev BE API
dev-api.consumr.ai—pw-enterprise-frontend/src/api/config.js:18—const dev = 'https://dev-api.consumr.ai'assigned when hostname isdev.consumr.ai. ✅ - Dev LangGraph
pw-dev-maven—pw-enterprise-frontend/src/api/config.js:31andpw-enterprise/api/product_health.py:55-58— both mapdevto thepw-dev-mavendeployment URL. ✅ - Test FE branch is
test—pw-enterprise-frontendgit —git branch -ashowsremotes/origin/testexists. (Finder wrongly marked this unverifiable; the branch IS present.) ✅ - Test FE host
test.consumr.ai—pw-enterprise-frontend/src/api/config.js:135-143— hostname branch setsurl = test,environment = 'test'. ✅ - Test BE branch is
test—pw-enterprisegit —remotes/origin/testexists. Note.github/workflows/test.ymlis an API-test workflow targetingalpha, NOT a test-env deploy. ✅ - Test BE API
test-api.consumr.ai—pw-enterprise-frontend/src/api/config.js:19,136—const test = 'https://test-api.consumr.ai'assigned when hostname istest.consumr.ai. ✅ - Test LangGraph
pw-dev-maven—pw-enterprise-frontend/src/api/config.js:142-143— undertest.consumr.ai,langgraphDeployment = 'dev'andlangraphUrl = langgraphDevUrl. ✅ - Prod FE branch is
main—pw-enterprise-frontendgit —git symbolic-ref refs/remotes/origin/HEAD=refs/remotes/origin/main;Mainworkflow runsmain-action.sh. ✅ - Prod FE host
app.consumr.ai—pw-enterprise-frontend/src/api/config.js:127-134— hostname branch setsurl = app,environment = 'app'. ✅ - Prod BE branch is
app—pw-enterprisegit —git symbolic-ref refs/remotes/origin/HEAD=refs/remotes/origin/app; local* app. ✅ - Prod BE API
app-api.consumr.ai—pw-enterprise-frontend/src/api/config.js:17,129—const app = 'https://app-api.consumr.ai'assigned underapp.consumr.ai. ✅ api.consumr.aiis legacy (not active) —pw-enterprise-frontend/src/api/config.js:15declaresconst api = 'https://api.consumr.ai'but no hostname branch assigns it tourl; active prod isapp-api.consumr.ai. Table now marks it legacy. ✅- Prod LangGraph
pw-prod-maven—pw-enterprise-frontend/src/api/config.js:32andpw-enterprise/api/product_health.py:55-57— both mapappto thepw-prod-mavenURL. ✅ - Local FE = feature branch → localhost —
pw-enterprise-frontend/src/api/config.js:103-125— code routeslocalhost/local.consumr.aihostnames; the ‘feature branch’ part is convention, not code-enforced. ⚠️ - Local BE = dev-api / 127.0.0.1:5001 —
pw-enterprise-frontend/src/api/config.js:104,118—local.consumr.aidefaults to127.0.0.1:5001(viaVITE_API_URL); plainlocalhostsetsurl = dev. ✅ - Local LangGraph
pw-dev-maven—pw-enterprise-frontend/src/api/config.js:124-125—localhostsetslanggraphDeployment = 'dev',langraphUrl = langgraphDevUrl. ✅
- Promotion flow:
dev → test → prod(visible in git history —testis fed by merges fromdev). - Environment selection: the frontend resolves its environment at runtime by hostname (
src/api/config.js), not a build flag. - Deploys: manual — GitHub Actions
workflow_dispatchon a self-hosted runner running shell scripts (dev-action.sh/main-action.shfor FE;pw-enterprise-dev-server.sh/pw-enterprise-main-server.shfor BE). The frontend dev deploy also purges the Cloudflare cache (the prodmain.ymlhas no purge job).
📎 Evidence
- Promotion
dev → test → prod—pw-enterprisegit merge log ontest— shows merges ofappINTOtestand PRs#9841 (I5216)etc.; a literalmerge dev into testwas not seen. Flow is convention-supported, not a hard pipeline. ⚠️ - Env resolved at runtime by hostname —
pw-enterprise-frontend/src/api/config.js:4,103-160— readswindow.location.hostnamethen if/else-if chain sets url/env/langgraph; onlyVITE_API_URLoverrides local URL. ✅ - Manual deploys via
workflow_dispatch—pw-enterprise/.github/workflows/dev.yml:2,Main.yml:3-4,pw-enterprise-frontend/.github/workflows/dev.yml:2,main.yml:2— all useon: workflow_dispatch. ✅ - Self-hosted runner —
pw-enterprise/.github/workflows/dev.yml:9&Main.yml:8,pw-enterprise-frontend/.github/workflows/dev.yml:9&main.yml:9— all jobs declareruns-on: self-hosted. ✅ - FE dev deploy runs
dev-action.sh—pw-enterprise-frontend/.github/workflows/dev.yml:11-15—cd /home/coder/rushab/; time ./dev-action.sh. Script lives on the runner, not in repo. ✅ - FE prod deploy runs
main-action.sh—pw-enterprise-frontend/.github/workflows/main.yml:11-15—cd /home/coder/rushab/; time ./main-action.sh. ✅ - BE dev deploy runs
pw-enterprise-dev-server.sh—pw-enterprise/.github/workflows/dev.yml:11-15—cd /home/coder/rushab/; time ./pw-enterprise-dev-server.sh. ✅ - BE prod deploy runs
pw-enterprise-main-server.sh—pw-enterprise/.github/workflows/Main.yml:10-14—cd /home/coder/rushab/; time ./pw-enterprise-main-server.sh. ✅ - FE cache purge is dev-only —
pw-enterprise-frontend/.github/workflows/dev.yml:18-26runspurge_profitwheel_cache.shafter deploy;main.yml(prod) has no purge job. Doc now scopes this to dev. ✅
📎 Evidence
- Stale
productionbranch exists (BE) —pw-enterprisegit —git branch -alistsremotes/origin/production. ✅ productionlast commit April 2024 —pw-enterprisegit —git log -1 remotes/origin/production=2024-04-11 17:51:49‘Added tracing for answer engine’. ✅- Real prod branch is
app(default) —pw-enterprisegit —git symbolic-ref refs/remotes/origin/HEAD=refs/remotes/origin/app; local checkout shows* app. ✅
Cloud Inventory
Section titled “Cloud Inventory”Known providers: GCP (Secret Manager, BigQuery), Azure (Key Vault — legacy), Cloudflare (Pages, Workers; Worker edge bindings: AI, Vectorize ×3, Hyperdrive). Cloudflare R2 is used for object storage server-side (boto3), not as a Worker binding.
📎 Evidence
- GCP Secret Manager (primary) —
pw-enterprise/library/gcp_secrets.py:1-18&pyproject.toml:101— importsgoogle.cloud.secretmanager; SDKgoogle-cloud-secret-manager>=2.26.0declared (line 101, not 100). ✅ - GCP BigQuery —
pw-enterprise/api/common.py:4,11&pyproject.toml:100—from google.cloud import bigquery;client = bigquery.Client(); SDKgoogle-cloud-bigquery>=3.39.0declared. ✅ - Azure Key Vault is legacy —
pw-enterprise/library/gcp_secrets.py:3-5(docstring ‘replacing Azure Key Vault’),library/secrets.py:109-116(*_key_vaultfns delegate to GCP),pyproject.toml:27-28,.env:91-93(AZURE_*keys empty). ✅ - Cloudflare Pages (FE hosting) —
pw-enterprise-frontend/wrangler.toml:3—pages_build_output_dir = "dist"is the Cloudflare Pages config key. ✅ - Cloudflare Workers —
pw-enterprise-frontend/src/api/config.js:13(a*.profitwheel.workers.devworker URL) &pw-enterprise/pyproject.toml:31(cloudflare>=4.3.1SDK). ✅ - Workers AI binding —
pw-enterprise-frontend/wrangler.toml:13-14,22-23—[ai] binding = "AI"for both default and[env.production]. ✅ - Vectorize binding (×3 indices) —
pw-enterprise-frontend/functions/_middleware.ts:11-13andworker-configuration.d.ts:9-11declareVECTORIZE_INDEX_SMALL/BASE/LARGE: VectorizeIndexin the WorkerEnv; configured via the Pages dashboard (onlyAIis declared inwrangler.toml), which is whywrangler.tomlalone doesn’t list it. ✅ - Hyperdrive binding —
pw-enterprise-frontend/functions/_middleware.ts:14(PRODDB: Hyperdrive) andworker-configuration.d.ts:12(DEVDB: Hyperdrive) declare it in the WorkerEnv; configured via the Pages dashboard, notwrangler.toml. ✅ - Cloudflare R2 (object storage, server-side) —
pw-enterprise/library/storage.py:1-7,32-37builds a boto3 S3 client against*.r2.cloudflarestorage.com;.env:144-148define the R2 keys. Used server-side, not as a Worker edge binding. ✅
📎 Evidence
- Cloud inventory pending note —
pw-docs/src/content/docs/environments-infrastructure.mdx:28-31— self-describing status note in the doc; not a factual system claim. 🔍 needs: cloud-account access to enumerate full per-provider inventory. ✅