CACAO Chain Validation
CACAO chain validation is the algorithm a node runs to decide whether a request is authorized: it walks the request's delegation chain — a SIWE/CACAO root plus zero or more UCAN sub-delegations, ending in a invocation — and admits it only if every link verifies cryptographically and stays within its parent's authority, terminating at the space's owner DID. This is the single gate behind every read and write, and getting its exact rules right is what makes TinyCloud authority server-independent.
Role
This is the heart of Layer 1 enforcement. Because the chain is self-describing and self-verifying, a node needs no account database to authorize a caller — the proof travels with the request (AuthHeaderGetter in tinycloud-node-server/src/auth_guards.rs lifts it off the HTTP headers before any route runs). It is the concrete validation of the capability model.
Actors
The owner DID (root, did:pkh) · zero or more intermediate session/delegate keys (did:key) · the final invoker · the node verifying against the target space.
The algorithm
A chain is root_delegation → [sub_delegation …] → invocation. The two link types are modeled in tinycloud-auth: a TinyCloudDelegation is either a UCAN or a SIWE/CACAO (ReCap); a TinyCloudInvocation is a UCAN. Validation (tinycloud-core/src/models/delegation.rs, models/invocation.rs, parentage in relationships/parent_delegations.rs) checks, per link:
- Signature. Each link is signed by the principal its parent delegated to. The root CACAO is signed by the owner (EIP-191 over the SIWE message); each UCAN is signed by its issuer key. A signature that doesn't verify against the expected DID rejects the chain.
- Issuer/audience linkage. Each sub-delegation's issuer must equal its parent's audience (the key the parent granted to); the invocation's issuer must equal the last delegation's audience. This is the parent-delegatee match enforced in
invocation.rs/parent_delegations.rs. - Time validity. Each link's
[nbf, exp]window must be valid now and contained within its parent's window — a child can never outlive its parent. - Scope containment (attenuation). The link's resource must be
extends-covered by the parent's resource (the path-containment rule in uri-addressing-grammar) and its ability must be covered by the parent's ability. See attenuation — a child can only narrow. - Root authority. The chain's root must be signed by the DID that owns the target space —
is_root_authoritycompares the space'sbase_didto the root delegator. A chain that doesn't bottom out at the space owner is rejected regardless of internal validity.
Only if every link passes 1–5 is the invocation admitted and dispatched to the service.
Crypto / replay
Root authority is EIP-191 secp256k1 over the SIWE/CACAO; sub-links are UCAN (Ed25519 did:key) signatures. Replay protection on the general invoke path rests on the time-bounds + the chain's hash-identity rather than a dedicated nonce-dedup table (see consistency-model).
Relationships
Validates a delegation chain of capabilities rooted in a SIWE/CACAO and extended by UCAN; enforces attenuation via extends; gates every invocation; the HTTP entry is auth_guards; the inverse operation (issuing a chain) is sign-in-flow.
Example
Request: invoke tinycloud.kv/get on …:applications/kv/xyz.tinycloud.listen/transcript/x. Chain: owner SIWE/CACAO root granting tinycloud.kv/get over …:applications/kv/xyz.tinycloud.listen/transcript/ to a session key → that key's UCAN invocation of the exact path. The node verifies the owner's signature, that the session key is the CACAO's audience, that transcript/x is extends-covered by transcript/, that times are valid, and that the root signer owns …:applications — then serves the read.
Status & drift
Shipped. The chain types and verification live in tinycloud-auth + tinycloud-core/src/models/{delegation,invocation}.rs; this concept is Sam's top documentation gap, now pinned to those paths. The general /invoke replay nuance is tracked in consistency-model.
Sources
tinycloud-node:tinycloud-core/src/models/delegation.rs,models/invocation.rs,relationships/parent_delegations.rs,tinycloud-node-server/src/auth_guards.rs(AuthHeaderGetter),tinycloud-auth/src/authorization.rs(TinyCloudDelegation/TinyCloudInvocation)