Skip to content

Request Lifecycle

This page traces what happens from the moment a browser sends an HTTP request to when it receives a JSON response. Understanding this flow helps you know where to add new behavior and where to look when something breaks.

Request flow

sequenceDiagram
    participant Browser
    participant FastAPI as FastAPI (app/main.py)
    participant Router as Route module (app/api/)
    participant AuthDep as Auth dependency (app/auth/dependencies.py)
    participant Service as Domain service (app/projects/, app/auth/, etc.)
    participant Store as Storage (app/storage/)

    Browser->>FastAPI: HTTP request to /v1/...
    FastAPI->>FastAPI: CORS check, logging middleware
    FastAPI->>Router: Route matched

    alt Protected endpoint
        Router->>AuthDep: require_current_user()
        AuthDep->>AuthDep: Extract Bearer token from header
        AuthDep->>AuthDep: Validate token (custom HMAC or Cognito JWT)
        AuthDep-->>Router: CurrentUser object
    end

    Router->>Service: Call domain service method
    Service->>Store: Read or write data (Postgres / S3 / JSON)
    Store-->>Service: Result
    Service-->>Router: Domain object or error
    Router-->>Browser: JSON response (200) or error envelope (4xx/5xx)

Key files

  • app/main.py — Creates the FastAPI app, sets up CORS, attaches the JSON logging middleware, and mounts the API router. Also registers startup/shutdown hooks for Codex container cleanup.
  • app/api/routes.py — Imports every route module and includes them under /v1. This is where you'd add a new route group.
  • app/auth/dependencies.py — Provides the require_current_user FastAPI dependency. Route handlers declare this as a parameter to require authentication.
  • app/core/settings.py — Loaded at startup. Every configuration decision (auth mode, storage backend, etc.) traces back here.
  • app/core/errors.py — Defines api_error(), the helper that produces the structured error envelope every route should use for failures.

Authentication

Every protected route declares a dependency on require_current_user. This dependency:

  1. Reads the Authorization: Bearer <token> header
  2. In custom auth mode: validates an HMAC-signed local token
  3. In cognito auth mode: fetches the Cognito JWKS and validates the JWT signature + claims

If the token is missing or invalid, FastAPI returns 401 before the route handler runs.

Some routes additionally require a specific user group (e.g., operator or root). Group checks happen inside the dependency.

Error shape

All errors, regardless of where they occur, return the same JSON envelope:

{
  "schema_version": 1,
  "error": {
    "code": "not_found",
    "message": "Repository abc123 not found",
    "retryable": false,
    "details": {}
  }
}
  • code is a stable machine-readable string (use it for branching in frontend code)
  • message is human-readable (show it in the UI)
  • retryable tells the client whether a retry makes sense (e.g., true for transient errors)
  • details is optional structured context (e.g., which field failed validation)

Debugging a failed request

Start with the most external check and work inward:

  1. Did the request reach FastAPI? Check the API logs for the request line.
  2. Did auth fail? A 401 with invalid_token code means the token is bad or missing. A 403 means the user lacks the required group.
  3. Did the route handler fail? Look for 5xx errors and the error code in the response.
  4. Did a downstream service fail? Check Postgres, S3, SQS, or Cognito. In AWS, check CloudWatch logs.