Expand description
macula 12’s UCAN, macula’s macula_ucan in Rust: tokens signed in the
node’s crypto profile (D7), and a provider’s authorization of one.
macula’s test/vectors/UCAN_V1.md is the contract, and
tests/vectors/ucan holds its vectors; every verdict here is macula’s,
reached in the same order.
A token is a JWT, header.payload.signature, each part base64url without
padding. The header names the profile’s algorithm: ML-DSA-87 in pq_pure,
ML-DSA-87-PS384 (the LAMPS composite id-MLDSA87-RSA4096-PSS-SHA512) in
pq_hybrid. The signature is the issuer’s node key’s over the header and
payload as sent. The payload’s iss is a did:key for the issuer’s key as
carried; aud is the lowercase hex node_id of the node that presents the
token, which must be the request’s verified caller; cap lists
{with, can}; exp is in seconds, at most MAX_LIFETIME past now.
A token may rest on a parent: its prf names the parent by proof_id,
and the parents travel beside it in the request’s caller-signed proofs.
The chain is walked to its root, which must be the issuer the policy
names; each link’s own signature and validity window hold, each parent’s
aud is the node_id of its child’s issuer, can is equal at every step,
and a child’s capability is covered by one of its parent’s (covers).
Every proof that travelled must be used.
Structs§
- Capability
- One grant: a
with(an MRI) and acan. - Context
- What a token is authorized against: the request’s verified caller, the
provider’s profile, the time in seconds, the request (
Noneto check the token alone, as a gate with no request in front of it), and the proofs that travelled with it, keyed byproof_id. - Options
- A token’s claims beyond
iss,audandcap:exp(seconds) is required, the rest optional.prfnames the token’s parent byproof_id; at most one. - Request
- The request a token is presented with: its realm id and procedure.
Enums§
- Create
Error - Why
createmints no token, naming the values it compared. - Policy
- What a gated procedure requires of a request’s token.
- Refusal
- Why a token does not authorize: one of
macula_ucan’s refusals, by the same name (Refusal::name).
Constants§
- MAX_
LIFETIME - The furthest past now, in seconds, that a token’s
expmay lie: ten years of 365.25 days, asmacula_ucan:max_lifetime/0. UCAN_V1 has no revocation, soexpis the only bound on a token’s life. Anexpin milliseconds lies far beyond it, so a token minted with one is refused, bycreateand byauthorize, rather than valid for tens of thousands of years.
Functions§
- authorize
- Whether
tokenauthorizesctx’s caller underp: the token’s claims when it does, or the first refusal, inmacula_ucan’s order. - carried_
key - The key a did:key carries, when it is a key in its one carried form for
profile(D13);Refusal::Malformedotherwise. - covers
- Whether a grant covers another grant or a request, by D7’s narrowing: a
realm grant covers its realm, an org grant covers that org and its
procedures, a procedure grant only itself. False for a
withthat is not one of the three MRIs, whose realm name is not canonical, or whose procedure has no org. - create
- A token from
issuer’s identity key, for the audience’s node_id, grantingcapsuntilo.exp. Anexpmore thanMAX_LIFETIMEpast now, or annbfnot beforeexp, is refused, naming the values. - did_key
- The did:key for a key as carried in
profile. - proof_
id - The id a child’s
prfnames a parent token by: the lowercase hex of the SHA-384 of the token’s bytes as they travel.