Expand description
Macula’s UCAN (User Controlled Authorization Networks) tokens: creation, verification, and introspection, plus the policy layer a provider gates an inbound CALL through.
Ported from macula-io/macula’s src/auth/macula_ucan_nif.erl and its
native Rust NIF (native/macula_ucan_nif/src/lib.rs) — both hand-roll a
JWT-shaped token (header.payload.signature, base64url-no-pad), EdDSA
over Ed25519, UCAN spec version "0.10.0" (the older JWT-based draft;
not the current non-JWT/IPLD UCAN 1.0 spec). Confirmed directly by
reading the NIF’s own Cargo.toml: no UCAN-spec crate is depended on at
all, only generic ed25519-dalek/serde_json/base64/sha2 — because
no library implements 0.10.0 (the only actively maintained Rust/Go UCAN
libraries target the incompatible 1.0.0-rc.1 CBOR/IPLD format, per
macula-go’s own ucan package doc, which made the identical
choice porting this same reference). This module does the same: hand-
rolled on the crypto/serialization primitives already in this crate
(ed25519-dalek via crate::identity, plus serde/serde_json/
base64 added for this module), matching the reference exactly rather
than adopting an incompatible library.
A token minted here verifies against macula-go’s ucan package,
the Erlang macula SDK, or vice versa — same header shape, same payload
field names (iss/aud/exp/nbf/nnc/cap/fct/prf), same
signing input (header_b64 + "." + payload_b64), same algorithm. Field
ORDER in the JSON is not part of the compatibility contract (a verifier
decodes into a struct, never re-encodes and compares bytes) — only the
field NAMES and the exact bytes signed matter.
Cross-referenced against macula-go/ucan/{ucan,policy}.go, itself
independently verified against this same Erlang/Rust reference earlier
this session — the two ports should stay behaviorally identical.
Structs§
- Capability
- One entry in a UCAN token’s capability list — mirrors
macula_ucan_nif’scapability() :: #{with := binary(), can := binary()}. - Create
Opts - Optional claims for
create— mirrorsmacula_ucan_nif’sucan_opts()map. - Payload
- A UCAN token’s decoded claims — the Rust-idiomatic counterpart to
WirePayload, returned fromdecode/verify. - Policy
- What a provider requires to answer one
(realm, procedure): open (any identified caller, the default) or UCAN-gated (the caller’s token must verify againstrequired_issuer). Mirrorsmacula_station_link.erl’s own policy shape exactly —open | {ucan_required, Issuer}— whereIssuerthere is the 32-byte Ed25519 public key the gate checks the token’s signature against, not a DID string (the reference code passes it straight tomacula_ucan_nif:verify/2, whose second argument is a raw public key).
Enums§
- Ucan
Error - Errors from token creation, decoding, or verification.
Functions§
- compute_
cid - Returns a UCAN token’s content identifier: SHA-256 of the raw token
bytes, base64url-no-pad encoded. NOT a real multihash/CIDv1 — matches
macula_ucan_nif:compute_cid/1’s own (loosely-named) scheme exactly. Used only for proof-chain references between UCANs (a child token’sprfentries name parent tokens by this value). - create
- Mints a new UCAN token, self-issued and signed by
id.issuerandaudienceare opaque DID strings (e.g."did:macula:io.macula.acme") — this module does not validate or resolve DID structure, matchingmacula_ucan_nif:create/4,5’s own scope exactly (that’smacula_did_nif’s job on the Erlang side, out of scope here).idsigns with its own Ed25519 private key; the resulting token verifies againstid’s public key (KeyPair::node_id), the same convention every advertised capability in this SDK already uses. - decode
- Parses a UCAN token’s payload WITHOUT verifying its signature or
checking expiration. Mirrors
macula_ucan_nif:decode/1— same warning applies: never use this for an authorization decision, onlyverifydoes that. - get_
audience - Decodes
token(without verifying it) and returns itsaudclaim. Mirrorsmacula_ucan_nif:get_audience/1. - get_
capabilities - Decodes
token(without verifying it) and returns itscapclaim. Mirrorsmacula_ucan_nif:get_capabilities/1. - get_
expiration - Decodes
token(without verifying it) and returns itsexpclaim, orNoneif absent. Mirrorsmacula_ucan_nif:get_expiration/1. - get_
issuer - Decodes
token(without verifying it) and returns itsissclaim. Mirrorsmacula_ucan_nif:get_issuer/1. - get_
proofs - Decodes
token(without verifying it) and returns itsprfclaim. Mirrorsmacula_ucan_nif:get_proofs/1. - is_
expired - Decodes
token(without verifying it) and reports whether itsexpclaim is in the past. A token with noexpclaim is never expired. Mirrorsmacula_ucan_nif:is_expired/1. - verify
- Checks a UCAN token’s signature against
public_key(the claimed issuer’s 32-byte Ed25519 public key) and itsexp/nbfclaims against the current time, returning the decoded payload only on full success. Mirrorsmacula_ucan_nif:verify/2exactly, including its check ORDER — public key shape, then token shape, thenexp, thennbf, then signature — matching both the Erlang fallback and the Rust NIF, which check claims before the signature; this module preserves that order for parity even though it means an invalid-but-well-formed token’s expiry is observable before its signature is checked.