The Core Insight
ATProto is a stateful, universally addressed data protocol. Records exist. They persist. They outlive any particular action taken on them. This is not incidental — it is the foundational property that makes ATProto what it is.
Capability Trees is built around this property. In the online verification case, statefulness is the point. A delegation is not a token you present at invocation time. It is a record that exists on its issuer's PDS right now, or it does not. Verification resolves live records and asks: does this chain currently exist? The answer is in the state of the world at the moment of asking. This is a different trust model than token-based capability systems, and the difference matters.
The Problem
Traditional object capability systems assume a controlled runtime. Possession of an unforgeable reference is sufficient authorization — if you hold it, you can use it. This works in closed systems where the runtime mediates all access.
In an open decentralized protocol like ATProto, this assumption breaks. Anyone can read records, build clients, and attempt to use references. The runtime cannot be trusted to mediate all access.
Modern distributed capability systems address this with audience restriction: a capability is cryptographically bound to its intended recipient and requires a signature from that recipient at invocation time. Possession alone is insufficient; you must prove you are the intended audience.
These systems are invocation-oriented — a capability token is presented to perform an action. ATProto is different in kind. It is a stateful, universally addressed data protocol where records persist and outlive any particular invocation. Capability Trees is built for this model. Authority is not carried in a token presented at invocation time. It exists in the state of the world — in records on PDSes, right now — and is verified by resolving that state directly. Capability Trees adds one property this model makes uniquely tractable: sovereign revocation without a revocation list, grounded in ATProto's existing deletion semantics.
Permission Sovereignty
ATProto already provides data sovereignty. Your data lives on your PDS. You control it, you can export it, you can migrate it. That problem is solved.
What ACLs cannot provide is permission sovereignty — the ability to control what others are authorized to do with your data, selectively and unilaterally, even against a malicious application. Under an ACL system, permissions are defined and enforced by the administrator. The application is the enforcement point. A malicious application can redefine or ignore the permission structure entirely. Your only recourse is exit.
Permission sovereignty means you hold the levers over your own authorization relationships independently of any application or administrator. Revoking a capability is an act on your PDS that no application can prevent or override. The application defines what permissions mean. The protocol enforces whether they are honored. ACLs leave enforcement to the application, making governance structures fragile and permission sovereignty impossible. Capability Trees moves enforcement to the protocol, making permission sovereignty real even against malicious applications.
This is not a minor implementation difference. It is a different theory of where enforcement lives — and where enforcement lives determines whose interests it serves.
The Mechanism
Bilateral Delegations
Every delegation in Capability Trees is bilateral. A delegation requires two records to be active simultaneously: an issuer record on the delegator's PDS and an acceptance record on the delegatee's PDS. Neither alone constitutes an active capability. Both together activate it.
The delegator's record is an invitation. The delegatee's record is a request. When both are present, the capability is active. When either is absent, it is not. Either party can void their side independently at any time, without the other party's cooperation or knowledge.
This makes every authorization relationship a mutual agreement — a social contract with cryptographic teeth on both sides.
The full lifecycle of a delegation:
A delegator issues an invitation — I am offering you this capability. A delegatee issues a request — I would like this capability. Either act can initiate the relationship. The other party's matching record constitutes it. Either party's deletion of their record voids it.
If the delegatee deletes their side, the delegator's record becomes an open invitation again. If the delegator deletes their side, the delegatee's record becomes a standing request. Deletion is not erasure — the surviving record retains its meaning and the relationship is recoverable by the same party re-issuing their side, so long as the other side remains.
Scope attenuation:
The delegator's record may be of broader scope than the delegatee's acceptance. You do not have to accept the full extent of what was offered — only what you need. A space that issues a blanket "can contribute here" invitation covers all of a member's contributions without requiring a fresh bilateral agreement per contribution. Each contribution is a narrower acceptance within the scope of the standing invitation.
Fractal accountability:
Each party in the chain is accountable upward to whoever granted them access and authoritative downward over whoever they delegated to. Governance happens as close to the terrain as possible.
Online Verification: Signed Request as Audience Proof
To verify a capability, the verifier resolves the full delegation chain live — every bilateral link from the root to the terminal recipient, each from its authoritative PDS. Both the issuer record and the acceptance record must be present and valid at each link.
The verification request itself is the audience proof. The requester signs the request with their private key. The verifier finds the intended recipient DID at the terminal link and checks it against the DID document of whoever signed the request. If they match, the requester has proven they are the intended audience without presenting anything beyond an authenticated request. This is the same inter-service authentication ATProto already uses throughout — Capability Trees inherits it as ambient infrastructure.
Root record anchoring ensures revocation is immediate. Every chain traces back to a root record on the issuing party's PDS. Deleting the root returns a 404 — the chain breaks immediately, without coordination, without a revocation list, without notifying downstream delegatees. Absence of the record is the answer.
UCAN Attestation: Portable Audience Binding
When the verifier issues a snapshot, it wraps the confirmed chain into a UCAN delegation — encoded in DAG-CBOR per the UCAN delegation specification — signed by the verification service's DID, with the audience field set to the requester's DID and an expiry bounding the staleness window. To use the UCAN, the holder proves they control the private key of the audience DID by signing a challenge with it. Possession of the UCAN alone is insufficient — you must also hold the private key of the DID it was issued to.
The PKI is identical to the online case. The difference is where the verification work happens — live resolution at request time versus a previously issued attestation the holder carries forward. The trust model is the same in both modes.
Revocation
The issuer deletes their delegation record. The PDS returns a 404. The verifier's cache updates. Active UCAN holders are notified immediately — point-to-point, no broadcast, no list, directly from the verifier's persistent state. Offline holders are caught the moment they reconnect. The revoker performs one action and the rest of the system converges on its own schedule, without coordination, without waiting for expiry.
UCAN deliberately leaves revocation underspecified — it is designed to be flexible across deployment contexts, and revocation is a problem each deployment must solve for itself. Capability Trees is that solution for ATProto. The gap UCAN left open is filled precisely and completely by the verifier's persistent state, without requiring anything beyond what the protocol already provides.
This is not a workaround. It is the best revocation infrastructure you could ask for — and it falls out of the architecture for free.
Verification
The chain is distributed across records on each issuer's PDS. Verification resolves each link from its authoritative source. Because links are resolved in parallel, verification latency is bounded by the slowest single PDS in the chain — not by chain depth.
The verification service returns one of three results:
Green light —
200 OK; all links resolved and valid; both sides of every bilateral link are present; the chain currently exists.Abort —
403 Forbidden; a link returned a definitive 404; the chain is broken; revocation is authoritative. The delegation record's absence on its issuer's PDS becomes a 403 to the requester — you are not authorized because the authorization no longer exists.Unresolvable —
503 Service Unavailable; one or more PDSes did not respond; the state is ambiguous. The 503 carries the correct semantic of "try again later" — the client knows this is an infrastructure problem, not a rejection.
The mapping to HTTP status codes is not incidental. The distinction between 403 and 503 at the HTTP layer is the same load-bearing distinction between abort and unresolvable in the trust model. A 404 on a delegation record is authoritative — the authorization no longer exists. A timeout is ambiguity about state. Collapsing these into the same signal would force clients to treat a network hiccup as a revocation, undermining the entire value of the stateful model.
Two Verification Modes
Online Verification: Stage and Commit
For one-off operations, the application stages the operation optimistically and waits for the green light before committing. The user sees a fast response immediately. Data integrity waits on the authoritative result in the background. On an unresolvable result, the operation is bounced and the user is told why — it is a temporary infrastructure issue, not a rejection.
This is standard optimistic concurrency. No exotic error handling required.
UCAN Attestation: Snapshot for Sustained Work
For high-frequency or offline use cases, the application requests a UCAN attestation from the verification service upfront. The verifier resolves the chain online, confirms both sides of every bilateral link, and issues a UCAN attesting to the validity of that chain for the requesting DID, with an expiry bounding the staleness window.
This mode serves two cases with the same mechanism:
High-frequency work: Request a UCAN at the start of the work session. Pay the verification cost once. Use the UCAN locally through the window. Refresh when it expires. Network bandwidth is not consumed on every operation.
Offline operation: Request a UCAN with a longer expiry before going offline. Use it while disconnected. The staleness tradeoff is explicit and chosen.
The verification service is identical in both cases. Expiry window is the only variable the application controls. And if the verifier made a mistake — a conservative revocation due to a temporarily unreachable PDS — the holder simply requests a fresh UCAN.
Capability Trees and UCAN
Capability Trees is the stateful layer. It answers: does this authorization currently exist in the world? The answer lives in PDS records, resolved live. This is the authoritative source of truth.
UCAN is the invocation layer. It answers: I was authorized at a specific moment — here is a portable proof of that. The answer lives in a signed token, carried forward through time or across a network boundary.
These are not competing models. They are complementary layers of the same system. You verify against the stateful layer to establish ground truth. You issue a UCAN when you need to carry that ground truth somewhere that cannot or should not re-verify from scratch. The UCAN does not replace the stateful check. It is a snapshot of it, valid for a bounded window, for a specific recipient.
This is also why Capability Trees fits ATProto naturally in a way that a pure token-based system would not. ATProto's data outlives any particular invocation. So does the authority Capability Trees encodes. The stateful layer is primary. UCAN appears only as a transport for verified state.
The verifier's persistent state closes the revocation story
The verifier is stateful by necessity — it maintains a cache of chain states to make the UCAN mode tractable. That same statefulness gives near-instant revocation even in the UCAN case, for free.
When a delegation record is deleted, the verifier's cache updates. Connected UCAN holders are notified immediately. Offline holders are caught the moment they reconnect — they present their UCAN, the verifier checks the cache, and if the chain broke while they were gone, 403. Expiry is therefore not a revocation mechanism. It is a cleanup mechanism. Revocation happens when state changes, which the verifier observes continuously.
Ecosystem Convergence
Capability Trees is ATProto-native, but its relevance is broader than ATProto alone.
UCAN encodes delegations in DAG-CBOR. ATProto records are DAG-CBOR. The UCAN delegation specification — co-authored by Brooklyn Zelenka and Daniel Holmgren — uses IPLD schemas, the same content-addressing substrate ATProto is built on. There is no serialization boundary between the stateful layer and the invocation layer. The verifier resolves DAG-CBOR delegation records, walks a DAG-CBOR chain, and produces a DAG-CBOR UCAN. The encoding is consistent throughout.
This is not coincidence. It is convergence — a set of people working on adjacent problems in decentralized systems arriving at shared primitives. DAG-CBOR as a shared data format. Content addressing as a shared integrity model. Audience-bound delegation as a shared authorization primitive. ATProto as the stateful substrate that gives the whole stack a home.
Capability Trees sits at this convergence point. It is implementable once, shared across every project that uses it, and legible to anything else in the ecosystem that speaks the same language.
Open Questions
The full picture of permissioned spaces requires more than Capability Trees alone. The space boundary question — how membership is defined, how the cryptographic boundary of a space stays current with its membership, how a space's collective signing key works without concentrating that key in any individual — is the most significant open question. It sits below this layer, in the infrastructure that Capability Trees builds on top of.
Work is actively underway. Nick Gerakines' metadata-only CAR proposal addresses the network boundary. The collective cryptography question — a skip ratchet based construction for epoch-based collective signing keys, where membership change is the epoch boundary — is the next piece of work. Brooklyn Zelenka's skip ratchet is the relevant prior art.
Above this layer, the governance question remains: how does a collective make binding decisions, and how is the legitimacy of those decisions made legible and enforceable at the protocol level? That is the virtualized administrator — a future document.
We are working through these questions. Please bear with us.
Properties
No ACLs at any layer
No revocation lists
No central administrator
No coordination required for revocation
Bilateral delegations — every authorization relationship requires mutual agreement, voidable from either side
Revocation effective within a single network round trip to the issuer's PDS
Verification latency bounded by slowest PDS, not chain depth
Two verification modes: online stateful for one-off operations, UCAN attestation for sustained or offline work
Verifier written once, shared by every project — ecosystem absorbs implementation cost once
Delegation chains fully legible and auditable
Fractal accountability: authority flows downward, accountability flows upward
Permission sovereignty: enforcement lives in the protocol, not the application
Ecosystem convergence: DAG-CBOR throughout, composable with UCAN and IPLD tooling