FastAPI HTTP surface for the harness scaffold. Owns request handling, route registration, lifespan hooks, and the in-memory session store. Imports from src/observability/ (instrumentation), src/models/ (Pydantic contracts) — never the other way around (enforced by import-linter).
main.app— theFastAPI()instance with CORS middleware, OTel auto-instrumentation, and the v1 router mounted. Exposed foruvicorn src.api.main:appand the FastAPITestClientfixtures intests/conftest.py.main.lifespan(app)— async context manager that runssetup_tracing→setup_logging→instrument_httpx→instrument_fastapionce on startup, then constructs theSessionStore. Single point of "what is process-globally configured?"routes.router—APIRouter(prefix="/api/v1"). Every route a real client should hit lives here; un-versioned routes live onappdirectly (only the FastAPI auto-generated docs at/docsand/redocqualify).routes.health—GET /api/v1/health→HealthResponse(status +importlib.metadata.version-derived build version).routes.echo—GET /api/v1/echo?msg=...→EchoResponse. Demonstrates the request/response contract pattern that real domain endpoints follow.sessions.SessionStore— single-process in-memory dict mapping session id → conversation history. Plumbed ontoapp.state.session_storein lifespan; replace with a Redis or DB-backed implementation for multi-process deployments.
- Every route returns a
StrictModelsubclass — never a raw dict. Theextra="forbid"config makes typos and renamed fields fail at construction, not three calls deep. - Routes are versioned under
/api/v1/. Adding a v2 endpoint = a new router, never a breaking change to v1. - The CORS policy is wide-open in the scaffold so the Vite dev server proxy works on first run; tighten via config when a real auth layer arrives.