Skip to content

Runbook: Route the Dashboard Through API Gateway (HTTP)

Owner: backend infra (Grenguar / Igor) Branch: feat/api-gw-frontend-ingress (off dev) PR scope: introduce API Gateway as the frontend's HTTP path. No breaking change — the ALB stays publicly reachable. No DNS flip, no cert work, no SG lockdown in this PR.

WebSocket support lives in the stacked follow-up feat/api-gw-websocket.

What this PR does

  1. Adds dashboard_alias_middleware to the backend FastAPI app (services/backend/src/tradai/backend/api/dashboard_aliases.py). It rewrites the dashboard's unversioned paths (/api/catalog/*, /api/experiments, /api/runs/*) to their /api/v1/* equivalents before routing.
  2. Extends API_ROUTES in infra/shared/tradai_infra_shared/config.py with the same unversioned paths so the existing API Gateway HTTP API (infra/edge/__main__.py) accepts and proxies them.
  3. Adds a pytest smoke suite that hits the dev API Gateway execute-api URL with a Cognito M2M client_credentials token (tests/e2e/test_api_gateway_smoke.py).

What this PR does not touch (deferred): - infra/edge/Pulumi.dev.yamlapi_domain / certificate_arn stay unset. The frontend will use the auto-generated <api_id>.execute-api… URL. - ALB security-group lockdown. - WAF re-association. - Squarespace DNS. - The legacy api-dev.tradai-system.com CNAME → ALB path. It stays live as the rollback path.

Current ⇄ target state (with this PR)

Today                                      With this PR
─────                                      ────────────
Browser → api-dev.tradai-system.com        Browser → <api_id>.execute-api…  ← NEW PATH
        → ALB (SG 0.0.0.0/0:443)                   → API GW (Cognito JWT)
        → FastAPI (JWT in app)                     → VPC Link → ALB → FastAPI
                                                                       (alias middleware
                                                                        rewrites /api/* → /api/v1/*)

                                           Browser → api-dev.tradai-system.com  ← unchanged rollback
                                                   → ALB → FastAPI

How to verify

  1. Deploy the edge stack: just infra-up-edge dev.
  2. Fetch an M2M token:
    curl -s -X POST \
      "https://tradai-dev.auth.eu-central-1.amazoncognito.com/oauth2/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -u "$M2M_CLIENT_ID:$M2M_CLIENT_SECRET" \
      -d "grant_type=client_credentials&scope=tradai-api/read tradai-api/write tradai-api/admin"
    
  3. Run the smoke suite:
    TRADAI_E2E_BASE_URL=https://<api_id>.execute-api.eu-central-1.amazonaws.com \
    TRADAI_M2M_CLIENT_ID=... \
    TRADAI_M2M_CLIENT_SECRET=... \
    just test-suite e2e -k api_gateway_smoke
    
  4. Manual: curl -H "Authorization: Bearer $TOKEN" "$TRADAI_E2E_BASE_URL/api/catalog/strategies" returns 200.
  5. Regression: curl https://api-dev.tradai-system.com/api/v1/health still returns 200 (ALB path intact).

Follow-ups, not in this PR

  • feat/api-gw-websocket (stacked PR) — add a WebSocket API for wss://.
  • Custom domain apigw-dev.tradai-system.com (cert + DomainName + ApiMapping + Squarespace CNAME).
  • Lock ALB SG to VPC-Link SG only.
  • Wire M2M_CLIENT_SECRET retrieval to Secrets Manager in CI.
  • Rotate the M2M client secret in Cognito (the previous value was leaked in a chat log; the new value should live only in Secrets Manager — see [TODO: secrets_manager_arn_for_m2m_secret]). Do NOT inline secret values in this runbook; reference the Secrets Manager ARN instead.

Interactions with in-flight PRs

  • #516 (prod hardening) — touches the same disable_execute_api_endpoint line in infra/edge/modules/api_gateway.py and the WAF wiring in infra/edge/__main__.py. On rebase, those two hunks need to be dropped (the conditional landed in 79aebef1 on dev already). Self-coordinated (Grenguar).
  • #600 / #596–#599 (v4 prod chain) — orthogonal.
  • #617 (this branch's predecessor, runbook docs) — supersede; close after merge.

Frontend (tradai-bot/tradai-dashboard) — separate PR

In the dashboard repo, set the Amplify-deployed env var to the API Gateway URL (or to a Squarespace CNAME pointing at API GW once domain work lands). Today the single value to change is VITE_API_BASE_URL.