Building DRS: verifiable delegation receipts for AI agents (UCAN v1 / DAG-CBOR) - drowning in spec edges and could use sane eyes
⚓ Rust 📅 2026-03-25 👤 surdeus 👁️ 3Hi everyone, I'm working on DRS (Delegation Receipt Standard) and I'm basically a lost sheep right now: I know roughly where the pasture is, but I could really use people who've actually shipped capability systems to sanity-check the design and poke holes before I write the first line of implementation code.
What I'm building
AI agents are increasingly calling tools, delegating to other agents, and acting on behalf of users. When something goes wrong, the question is always the same: who authorized this action, with what limits, and can we prove it?
DRS is a portable, verifiable "receipt" for delegation - not "trust our logs," but cryptographic proof of who delegated what to whom, with clear bounds and room for consent and compliance metadata. Think: agents calling tools and other services, with auditors able to reconstruct the full chain of authority in a standard format.
What it is technically
DRS is a UCAN Profile - a constrained, extended use of UCAN v1.0.0-rc.1; not a parallel authorization scheme. I'm building on top of UCAN rather than reinventing delegation chains from scratch (I already tried that; it was a bad idea).
Concretely, the boring spec parts matter a lot:
- Encoding: v1 is DAG-CBOR / IPLD, not JWT-era v0.x. Mental model "UCAN = JWT +
att" is outdated. - Delegation:
sub,cmd,pol(subject, command path, policy with jq-style selectors and operators like==,like,all,any). - Proofs:
prflives on invocations, not on each delegation -- the chain is assembled at invocation time. - Policies: the spec expects runtime evaluation of every delegation's policy against the invocation
args(conjunctive across the chain), not a neat "child policy always structurally tightens parent" check.
Why the planned stack looks like this
I'm aiming for infrastructure-grade verification performance, so the design splits across three languages by responsibility:
- Rust (
drs-core) for the hot path: Ed25519 signatures (viaed25519-dalek2.x with S < L enforced by default), CID computation, DAG-CBOR canonicalization (viaserde_ipld_dagcbor, not the deprecatedlibipld), and capability indexing. Compiles to native + WASM so the browser/TS path never does naive crypto in JavaScript. - Go (
drs-verify) for the verification service: bounded LRU caches for DID resolution (hard cap 10k entries), status-list cache with TTL andsync.Onceconcurrency guard, and middleware-shaped integration targeting MCP and A2A interceptor patterns. Single static binary deployment. - TypeScript (
@drs/sdk) for issuance ergonomics only. Low-frequency path. All crypto delegated to the Rust WASM module.
Where I am now: architecture, language/algorithms doc, technical audit against UCAN v1.0.0-rc.1, diagrams - no implementation code yet. I'll open-source the docs and start coding soon; happy to share drafts
What would help
- Spec review:
prf,polsemantics, CID/canonicalization - catch anywhere I'm still thinking v0.x by accident. - Production war stories: UCAN-like systems at scale , caching, revocation/status lists, DID resolution.
- Contributors for Rust / Go / TS, tests, docs, adversarial review.
If you've touched UCAN, capabilities, SPIFFE-ish identity, or agent middleware, I'd love comments
1 post - 1 participant
🏷️ Rust_feed