carry::access, deployed on Sui testnet. It holds the access policy, mints Receipt proof objects, and recomputes the authorization verdict on-chain.
Objects
AccessPolicy
A shared object: the agent × namespace grants table, plus the receipt-chain head (
receipt_count, chain_head).OwnerCap
An owned capability. Only the holder can change grants on its policy.
Receipt
An owned,
Display-enabled proof object minted on each anchor.AccessPolicy
is_allowed returns true unless a namespace was explicitly revoked for an agent. receipt_count and chain_head track the tamper-evident receipt chain.
Granting and revoking
Only theOwnerCap holder can change access:
is_allowed is a public, read-only function — anchor_receipt calls it on-chain to recompute a proof’s verdict, and the walletless verifier calls it via devInspect (no gas, no signing) to re-check any proof against the live policy.
Anchoring a receipt
anchor_receipt is the heart of the proof layer. It recomputes the verdict, extends the hash chain, mints the Receipt, and transfers it to the signer:
anchor_receipt takes the policy as &mut and is callable by anyone — the receipt chain is append-only. Only set_access requires the OwnerCap.Display metadata
Ininit, the module claims a Publisher and registers a Display<Receipt> so wallets and explorers render each proof as a “Carry Proof #” rather than a raw object.
Tests
The Move tests assert the behavior that matters:blake2b256_abc_golden— pins the hash so it matches the TypeScript verifier byte-for-byte.gate_defaults_allow_then_revokes— default-allow, then revoke flipsis_allowed.anchor_mints_receipt_and_chains— anchoring creates aReceipt, incrementsseq, and chains correctly.