@forestrie/mcp-register 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +178 -2
  3. package/bin/mcp-register.mjs +2 -0
  4. package/dist/core/base64.d.ts +7 -0
  5. package/dist/core/base64.d.ts.map +1 -0
  6. package/dist/core/base64.js +20 -0
  7. package/dist/core/base64.js.map +1 -0
  8. package/dist/core/delegation.d.ts +56 -0
  9. package/dist/core/delegation.d.ts.map +1 -0
  10. package/dist/core/delegation.js +130 -0
  11. package/dist/core/delegation.js.map +1 -0
  12. package/dist/core/grant.d.ts +41 -0
  13. package/dist/core/grant.d.ts.map +1 -0
  14. package/dist/core/grant.js +78 -0
  15. package/dist/core/grant.js.map +1 -0
  16. package/dist/core/hex.d.ts +4 -0
  17. package/dist/core/hex.d.ts.map +1 -0
  18. package/dist/core/hex.js +18 -0
  19. package/dist/core/hex.js.map +1 -0
  20. package/dist/core/index.d.ts +28 -0
  21. package/dist/core/index.d.ts.map +1 -0
  22. package/dist/core/index.js +21 -0
  23. package/dist/core/index.js.map +1 -0
  24. package/dist/core/issue.d.ts +38 -0
  25. package/dist/core/issue.d.ts.map +1 -0
  26. package/dist/core/issue.js +135 -0
  27. package/dist/core/issue.js.map +1 -0
  28. package/dist/core/limits.d.ts +9 -0
  29. package/dist/core/limits.d.ts.map +1 -0
  30. package/dist/core/limits.js +9 -0
  31. package/dist/core/limits.js.map +1 -0
  32. package/dist/core/scrapi.d.ts +66 -0
  33. package/dist/core/scrapi.d.ts.map +1 -0
  34. package/dist/core/scrapi.js +174 -0
  35. package/dist/core/scrapi.js.map +1 -0
  36. package/dist/core/signer.d.ts +24 -0
  37. package/dist/core/signer.d.ts.map +1 -0
  38. package/dist/core/signer.js +2 -0
  39. package/dist/core/signer.js.map +1 -0
  40. package/dist/core/statement.d.ts +26 -0
  41. package/dist/core/statement.d.ts.map +1 -0
  42. package/dist/core/statement.js +70 -0
  43. package/dist/core/statement.js.map +1 -0
  44. package/dist/core/version.d.ts +23 -0
  45. package/dist/core/version.d.ts.map +1 -0
  46. package/dist/core/version.js +23 -0
  47. package/dist/core/version.js.map +1 -0
  48. package/dist/core/x402.d.ts +99 -0
  49. package/dist/core/x402.d.ts.map +1 -0
  50. package/dist/core/x402.js +202 -0
  51. package/dist/core/x402.js.map +1 -0
  52. package/dist/net/delegate.d.ts +56 -0
  53. package/dist/net/delegate.d.ts.map +1 -0
  54. package/dist/net/delegate.js +182 -0
  55. package/dist/net/delegate.js.map +1 -0
  56. package/dist/net/http.d.ts +17 -0
  57. package/dist/net/http.d.ts.map +1 -0
  58. package/dist/net/http.js +52 -0
  59. package/dist/net/http.js.map +1 -0
  60. package/dist/net/index.d.ts +14 -0
  61. package/dist/net/index.d.ts.map +1 -0
  62. package/dist/net/index.js +13 -0
  63. package/dist/net/index.js.map +1 -0
  64. package/dist/net/write.d.ts +55 -0
  65. package/dist/net/write.d.ts.map +1 -0
  66. package/dist/net/write.js +46 -0
  67. package/dist/net/write.js.map +1 -0
  68. package/dist/node/cli.d.ts +8 -0
  69. package/dist/node/cli.d.ts.map +1 -0
  70. package/dist/node/cli.js +143 -0
  71. package/dist/node/cli.js.map +1 -0
  72. package/dist/node/grant-store.d.ts +49 -0
  73. package/dist/node/grant-store.d.ts.map +1 -0
  74. package/dist/node/grant-store.js +95 -0
  75. package/dist/node/grant-store.js.map +1 -0
  76. package/dist/node/grant-tools.d.ts +29 -0
  77. package/dist/node/grant-tools.d.ts.map +1 -0
  78. package/dist/node/grant-tools.js +498 -0
  79. package/dist/node/grant-tools.js.map +1 -0
  80. package/dist/node/ledger.d.ts +26 -0
  81. package/dist/node/ledger.d.ts.map +1 -0
  82. package/dist/node/ledger.js +78 -0
  83. package/dist/node/ledger.js.map +1 -0
  84. package/dist/node/payer.d.ts +48 -0
  85. package/dist/node/payer.d.ts.map +1 -0
  86. package/dist/node/payer.js +170 -0
  87. package/dist/node/payer.js.map +1 -0
  88. package/dist/node/resolve-input.d.ts +19 -0
  89. package/dist/node/resolve-input.d.ts.map +1 -0
  90. package/dist/node/resolve-input.js +76 -0
  91. package/dist/node/resolve-input.js.map +1 -0
  92. package/dist/node/server.d.ts +47 -0
  93. package/dist/node/server.d.ts.map +1 -0
  94. package/dist/node/server.js +212 -0
  95. package/dist/node/server.js.map +1 -0
  96. package/dist/node/signer-file.d.ts +34 -0
  97. package/dist/node/signer-file.d.ts.map +1 -0
  98. package/dist/node/signer-file.js +183 -0
  99. package/dist/node/signer-file.js.map +1 -0
  100. package/dist/node/store.d.ts +40 -0
  101. package/dist/node/store.d.ts.map +1 -0
  102. package/dist/node/store.js +117 -0
  103. package/dist/node/store.js.map +1 -0
  104. package/dist/node/text.d.ts +29 -0
  105. package/dist/node/text.d.ts.map +1 -0
  106. package/dist/node/text.js +124 -0
  107. package/dist/node/text.js.map +1 -0
  108. package/dist/node/tools.d.ts +118 -0
  109. package/dist/node/tools.d.ts.map +1 -0
  110. package/dist/node/tools.js +548 -0
  111. package/dist/node/tools.js.map +1 -0
  112. package/package.json +108 -3
  113. package/src/core/base64.ts +18 -0
  114. package/src/core/delegation.ts +239 -0
  115. package/src/core/grant.ts +127 -0
  116. package/src/core/hex.ts +18 -0
  117. package/src/core/index.ts +84 -0
  118. package/src/core/issue.ts +209 -0
  119. package/src/core/limits.ts +8 -0
  120. package/src/core/scrapi.ts +236 -0
  121. package/src/core/signer.ts +23 -0
  122. package/src/core/statement.ts +133 -0
  123. package/src/core/version.ts +25 -0
  124. package/src/core/x402.ts +314 -0
  125. package/src/net/delegate.ts +274 -0
  126. package/src/net/http.ts +71 -0
  127. package/src/net/index.ts +26 -0
  128. package/src/net/write.ts +124 -0
  129. package/src/node/cli.ts +170 -0
  130. package/src/node/grant-store.ts +154 -0
  131. package/src/node/grant-tools.ts +707 -0
  132. package/src/node/ledger.ts +98 -0
  133. package/src/node/payer.ts +241 -0
  134. package/src/node/resolve-input.ts +96 -0
  135. package/src/node/server.ts +332 -0
  136. package/src/node/signer-file.ts +251 -0
  137. package/src/node/store.ts +175 -0
  138. package/src/node/text.ts +153 -0
  139. package/src/node/tools.ts +810 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,UAAU,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,OAAO,EACP,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,eAAe,EACf,0BAA0B,EAC1B,YAAY,EACZ,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,qBAAqB,EACrB,sBAAsB,EACtB,aAAa,GACd,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `@forestrie/mcp-register` — the browser-safe core.
3
+ *
4
+ * This is the `"."` export. Everything reachable from here is pure over
5
+ * bytes: no `node:*`, no `fetch`, no filesystem, no MCP SDK, no key
6
+ * material. `"./net"` is the only place `fetch` is called, and `"./server"`
7
+ * is where the MCP adapter, the signer backend and the key file live.
8
+ * `pnpm run check:browser-safe` bundles this file for `platform: "browser"`
9
+ * and fails on any edge to a node builtin.
10
+ *
11
+ */
12
+ export { PACKAGE_VERSION, VERIFIER_VERSION, RESOLVE_VERSION, } from "./version.js";
13
+ export { MAX_STATEMENT_BYTES } from "./limits.js";
14
+ export { base64ToBytes, bytesToBase64 } from "./base64.js";
15
+ export { GrantError, inspectGrant, prepareGrantProblems, statementGrantProblems, } from "./grant.js";
16
+ export { MAX_PARENT_GRANT_BYTES, completeGrant, dataLogCreateExtendFlags, grantContent, issueChildGrant, parentGrantProblems, registerGrantBody, } from "./issue.js";
17
+ export { DEFAULT_PAY_ASSET, DEFAULT_PAY_NETWORK, PaymentError, TESTNETS, grantPaymentNonce, readPaymentPayload, readPaymentRequired, selectWithinCaps, } from "./x402.js";
18
+ export { StatementError, signStatement } from "./statement.js";
19
+ export { readProblem, readReceiptResponse, readRegisterGrantResponse, readRegisterResponse, readStatusResponse, } from "./scrapi.js";
20
+ export { DEFAULT_MMR_END, DelegationError, buildCertificateSubmission, checkVoucher, findStandingEntry, } from "./delegation.js";
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,wBAAwB,EACxB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AASnB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AASrB,OAAO,EACL,eAAe,EACf,eAAe,EACf,0BAA0B,EAC1B,YAAY,EACZ,iBAAiB,GAClB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { type GrantView } from "./grant.js";
2
+ import type { Es256Signer } from "./signer.js";
3
+ /** canopy reads at most this much register-grant body (`auth-grant.ts`). */
4
+ export declare const MAX_PARENT_GRANT_BYTES: number;
5
+ /** GF_CREATE|GF_EXTEND (byte 3), GF_DATA_LOG (byte 7): a data-log creation
6
+ * grant, the shape that both opens the child log and carries statements. */
7
+ export declare function dataLogCreateExtendFlags(): Uint8Array;
8
+ export interface IssueGrantInput {
9
+ /** The child data log the grant creates (UUID). */
10
+ logId: string;
11
+ /** The requester's authority log the grant is sequenced into (UUID). */
12
+ ownerLogId: string;
13
+ /** The key the grant names: 64 bytes x‖y of the performer's log key. */
14
+ grantData: Uint8Array;
15
+ /** The batch ceiling canopy prices a paid child grant by. At least 1. */
16
+ maxHeight: number;
17
+ }
18
+ export interface IssuedGrant {
19
+ /** The signed grant, untagged COSE Sign1. */
20
+ grant: Uint8Array;
21
+ /** The canonical grant v0 CBOR that was signed (its SHA-256 is the payload). */
22
+ grantPayload: Uint8Array;
23
+ flags: Uint8Array;
24
+ }
25
+ export declare function issueChildGrant(input: IssueGrantInput, authority: Es256Signer): Promise<IssuedGrant>;
26
+ /**
27
+ * Why `parent` cannot authorise a child grant signed by `authorityXY`, or
28
+ * `[]`. The parent is the requester's own authority grant: an auth-log
29
+ * grant naming the authority key, whose log becomes the child's owner.
30
+ */
31
+ export declare function parentGrantProblems(parent: GrantView, authorityXY: Uint8Array): string[];
32
+ /** The register-grant request body: canonical CBOR `{parentGrant: <bytes>}`. */
33
+ export declare function registerGrantBody(parentGrant: Uint8Array): Uint8Array;
34
+ /** Merge the sealed receipt and the entry's idtimestamp into the grant. */
35
+ export declare function completeGrant(grant: Uint8Array, receipt: Uint8Array, entryIdHex: string): Uint8Array;
36
+ /** The grant v0 CBOR a grant carries at unprotected -65538: its content. */
37
+ export declare function grantContent(grant: Uint8Array): Uint8Array;
38
+ //# sourceMappingURL=issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../src/core/issue.ts"],"names":[],"mappings":"AAoCA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW/C,4EAA4E;AAC5E,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAEhD;6EAC6E;AAC7E,wBAAgB,wBAAwB,IAAI,UAAU,CAKrD;AAED,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,SAAS,EAAE,UAAU,CAAC;IACtB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,KAAK,EAAE,UAAU,CAAC;IAClB,gFAAgF;IAChF,YAAY,EAAE,UAAU,CAAC;IACzB,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,WAAW,GACrB,OAAO,CAAC,WAAW,CAAC,CAwDtB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,UAAU,GACtB,MAAM,EAAE,CAeV;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,CAIrE;AAID,2EAA2E;AAC3E,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,UAAU,EACnB,UAAU,EAAE,MAAM,GACjB,UAAU,CAeZ;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAU1D"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Issue a child grant as the requester, and complete it once canopy has
3
+ * sealed it.
4
+ *
5
+ * The requester owns an authority log (ARC-0028: the requester funds, the
6
+ * performer writes) and is its own grant issuer: it signs a child grant
7
+ * with its authority key, naming the performer's log key in `grantData`.
8
+ * Forestrie runs no issuer.
9
+ *
10
+ * The bytes are the ES256 profile of `@forestrie/grant-builder`'s
11
+ * `signGrantPayloadWithEs256Pem`, which univocity verifies
12
+ * (`verifyCoseSign1ES256`), with the PEM replaced by the signer seam:
13
+ *
14
+ * - untagged COSE Sign1, protected `{1: -7}` (wire `a10126`);
15
+ * - payload the 32-byte SHA-256 of the canonical grant v0 CBOR;
16
+ * - signature over `["Signature1", protected, h'', payload]`, r‖s;
17
+ * - unprotected `{-65537: 8 zero bytes, -65538: grant v0 CBOR}`, in that
18
+ * canonical order.
19
+ *
20
+ * grant-builder itself is not imported: its index pulls in its node-only
21
+ * PEM module, and this file is browser-safe.
22
+ *
23
+ * Completing a grant merges the receipt (396) and the entry's idtimestamp
24
+ * (-65537) into the unprotected header without re-signing, as forestrie-cli
25
+ * `register-grant-complete.ts` does. The completed grant is the
26
+ * `Forestrie-Grant` credential register_statement and delegate_sealing take.
27
+ */
28
+ import { appendCborBstr, appendCborText, decodeCoseSign1, encodeCborDeterministic, encodeGrantPayloadV0Canonical, mergeUnprotectedIntoCoseSign1, uuidToBytes, } from "@forestrie/encoding";
29
+ import { GrantError } from "./grant.js";
30
+ import { bytesEqual, sha256 } from "./hex.js";
31
+ const ES256_PROTECTED_HEADER = new Uint8Array([0xa1, 0x01, 0x26]);
32
+ // CBOR negative-int keys (major type 1): -65537, then -65538.
33
+ const CBOR_KEY_IDTIMESTAMP = [0x3a, 0x00, 0x01, 0x00, 0x00];
34
+ const CBOR_KEY_FORESTRIE_GRANT_V0 = [0x3a, 0x00, 0x01, 0x00, 0x01];
35
+ const HEADER_RECEIPT = 396;
36
+ const HEADER_IDTIMESTAMP = -65537;
37
+ /** canopy's register-grant body key for the parent grant evidence. */
38
+ const PARENT_GRANT_BODY_KEY = "parentGrant";
39
+ /** canopy reads at most this much register-grant body (`auth-grant.ts`). */
40
+ export const MAX_PARENT_GRANT_BYTES = 16 * 1024;
41
+ /** GF_CREATE|GF_EXTEND (byte 3), GF_DATA_LOG (byte 7): a data-log creation
42
+ * grant, the shape that both opens the child log and carries statements. */
43
+ export function dataLogCreateExtendFlags() {
44
+ const flags = new Uint8Array(8);
45
+ flags[3] = 0x03;
46
+ flags[7] = 0x02;
47
+ return flags;
48
+ }
49
+ export async function issueChildGrant(input, authority) {
50
+ let logId;
51
+ let ownerLogId;
52
+ try {
53
+ logId = uuidToBytes(input.logId);
54
+ ownerLogId = uuidToBytes(input.ownerLogId);
55
+ }
56
+ catch {
57
+ throw new GrantError(`logId and ownerLogId must be UUIDs (got ${input.logId}, ${input.ownerLogId})`);
58
+ }
59
+ if (bytesEqual(logId, ownerLogId))
60
+ throw new GrantError("a child grant must name a log other than its owner (logId equals ownerLogId)");
61
+ if (input.grantData.length !== 64)
62
+ throw new GrantError(`grantData must be a 64-byte ES256 x‖y (got ${input.grantData.length} bytes): canopy forwards only ES256 child roots`);
63
+ if (!Number.isSafeInteger(input.maxHeight) || input.maxHeight < 1)
64
+ throw new GrantError(`maxHeight must be a positive integer (got ${input.maxHeight})`);
65
+ const flags = dataLogCreateExtendFlags();
66
+ const grantPayload = encodeGrantPayloadV0Canonical({
67
+ logId,
68
+ ownerLogId,
69
+ grant: flags,
70
+ maxHeight: input.maxHeight,
71
+ minGrowth: 0,
72
+ grantData: input.grantData,
73
+ });
74
+ const payload = await sha256(grantPayload);
75
+ const sig = [0x84];
76
+ appendCborText(sig, "Signature1");
77
+ appendCborBstr(sig, ES256_PROTECTED_HEADER);
78
+ appendCborBstr(sig, new Uint8Array(0));
79
+ appendCborBstr(sig, payload);
80
+ const signature = await authority.sign(new Uint8Array(sig));
81
+ if (signature.length !== 64)
82
+ throw new GrantError(`the authority signer returned ${signature.length} bytes; ES256 needs a 64-byte r‖s`);
83
+ const out = [0x84];
84
+ appendCborBstr(out, ES256_PROTECTED_HEADER);
85
+ out.push(0xa2);
86
+ out.push(...CBOR_KEY_IDTIMESTAMP);
87
+ appendCborBstr(out, new Uint8Array(8));
88
+ out.push(...CBOR_KEY_FORESTRIE_GRANT_V0);
89
+ appendCborBstr(out, grantPayload);
90
+ appendCborBstr(out, payload);
91
+ appendCborBstr(out, signature);
92
+ return { grant: new Uint8Array(out), grantPayload, flags };
93
+ }
94
+ /**
95
+ * Why `parent` cannot authorise a child grant signed by `authorityXY`, or
96
+ * `[]`. The parent is the requester's own authority grant: an auth-log
97
+ * grant naming the authority key, whose log becomes the child's owner.
98
+ */
99
+ export function parentGrantProblems(parent, authorityXY) {
100
+ const problems = [];
101
+ if (!parent.authLog)
102
+ problems.push(`the parent grant's flags ${parent.flagsHex} are not an authority-log grant (GF_AUTH_LOG); only an authority log can own a child log`);
103
+ if (parent.grantData.length !== 64)
104
+ problems.push(`the parent grant names a ${parent.grantData.length}-byte key; canopy's prepare refuses non-ES256 parents, so the authority key must be ES256`);
105
+ else if (!bytesEqual(parent.grantData, authorityXY))
106
+ problems.push("the parent grant names a different key than this server's authority key, so this key does not own that authority log and cannot issue under it");
107
+ return problems;
108
+ }
109
+ /** The register-grant request body: canonical CBOR `{parentGrant: <bytes>}`. */
110
+ export function registerGrantBody(parentGrant) {
111
+ return encodeCborDeterministic(new Map([[PARENT_GRANT_BODY_KEY, parentGrant]]));
112
+ }
113
+ const ENTRY_ID = /^[0-9a-f]{32}$/;
114
+ /** Merge the sealed receipt and the entry's idtimestamp into the grant. */
115
+ export function completeGrant(grant, receipt, entryIdHex) {
116
+ if (!ENTRY_ID.test(entryIdHex))
117
+ throw new GrantError(`entryId must be 32 lowercase hex (got ${entryIdHex})`);
118
+ const idtimestamp = new Uint8Array(8);
119
+ for (let i = 0; i < 8; i++)
120
+ idtimestamp[i] = parseInt(entryIdHex.slice(i * 2, i * 2 + 2), 16);
121
+ return mergeUnprotectedIntoCoseSign1(grant, new Map([
122
+ [HEADER_RECEIPT, receipt],
123
+ [HEADER_IDTIMESTAMP, idtimestamp],
124
+ ]));
125
+ }
126
+ /** The grant v0 CBOR a grant carries at unprotected -65538: its content. */
127
+ export function grantContent(grant) {
128
+ const sign1 = decodeCoseSign1(grant);
129
+ const unprotected = sign1?.unprotected;
130
+ const content = unprotected instanceof Map ? unprotected.get(-65538) : undefined;
131
+ if (!(content instanceof Uint8Array) || content.length === 0)
132
+ throw new GrantError("not a Forestrie-Grant: no grant v0 CBOR at unprotected label -65538");
133
+ return content;
134
+ }
135
+ //# sourceMappingURL=issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue.js","sourceRoot":"","sources":["../../src/core/issue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * canopy's statement size limit, `maxStatementSize` in its SCITT
3
+ * configuration (canopy `scrapi/transparency-configuration.ts`): 4 MiB,
4
+ * checked against the signed statement's Content-Length. The limit is on
5
+ * the COSE Sign1 as sent, so the payload must leave room for the headers
6
+ * and the signature.
7
+ */
8
+ export declare const MAX_STATEMENT_BYTES: number;
9
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../src/core/limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,QAAkB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * canopy's statement size limit, `maxStatementSize` in its SCITT
3
+ * configuration (canopy `scrapi/transparency-configuration.ts`): 4 MiB,
4
+ * checked against the signed statement's Content-Length. The limit is on
5
+ * the COSE Sign1 as sent, so the payload must leave room for the headers
6
+ * and the signature.
7
+ */
8
+ export const MAX_STATEMENT_BYTES = 4 * 1024 * 1024;
9
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../src/core/limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC"}
@@ -0,0 +1,66 @@
1
+ /** The parts of a response these readers look at. Headers keyed lowercase. */
2
+ export interface ResponseView {
3
+ url: string;
4
+ status: number;
5
+ headers: Record<string, string>;
6
+ body: Uint8Array;
7
+ }
8
+ export interface Problem {
9
+ status: number;
10
+ title: string;
11
+ detail?: string;
12
+ reason?: string;
13
+ /** From the response's Retry-After, e.g. canopy's queue-full 503. */
14
+ retryAfterSeconds?: number;
15
+ }
16
+ export declare function readProblem(res: ResponseView): Problem;
17
+ /** The origin of a base URL, or `undefined` when it does not parse. */
18
+ export declare function originOf(baseUrl: string): string | undefined;
19
+ export type RegisterOutcome = {
20
+ kind: "accepted";
21
+ statusUrl: string;
22
+ retryAfterSeconds?: number;
23
+ } | {
24
+ kind: "problem";
25
+ problem: Problem;
26
+ };
27
+ export declare function readRegisterResponse(res: ResponseView, origin?: string): RegisterOutcome;
28
+ export type RegisterGrantOutcome = RegisterOutcome | {
29
+ kind: "payment_required";
30
+ /** The raw `X-PAYMENT-REQUIRED` header (base64 JSON), undecoded. */
31
+ paymentRequiredHeader: string;
32
+ problem: Problem;
33
+ };
34
+ /**
35
+ * canopy's answer to `POST /register/{R}/grants`: 303 to the grant's status
36
+ * URL, or 402 with an `X-PAYMENT-REQUIRED` challenge when the parent grant
37
+ * makes this child payment-gated (and again, with canopy's reason, when a
38
+ * presented `X-PAYMENT` is refused). A 402 without the header is a problem.
39
+ */
40
+ export declare function readRegisterGrantResponse(res: ResponseView, origin?: string): RegisterGrantOutcome;
41
+ export type StatusOutcome = {
42
+ kind: "pending";
43
+ retryAfterSeconds: number;
44
+ } | {
45
+ kind: "sequenced";
46
+ receiptUrl: string;
47
+ massifHeight: number;
48
+ entryId: string;
49
+ } | {
50
+ kind: "problem";
51
+ problem: Problem;
52
+ };
53
+ export declare function readStatusResponse(res: ResponseView, origin?: string): StatusOutcome;
54
+ export type ReceiptOutcome = {
55
+ kind: "sealed";
56
+ receipt: Uint8Array;
57
+ contentType?: string;
58
+ } | {
59
+ kind: "awaiting_seal";
60
+ reason: string;
61
+ } | {
62
+ kind: "problem";
63
+ problem: Problem;
64
+ };
65
+ export declare function readReceiptResponse(res: ResponseView): ReceiptOutcome;
66
+ //# sourceMappingURL=scrapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrapi.d.ts","sourceRoot":"","sources":["../../src/core/scrapi.ts"],"names":[],"mappings":"AAmBA,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAkCtD;AAqCD,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM5D;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1C,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,eAAe,CAYjB;AAED,MAAM,MAAM,oBAAoB,GAC5B,eAAe,GACf;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEN;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,YAAY,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,oBAAoB,CAStB;AAID,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAC9C;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1C,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,YAAY,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,aAAa,CAcf;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAY1C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,cAAc,CAgBrE"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Read canopy's answers to the write path, over already-fetched responses.
3
+ *
4
+ * The registration contract (canopy `scrapi/register-signed-statement.ts`,
5
+ * `scrapi/query-registration-status.ts`, `scrapi/resolve-receipt.ts`):
6
+ *
7
+ * - `POST /register/{R}/entries` answers 303 with `Location` = the
8
+ * transient status URL `…/logs/{R}/{T}/entries/{sha256(statement)}`.
9
+ * - The status URL answers 303 to itself (`Retry-After`) until the entry is
10
+ * sequenced, then 303 to the permanent receipt URL
11
+ * `…/logs/{R}/{T}/{massifHeight}/entries/{entryId}/receipt`.
12
+ * - The receipt URL answers 404 "checkpoint missing" (or "checkpoint does
13
+ * not cover entry") until a checkpoint covering the entry is sealed,
14
+ * then 200 with the receipt. Other 404s are faults.
15
+ * - Failures are `application/problem+cbor` maps `{title, status, detail?,
16
+ * reason?}`.
17
+ */
18
+ import { decodeCborDeterministic } from "@forestrie/encoding";
19
+ export function readProblem(res) {
20
+ const retry = retryAfter(res);
21
+ const base = {
22
+ status: res.status,
23
+ title: `HTTP ${res.status}`,
24
+ ...(retry !== undefined ? { retryAfterSeconds: retry } : {}),
25
+ };
26
+ if (res.body.length === 0)
27
+ return base;
28
+ try {
29
+ const decoded = decodeCborDeterministic(res.body);
30
+ const get = (k) => decoded instanceof Map
31
+ ? decoded.get(k)
32
+ : typeof decoded === "object" && decoded !== null
33
+ ? decoded[k]
34
+ : undefined;
35
+ const title = get("title");
36
+ const detail = get("detail");
37
+ const reason = get("reason");
38
+ if (typeof title === "string")
39
+ return {
40
+ ...base,
41
+ title,
42
+ ...(typeof detail === "string" ? { detail } : {}),
43
+ ...(typeof reason === "string" ? { reason } : {}),
44
+ };
45
+ }
46
+ catch {
47
+ // Not CBOR: fall through to printable text.
48
+ }
49
+ const text = new TextDecoder()
50
+ .decode(res.body)
51
+ .replace(/[^\x20-\x7e]+/g, " ")
52
+ .trim();
53
+ return text ? { ...base, detail: text.slice(0, 200) } : base;
54
+ }
55
+ /**
56
+ * Resolve a Location against the URL that answered, and keep it on the
57
+ * expected origin: a status or receipt URL that points elsewhere is not
58
+ * followed (the caller would otherwise fetch wherever a server says).
59
+ */
60
+ function follow(location, res, origin) {
61
+ let url;
62
+ try {
63
+ url = new URL(location, res.url);
64
+ }
65
+ catch {
66
+ return {
67
+ ok: false,
68
+ problem: {
69
+ status: res.status,
70
+ title: "Invalid Location",
71
+ detail: `the Location header is not a URL: ${location.slice(0, 200)}`,
72
+ },
73
+ };
74
+ }
75
+ if (origin !== undefined && url.origin !== origin)
76
+ return {
77
+ ok: false,
78
+ problem: {
79
+ status: res.status,
80
+ title: "Unexpected Location",
81
+ detail: `the Location header points to ${url.origin}, not ${origin}; not following it`,
82
+ },
83
+ };
84
+ return { ok: true, url: url.toString() };
85
+ }
86
+ /** The origin of a base URL, or `undefined` when it does not parse. */
87
+ export function originOf(baseUrl) {
88
+ try {
89
+ return new URL(baseUrl).origin;
90
+ }
91
+ catch {
92
+ return undefined;
93
+ }
94
+ }
95
+ export function readRegisterResponse(res, origin) {
96
+ if (res.status === 303 && res.headers["location"]) {
97
+ const next = follow(res.headers["location"], res, origin);
98
+ if (!next.ok)
99
+ return { kind: "problem", problem: next.problem };
100
+ const retry = retryAfter(res);
101
+ return {
102
+ kind: "accepted",
103
+ statusUrl: next.url,
104
+ ...(retry !== undefined ? { retryAfterSeconds: retry } : {}),
105
+ };
106
+ }
107
+ return { kind: "problem", problem: readProblem(res) };
108
+ }
109
+ /**
110
+ * canopy's answer to `POST /register/{R}/grants`: 303 to the grant's status
111
+ * URL, or 402 with an `X-PAYMENT-REQUIRED` challenge when the parent grant
112
+ * makes this child payment-gated (and again, with canopy's reason, when a
113
+ * presented `X-PAYMENT` is refused). A 402 without the header is a problem.
114
+ */
115
+ export function readRegisterGrantResponse(res, origin) {
116
+ const header = res.headers["x-payment-required"];
117
+ if (res.status === 402 && header)
118
+ return {
119
+ kind: "payment_required",
120
+ paymentRequiredHeader: header,
121
+ problem: readProblem(res),
122
+ };
123
+ return readRegisterResponse(res, origin);
124
+ }
125
+ const RECEIPT_PATH = /\/(\d+)\/entries\/([0-9a-f]{32})\/receipt$/;
126
+ export function readStatusResponse(res, origin) {
127
+ if (res.status !== 303)
128
+ return { kind: "problem", problem: readProblem(res) };
129
+ const next = follow(res.headers["location"] ?? res.url, res, origin);
130
+ if (!next.ok)
131
+ return { kind: "problem", problem: next.problem };
132
+ const match = RECEIPT_PATH.exec(new URL(next.url).pathname);
133
+ if (match)
134
+ return {
135
+ kind: "sequenced",
136
+ receiptUrl: next.url,
137
+ massifHeight: Number(match[1]),
138
+ entryId: match[2],
139
+ };
140
+ return { kind: "pending", retryAfterSeconds: retryAfter(res) ?? 1 };
141
+ }
142
+ /**
143
+ * The 404s that mean "sequenced, not yet sealed": no checkpoint yet, or one
144
+ * that predates the entry (canopy `scrapi/resolve-receipt.ts`). canopy
145
+ * answers 404 for other reasons too — a missing massif, a height or index
146
+ * mismatch, an unknown forest — and those will not fix themselves by
147
+ * waiting, so they are problems, with canopy's reason.
148
+ */
149
+ const AWAITING_SEAL = /checkpoint missing\)$|checkpoint does not cover entry\)$/;
150
+ export function readReceiptResponse(res) {
151
+ if (res.status === 404) {
152
+ const problem = readProblem(res);
153
+ if (AWAITING_SEAL.test(problem.title))
154
+ return { kind: "awaiting_seal", reason: problem.title };
155
+ return { kind: "problem", problem };
156
+ }
157
+ if (res.status === 200 && res.body.length > 0)
158
+ return {
159
+ kind: "sealed",
160
+ receipt: res.body,
161
+ ...(res.headers["content-type"]
162
+ ? { contentType: res.headers["content-type"] }
163
+ : {}),
164
+ };
165
+ return { kind: "problem", problem: readProblem(res) };
166
+ }
167
+ function retryAfter(res) {
168
+ const raw = res.headers["retry-after"];
169
+ if (raw === undefined)
170
+ return undefined;
171
+ const n = Number(raw);
172
+ return Number.isFinite(n) && n >= 0 ? n : undefined;
173
+ }
174
+ //# sourceMappingURL=scrapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrapi.js","sourceRoot":"","sources":["../../src/core/scrapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The signer seam: every signature this package makes goes through one
3
+ * `Es256Signer`. Core code builds the exact bytes to be signed and hands
4
+ * them over; it never sees a private key, and no signature byte ever
5
+ * arrives from a tool argument. Where the key lives — a local key file
6
+ * (the default, `src/node/signer-file.ts`), a KMS, a remote signer — is the
7
+ * backend's business.
8
+ *
9
+ * ES256 only: canopy's child-log paths (register-grant auto-forward and
10
+ * `POST /api/forest/{child}/prepare`) accept 64-byte P-256 roots only, so a
11
+ * KS256 log key could not delegate its own sealing without an operator.
12
+ */
13
+ export interface Es256Signer {
14
+ /** The P-256 public key as 64 bytes x‖y — what a grant's `grantData` names. */
15
+ publicKeyXY(): Promise<Uint8Array>;
16
+ /**
17
+ * ECDSA P-256 with SHA-256 over `message` (the signer hashes), returned as
18
+ * IEEE P1363 r‖s, 64 bytes. For COSE that message is the Sig_structure.
19
+ */
20
+ sign(message: Uint8Array): Promise<Uint8Array>;
21
+ /** Where the key lives, for humans: never key material. */
22
+ readonly description: string;
23
+ }
24
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/core/signer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC;;;OAGG;IACH,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,2DAA2D;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../../src/core/signer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import type { Es256Signer } from "./signer.js";
2
+ export declare class StatementError extends Error {
3
+ readonly code: "invalid_input" | "too_large" | "signer_failed";
4
+ constructor(code: "invalid_input" | "too_large" | "signer_failed", message: string);
5
+ }
6
+ export interface SignStatementInput {
7
+ payload: Uint8Array;
8
+ /** The payload's media type, carried in protected header 3. */
9
+ contentType: string;
10
+ /** CWT iss; defaults to the hex of the kid. */
11
+ issuer?: string;
12
+ /** CWT sub; defaults to `sha-256:<hex of payload>`, as forestrie-cli does. */
13
+ subject?: string;
14
+ /** CWT iat, seconds since the epoch; omitted when absent. */
15
+ issuedAt?: number;
16
+ }
17
+ export interface SignedStatement {
18
+ statement: Uint8Array;
19
+ /** sha256 of the statement: the id in canopy's status URL. */
20
+ contentHash: string;
21
+ kid: Uint8Array;
22
+ issuer: string;
23
+ subject: string;
24
+ }
25
+ export declare function signStatement(input: SignStatementInput, signer: Es256Signer): Promise<SignedStatement>;
26
+ //# sourceMappingURL=statement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statement.d.ts","sourceRoot":"","sources":["../../src/core/statement.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,qBAAa,cAAe,SAAQ,KAAK;IAErC,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW,GAAG,eAAe;gBAArD,IAAI,EAAE,eAAe,GAAG,WAAW,GAAG,eAAe,EAC9D,OAAO,EAAE,MAAM;CAIlB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,UAAU,CAAC;IACpB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,UAAU,CAAC;IACtB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC,CA0E1B"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Build and sign the statement canopy registers: an untagged COSE Sign1,
3
+ * payload attached, protected header `{1: -7, 3: cty, 4: kid, 15: {1: iss,
4
+ * 2: sub}}`, empty unprotected header.
5
+ *
6
+ * Byte-for-byte the construction of `@forestrie/encoding`'s
7
+ * `signCoseSign1Statement` (the one forestrie-cli uses), with the
8
+ * WebCrypto call replaced by the signer seam: the same protected map, the
9
+ * same Sig_structure, the same envelope encoder.
10
+ *
11
+ * kid is the key's 32-byte x coordinate, the binding canopy checks first
12
+ * (canopy `grant/statement-signer-binding.ts`).
13
+ */
14
+ import { COSE_ALG_ES256, encodeCoseProtectedMapBytes, encodeCoseSign1Statement, encodeSigStructure, verifyCoseSign1WithParsedKey, } from "@forestrie/encoding";
15
+ import { MAX_STATEMENT_BYTES } from "./limits.js";
16
+ import { sha256, toHex } from "./hex.js";
17
+ export class StatementError extends Error {
18
+ code;
19
+ constructor(code, message) {
20
+ super(message);
21
+ this.code = code;
22
+ }
23
+ }
24
+ export async function signStatement(input, signer) {
25
+ if (input.payload.length === 0)
26
+ throw new StatementError("invalid_input", "payload is empty");
27
+ if (input.payload.length > MAX_STATEMENT_BYTES)
28
+ throw new StatementError("too_large", `payload is ${input.payload.length} bytes; canopy accepts signed statements up to ${MAX_STATEMENT_BYTES} bytes. Register a small manifest naming the artefact's digest instead`);
29
+ if (!input.contentType.trim())
30
+ throw new StatementError("invalid_input", "contentType is empty");
31
+ const xy = await signer.publicKeyXY();
32
+ if (xy.length !== 64)
33
+ throw new StatementError("signer_failed", `signer returned a ${xy.length}-byte public key; ES256 needs 64 bytes x‖y`);
34
+ const kid = xy.slice(0, 32);
35
+ const issuer = input.issuer ?? toHex(kid);
36
+ const subject = input.subject ?? `sha-256:${toHex(await sha256(input.payload))}`;
37
+ const options = {
38
+ alg: COSE_ALG_ES256,
39
+ cty: input.contentType,
40
+ cwtClaims: {
41
+ iss: issuer,
42
+ sub: subject,
43
+ ...(input.issuedAt !== undefined ? { iat: input.issuedAt } : {}),
44
+ },
45
+ };
46
+ const sigStructure = encodeSigStructure(encodeCoseProtectedMapBytes(kid, options), new Uint8Array(0), input.payload);
47
+ const signature = await signer.sign(sigStructure);
48
+ if (signature.length !== 64)
49
+ throw new StatementError("signer_failed", `signer returned a ${signature.length}-byte signature; ES256 is 64 bytes r‖s`);
50
+ const statement = encodeCoseSign1Statement(input.payload, kid, signature, options);
51
+ // Check our own work before canopy does: a signer that signs with a key
52
+ // other than the one it reports would otherwise surface as a bare 403.
53
+ const verified = await verifyCoseSign1WithParsedKey(statement, {
54
+ x: xy.slice(0, 32),
55
+ y: xy.slice(32),
56
+ curve: "P-256",
57
+ });
58
+ if (!verified)
59
+ throw new StatementError("signer_failed", "the signature does not verify under the signer's own public key");
60
+ if (statement.length > MAX_STATEMENT_BYTES)
61
+ throw new StatementError("too_large", `the signed statement is ${statement.length} bytes; canopy's limit is ${MAX_STATEMENT_BYTES}`);
62
+ return {
63
+ statement,
64
+ contentHash: toHex(await sha256(statement)),
65
+ kid,
66
+ issuer,
67
+ subject,
68
+ };
69
+ }
70
+ //# sourceMappingURL=statement.js.map