Alpha. Vary is under active development and not ready for production use. Syntax, APIs, performance, and behaviour may change between releases.
api_context
import api_context carries the typed request metadata that handler
bindings declare as parameter types. The compiler decodes route
metadata, the request ID, the idempotency key, and the verified identity
once at the boundary; handlers see a single RequestContext value.
Mental model
The boundary fills RequestContext once per request, before the handler
runs. The Vary HTTP runtime owns parsing, session validation, CSRF, and
API token verification, so handler code never re-parses headers or
re-validates tokens. A handler that needs to branch on the caller reads
fields and helper results from the context.
import api_context
def handle_request(request: ListIssuesQuery, ctx: RequestContext) -> Str {
if ctx.auth_kind == RequestAuthKind.OPTIONAL and ctx.auth_verified {
return list_for_authenticated(ctx, request)
}
return list_for_anonymous(request)
}
Route metadata
Every context carries a RequestRouteMetadata describing the route the
boundary matched:
| Field | Meaning |
|---|---|
operation_id | Stable id in OpenAPI and the route manifest. |
method | HTTP verb. |
path | Route path template (e.g. /api/v1/issues/{id}). |
auth_kind | DEFAULT, NONE, OPTIONAL, SESSION, or CAPABILITY. |
cache | RequestCachePolicy with public/private cache hints. |
field_policy | Projection name from fields public ..., if any. |
request_route_metadata(...) and the cache helpers (request_cache_public,
request_cache_private_no_store, request_cache_default) construct these
values in tests and in code that needs to build a context manually.
Request identity
| Field | When set |
|---|---|
request_id: RequestId | Always; falls back to "req_unavailable". |
idempotency_key: Str? | Present for idempotent routes with the header. |
remote_address: Str?, user_agent: Str? | When the runtime exposes transport metadata. |
required_idempotency_key(ctx) returns Result[IdempotencyKey, ApiBoundaryError]
for mutation handlers that must refuse replays missing the header.
Verified authentication
For auth optional, auth session, and auth capability routes, the
runtime fills the verified identity fields after passing the boundary's
auth gates:
| Field | Meaning |
|---|---|
auth_verified: Bool | Session, JWT, or API token was verified. |
csrf_verified: Bool | The configured CSRF policy was satisfied. |
principal_id: Str? | Stable internal user id. |
subject: Str? | OIDC/JWT sub. |
issuer: Str? | OIDC/JWT iss. |
session_id: Str? | Session row id (set when using a session cookie). |
api_token_id: Str? | Hashed token id, when the request used a bearer token. |
roles: List[Str] | Roles attached to the verified identity. |
capabilities: CapabilitySet | Capabilities from the JWT/OIDC claim path. |
Helpers
import api_context
let actor = api_context.authenticated_user(ctx)?
api_context.require_csrf(ctx)?
api_context.required_capability(ctx, "issues.write")?
let viewer = api_context.optional_user(ctx)
let read_only = api_context.has_capability(ctx, "issues.read")
| Helper | Return type | Notes |
|---|---|---|
optional_user(ctx) | RequestUserId? | None for anonymous auth optional calls. |
authenticated_user(ctx) | Result[RequestUserId, ApiBoundaryError] | auth_failure if session missing or unverified. |
authenticated_user_id(ctx) | Result[Str, ApiBoundaryError] | Same gate; returns the bare id for log fields. |
has_capability(ctx, name) | Bool | Also requires auth_verified. |
required_capability(ctx, name) | Result[None, ApiBoundaryError] | Fails with capability_required. |
request_capabilities(ctx) | List[Str] | Full verified capability list for policies or audit. |
require_csrf(ctx) | Result[None, ApiBoundaryError] | csrf_required when csrf_verified is false. |
See also
| Topic | Where |
|---|---|
| Production auth configuration | Public API security |
| Handler context | Public JSON APIs |
| Route auth clauses | HTTP services |