Authorization¶
A11 carries signed delegation statements to an application verifier, then
reuses the verified result within one session stream. The runtime owns the
canonical envelope, bounded context storage, propagation, and request
restrictions. The application owns signature verification, trust policy, and
the claims placed in VerifiedAuthorization.
Authorization envelope¶
AuthorizationEnvelope contains a version and an ordered chain of compact JWS
statements. A11 validates its structural limits:
- version
1; - one to eight ASCII compact JWS statements;
- at most 16 KiB after canonical MessagePack encoding.
encode_authorization() and decode_authorization() use the native binary
form carried by action headers. authorization_to_text() and
authorization_from_text() use the a11-auth/1. base64url form required by an
ASCII HTTP header. The fingerprint is the base64url SHA-256 digest of the
canonical envelope.
Structural decoding does not verify JWS signatures. A verifier returns
VerifiedAuthorization only after applying the application's keys, audience,
expiry, and delegation policy.
Connection authorization¶
install_authorizer(registry, verifier) registers the reserved
__authorize__ action and applies its context store to the registry. Other
incoming actions must then resolve a valid context before their handler runs.
The verifier accepts the native envelope bytes and returns the effective identity and authority:
import time
import a11
async def verify(value: bytes) -> a11.VerifiedAuthorization:
envelope = a11.decode_authorization(value)
claims = await trust_policy.verify(envelope.chain)
return a11.VerifiedAuthorization(
envelope=envelope,
subject=claims.subject,
subject_kind=claims.subject_kind,
actors=claims.actors,
audience=claims.audience,
expires_at=claims.expires_at,
grants=claims.grants,
restrictions=claims.restrictions,
)
contexts = a11.install_authorizer(registry, verify)
The verifier may be synchronous or asynchronous. An expired result is rejected when the context is installed.
The client sends the complete proof once:
The receiver returns a random 128-bit context ID, expiry, envelope fingerprint, and default flag. A default context applies to later actions on the same session stream without another authorization header. A non-default context is selected explicitly:
context = await a11.establish_authorization(
connection,
envelope,
make_default=False,
)
action = connection.action("restricted-operation", schema)
a11.set_authorization_reference(action, context.context_id)
await action.call()
Contexts are scoped to the receiving Session and WireStream. They do not
cross a new connection or another stream. Expired entries are pruned, each
stream has a bounded context set, and session completion clears its entries.
replace= rotates a context while keeping installation and removal in one
receiver operation.
Request restrictions¶
The context store enforces supported restrictions before dispatching an
incoming action:
| Field | Constraint |
|---|---|
actions |
Action name must match one of the * and ? glob patterns |
identities |
Verified audience must appear in the list |
request_id |
Action ID must equal the bound request ID |
The verifier defines the restrictions after validating the delegation chain.
Malformed restrictions fail closed with PERMISSION_DENIED.
Per-action verification¶
Applications that do not install a connection authorizer can carry and verify a complete proof on one action:
The receiving handler calls
verify_action_authorization(action, verifier) before reading the resulting
get_verified_authorization(action) value. A complete proof and a context
reference are mutually exclusive headers.
Nested actions with I/O propagation inherit the immutable verified
authorization object. Detached children created with propagate_io=False do
not inherit connection authority. Raw context references are scoped to their
original stream and are excluded from generic header forwarding.
Authorization and model tool policy¶
Connection authorization establishes caller identity and effective authority for action dispatch. The LLM allowed-action header selects tools offered to a model for one turn. Applications using both enforce the connection context at the registry and apply the model allow-list inside the interaction action.
a11.authorization
¶
Exchange verified authorization once and reuse it on an A11 connection.
AuthorizationEnvelope
¶
A versioned ordered sequence of compact signed delegation statements.
VerifiedAuthorization
¶
VerifiedAuthorization(envelope: AuthorizationEnvelope, subject: str, subject_kind: str, actors: Sequence[str], audience: str, expires_at: SupportsFloat, grants: Any = (), restrictions: Any = {}, authorization_epoch: SupportsInt = 0, provenance: Sequence[str] = (), assurance: str = '')
Identity and effective authority returned by an application verifier.
AuthorizationVerifier
¶
Bases: Protocol
Verify one native x-a11-auth value for a configured audience.
AuthorizationContextResponse
¶
Bases: BaseModel
The receiver-issued handle for one connection authorization context.
encode_authorization
¶
encode_authorization(envelope: AuthorizationEnvelope) -> bytes
Encode an authorization envelope in its native binary form.
decode_authorization
¶
decode_authorization(value: bytes | bytearray | memoryview) -> AuthorizationEnvelope
Decode a canonical native binary authorization value.
authorization_to_text
¶
authorization_to_text(envelope: AuthorizationEnvelope) -> str
Encode an envelope for an ASCII-only physical HTTP header.
authorization_from_text
¶
authorization_from_text(value: str) -> AuthorizationEnvelope
Decode the physical HTTP-header representation of an envelope.
get_authorization
¶
get_authorization(action: Action) -> AuthorizationEnvelope | None
Decode the action's full authorization value without verifying it.
set_authorization_header
¶
set_authorization_header(action: Action, envelope: AuthorizationEnvelope | None) -> Action
Set or remove the action's complete signed authorization chain.
set_authorization_reference
¶
Select a non-default context previously issued on this stream.
verify_action_authorization
async
¶
verify_action_authorization(action: Action, verifier: AuthorizationVerifier) -> VerifiedAuthorization
Verify and bind a complete value carried by one action.
get_verified_authorization
¶
get_verified_authorization(action: Action) -> VerifiedAuthorization | None
Return the immutable context already bound to an incoming action.
install_authorizer
¶
install_authorizer(registry: Any, verifier: AuthorizationVerifier, *, contexts: AuthorizationContextStore | None = None) -> AuthorizationContextStore
Register __authorize__ and return its connection context store.
establish_authorization
async
¶
establish_authorization(connection: Any, envelope: AuthorizationEnvelope, *, make_default: bool = True, replace: str | None = None) -> AuthorizationContextResponse
Authorize a connection and return its receiver-issued context.