{"_id":"@bandeira-tech/b3nd-canon","_rev":"3-7e2feffb09ae5bce6829d554f807fc84","name":"@bandeira-tech/b3nd-canon","dist-tags":{"latest":"0.15.1"},"versions":{"0.11.0":{"name":"@bandeira-tech/b3nd-canon","version":"0.11.0","license":"MIT","_id":"@bandeira-tech/b3nd-canon@0.11.0","maintainers":[{"name":"r-bandeira-tech","email":"bandeira-tech@pm.me"}],"homepage":"https://github.com/bandeira-tech/b3nd-canon#readme","bugs":{"url":"https://github.com/bandeira-tech/b3nd-canon/issues"},"dist":{"shasum":"db26319dc5a99963683c24dd56c458c6d36c915f","tarball":"https://registry.npmjs.org/@bandeira-tech/b3nd-canon/-/b3nd-canon-0.11.0.tgz","fileCount":52,"integrity":"sha512-VU2hLhX2T1d10gxY0lKYo7mmjJGIad/6M9MQ5Ccp3ou1nmeXxedA7Y9wEj/DuRV5LEHrj9tOtMHg2oeApp5ViA==","signatures":[{"sig":"MEUCIQDEX9QGKKllmS/nacRBVOLHADvKkgAmG12u2DSCz+I2aQIgJetVXJ5q+4Cliu5rbFf6mcEj+EwNCknehWlNEGjRvPk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107831},"module":"./esm/mod.js","engines":{"node":">=20"},"exports":{".":{"types":"./esm/mod.d.ts","import":"./esm/mod.js"},"./msg":{"types":"./esm/msg.d.ts","import":"./esm/msg.js"},"./auth":{"types":"./esm/auth.d.ts","import":"./esm/auth.js"},"./hash":{"types":"./esm/hash.d.ts","import":"./esm/hash.js"},"./encrypt":{"types":"./esm/encrypt.d.ts","import":"./esm/encrypt.js"}},"gitHead":"7cd12378e02e5f703723f45932b0f504233101a5","scripts":{},"_npmUser":{"name":"r-bandeira-tech","email":"bandeira-tech@pm.me"},"repository":{"url":"git+https://github.com/bandeira-tech/b3nd-canon.git","type":"git"},"_npmVersion":"11.6.2","description":"B3nd Canon — protocol-building toolkit: msg, hash, auth, encrypt","directories":{},"sideEffects":false,"_nodeVersion":"24.11.1","dependencies":{"canonicalize":"2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/b3nd-canon_0.11.0_1777554207085_0.5493047418247143","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@bandeira-tech/b3nd-canon","version":"0.12.0","license":"MIT","_id":"@bandeira-tech/b3nd-canon@0.12.0","maintainers":[{"name":"r-bandeira-tech","email":"bandeira-tech@pm.me"}],"homepage":"https://github.com/bandeira-tech/b3nd-canon#readme","bugs":{"url":"https://github.com/bandeira-tech/b3nd-canon/issues"},"dist":{"shasum":"158d431292ef24978c9ed8cfc77243067f792038","tarball":"https://registry.npmjs.org/@bandeira-tech/b3nd-canon/-/b3nd-canon-0.12.0.tgz","fileCount":58,"integrity":"sha512-vlPrWRPsg2w08B0G3vgNXQIRLyuYZc0eIawwaenKSuLIMSa8D2EU9fuiS+U7QnxP12E8XPXWtAVjuB6H2vx2Mw==","signatures":[{"sig":"MEUCIQCZpdAmF4+VCVuIwnD60E6+xLKjqV2YTZFGCkFO8n8JzQIgPU+Vs9MKPVZZAjdwIsnM3arQ9iSAp5H2vmKDQEEggyE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108772},"module":"./esm/mod.js","engines":{"node":">=20"},"exports":{".":{"types":"./esm/mod.d.ts","import":"./esm/mod.js"},"./msg":{"types":"./esm/msg.d.ts","import":"./esm/msg.js"},"./auth":{"types":"./esm/auth.d.ts","import":"./esm/auth.js"},"./hash":{"types":"./esm/hash.d.ts","import":"./esm/hash.js"},"./encrypt":{"types":"./esm/encrypt.d.ts","import":"./esm/encrypt.js"}},"gitHead":"018b6edcf2e44ac6672a2b984b47f755179e726d","scripts":{},"_npmUser":{"name":"r-bandeira-tech","email":"bandeira-tech@pm.me"},"repository":{"url":"git+https://github.com/bandeira-tech/b3nd-canon.git","type":"git"},"_npmVersion":"11.6.2","description":"B3nd Canon — protocol-building toolkit: msg, auth (hash + encrypt re-exported from b3nd-core)","directories":{},"sideEffects":false,"_nodeVersion":"24.11.1","dependencies":{"canonicalize":"2.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/b3nd-canon_0.12.0_1778073610600_0.2948137025969202","host":"s3://npm-registry-packages-npm-production"}},"0.15.1":{"name":"@bandeira-tech/b3nd-canon","version":"0.15.1","description":"B3nd Canon — protocol-building toolkit: msg, auth (hash + encrypt re-exported from b3nd-core)","homepage":"https://github.com/bandeira-tech/b3nd-canon#readme","repository":{"type":"git","url":"git+https://github.com/bandeira-tech/b3nd-canon.git"},"license":"MIT","bugs":{"url":"https://github.com/bandeira-tech/b3nd-canon/issues"},"module":"./esm/mod.js","exports":{".":{"types":"./esm/mod.d.ts","import":"./esm/mod.js"},"./msg":{"types":"./esm/msg.d.ts","import":"./esm/msg.js"},"./hash":{"types":"./esm/hash.d.ts","import":"./esm/hash.js"},"./auth":{"types":"./esm/auth.d.ts","import":"./esm/auth.js"},"./encrypt":{"types":"./esm/encrypt.d.ts","import":"./esm/encrypt.js"},"./binary":{"types":"./esm/binary.d.ts","import":"./esm/binary.js"},"./data":{"types":"./esm/data.d.ts","import":"./esm/data.js"}},"scripts":{},"engines":{"node":">=20"},"sideEffects":false,"publishConfig":{"access":"public"},"dependencies":{"canonicalize":"2.0.0"},"gitHead":"4b78709fb2a61f4d5a111acfebd2258c812ba6da","_id":"@bandeira-tech/b3nd-canon@0.15.1","_nodeVersion":"22.23.1","_npmVersion":"12.0.1","dist":{"integrity":"sha512-NS/R/V0qiUjXv1iGwHPaLViBWIkmbXfNvcDrMLISq3DNpDuXaLq8k/epw30BHGKUq5b7JT/+CaL+WavJI/59Tg==","shasum":"921245a34fe5b41e5d9dfa99734a02fe13452b14","tarball":"https://registry.npmjs.org/@bandeira-tech/b3nd-canon/-/b3nd-canon-0.15.1.tgz","fileCount":73,"unpackedSize":139430,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFZ2OpApYyvm+RMKWfGxpT44FIN+8Iw5SxXz/Op5SNBfAiEAjMoMjrc04aU5vD6niT22yscNKd9pmIRbebGmRoLATsE="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:3eadd5a2-dae9-45cb-acb7-851f52aa173f"}},"directories":{},"maintainers":[{"name":"r-bandeira-tech","email":"bandeira-tech@pm.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/b3nd-canon_0.15.1_1783937756810_0.2620112586279877"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-30T13:03:26.990Z","modified":"2026-07-13T10:15:57.133Z","0.11.0":"2026-04-30T13:03:27.214Z","0.12.0":"2026-05-06T13:20:10.756Z","0.15.1":"2026-07-13T10:15:56.982Z"},"bugs":{"url":"https://github.com/bandeira-tech/b3nd-canon/issues"},"license":"MIT","homepage":"https://github.com/bandeira-tech/b3nd-canon#readme","repository":{"type":"git","url":"git+https://github.com/bandeira-tech/b3nd-canon.git"},"description":"B3nd Canon — protocol-building toolkit: msg, auth (hash + encrypt re-exported from b3nd-core)","maintainers":[{"name":"r-bandeira-tech","email":"bandeira-tech@pm.me"}],"readme":"# B3nd Canon\n\nProtocol-building toolkit for B3nd. Message envelopes, content addressing,\naccess control, and encryption -- the pieces a protocol designer composes on top\nof the core framework.\n\n[GitHub](https://github.com/bandeira-tech/b3nd-canon)\n\nDepends on\n[@bandeira-tech/b3nd-core](https://github.com/bandeira-tech/b3nd-core) for types\nand encoding.\n\n## Message Layer\n\nThe message primitive is `[uri, payload]`. When the payload follows the\nMessageData convention it carries `{ auth, inputs, outputs }` -- a signed\nenvelope that the rig decomposes into individual writes.\n\n```typescript\nimport {\n  message,\n  messageDataHandler,\n  messageDataProgram,\n} from \"@bandeira-tech/b3nd-canon/msg\";\nimport {\n  connection,\n  DataStoreClient,\n  Identity,\n  MemoryStore,\n  Rig,\n} from \"@bandeira-tech/b3nd-core\";\n\nconst client = new DataStoreClient(new MemoryStore());\n\nconst rig = new Rig({\n  routes: {\n    receive: [connection(client, [\"*\"])],\n    read: [connection(client, [\"*\"])],\n  },\n  programs: { \"hash://sha256\": messageDataProgram },\n  handlers: { \"msgdata:valid\": messageDataHandler },\n});\n\nconst id = await Identity.generate();\nconst auth = [\n  await id.sign({ inputs: [], outputs: [[\"mutable://open/x\", { v: 1 }]] }),\n];\nconst envelope = await message({\n  auth,\n  inputs: [],\n  outputs: [[\"mutable://open/x\", { v: 1 }]],\n});\n// envelope = [\"hash://sha256/{hex}\", { auth, inputs, outputs }]\n\nawait rig.send([envelope]);\n// The handler decomposes the envelope: persists the envelope at hash://,\n// writes each output to its destination URI, and nullifies inputs.\n```\n\n## Content Addressing\n\nHash-based URIs using `hash://sha256/{hex}`. JSON payloads canonicalized per RFC\n8785 before hashing.\n\n```typescript\nimport {\n  computeSha256,\n  generateHashUri,\n  verifyHashContent,\n} from \"@bandeira-tech/b3nd-canon/hash\";\n\nconst hash = await computeSha256({ hello: \"world\" });\nconst uri = generateHashUri(hash);\n// \"hash://sha256/93a23971a914e5eacbf0a8d25154cda309c3c1c72fbb9914d47c60f3cb681588\"\n\nconst result = await verifyHashContent(uri, { hello: \"world\" });\n// { valid: true, algorithm: \"sha256\", digest: \"93a2...\" }\n```\n\n### Hash Validator\n\nWrite-once enforcement for content-addressed storage:\n\n```typescript\nimport { hashValidator } from \"@bandeira-tech/b3nd-canon/hash\";\n\nconst rig = new Rig({\n  routes: { ... },\n  programs: { \"hash://sha256\": hashValidator(readFn) },\n});\n```\n\n## Access Control\n\nSignature-based access control that composes with the rig as programs.\n\n```typescript\nimport {\n  authValidation,\n  createCombinedAccess,\n  createPubkeyBasedAccess,\n} from \"@bandeira-tech/b3nd-canon/auth\";\n\n// Pubkey-based: the host names the domain (the program is\n// protocol://host); the owner pubkey is the first path segment.\n// mutable://accounts/{pubkey}/* requires a signature from {pubkey}\n// (or an explicitly granted key). Host-less locators throw.\nconst pubkeyAccess = createPubkeyBasedAccess();\n\n// Combined: pubkey namespace + relative path access lists\nconst access = createCombinedAccess(readFn);\n\n// Wire into rig as a program\nconst validate = authValidation(access);\n```\n\n## Encryption\n\nEd25519 signing, X25519 encryption, AES-GCM symmetric, and PBKDF2 key\nderivation. Shared with b3nd-core (Identity needs it).\n\n```typescript\nimport {\n  createAuthenticatedMessage,\n  decrypt,\n  encrypt,\n  generateEncryptionKeyPair,\n  generateSigningKeyPair,\n  sign,\n  verify,\n} from \"@bandeira-tech/b3nd-canon/encrypt\";\n\n// Sign a payload\nconst keys = await generateSigningKeyPair();\nconst signature = await sign(keys.privateKey, { action: \"transfer\" });\nconst valid = await verify(\n  keys.publicKeyHex,\n  { action: \"transfer\" },\n  signature,\n);\n\n// Encrypt (X25519 ECDH + HKDF + AES-GCM, forward secrecy via ephemeral keys)\nconst encKeys = await generateEncryptionKeyPair();\nconst encrypted = await encrypt(\n  new TextEncoder().encode(\"secret\"),\n  encKeys.publicKeyHex,\n);\nconst plaintext = await decrypt(encKeys.privateKeyHex, encrypted);\n```\n\n## b3nd-data\n\nFive behavior-named schemes — `hash://`, `immutable://`, `mutable://`,\n`signed://`, `encrypted://` — that put the **infrastructure guarantee** in the\ndata layer and let the **application domain** live in the path. Apps mount under\nany base path; protocol modules ship shape, not scheme. Lineage runs from early\nb3nd-sdk and firecat into the b3nd-data protocol shipped here.\n\nCanon exposes the vocabulary as data (constants + inspection helpers) and ships\nthe small set of utilities that go with it (base-path templating,\ndecomposed-record paths). Enforcement is an app/operator concern — none of these\nhelpers throw on \"wrong\" input; they return inspection results so callers\ncompose their own rules.\n\n```typescript\nimport {\n  checkSchemeIdShape, // returns a reason string for thing://<opaque-id> shapes\n  dataUri,\n  entryUri, // <root>/{data|meta|entries}/...\n  interpolateBasePath, // mutable://{account?shared}/notes\n  isBehaviorScheme, // true for hash://, immutable://, mutable://, signed://, encrypted://\n  metaUri,\n  parseDecomposed,\n  SCHEMES, // { hash, immutable, mutable, signed, encrypted }\n} from \"@bandeira-tech/b3nd-canon/data\";\n\n// Schemes name behaviors (rules), not domains\nconst inbox = interpolateBasePath(\n  \"encrypted://{account?anon}/inbox\",\n  { pubkey: \"0xabc\" },\n);\n// \"encrypted://0xabc/inbox\"\n\n// Decomposed record paths separate canonical data, bookkeeping, and history\nconst root = `${SCHEMES.signed}0xabc/taskwatch/t/abc123`;\ndataUri(root, \"title\");\n// \"signed://0xabc/taskwatch/t/abc123/data/title\"\nentryUri(root, \"2026-06-19T20:00:00Z\", \"progress\");\n// \"signed://0xabc/taskwatch/t/abc123/entries/2026-06-19T20:00:00Z-progress\"\n```\n\nSee `b3nd-skill notes/uri-scheme-shape.md` and `notes/base-path-injection.md`\nfor the rationale.\n\n## Libraries\n\n| Library        | Description                                                             |\n| -------------- | ----------------------------------------------------------------------- |\n| `b3nd-msg`     | Message envelopes, MessageData convention, program + handler            |\n| `b3nd-auth`    | Pubkey-based access control, relative path access, signature validation |\n| `b3nd-binary`  | JSON-safe binary codec (Uint8Array / ArrayBuffer round-trip)            |\n| `b3nd-data`    | Five behavior-named schemes, base-path templating, decomposed paths     |\n| `b3nd-hash`    | Content addressing — re-exported from `b3nd-core/hash`                  |\n| `b3nd-encrypt` | Ed25519 + X25519 + AES-GCM — re-exported from `b3nd-core/encrypt`       |\n\n## Subpath Exports\n\n```typescript\nimport { ... } from \"@bandeira-tech/b3nd-canon\";           // msg + auth + binary + data\nimport { ... } from \"@bandeira-tech/b3nd-canon/msg\";       // message envelopes\nimport { ... } from \"@bandeira-tech/b3nd-canon/auth\";      // access control\nimport { ... } from \"@bandeira-tech/b3nd-canon/binary\";    // binary JSON codec\nimport { ... } from \"@bandeira-tech/b3nd-canon/data\";      // b3nd-data: schemes, templates, paths\nimport { ... } from \"@bandeira-tech/b3nd-canon/hash\";      // content addressing (from b3nd-core)\nimport { ... } from \"@bandeira-tech/b3nd-canon/encrypt\";   // signing + encryption (from b3nd-core)\n```\n\n## Development\n\n```bash\ndeno task check       # Type check (covers every subpath via mod.ts)\ndeno task test        # Run libs/**/*.test.ts\ndeno task build:npm   # dnt dual-publish output to ./npm\n```\n\n## Project Structure\n\n```\n*.ts           # Subpath entry stubs (mod, msg, hash, auth, encrypt, binary, uri)\nlibs/          # In-repo libraries (msg, auth, binary, uri — hash and\n               # encrypt are re-exported from b3nd-core)\n```\n\n## Related\n\n- [b3nd-core](https://github.com/bandeira-tech/b3nd-core) -- framework\n  foundation (types, rig, clients, network)\n- [b3nd-sdk](https://github.com/bandeira-tech/b3nd-sdk) -- SDK umbrella that\n  re-exports core + canon\n\n## License\n\nMIT\n","readmeFilename":"README.md"}