qfa.api.app#

Application factory and composition root.

Module attributes

RATE_LIMIT_RETRY_AFTER_FALLBACK_SECONDS

Used only when the provider sent no usable Retry-After header.

LLMFactory

Factory that builds an LLMPort from settings.

Functions

build_llm_client(settings)

Build an LLM client from the provided settings.

create_app(*[, llm_factory])

Create and configure the FastAPI application.

register_exception_handlers(app)

Register all exception handlers on the application.

Classes

RequestIdMiddleware(app)

Pure ASGI middleware that assigns a unique request ID to every request.

RequestLoggingMiddleware(app)

Pure ASGI middleware that logs every HTTP request.

qfa.api.app.RATE_LIMIT_RETRY_AFTER_FALLBACK_SECONDS = 30#

Used only when the provider sent no usable Retry-After header.

Not a setting (ADR-018 keeps this off an env var): ~3x the adapter’s wait_exponential(max=10) backoff cap, long enough to outlast a burst the internal retry budget already failed to ride out.

class qfa.api.app.RequestIdMiddleware(app: Callable[[MutableMapping[str, Any], Callable[[], Awaitable[MutableMapping[str, Any]]], Callable[[MutableMapping[str, Any]], Awaitable[None]]], Awaitable[None]])[source]#

Bases: object

Pure ASGI middleware that assigns a unique request ID to every request.

Generates a fresh uuid4() per request and surfaces it two ways:

  • X-Request-ID response header — canonical UUID string format.

  • scope["state"]["request_id"] — the same string, for logging, error envelopes, and downstream FastAPI dependencies. The call_scope_for() dep reads it from request.state.request_id and passes it into call_scope as request_id, so the header, logs, and llm_calls.call_id rows always share one UUID.

Parameters:

app (ASGIApp) – The wrapped ASGI application.

class qfa.api.app.RequestLoggingMiddleware(app: Callable[[MutableMapping[str, Any], Callable[[], Awaitable[MutableMapping[str, Any]]], Callable[[MutableMapping[str, Any]], Awaitable[None]]], Awaitable[None]])[source]#

Bases: object

Pure ASGI middleware that logs every HTTP request.

Logs method, path, status code, duration, request ID, and tenant name (when available). Never logs API keys or request bodies.

qfa.api.app.build_llm_client(settings: LLMSettings) LiteLLMClient[source]#

Build an LLM client from the provided settings.

Parameters:

settings (LLMSettings) – The LLM configuration settings.

Returns:

A configured LLM client instance.

Return type:

LiteLLMClient

qfa.api.app.LLMFactory#

Factory that builds an LLMPort from settings.

The default is build_llm_client (real LiteLLM client). Tests can pass their own factory to create_app to inject a fake without monkeypatching.

alias of Callable[[LLMSettings], LLMPort]

qfa.api.app.register_exception_handlers(app: FastAPI) None[source]#

Register all exception handlers on the application.

Parameters:

app (FastAPI) – The FastAPI application instance.

qfa.api.app.create_app(*, llm_factory: Callable[[LLMSettings], LLMPort] | None = None) FastAPI[source]#

Create and configure the FastAPI application.

Parameters:

llm_factory (LLMFactory | None) – Optional override for the LLM-port factory. Defaults to build_llm_client (the real LiteLLM client). Tests pass a fake factory here to inject a stubbed LLMPort without monkeypatching — the lifespan still wraps it in TrackingLLMAdapter exactly as it would the real client.

Returns:

The fully configured application instance.

Return type:

FastAPI