Production N.E.S.T.
nest.thephenom.app is the production N.E.S.T. surface, served by the phenom-backend-prod Cloudflare Pages project + the nest-api-prod Cloudflare Worker, built against the real production infrastructure in phenom-infra/environments/production/ (api.thephenom.app + phenom-prod Cognito pool + phenom-prod-media-storage).TL;DR. Two N.E.S.T. surfaces today — nest.thephenom.app (production, this page) and nest-firebase.thephenom.app (frozen pre-migration snapshot, see firebase-main snapshot). The nest-prod.thephenom.app parallel URL was retired on 2026-05-16 when its backing stack was merged into nest.thephenom.app. dev-nest.thephenom.app exists for the develop branch; see the dev-nest section in Infrastructure.
Topology
graph LR
Branch(["github.com/Phenom-earth/phenom-backend<br/>branch: main"])
Pages(["CF Pages<br/>phenom-backend-prod"])
Worker(["CF Worker<br/>nest-api-prod"])
Domain(["nest.thephenom.app"])
Cognito(["AWS Cognito<br/>phenom-prod<br/>us-east-1_knEL7cqS3"])
Hasura(["Hasura GraphQL<br/>api.thephenom.app"])
Bucket(["S3<br/>phenom-prod-media-storage"])
Lambdas(["Cognito triggers<br/>phenom-prod-hasura-cognito-trigger<br/>phenom-prod-hasura-cognito-sync-users"])
Branch -->|"push triggers layer-3 jobs"| Pages
Branch -->|"push triggers layer-3 jobs"| Worker
Domain -->|"DNS proxied CNAME → phenom-backend-prod.pages.dev"| Pages
Domain -->|"routes /api/* + /health"| Worker
Worker -->|"Bearer JWT (verified against Cognito JWKS)"| Hasura
Worker -->|"AWS SigV4 presigned GETs"| Bucket
Worker -.->|"JWT issuer validation"| Cognito
Cognito -->|"pre-token / post-auth / post-confirm"| Lambdas
Lambdas -->|"GraphQL mutations via aws_lb.main"| HasuraResource map
| Surface | Resource | Notes |
|---|---|---|
| Branch | main on Phenom-earth/phenom-backend | Pushes trigger layer-3-deploy-worker-prod + layer-3-deploy-pages-prod in .github/workflows/nest-ci.yml. |
| Pages project | phenom-backend-prod (production_branch = main) | Custom domain: nest.thephenom.app. Subdomain: phenom-backend-prod.pages.dev. |
| Worker script | nest-api-prod | Deployed via wrangler deploy --env production from admin_sandbox/nest-api/wrangler.toml’s [env.production] block. |
| Worker routes | nest.thephenom.app/api/*, nest.thephenom.app/health → nest-api-prod | Bound via Cloudflare API. |
| DNS | CNAME nest.thephenom.app → phenom-backend-prod.pages.dev, proxied | Managed via Cloudflare API (NOT in TF yet — follow-up). |
| CF Access | none | The React app’s own Cognito sign-in is the sole auth gate. No Cloudflare Access app in front. |
| Cognito pool | us-east-1_knEL7cqS3 (phenom-prod), client 8uun49ru7f3fdvmlc12vqig3a | Managed in phenom-infra/environments/production/cognito.tf. |
| Hasura | api.thephenom.app/v1/graphql (ALB → phenom-prod-graphql ECS service) | Managed in phenom-infra/environments/production/. |
| Cognito triggers | phenom-prod-hasura-cognito-trigger (JWT-claim shaper) + phenom-prod-hasura-cognito-sync-users (writes user rows to prod Hasura via aws_lb.main) | Managed in phenom-infra/environments/production/cognito.tf. |
| Media bucket | phenom-prod-media-storage | Worker signs presigned GETs against this bucket. nest-api-prod’s IAM principal is phenom-nest-api-prod-s3 (managed in phenom-infra/environments/production/nest-api-media.tf). |
Cognito → SES via noreply@thephenom.app | Set in phenom-infra/environments/production/cognito.tf. See Cognito Email via SES. |
CI deploy jobs
Pushes to main trigger two parallel jobs after the Layer 1 + 2 gates pass:
layer-3-deploy-worker-prod—wrangler deploy --env productionfromadmin_sandbox/nest-api/. Re-deploys thenest-api-prodWorker.layer-3-deploy-pages-prod—vite buildfromadmin_sandbox/phenom/with hardcoded prod env vars (VITE_HASURA_GRAPHQL_URL=https://api.thephenom.app/v1/graphql,VITE_COGNITO_USER_POOL_ID=us-east-1_knEL7cqS3,VITE_COGNITO_CLIENT_ID=8uun49ru7f3fdvmlc12vqig3a,VITE_CHAT_SERVER_URL=https://chat.thephenom.app), thenwrangler pages deploy dist --project-name=phenom-backend-prod --branch=main.
Both jobs gate on github.ref == 'refs/heads/main'.
Why prod Cognito IDs are hardcoded in CI, not GH secrets
The Cognito pool ID and public client ID are not secrets — they’re addressable identifiers that end up in the bundled JS regardless. Hardcoding them in the workflow makes the configuration self-documenting and avoids the “wait, which env’s secret is this set to?” confusion the staging path has historically had. If you ever want to flip the pool, change the literal in the workflow + open a PR.
Worker secrets (write-only, not in TF)
nest-api-prod’s four write-only Worker secrets:
| Secret | Source |
|---|---|
AWS_ACCESS_KEY_ID | Access key on aws_iam_user.nest_api_prod_s3 (managed in phenom-infra/environments/production/nest-api-media.tf) — scoped to phenom-prod-media-storage only. |
AWS_SECRET_ACCESS_KEY | (same) |
CF_ACCESS_DOCS_CLIENT_ID | CF Access service token “nest-prod docs proxy” — authorized on the int-docs Access policy. |
CF_ACCESS_DOCS_CLIENT_SECRET | (same) |
To rotate: regenerate the underlying credential (IAM access key or CF Access service token), then bunx wrangler secret put <NAME> --name nest-api-prod from admin_sandbox/nest-api/.
Cognito Lambda triggers — where they write
phenom-prod-hasura-cognito-sync-users runs on post_authentication and post_confirmation. Its env: GRAPHQL_DOMAIN = aws_lb.main.dns_name (the prod ALB internal DNS, routing inside the VPC straight to the phenom-prod-graphql ECS service) + SECRETS_ARN = aws_secretsmanager_secret.app_secrets.arn (the prod admin-secret bag). So writes from the Lambda land in phenom-prod-postgres via the prod Hasura instance — not in staging.
phenom-prod-hasura-cognito-trigger runs on pre_token_generation and is purely a JWT-claim shaper — no env, no Hasura call.
Both Lambdas are wired only to aws_cognito_user_pool.main (the prod pool) via aws_lambda_permission — the staging pool’s Lambdas live in a separate environment and cannot invoke these.
Retired surfaces (historical)
nest-prod.thephenom.app(2026-05-14 → 2026-05-16): parallel-deploy URL used to verify the prod-infra build before pointing user traffic at it. Custom domain, DNS, Worker routes, and CF Access app deleted on 2026-05-16. The backing Pages project (phenom-backend-prod) and Worker (nest-api-prod) were kept and re-pointed atnest.thephenom.app.- The legacy
phenom-backendPages project (staging-backed) lost its custom domain on 2026-05-16. The project itself is orphaned and pending deletion — blocked on a deployments-cleanup pass.
Related
- firebase-main holding URL — the frozen pre-migration snapshot.
- Infrastructure — current production topology overview.
- Cognito Email via SES — email delivery setup shared across all three pools.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.