### UCAN Metadata Example (JavaScript) Source: https://github.com/ucan-wg/spec/blob/main/README.md Illustrates the 'meta' field in a UCAN, which allows for arbitrary metadata, facts, and proofs of knowledge. This data must be self-evident and externally verifiable, and is not semantically meaningful to delegation chains. Examples include challenges and hash preimages. ```javascript { // ... "meta": { "challenges": { "example.com": "abcdef", "another.example.net": "12345" }, "sha3_256": { "B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9": "hello world" } } } ``` -------------------------------- ### UCAN Token Envelope Example (JavaScript) Source: https://github.com/ucan-wg/spec/blob/main/README.md Demonstrates the structure of a UCAN token envelope in JavaScript, including the signature bytes, signature payload header, and the UCAN token payload with example fields. This format is used for representing signed capabilities. ```javascript [ { "/": {"bytes": "bdNVZn+uTrQ8bgq5LocO2y3gqIyuEtvYWRUH9YT+SRK6v/SX8bjt+VZ9JIPVTdxkWb6nhVKBt6JGpgnjABpOCA"}}, { "h": {"/": {"bytes": "NAHtAe0BE3E"}}, // i.e. signed with Ed25519, encoded with DAG-CBOR "ucan/example@1.0.0-rc.1": { // Body fields, for example: "hello": "world" } } ] ``` -------------------------------- ### UCAN Nonce Example (JavaScript) Source: https://github.com/ucan-wg/spec/blob/main/README.md Demonstrates the structure of the 'nonce' field within a UCAN object, which is used to prevent replay attacks and ensure unique CIDs per delegation. The nonce can be a randomly generated string or a monotonically increasing count. ```javascript { // ... "nonce": {"/": {"bytes": "bGlnaHQgd29yay4"}} } ``` -------------------------------- ### UCAN Basic Delegation Chain Example Source: https://context7.com/ucan-wg/spec/llms.txt Demonstrates the structure of a UCAN delegation payload, where Bob delegates account access to Carol. It outlines the key fields required for delegation and the verification steps the audience must perform. ```javascript // Bob delegates account access to Carol { "iss": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", // Issuer (Bob) "aud": "did:key:z6MkmJceVoQSHs45cReEXoLtWm1wosCG8RLxfKwhxoqzoTkC", // Audience (Carol) "sub": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", // Subject (Bob's resource) "cmd": "/account", // Command capability "pol": [], // No policy constraints "exp": 1753353393, // Expiration timestamp "nonce": "J20r9pHkJ/yoNirD" // Unique nonce } // The audience (Carol) must verify: // 1. The signature matches the issuer's DID public key // 2. The `aud` field matches Carol's DID // 3. The token has not expired // 4. The nonce is unique (replay protection) ``` -------------------------------- ### Policy Language Constraints in JavaScript Source: https://context7.com/ucan-wg/spec/llms.txt Illustrates how to use Lisp-like expressions to constrain capability usage with rich validation logic. Examples cover email sending, comparison operators, pattern matching with wildcards, logical operators (AND, OR, NOT), and collection operators (any, all). Policy validation returns true/false, with failed validation resulting in a MatchError. ```javascript { "cmd": "/msg/send", "args": { "from": "alice@example.com", "to": ["bob@example.com", "carol@not.example.com"] }, "pol": [ ["==", ".from", "alice@example.com"], ["any", ".to", ["like", ".", "*@example.com"]] ] } ``` ```javascript { "args": { "a": [1, 2, {"b": 3}], "b": 1 }, "pol": [ ["==", ".a", [1, 2, {"b": 3}]], ["!=", ".b", 2], ["<", ".b", 2], [">", ".b", 0], ["<=", ".b", 2], [">=", ".b", 0] ] } ``` ```javascript { "args": { "text": "Alice*, Bob, Carol." }, "pol": [ ["like", ".text", "Alice\\*, Bob*, Carol."] ] } ``` ```javascript { "args": { "name": "Katie", "age": 35, "nationalities": ["Canadian", "South African"] }, "pol": [ ["and", [ ["==", ".name", "Katie"], ["==", ".age", 35], ["==", ".nationalities", ["Canadian", "South African"]] ]], ["or", [ ["==", ".name", "Katie"], [">", ".age", 45] ]], ["not", ["==", ".name", "Bob"]] ] } ``` ```javascript { "args": { "items": [{"b": 1}, {"b": 2}, {"z": [7, 8, 9]}] }, "pol": [ ["any", ".items", ["==", ".b", 2]], ["all", ".items", [">", ".b", 0]] ] } ``` ```javascript { "args": { "newsletters": { "recipients": [ {"email": "bob@example.com"}, {"email": "alice@example.com"} ] } }, "pol": [ ["all", ".newsletters", ["any", ".recipients", ["==", ".email", "bob@example.com"] ] ] ] } ``` ```javascript // Policy validation returns true/false // Failed validation results in MatchError ``` -------------------------------- ### Time-Bounded Delegations in JavaScript Source: https://context7.com/ucan-wg/spec/llms.txt Demonstrates how to set expiration and 'not before' timestamps to limit the validity window of capabilities. It includes examples for specific periods, future activation, no expiration, and validation with clock drift tolerance. The 'nbf' (not before) and 'exp' (expires) fields are used for time bounding. ```javascript { "iss": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", "aud": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", "sub": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", "cmd": "/msg/send", "nbf": 1529496683, // Not valid before: May 20, 2018 "exp": 1575606941, // Expires: Dec 6, 2019 "nonce": "AQIDBAECBAQAQIDBAECBAQ" } ``` ```javascript { "cmd": "/conference/materials", "nbf": 1735689600, // Not valid until Jan 1, 2025 "exp": 1738368000 // Expires Feb 1, 2025 } ``` ```javascript { "cmd": "/storage/quota", "nbf": 1529496683, "exp": null // Explicitly never expires } ``` ```javascript { "cmd": "/api/read", // No nbf field means valid from Unix epoch "exp": 1575606941 } ``` ```javascript // Validation with clock drift tolerance (±60 seconds recommended) const now = Date.now() / 1000; const buffer = 60; function isValid(token) { const nbf = token.nbf || 0; const exp = token.exp; if (exp !== null && now > exp + buffer) return false; // Expired if (now < nbf - buffer) return false; // Not yet valid return true; } ``` -------------------------------- ### Hierarchical Command Structure (JavaScript) Source: https://context7.com/ucan-wg/spec/llms.txt Explains the hierarchical command structure in UCANs, where commands are organized in a path-based hierarchy. Parent commands implicitly prove child commands, simplifying authorization. This section provides examples of command hierarchies and their implications for delegation. ```javascript // Command examples with hierarchical proofs const commands = { root: "/", // Top (wildcard) - proves ALL commands crud: "/crud", // Proves all CRUD operations read: "/crud/read", // Proved by /crud or / mutate: "/crud/mutate", // Proved by /crud or / create: "/crud/mutate/create", // Proved by /crud/mutate, /crud, or / update: "/crud/mutate/update", destroy: "/crud/mutate/destroy", msg: "/msg", // Separate namespace send: "/msg/send", // Only proved by /msg or / receive: "/msg/receive" }; // Example: Bob has /crud, can invoke /crud/read { "iss": "did:key:z6Mkm...Bob", "sub": "did:key:z6Mkm...Resource", "cmd": "/crud/read", "prf": [{"/": "CID_OF_DELEGATION_WITH_/crud"}] // Delegation gave /crud } // Example: Bob CANNOT invoke /msg/send with /crud delegation // /crud does NOT prove /msg/send (different namespace) // Reserved namespace: /ucan/* is reserved for future UCAN operations // Example: /ucan/revoke for revocation operations ``` -------------------------------- ### UCAN Issuer and Audience Example (JavaScript) Source: https://github.com/ucan-wg/spec/blob/main/README.md This snippet demonstrates the typical format for the 'aud' (audience) and 'iss' (issuer) fields within a UCAN token, which represent the receiver and sender respectively. These fields utilize Decentralized Identifiers (DIDs) to specify the participating entities. ```javascript { "aud": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", "iss": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" } ``` -------------------------------- ### UCAN Token Time Bounds (JavaScript) Source: https://github.com/ucan-wg/spec/blob/main/README.md Illustrates the 'nbf' (not before) and 'exp' (expires at) fields for UCAN tokens. 'nbf' is optional and delays token validity, while 'exp' is recommended for security and can be set to null for indefinite validity. Timestamps must be integers in seconds since the Unix epoch. ```json { "nbf": 1529496683, "exp": 1575606941 } ``` ```json { "exp": 1575606941 } ``` ```json { "nbf": 1529496683, "exp": null } ``` -------------------------------- ### Multi-Level Delegation Chain with Proofs (JavaScript) Source: https://context7.com/ucan-wg/spec/llms.txt Illustrates a multi-level delegation chain where authority is passed through intermediaries, requiring cryptographic proofs for validation. The invocation includes the full proof chain, detailing the delegation from Alice to Bob, and then to Carol. This ensures that each step in the delegation is verifiable. ```javascript // Scenario: Alice delegates to Bob, Bob delegates to Carol, Carol invokes // Carol's invocation includes the full proof chain { "iss": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", // Issuer (Carol) "aud": "did:key:z6MkmJceVoQSHs45cReEXoLtWm1wosCG8RLxfKwhxoqzoTkC", // Audience (resource) "sub": "did:key:z6MkmJceVoQSHs45cReEXoLtWm1wosCG8RLxfKwhxoqzoTkC", // Subject (resource) "cmd": "/msg/send", "exp": null, "iat": 1753353393, "prf": [ // Proof 1: Alice -> Bob delegation (CID reference) {"/": {"bytes": "glhAlC+rtXKanMs7eUsDKDbzBoPI1RIoBhxs3nHh/XbBc9O..."}}, // Proof 2: Bob -> Carol delegation (CID reference) {"/": {"bytes": "glhA1IoOl5rpsUsdwbfKD6Ly/Tf6h90ODLY5ru2FSDJ9s2Z..."}} ], "args": {}, "nonce": "AQEDCAEBAwgBAQMIAQEDCA" } // Validation process: // 1. Resolve all proof CIDs to get full delegation tokens // 2. Verify proof chain alignment: // - Proof[0].aud == Proof[1].iss (Bob) // - Proof[1].aud == Invocation.iss (Carol) // - All proofs have same subject // 3. Verify all signatures in the chain // 4. Check all tokens in chain are not expired // 5. Verify command is attenuated (same or more restrictive) ``` -------------------------------- ### Integrate UCAN with Legacy ACL using JavaScript Source: https://context7.com/ucan-wg/spec/llms.txt Illustrates how to integrate UCAN with existing access control systems by employing an agent to manage external authorization. The DBAgent acts as a bridge, delegating permissions via UCANs, which are then used by clients to invoke operations. The agent validates the UCAN chain and uses its own ACL credentials for the actual system access. ```javascript // Scenario: Database with existing ACL system // DBAgent acts as bridge between UCAN and ACL // 1. DBAgent registers in external ACL system // (Out of band - not shown) // 2. DBAgent delegates to Alice { "iss": "did:key:z6Mkm...DBAgent", "aud": "did:key:z6Mkm...Alice", "sub": "did:key:z6Mkm...DBAgent", "cmd": "/db/write", "exp": 1753353393 } // 3. Alice delegates to Bob { "iss": "did:key:z6Mkm...Alice", "aud": "did:key:z6Mkm...Bob", "sub": "did:key:z6Mkm...DBAgent", "cmd": "/db/write", "exp": 1753353393, "prf": [{"/": "CID_DBAGENT_TO_ALICE"}] } // 4. Bob invokes (sends to DBAgent) { "iss": "did:key:z6Mkm...Bob", "aud": "did:key:z6Mkm...DBAgent", "sub": "did:key:z6Mkm...DBAgent", "cmd": "/db/write", "args": {"key": "value"}, "prf": [ {"/": "CID_DBAGENT_TO_ALICE"}, {"/": "CID_ALICE_TO_BOB"} ] } // 5. DBAgent validates UCAN chain // 6. DBAgent uses its ACL credentials to access external system const aclResponse = await externalDatabase.write({ accessToken: dbAgent.aclToken, // From external auth system key: "key", value: "value" }); // 7. DBAgent returns response to Bob // ACK or NAK based on external system result // Note: Security guarantees are weaker because: // - Surface area includes external ACL system // - Part of auth lives outside UCAN // - Recommended: Make executor BE the resource when possible ``` -------------------------------- ### Metadata Field for Proofs of Knowledge (JavaScript) Source: https://context7.com/ucan-wg/spec/llms.txt Demonstrates using the optional 'meta' field in UCANs to include non-delegated, externally verifiable data. This is useful for challenge-response mechanisms, hash preimages, or Merkle proofs. ```javascript // Example: Server challenges and hash preimages { "iss": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", "aud": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", "sub": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", "cmd": "/api/access", "exp": 1753353393, "nonce": "AQIDBAECBAQAQIDBAECBAQ", "meta": { // Server challenge responses (externally verifiable) "challenges": { "example.com": "abcdef", "another.example.net": "12345" }, // Hash preimages "sha3_256": { "B94D27B9934D3E08A52E52D7DA7DABFAC484EFE37A5380EE9088F7ACE2EFCDE9": "hello world" }, // Merkle proofs "merkle_proof": { "root": "zdpu...", "path": ["left", "right", "left"], "siblings": ["zdpu...", "zdpu...", "zdpu..."] } } } // Important constraints: // 1. Meta field is OPTIONAL // 2. Data MUST be self-evident and externally verifiable // 3. Meta is NOT semantically meaningful to delegation chains // 4. Do NOT use nonce field for challenges - use meta instead ``` -------------------------------- ### Self-Signed Invocation (JavaScript) Source: https://context7.com/ucan-wg/spec/llms.txt Demonstrates direct invocation of a command on a resource owned by the issuer, without requiring delegation proofs. This is useful for agents acting on their own behalf. The JSON object includes issuer, audience, subject, command, and other relevant metadata. ```javascript // Agent invokes command on their own resource { "iss": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", // Issuer "aud": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", // Audience (self) "sub": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", // Subject (self) "cmd": "/msg/send", // Command "exp": null, // Never expires "iat": 1753353393, // Issued at "iss": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", "prf": [], // No proofs needed "args": {}, // Command arguments "nonce": "AQIDBAECBAQAQIDBAECBAQ" // Unique nonce } // Validation steps: // 1. Verify iss == aud == sub (self-invocation) // 2. Verify signature with issuer's public key // 3. Check token hasn't expired (null means never expires) // 4. Verify nonce uniqueness ``` -------------------------------- ### Powerline Delegation (JavaScript) Source: https://context7.com/ucan-wg/spec/llms.txt Demonstrates how to grant unrestricted authority (powerline) using UCANs. This allows the delegate to act on behalf of the issuer for any resource. Use with extreme caution as it grants complete authority. Typically used for linking devices controlled by the same user. ```javascript // WARNING: Powerline grants complete authority - use with extreme caution // Typically used for linking devices controlled by the same user // Alice grants Bob complete authority (powerline) { "iss": "did:key:z6MkmT9j6fVZqzXV8u2wVVSu49gYSRYGSQnduWXF6foAJrqz", // Alice "aud": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", // Bob "sub": null, // NULL = powerline "cmd": "/msg/send", "exp": null, "nonce": "AQIDBAECBAQAQIDBAECBAQ" } // Bob can now delegate ANY resource to Carol { "iss": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", // Bob "aud": "did:key:z6MkmJceVoQSHs45cReEXoLtWm1wosCG8RLxfKwhxoqzoTkC", // Carol "sub": "did:key:z6MkmJceVoQSHs45cReEXoLtWm1wosCG8RLxfKwhxoqzoTkC", // ANY subject "cmd": "/msg/send", "exp": null, "prf": [{"/": "CID_OF_POWERLINE_DELEGATION"}], // References Alice->Bob powerline "nonce": "AQEDCAEBAwgBAQMIAQEDCA" } // Carol invokes with powerline proof chain { "iss": "did:key:z6MkgGykN9ARNFjEzowVq4mLP2kL4NsyAaDGXeJFQ5qE1bfg", "sub": "did:key:z6MkmJceVoQSHs45cReEXoLtWm1wosCG8RLxfKwhxoqzoTkC", "cmd": "/msg/send", "prf": [ {"/": "CID_ALICE_TO_BOB_POWERLINE"}, // sub: null {"/": "CID_BOB_TO_CAROL"} // sub: specific resource ], "nonce": "AQEDCAEBAwgBAQMIAQEDCA" } // Security note: Powerline enables Bob to update Alice's keys, // revoke Alice's UCANs, and use any resources delegated to Alice // Only use between devices you fully control ``` -------------------------------- ### CRDT and Replicated State Authorization (JavaScript) Source: https://context7.com/ucan-wg/spec/llms.txt Illustrates using UCANs to authorize actions in eventually consistent systems (CRDTs). Multiple replicas can independently apply changes, with UCANs ensuring provenance and authorization for merge operations. ```javascript // Scenario: Multiple agents updating a grow-only set CRDT // Each maintains local invocation log, changes gossip between peers // Setup: CRDT delegates merge capability to Alice and Bob const crdtDelegations = [ { "iss": "did:key:z6Mkm...CRDT", "aud": "did:key:z6Mkm...Alice", "sub": "did:key:z6Mkm...CRDT", "cmd": "/crdt/merge", "exp": null }, { "iss": "did:key:z6Mkm...CRDT", "aud": "did:key:z6Mkm...Bob", "sub": "did:key:z6Mkm...CRDT", "cmd": "/crdt/merge", "exp": null } ]; // Bob invites Carol by sub-delegating { "iss": "did:key:z6Mkm...Bob", "aud": "did:key:z6Mkm...Carol", "sub": "did:key:z6Mkm...CRDT", "cmd": "/crdt/merge", "exp": null, "prf": [{"/": "CID_CRDT_TO_BOB"}] } // All three agents perform local operations // Alice adds "Apple" { "iss": "did:key:z6Mkm...Alice", "sub": "did:key:z6Mkm...CRDT", "cmd": "/crdt/merge", "args": {"add": "Apple"}, "prf": [{"/": "CID_CRDT_TO_ALICE"}] } // Bob adds "Banana" and "Carrot" { "iss": "did:key:z6Mkm...Bob", "sub": "did:key:z6Mkm...CRDT", "cmd": "/crdt/merge", "args": {"add": ["Banana", "Carrot"]}, "prf": [{"/": "CID_CRDT_TO_BOB"}] } // Carol adds "Carrot" (duplicate, CRDT handles idempotency) { "iss": "did:key:z6Mkm...Carol", "sub": "did:key:z6Mkm...CRDT", "cmd": "/crdt/merge", "args": {"add": "Carrot"}, "prf": [ {"/": "CID_CRDT_TO_BOB"}, {"/": "CID_BOB_TO_CAROL"} ] } // Invocations gossip peer-to-peer // Each replica validates and applies changes // Final state converges: {"Apple", "Banana", "Carrot"} // Provenance maintained through invocation log ``` -------------------------------- ### Revoke UCAN Delegation with JavaScript Source: https://context7.com/ucan-wg/spec/llms.txt Demonstrates how to revoke a specific UCAN delegation, which invalidates all subsequent delegations in the chain. This process involves creating a revocation UCAN that references the UCAN to be revoked. Validators must maintain a revocation store and check all proofs against this list. ```javascript // Scenario: Alice delegates to Bob, Bob delegates to Carol // Alice later revokes Bob's delegation // Original delegation: Alice -> Bob const aliceToBob = { "iss": "did:key:z6Mkm...Alice", "aud": "did:key:z6Mkm...Bob", "sub": "did:key:z6Mkm...Resource", "cmd": "/db/write", "exp": 1753353393, "nonce": "...", "cid": "zdpu...ABC" // CID of this delegation }; // Bob delegates to Carol const bobToCarol = { "iss": "did:key:z6Mkm...Bob", "aud": "did:key:z6Mkm...Carol", "sub": "did:key:z6Mkm...Resource", "cmd": "/db/write", "exp": 1753353393, "prf": [{"/": "zdpu...ABC"}] // References Alice->Bob }; // Alice revokes the delegation to Bob const revocation = { "iss": "did:key:z6Mkm...Alice", "aud": "did:key:z6Mkm...Resource", // Send to executor "sub": "did:key:z6Mkm...Resource", "cmd": "/ucan/revoke", "args": { "revoke": "zdpu...ABC" // CID of delegation to revoke }, "prf": [ {"/": "zdpu...ABC"}, // The delegation being revoked {"/": "zdpu...BobCarol"} // Optional: proof of downstream impact ] }; // After revocation, Carol's invocation is rejected const carolInvocation = { "iss": "did:key:z6Mkm...Carol", "aud": "did:key:z6Mkm...Resource", "cmd": "/db/write", "args": {"key": "value"}, "prf": [ {"/": "zdpu...ABC"}, // REVOKED {"/": "zdpu...BobCarol"} ] }; // Returns: NAK - delegation zdpu...ABC has been revoked // Validators must: // 1. Maintain revocation store indexed by CID // 2. Check all proofs against revocation list // 3. Mark revoked CIDs as permanently invalid // 4. Invalidate all downstream delegations ```