UCAN revocation is achieved via a Certificate Revocation List expressed as a grow-only prefix trie. It must contain both the revoked UCAN, and be signed by a DID in the proof chain above the target UCAN.

This lives at /revoke/*. For a UCAN to be valid, a validator must construct a proof of non-inclusion, in addition to the UCAN's internal structural checks. A revocation claim contains the following information:

data RevocationClaim = RevocationClaim
-- Links
{ revoke :: HardLink UCAN -- UCAN to revoke
, resolved :: HardLink UCAN -- Resolved revoked UCAN
-- Metadata
, revoker :: DID -- DID in proof chain
, sig :: Base64Url -- signRSA(didPK, revokedCID)
type RevocationTable = Map (CidOf UCAN) RevocationClaim

The revoke and resolved may be the same. We rely on the content addressed hard links to de-deuplcate storage if they're identical. If the original revoked UCAN is Merkle compressed, dereference at least the parts that include the revoker's DID through to the genesis DID.