delegated
delegated is a small Rust library for evaluating issuer-signed bearer capability tokens.
It answers one question: does a token issued by a key this service explicitly trusts authorize the operation this service is about to execute?
It does not discover issuers, authenticate users, validate OIDC or SPIFFE identities, terminate TLS, operate a control plane, or turn caller-supplied request metadata into trusted context.
What the crate provides
- A strict
0.2JSON capability format and Rust data model. DelegationTokenBuilderfor issuing Ed25519-signed capabilities.Evaluatorfor binding a capability to the audience, action, resource, and delegation depth supplied by the host.IssuerKeyResolverfor connecting evaluation to explicitly trusted issuer keys.TrustStateStorefor connecting evaluation to revocation, agent-deny, and atomic replay state.AuditEventandAuditSinkfor recording allow and deny decisions.- In-memory key, state, and audit implementations for tests and single-process use.
The crate provides an authorization decision primitive. It does not provide an HTTP server, middleware, database, identity provider, multi-hop delegation protocol, or proof that the bearer is the agent named in the token.
Security model
- The host configures trusted issuer keys through
IssuerKeyResolver. - The issuer signs every capability claim with Ed25519.
- The host supplies
OperationContextfrom the actual route/tool/operation being executed. - Audience, action, resource, and delegation-depth constraints fail closed.
TrustStateStoreprovides revocation, agent deny, and atomic nonce consumption.- Trust-store errors deny evaluation;
evaluate_and_auditalso prevents an allow from being returned when audit persistence fails.
Tokens are bearer credentials. Anyone possessing a valid token can use it until it expires, is revoked, or its nonce is consumed. Use short lifetimes and transport security.
Example
use ;
use SigningKey;
use ;
let issuer_key = from_bytes;
let trusted_keys = new;
trusted_keys.insert?;
let now = now;
let token = new
.token_id
.issuer
.agent_id
.delegator_id
.audience
.allowed_action
.allowed_resource
.max_delegation_depth
.issued_at
.expires_at
.nonce
.key_id
.build_and_sign?;
let raw = to_vec?;
// Construct this from the handler/route and validated target, never from `raw`.
let operation = new
.with_resource
.with_delegation_depth;
let state = new;
let =
new.evaluate;
if decision.allowed
# Ok::
InMemoryTrustState is a reference implementation for tests and single-process services.
Distributed deployments must provide shared storage with atomic consume_nonce behavior.
Required deployment work
- Load issuer keys from trusted configuration or a verified key service.
- Implement durable shared
TrustStateStorestorage. - Build
OperationContextfrom the operation that will actually run. - Persist
AuditEventto a durable, access-controlled sink before executing an allow. - Protect bearer tokens in transit and at rest.
Checks
The wire contract is documented in SPEC.md. The project is pre-1.0 and the 0.2
wire format is intentionally incompatible with the earlier experimental format.
License
MIT OR Apache-2.0