@peac/protocol 0.12.13 → 0.13.0

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.
@@ -43,17 +43,32 @@ export declare function parsePolicyManifest(text: string, contentType?: string):
43
43
  */
44
44
  export declare function fetchPolicyManifest(baseUrl: string): Promise<PEACPolicyManifest>;
45
45
  /**
46
- * @deprecated Use parseIssuerConfig instead. Will be removed in v1.0.
46
+ * @deprecated Parses a legacy dual-purpose `peac.txt` manifest that carried
47
+ * both policy hints and key-discovery fields (`verify`, `jwks`). This shape
48
+ * is retired: `peac.txt` is a policy-document surface per
49
+ * `docs/specs/PEAC-TXT.md`, and the normative key-discovery chain is
50
+ * `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS
51
+ * (see `docs/specs/PEAC-ISSUER.md`). Use `parseIssuerConfig` for issuer
52
+ * metadata, and `@peac/policy-kit.parsePolicyDocument` for `peac-policy/0.1`
53
+ * documents referenced from `peac.txt`. Removal target: next cleanup release.
47
54
  *
48
- * Parse a PEAC discovery manifest from YAML-like text.
49
- * This function is maintained for backward compatibility only.
55
+ * Parse a PEAC discovery manifest from YAML-like text. Retained only for
56
+ * backward compatibility with callers that have not yet migrated.
50
57
  */
51
58
  export declare function parseDiscovery(text: string): PEACDiscovery;
52
59
  /**
53
- * @deprecated Use fetchIssuerConfig instead. Will be removed in v1.0.
60
+ * @deprecated Fetches /.well-known/peac.txt and parses it as a legacy
61
+ * dual-purpose manifest. This shape is retired: `peac.txt` is a policy
62
+ * document (see `docs/specs/PEAC-TXT.md`) and key discovery flows through
63
+ * `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS
64
+ * (see `docs/specs/PEAC-ISSUER.md`). Use `fetchIssuerConfig` for issuer
65
+ * metadata. To parse the `peac-policy/0.1` document referenced from
66
+ * `peac.txt`, fetch its bytes and call
67
+ * `@peac/policy-kit.parsePolicyDocument`. Removal target: next cleanup
68
+ * release.
54
69
  *
55
- * Fetch and parse PEAC discovery from an issuer URL.
56
- * This function is maintained for backward compatibility only.
70
+ * Fetch and parse PEAC discovery from an issuer URL. Retained only for
71
+ * backward compatibility with callers that have not yet migrated.
57
72
  */
58
73
  export declare function fetchDiscovery(issuerUrl: string): Promise<PEACDiscovery>;
59
74
  //# sourceMappingURL=discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EAOd,MAAM,cAAc,CAAC;AAMtB;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAoGzE;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsCpF;AAiBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAoD1F;AAkFD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA+CtF;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAkD1D;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B9E"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EAOd,MAAM,cAAc,CAAC;AAMtB;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAoGzE;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsCpF;AAiBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAoD1F;AAkFD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA+CtF;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAkD1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B9E"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Document binding utilities (Layer 3)
3
+ *
4
+ * Generalized binding helpers for `peac-policy/0.1` policy documents,
5
+ * x402 PR #1986 `terms` representations, and any other referenced
6
+ * document. Three-state semantics (`verified` / `failed` / `unavailable`)
7
+ * are reused from `policy-binding`.
8
+ *
9
+ * Helper-naming rule (normative, see `docs/specs/DOCUMENT-BINDING.md`):
10
+ * - `computeJsonDocumentDigestJcs` is JSON-only (RFC 8785 JCS + SHA-256).
11
+ * - `computeTextDocumentDigestUtf8` is text-only (UTF-8 with `\n` line
12
+ * endings + NFC, preserving all other bytes including trailing
13
+ * whitespace).
14
+ * - `computeDocumentDigest` is the umbrella dispatcher.
15
+ *
16
+ * The `Jcs` suffix is reserved for JSON-only helpers; text-only helpers
17
+ * name their scheme. This prevents the `aipref/resolver.ts` historical
18
+ * bug where a sort-keys `JSON.stringify` digest was labelled `JCS-SHA256`.
19
+ *
20
+ * The `policy_binding` field on the verifier report is the byte-stable
21
+ * legacy mirror of `bindings.policy`; both are populated identically.
22
+ *
23
+ * @see docs/specs/DOCUMENT-BINDING.md
24
+ * @see packages/protocol/src/policy-binding.ts
25
+ */
26
+ import type { JsonValue } from '@peac/kernel';
27
+ import type { PolicyBindingStatus } from './verifier-types.js';
28
+ export type DocumentRepresentation = 'uri' | 'markdown' | 'plaintext' | 'json';
29
+ /**
30
+ * Compute the RFC 8785 JCS canonicalization + SHA-256 digest of a JSON
31
+ * document. Returns the canonical PEAC self-describing hash format
32
+ * `'sha256:<64 lowercase hex>'`. Suitable for `peac-policy/0.1` policy
33
+ * docs and any other JSON-shaped document carried in or referenced from
34
+ * a record.
35
+ */
36
+ export declare function computeJsonDocumentDigestJcs(value: JsonValue): Promise<string>;
37
+ /**
38
+ * Compute the SHA-256 digest of a UTF-8 text document after the minimal
39
+ * canonical normalization documented in `docs/specs/DOCUMENT-BINDING.md`:
40
+ *
41
+ * 1. Normalize line endings to `\n` (strip `\r` before `\n`; replace a
42
+ * lone `\r` with `\n`).
43
+ * 2. Normalize Unicode to NFC.
44
+ * 3. Preserve all other bytes exactly.
45
+ *
46
+ * Trailing whitespace is **not** stripped. Blank lines are **not**
47
+ * collapsed. Case is **not** normalized. The intent is a deterministic
48
+ * representation envelope identity, not a "pretty-print before hashing"
49
+ * scheme. Text representations like `markdown` and `plaintext` are
50
+ * frequently signed by publishers, and silent transformations would
51
+ * break those signatures.
52
+ *
53
+ * Returns the canonical PEAC self-describing hash format
54
+ * `'sha256:<64 lowercase hex>'`.
55
+ *
56
+ * @param bytes UTF-8 string to hash (single representation envelope).
57
+ * @param representation Tag recorded by the caller; not currently
58
+ * altering the hash but reserved so future representation-specific
59
+ * normalization rules can be added without renaming the helper.
60
+ */
61
+ export declare function computeTextDocumentDigestUtf8(bytes: string, _representation: 'markdown' | 'plaintext'): Promise<string>;
62
+ /**
63
+ * Umbrella dispatcher. Selects the correct scheme-specific helper from
64
+ * `input.representation`.
65
+ *
66
+ * For `representation: 'uri'`, the bytes the caller fetched from the URI
67
+ * MUST be supplied via `bytes`. Without bytes the dispatcher returns
68
+ * `'unavailable'`: the URI alone is not enough to bind, and PEAC does
69
+ * not perform network I/O from this layer (callers fetch under their own
70
+ * SSRF / redirect / timeout policy). When bytes are supplied for a URI,
71
+ * they are hashed via the text helper.
72
+ */
73
+ export declare function computeDocumentDigest(input: {
74
+ representation: 'json';
75
+ value: JsonValue;
76
+ } | {
77
+ representation: 'markdown' | 'plaintext';
78
+ bytes: string;
79
+ } | {
80
+ representation: 'uri';
81
+ uri: string;
82
+ bytes?: string;
83
+ }): Promise<string | 'unavailable'>;
84
+ /**
85
+ * Three-state binding check. Same semantics as `checkPolicyBinding`:
86
+ *
87
+ * - `'unavailable'` when either digest is missing.
88
+ * - `'verified'` when both digests are present and match exactly.
89
+ * - `'failed'` when both digests are present but do not match.
90
+ *
91
+ * The legacy `checkPolicyBinding` export delegates to this function.
92
+ */
93
+ export declare function checkDocumentBinding(receiptDigest: string | undefined, localDigest: string | undefined): PolicyBindingStatus;
94
+ //# sourceMappingURL=document-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-binding.d.ts","sourceRoot":"","sources":["../src/document-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG/D,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAGpF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,UAAU,GAAG,WAAW,GACxC,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EACD;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC5C;IAAE,cAAc,EAAE,UAAU,GAAG,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,cAAc,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,CAWjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,mBAAmB,CAKrB"}
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var uuidv7 = require('uuidv7');
4
- var crypto = require('@peac/crypto');
4
+ var crypto$1 = require('@peac/crypto');
5
5
  var zod = require('zod');
6
6
  var schema = require('@peac/schema');
7
- var crypto$1 = require('crypto');
7
+ var crypto$2 = require('crypto');
8
8
  var kernel = require('@peac/kernel');
9
9
 
10
10
  // src/issue.ts
@@ -20,7 +20,7 @@ function fireTelemetryHook(fn, input) {
20
20
  }
21
21
  }
22
22
  function hashReceipt(jws) {
23
- const hash = crypto$1.createHash("sha256").update(jws).digest("hex");
23
+ const hash = crypto$2.createHash("sha256").update(jws).digest("hex");
24
24
  return `sha256:${hash.slice(0, 16)}`;
25
25
  }
26
26
 
@@ -163,7 +163,7 @@ async function issueWire01(options) {
163
163
  }
164
164
  const validatedSnapshot = schema.validateSubjectSnapshot(options.subject_snapshot);
165
165
  const startTime = performance.now();
166
- const jws = await crypto.sign(claims, options.privateKey, options.kid);
166
+ const jws = await crypto$1.sign(claims, options.privateKey, options.kid);
167
167
  fireTelemetryHook(options.telemetry?.onReceiptIssued, {
168
168
  receiptHash: hashReceipt(jws),
169
169
  issuer: options.iss,
@@ -225,7 +225,7 @@ async function issueWire02(options) {
225
225
  }
226
226
  });
227
227
  }
228
- const jws = await crypto.signWire02(claims, options.privateKey, options.kid);
228
+ const jws = await crypto$1.signWire02(claims, options.privateKey, options.kid);
229
229
  return { jws };
230
230
  }
231
231
  function parseIssuerConfig(json) {
@@ -991,8 +991,23 @@ async function fetchPointerSafe(pointerUrl, options) {
991
991
  }
992
992
 
993
993
  // src/jwks-resolver.ts
994
- var DEFAULT_CACHE_TTL_MS = 5 * 60 * 1e3;
995
- var DEFAULT_MAX_CACHE_ENTRIES = 1e3;
994
+ var HARD_CACHE_TTL_MS_BUILTIN = 5 * 60 * 1e3;
995
+ var HARD_MAX_CACHE_ENTRIES_BUILTIN = 1e3;
996
+ function __parseEnvPositiveInt(name, fallback, env = typeof process !== "undefined" ? process.env : {}) {
997
+ const raw = env[name];
998
+ if (!raw) return fallback;
999
+ if (!/^[1-9][0-9]*$/.test(raw)) return fallback;
1000
+ const parsed = parseInt(raw, 10);
1001
+ return parsed > 0 ? parsed : fallback;
1002
+ }
1003
+ var DEFAULT_CACHE_TTL_MS = __parseEnvPositiveInt(
1004
+ "PEAC_JWKS_CACHE_TTL_MS",
1005
+ HARD_CACHE_TTL_MS_BUILTIN
1006
+ );
1007
+ var DEFAULT_MAX_CACHE_ENTRIES = __parseEnvPositiveInt(
1008
+ "PEAC_JWKS_CACHE_MAX_ENTRIES",
1009
+ HARD_MAX_CACHE_ENTRIES_BUILTIN
1010
+ );
996
1011
  var jwksCache = /* @__PURE__ */ new Map();
997
1012
  var KID_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
998
1013
  var MAX_KID_THUMBPRINT_ENTRIES = 1e4;
@@ -1267,7 +1282,7 @@ async function verifyReceipt(optionsOrJws) {
1267
1282
  const startTime = performance.now();
1268
1283
  let jwksFetchTime;
1269
1284
  try {
1270
- const { header, payload } = crypto.decode(receiptJws);
1285
+ const { header, payload } = crypto$1.decode(receiptJws);
1271
1286
  const constraintResult = schema.validateKernelConstraints(payload);
1272
1287
  if (!constraintResult.valid) {
1273
1288
  const v = constraintResult.violations[0];
@@ -1343,7 +1358,7 @@ async function verifyReceipt(optionsOrJws) {
1343
1358
  };
1344
1359
  }
1345
1360
  const publicKey = jwkToPublicKey(jwk);
1346
- const result = await crypto.verify(receiptJws, publicKey);
1361
+ const result = await crypto$1.verify(receiptJws, publicKey);
1347
1362
  if (!result.valid) {
1348
1363
  const durationMs = performance.now() - startTime;
1349
1364
  fireTelemetryHook(telemetry?.onReceiptVerified, {
@@ -1447,10 +1462,17 @@ function sanitizeParseIssues(issues) {
1447
1462
  }));
1448
1463
  }
1449
1464
  async function verifyLocal(jws, publicKey, options = {}) {
1450
- const { issuer, subjectUri, maxClockSkew = 300, strictness = "strict", policyDigest } = options;
1465
+ const {
1466
+ issuer,
1467
+ subjectUri,
1468
+ maxClockSkew = 300,
1469
+ strictness = "strict",
1470
+ policyDigest,
1471
+ bindings: callerBindings
1472
+ } = options;
1451
1473
  const now = options.now ?? Math.floor(Date.now() / 1e3);
1452
1474
  try {
1453
- const result = await crypto.verify(jws, publicKey);
1475
+ const result = await crypto$1.verify(jws, publicKey);
1454
1476
  if (!result.valid) {
1455
1477
  return {
1456
1478
  valid: false,
@@ -1597,6 +1619,11 @@ async function verifyLocal(jws, publicKey, options = {}) {
1597
1619
  }
1598
1620
  };
1599
1621
  }
1622
+ const bindings = {
1623
+ policy: bindingStatus,
1624
+ ...callerBindings?.terms !== void 0 && { terms: callerBindings.terms },
1625
+ ...callerBindings?.documents !== void 0 && callerBindings.documents.length > 0 && { documents: callerBindings.documents }
1626
+ };
1600
1627
  return {
1601
1628
  valid: true,
1602
1629
  variant: "wire-02",
@@ -1604,7 +1631,8 @@ async function verifyLocal(jws, publicKey, options = {}) {
1604
1631
  kid: result.header.kid,
1605
1632
  wireVersion: "0.2",
1606
1633
  warnings: schema.sortWarnings(accumulatedWarnings),
1607
- policy_binding: bindingStatus
1634
+ policy_binding: bindingStatus,
1635
+ bindings
1608
1636
  };
1609
1637
  }
1610
1638
  return {
@@ -1709,16 +1737,44 @@ function setVaryPurposeHeader(headers) {
1709
1737
  headers.set("Vary", schema.PEAC_PURPOSE_HEADER);
1710
1738
  }
1711
1739
  }
1712
- async function computePolicyDigestJcs(policy) {
1713
- const hex = await crypto.jcsHash(policy);
1740
+ async function computeJsonDocumentDigestJcs(value) {
1741
+ const hex = await crypto$1.jcsHash(value);
1714
1742
  return `${kernel.HASH.prefix}${hex}`;
1715
1743
  }
1716
- function checkPolicyBinding(receiptDigest, localDigest) {
1744
+ async function computeTextDocumentDigestUtf8(bytes, _representation) {
1745
+ const normalized = bytes.replace(/\r\n/g, "\n").replace(/\r/g, "\n").normalize("NFC");
1746
+ const buf = new TextEncoder().encode(normalized);
1747
+ const hashBuffer = await crypto.subtle.digest("SHA-256", buf);
1748
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
1749
+ const hex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
1750
+ return `${kernel.HASH.prefix}${hex}`;
1751
+ }
1752
+ async function computeDocumentDigest(input) {
1753
+ switch (input.representation) {
1754
+ case "json":
1755
+ return computeJsonDocumentDigestJcs(input.value);
1756
+ case "markdown":
1757
+ case "plaintext":
1758
+ return computeTextDocumentDigestUtf8(input.bytes, input.representation);
1759
+ case "uri":
1760
+ if (typeof input.bytes !== "string") return "unavailable";
1761
+ return computeTextDocumentDigestUtf8(input.bytes);
1762
+ }
1763
+ }
1764
+ function checkDocumentBinding(receiptDigest, localDigest) {
1717
1765
  if (receiptDigest === void 0 || localDigest === void 0) {
1718
1766
  return "unavailable";
1719
1767
  }
1720
1768
  return schema.verifyPolicyBinding(receiptDigest, localDigest);
1721
1769
  }
1770
+
1771
+ // src/policy-binding.ts
1772
+ async function computePolicyDigestJcs(policy) {
1773
+ return computeJsonDocumentDigestJcs(policy);
1774
+ }
1775
+ function checkPolicyBinding(receiptDigest, localDigest) {
1776
+ return checkDocumentBinding(receiptDigest, localDigest);
1777
+ }
1722
1778
  var DEFAULT_VERIFIER_LIMITS = {
1723
1779
  max_receipt_bytes: kernel.VERIFIER_LIMITS.maxReceiptBytes,
1724
1780
  max_jwks_bytes: kernel.VERIFIER_LIMITS.maxJwksBytes,
@@ -1861,7 +1917,7 @@ var VerificationReportBuilder = class {
1861
1917
  * @param type - Input type
1862
1918
  */
1863
1919
  async setInputAsync(receiptBytes, type = "receipt_jws") {
1864
- const digestHex = await crypto.sha256Hex(receiptBytes);
1920
+ const digestHex = await crypto$1.sha256Hex(receiptBytes);
1865
1921
  return this.setInputWithDigest(digestHex, type);
1866
1922
  }
1867
1923
  /**
@@ -2044,11 +2100,11 @@ function createReportBuilder(policy) {
2044
2100
  }
2045
2101
  async function computeReceiptDigest(receiptBytes) {
2046
2102
  const bytes = typeof receiptBytes === "string" ? new TextEncoder().encode(receiptBytes) : receiptBytes;
2047
- return crypto.sha256Hex(bytes);
2103
+ return crypto$1.sha256Hex(bytes);
2048
2104
  }
2049
2105
  async function buildFailureReport(policy, receiptBytes, reason, failedCheckId, errorCode, detail, options) {
2050
2106
  const bytes = typeof receiptBytes === "string" ? new TextEncoder().encode(receiptBytes) : receiptBytes;
2051
- const digestHex = await crypto.sha256Hex(bytes);
2107
+ const digestHex = await crypto$1.sha256Hex(bytes);
2052
2108
  const builder = createReportBuilder(policy).setInputWithDigest(digestHex).failure(reason, options?.issuer, options?.kid);
2053
2109
  const failedIndex = CHECK_IDS.indexOf(failedCheckId);
2054
2110
  for (let i = 0; i < CHECK_IDS.length; i++) {
@@ -2066,7 +2122,7 @@ async function buildFailureReport(policy, receiptBytes, reason, failedCheckId, e
2066
2122
  }
2067
2123
  async function buildSuccessReport(policy, receiptBytes, issuer, kid, checkDetails, options) {
2068
2124
  const bytes = typeof receiptBytes === "string" ? new TextEncoder().encode(receiptBytes) : receiptBytes;
2069
- const digestHex = await crypto.sha256Hex(bytes);
2125
+ const digestHex = await crypto$1.sha256Hex(bytes);
2070
2126
  const builder = createReportBuilder(policy).setInputWithDigest(digestHex).success(issuer, kid);
2071
2127
  for (const checkId of CHECK_IDS) {
2072
2128
  if (checkId === "issuer.discovery" && policy.mode === "offline_only") {
@@ -2148,7 +2204,7 @@ async function verifyReceiptCore(options) {
2148
2204
  } = options;
2149
2205
  const receiptJws = typeof receipt === "string" ? receipt : new TextDecoder().decode(receipt);
2150
2206
  const receiptBytes = typeof receipt === "string" ? new TextEncoder().encode(receipt) : receipt;
2151
- const receiptDigestHex = await crypto.sha256Hex(receiptBytes);
2207
+ const receiptDigestHex = await crypto$1.sha256Hex(receiptBytes);
2152
2208
  const builder = createReportBuilder(policy);
2153
2209
  builder.setInputWithDigest(receiptDigestHex);
2154
2210
  const nowSeconds = referenceTime ?? Math.floor(Date.now() / 1e3);
@@ -2158,7 +2214,7 @@ async function verifyReceiptCore(options) {
2158
2214
  let header;
2159
2215
  let payload;
2160
2216
  try {
2161
- const decoded = crypto.decode(receiptJws);
2217
+ const decoded = crypto$1.decode(receiptJws);
2162
2218
  header = decoded.header;
2163
2219
  payload = decoded.payload;
2164
2220
  builder.pass("jws.parse");
@@ -2232,7 +2288,7 @@ async function verifyReceiptCore(options) {
2232
2288
  if (pinnedKey) {
2233
2289
  builder.skip("issuer.discovery", { reason: "pinned_key_available" });
2234
2290
  if (pinnedKey.jwk) {
2235
- const actualThumbprint = await crypto.computeJwkThumbprint(pinnedKey.jwk);
2291
+ const actualThumbprint = await crypto$1.computeJwkThumbprint(pinnedKey.jwk);
2236
2292
  if (actualThumbprint !== pinnedKey.jwk_thumbprint_sha256) {
2237
2293
  builder.fail("key.resolve", "E_VERIFY_POLICY_VIOLATION", {
2238
2294
  error: "Pinned JWK thumbprint does not match declared thumbprint",
@@ -2245,7 +2301,7 @@ async function verifyReceiptCore(options) {
2245
2301
  report: includeMeta ? builder.addTimestamp().build() : builder.build()
2246
2302
  };
2247
2303
  }
2248
- publicKey = crypto.jwkToPublicKeyBytes(pinnedKey.jwk);
2304
+ publicKey = crypto$1.jwkToPublicKeyBytes(pinnedKey.jwk);
2249
2305
  keySource = "pinned_keys";
2250
2306
  keyThumbprint = actualThumbprint;
2251
2307
  builder.pass("key.resolve", {
@@ -2256,7 +2312,7 @@ async function verifyReceiptCore(options) {
2256
2312
  });
2257
2313
  } else if (pinnedKey.public_key) {
2258
2314
  try {
2259
- publicKey = crypto.base64urlDecode(pinnedKey.public_key);
2315
+ publicKey = crypto$1.base64urlDecode(pinnedKey.public_key);
2260
2316
  if (publicKey.length !== 32) {
2261
2317
  throw new Error(`Expected 32 bytes, got ${publicKey.length}`);
2262
2318
  }
@@ -2320,7 +2376,7 @@ async function verifyReceiptCore(options) {
2320
2376
  report: includeMeta ? builder.addTimestamp().build() : builder.build()
2321
2377
  };
2322
2378
  }
2323
- const actualThumbprint = await crypto.computeJwkThumbprint(jwk);
2379
+ const actualThumbprint = await crypto$1.computeJwkThumbprint(jwk);
2324
2380
  if (actualThumbprint !== pinnedKey.jwk_thumbprint_sha256) {
2325
2381
  builder.fail("key.resolve", "E_VERIFY_POLICY_VIOLATION", {
2326
2382
  error: "JWK thumbprint does not match pinned key",
@@ -2333,7 +2389,7 @@ async function verifyReceiptCore(options) {
2333
2389
  report: includeMeta ? builder.addTimestamp().build() : builder.build()
2334
2390
  };
2335
2391
  }
2336
- publicKey = crypto.jwkToPublicKeyBytes(jwk);
2392
+ publicKey = crypto$1.jwkToPublicKeyBytes(jwk);
2337
2393
  keySource = "pinned_keys";
2338
2394
  keyThumbprint = actualThumbprint;
2339
2395
  builder.pass("key.resolve", { source: keySource, kid, thumbprint_verified: true });
@@ -2381,13 +2437,13 @@ async function verifyReceiptCore(options) {
2381
2437
  report: includeMeta ? builder.addTimestamp().build() : builder.build()
2382
2438
  };
2383
2439
  }
2384
- publicKey = crypto.jwkToPublicKeyBytes(jwk);
2440
+ publicKey = crypto$1.jwkToPublicKeyBytes(jwk);
2385
2441
  keySource = "jwks_discovery";
2386
- keyThumbprint = await crypto.computeJwkThumbprint(jwk);
2442
+ keyThumbprint = await crypto$1.computeJwkThumbprint(jwk);
2387
2443
  builder.pass("key.resolve", { source: keySource, kid, thumbprint: keyThumbprint });
2388
2444
  }
2389
2445
  try {
2390
- const result = await crypto.verify(receiptJws, publicKey);
2446
+ const result = await crypto$1.verify(receiptJws, publicKey);
2391
2447
  if (!result.valid) {
2392
2448
  builder.fail("jws.signature", "E_VERIFY_SIGNATURE_INVALID", {
2393
2449
  error: "Ed25519 signature verification failed"
@@ -2464,7 +2520,7 @@ async function verifyReceiptCore(options) {
2464
2520
  builder.addArtifact("issuer_key_thumbprint", keyThumbprint);
2465
2521
  }
2466
2522
  if (jwksRawBytes) {
2467
- const jwksDigestHex = await crypto.sha256Hex(jwksRawBytes);
2523
+ const jwksDigestHex = await crypto$1.sha256Hex(jwksRawBytes);
2468
2524
  builder.addArtifact("issuer_jwks_digest", createDigest(jwksDigestHex));
2469
2525
  }
2470
2526
  const report = includeMeta ? builder.addTimestamp().build() : builder.build();
@@ -2884,7 +2940,7 @@ async function fetchPointerWithDigest(options) {
2884
2940
  message: jwsValidation.message
2885
2941
  };
2886
2942
  }
2887
- const actualDigest = await crypto.sha256Hex(receipt);
2943
+ const actualDigest = await crypto$1.sha256Hex(receipt);
2888
2944
  if (actualDigest !== expectedDigest) {
2889
2945
  return {
2890
2946
  ok: false,
@@ -2996,35 +3052,35 @@ async function verifyAndFetchPointer(pointerHeader, fetchOptions) {
2996
3052
 
2997
3053
  Object.defineProperty(exports, "base64urlDecode", {
2998
3054
  enumerable: true,
2999
- get: function () { return crypto.base64urlDecode; }
3055
+ get: function () { return crypto$1.base64urlDecode; }
3000
3056
  });
3001
3057
  Object.defineProperty(exports, "base64urlEncode", {
3002
3058
  enumerable: true,
3003
- get: function () { return crypto.base64urlEncode; }
3059
+ get: function () { return crypto$1.base64urlEncode; }
3004
3060
  });
3005
3061
  Object.defineProperty(exports, "computeJwkThumbprint", {
3006
3062
  enumerable: true,
3007
- get: function () { return crypto.computeJwkThumbprint; }
3063
+ get: function () { return crypto$1.computeJwkThumbprint; }
3008
3064
  });
3009
3065
  Object.defineProperty(exports, "generateKeypair", {
3010
3066
  enumerable: true,
3011
- get: function () { return crypto.generateKeypair; }
3067
+ get: function () { return crypto$1.generateKeypair; }
3012
3068
  });
3013
3069
  Object.defineProperty(exports, "jwkToPublicKeyBytes", {
3014
3070
  enumerable: true,
3015
- get: function () { return crypto.jwkToPublicKeyBytes; }
3071
+ get: function () { return crypto$1.jwkToPublicKeyBytes; }
3016
3072
  });
3017
3073
  Object.defineProperty(exports, "sha256Bytes", {
3018
3074
  enumerable: true,
3019
- get: function () { return crypto.sha256Bytes; }
3075
+ get: function () { return crypto$1.sha256Bytes; }
3020
3076
  });
3021
3077
  Object.defineProperty(exports, "sha256Hex", {
3022
3078
  enumerable: true,
3023
- get: function () { return crypto.sha256Hex; }
3079
+ get: function () { return crypto$1.sha256Hex; }
3024
3080
  });
3025
3081
  Object.defineProperty(exports, "verify", {
3026
3082
  enumerable: true,
3027
- get: function () { return crypto.verify; }
3083
+ get: function () { return crypto$1.verify; }
3028
3084
  });
3029
3085
  exports.CHECK_IDS = CHECK_IDS;
3030
3086
  exports.DEFAULT_NETWORK_SECURITY = DEFAULT_NETWORK_SECURITY;
@@ -3034,11 +3090,15 @@ exports.NON_DETERMINISTIC_ARTIFACT_KEYS = NON_DETERMINISTIC_ARTIFACT_KEYS;
3034
3090
  exports.VerificationReportBuilder = VerificationReportBuilder;
3035
3091
  exports.buildFailureReport = buildFailureReport;
3036
3092
  exports.buildSuccessReport = buildSuccessReport;
3093
+ exports.checkDocumentBinding = checkDocumentBinding;
3037
3094
  exports.checkPolicyBinding = checkPolicyBinding;
3038
3095
  exports.clearJWKSCache = clearJWKSCache;
3039
3096
  exports.clearKidThumbprints = clearKidThumbprints;
3097
+ exports.computeDocumentDigest = computeDocumentDigest;
3098
+ exports.computeJsonDocumentDigestJcs = computeJsonDocumentDigestJcs;
3040
3099
  exports.computePolicyDigestJcs = computePolicyDigestJcs;
3041
3100
  exports.computeReceiptDigest = computeReceiptDigest;
3101
+ exports.computeTextDocumentDigestUtf8 = computeTextDocumentDigestUtf8;
3042
3102
  exports.createDefaultPolicy = createDefaultPolicy;
3043
3103
  exports.createDigest = createDigest;
3044
3104
  exports.createEmptyReport = createEmptyReport;