@forestrie/receipt-verify 2.0.0 → 2.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"grant-codec.d.ts","sourceRoot":"","sources":["../src/grant-codec.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAuDjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,CAO3D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;CACzB,CAsBA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAa3D"}
1
+ {"version":3,"file":"grant-codec.d.ts","sourceRoot":"","sources":["../src/grant-codec.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAiFjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,CAS3D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;CACzB,CAuBA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAa3D"}
@@ -18,6 +18,26 @@ function leftPad(b, length) {
18
18
  out.set(b, length - b.length);
19
19
  return out;
20
20
  }
21
+ /**
22
+ * Grant wire v0 map keys are 0–6; keys 7 (`signer`) and 8 (`kind`) were
23
+ * retired before this package existed (FOR-580 owner ruling) and must be
24
+ * rejected here the same way the encoding and canopy-api codecs already do
25
+ * on the admission path (`packages/shared/encoding/src/grant-codec.ts`,
26
+ * `packages/apps/canopy-api/src/grant/codec.ts`) — this codec previously
27
+ * decoded by key number and silently ignored them.
28
+ */
29
+ function assertNoObsoleteWireKeys(m) {
30
+ const keys = m instanceof Map
31
+ ? [...m.keys()]
32
+ : Object.keys(m)
33
+ .map(Number)
34
+ .filter((n) => Number.isFinite(n));
35
+ for (const k of keys) {
36
+ if (k === 7 || k === 8) {
37
+ throw new Error("Grant wire v0: obsolete CBOR keys 7 (signer) and 8 (kind) must not be present; use grantData in the commitment only.");
38
+ }
39
+ }
40
+ }
21
41
  function mapToGrant(m) {
22
42
  const get = (k) => m instanceof Map ? m.get(k) : m[k];
23
43
  const requireBstr = (v, minLen = 0) => {
@@ -52,7 +72,9 @@ export function decodeGrantPayload(bytes) {
52
72
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
53
73
  throw new Error("Grant payload must be a CBOR map");
54
74
  }
55
- return mapToGrant(raw);
75
+ const m = raw;
76
+ assertNoObsoleteWireKeys(m);
77
+ return mapToGrant(m);
56
78
  }
57
79
  export function decodeGrantResponse(bytes) {
58
80
  const raw = decodeCborDeterministic(bytes);
@@ -60,6 +82,7 @@ export function decodeGrantResponse(bytes) {
60
82
  throw new Error("Grant response must be a CBOR map");
61
83
  }
62
84
  const m = raw;
85
+ assertNoObsoleteWireKeys(m);
63
86
  const get = (k) => m instanceof Map ? m.get(k) : m[k];
64
87
  const idtimestampVal = get(CBOR_KEY_IDTIMESTAMP);
65
88
  if (!(idtimestampVal instanceof Uint8Array) ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forestrie/receipt-verify",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Offline SCITT grant receipt verification (ADR-0045)",
@@ -29,8 +29,8 @@
29
29
  "dependencies": {
30
30
  "@noble/hashes": "^1.7.1",
31
31
  "@forestrie/chain-rpc": "0.3.0",
32
- "@forestrie/encoding": "0.8.0",
33
- "@forestrie/merklelog": "0.4.0"
32
+ "@forestrie/merklelog": "0.4.0",
33
+ "@forestrie/encoding": "0.8.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "esbuild": "^0.24.0",
@@ -25,6 +25,32 @@ function leftPad(b: Uint8Array, length: number): Uint8Array {
25
25
  return out;
26
26
  }
27
27
 
28
+ /**
29
+ * Grant wire v0 map keys are 0–6; keys 7 (`signer`) and 8 (`kind`) were
30
+ * retired before this package existed (FOR-580 owner ruling) and must be
31
+ * rejected here the same way the encoding and canopy-api codecs already do
32
+ * on the admission path (`packages/shared/encoding/src/grant-codec.ts`,
33
+ * `packages/apps/canopy-api/src/grant/codec.ts`) — this codec previously
34
+ * decoded by key number and silently ignored them.
35
+ */
36
+ function assertNoObsoleteWireKeys(
37
+ m: Map<number, unknown> | Record<number, unknown>,
38
+ ): void {
39
+ const keys =
40
+ m instanceof Map
41
+ ? [...m.keys()]
42
+ : Object.keys(m as Record<string, unknown>)
43
+ .map(Number)
44
+ .filter((n) => Number.isFinite(n));
45
+ for (const k of keys) {
46
+ if (k === 7 || k === 8) {
47
+ throw new Error(
48
+ "Grant wire v0: obsolete CBOR keys 7 (signer) and 8 (kind) must not be present; use grantData in the commitment only.",
49
+ );
50
+ }
51
+ }
52
+ }
53
+
28
54
  function mapToGrant(m: Map<number, unknown> | Record<number, unknown>): Grant {
29
55
  const get = (k: number): unknown =>
30
56
  m instanceof Map ? m.get(k) : (m as Record<number, unknown>)[k];
@@ -63,7 +89,9 @@ export function decodeGrantPayload(bytes: Uint8Array): Grant {
63
89
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
64
90
  throw new Error("Grant payload must be a CBOR map");
65
91
  }
66
- return mapToGrant(raw as Map<number, unknown> | Record<number, unknown>);
92
+ const m = raw as Map<number, unknown> | Record<number, unknown>;
93
+ assertNoObsoleteWireKeys(m);
94
+ return mapToGrant(m);
67
95
  }
68
96
 
69
97
  export function decodeGrantResponse(bytes: Uint8Array): {
@@ -75,6 +103,7 @@ export function decodeGrantResponse(bytes: Uint8Array): {
75
103
  throw new Error("Grant response must be a CBOR map");
76
104
  }
77
105
  const m = raw as Map<number, unknown> | Record<number, unknown>;
106
+ assertNoObsoleteWireKeys(m);
78
107
  const get = (k: number): unknown =>
79
108
  m instanceof Map ? m.get(k) : (m as Record<number, unknown>)[k];
80
109
  const idtimestampVal = get(CBOR_KEY_IDTIMESTAMP);