Runtime & request lifecycle
What happens when the process starts, what state lives where, and the precise path of one HTTP request from socket to response model.
Runtime lifecycle
The runtime is a single FastAPI application defined in api/routes.py. Importing the module is the boot sequence, there is no separate bootstrap. The order is fixed and side-effectful:
flowchart TD A["import api.routes"] --> B["FastAPI(app) constructed"] B --> C["add CORSMiddlewareProcess startup / runtime lifecycle. Source: api/routes.py lines 43–75, 84–100, 671–1224.
(CORS_ORIGINS env, default *)"] C --> D["add _SecurityHeadersMiddleware
(nosniff · DENY · XSS · Referrer-Policy)"] D --> E["init_db()"] E --> F{"SESSION_SECRET ephemeral
AND AUTH_COOKIE_SECURE?"} F -->|yes| G["RuntimeError, refuse to start"] F -->|no| H["validate_on_startup()
print [SECURITY] warnings to stderr"] H --> I["Instantiate module-singleton engines
_evidence_engine · _compliance_engine · _risk_engine
_quality_engine · _trust_engine · _identity_engine
_passport_engine · _reputation_engine · _signal_engine
_control_center_engine"] I --> J["_registry = PersistentAgentRegistry(MemoryPersistenceStore())"] J --> K["include_router(cc · artifact · auth · org · billing · observability · security)"] K --> L["App ready, serving"]
Two security gates run at import time before any request is served:
- Production start gate (V-F3). If the session secret is ephemeral and
AUTH_COOKIE_SECUREis true (production posture), import raisesRuntimeErrorand the process refuses to start. This makes an unsafe production config a hard failure, not a warning. - Secret advisories (V-F2).
validate_on_startup()prints[SECURITY]warnings to stderr for missing/soft secrets without blocking development.
After the gates, every capability engine is constructed once as a module-level singleton. The intelligence, passport, reputation, signal and control-center engines are stateless: they hold no per-request state, so a single shared instance is safe. The one stateful object is the registry.
Runtime state & lifetimes
| State | Where | Lifetime |
|---|---|---|
| Capability engines | module singletons (_trust_engine, …) | process; stateless, no accumulation |
| Agent registry | _registry = PersistentAgentRegistry(MemoryPersistenceStore()) | process; survives requests, lost on restart |
| Per-request trust profile | AgentTrustScoreEngine() created inside the handler | one request → exactly one observation |
| Provider config | ProviderConfig.from_env() per audit call | read fresh each request; holds no secret values |
| Validation records | SQLite via repository / init_db() | persistent (legacy validation endpoints) |
AgentTrustScoreEngine per request? The score engine accumulates observations in memory. Creating it per request guarantees an evidence-derived passport reflects exactly one observation, with no cross-request bleed. The long-lived registry is the deliberate exception where cross-request accumulation is wanted.Request lifecycle
Every request traverses the same outer shell before reaching a handler, and the same serialization on the way out. Middleware is applied in reverse registration order, so the security-headers middleware wraps the response last:
sequenceDiagram
autonumber
participant C as Client
participant SH as SecurityHeaders MW
participant CORS as CORS MW
participant R as Route handler
participant P as Pydantic model
participant E as Engine(s)
C->>SH: HTTP request
SH->>CORS: forward
CORS->>R: dispatch (method + path match)
R->>P: validate request body
alt invalid body / unknown enum
P-->>C: 422 Unprocessable Entity
else valid
P->>E: typed request → engine call(s)
E-->>R: domain object(s)
R->>R: to_export_dict() → response model
R-->>CORS: response
CORS-->>SH: add CORS headers
SH-->>C: + X-Content-Type-Options / X-Frame-Options / X-XSS-Protection / Referrer-Policy
end
Request lifecycle, outer middleware shell, validation, engine composition, response. Source: api/routes.py lines 54–73, 315+.The handler body is deliberately thin: it validates, composes one or more engines, and serializes the domain object via that capability's to_export_dict(). No business logic lives in the route. The audit endpoint is the one that reaches all the way down to a provider; the assessment endpoints operate purely on a supplied evidence envelope.
CORS_ORIGINS env var (JSON array), defaulting to ["*"] for extension + dev-dashboard use; credentials are disabled; methods are limited to GET/POST/DELETE/OPTIONS. Four hardening headers are set with setdefault so a handler can override them but never lose them. See security boundaries.