capacity-attest 0.1.2 → 0.2.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.
package/dist/schema.d.ts CHANGED
@@ -3,6 +3,157 @@ export declare const ASSET_TYPES: readonly ["gpu-hours", "storage", "api-credits
3
3
  export type AssetType = (typeof ASSET_TYPES)[number];
4
4
  export declare const DELIVERED_VALUES: readonly ["yes", "no", "partial"];
5
5
  export type Delivered = (typeof DELIVERED_VALUES)[number];
6
+ export declare const MEASURED_UNITS: readonly ["gpu-second", "byte", "byte-second", "call", "token", "credit"];
7
+ export type MeasuredUnit = (typeof MEASURED_UNITS)[number];
8
+ export declare const MEASURED_BASIS_VALUES: readonly ["supplied", "consumed"];
9
+ export type MeasuredBasis = (typeof MEASURED_BASIS_VALUES)[number];
10
+ export declare const MEASURED_ATTRIBUTION_VALUES: readonly ["buyer", "seller", "third-party", "undisclosed"];
11
+ export type MeasuredAttribution = (typeof MEASURED_ATTRIBUTION_VALUES)[number];
12
+ /**
13
+ * Which units are meaningful for which assetType. A literal 4-row table, not
14
+ * a derivation: there is nothing here to infer, and therefore nothing that
15
+ * can differ between reimplementations in other languages.
16
+ */
17
+ export declare const UNITS_BY_ASSET_TYPE: Record<AssetType, readonly MeasuredUnit[]>;
18
+ /**
19
+ * The `measured` block. Strict: unknown keys are REFUSED, not stripped —
20
+ * stripping would let a producer believe it is sending data that silently
21
+ * falls out of the preimage. `readingsHash` is the only optional key in the
22
+ * block, because its absence itself carries meaning (there either is a pinned
23
+ * meter dump or there is not); making any other field optional would add a
24
+ * branch to the canonicalization without absence saying anything.
25
+ */
26
+ export declare const MeasuredSchema: z.ZodObject<{
27
+ unit: z.ZodEnum<{
28
+ "gpu-second": "gpu-second";
29
+ byte: "byte";
30
+ "byte-second": "byte-second";
31
+ call: "call";
32
+ token: "token";
33
+ credit: "credit";
34
+ }>;
35
+ basis: z.ZodEnum<{
36
+ supplied: "supplied";
37
+ consumed: "consumed";
38
+ }>;
39
+ promisedAmount: z.ZodString;
40
+ deliveredAmount: z.ZodString;
41
+ period: z.ZodObject<{
42
+ start: z.ZodString;
43
+ end: z.ZodString;
44
+ }, z.core.$strict>;
45
+ method: z.ZodObject<{
46
+ attribution: z.ZodEnum<{
47
+ buyer: "buyer";
48
+ seller: "seller";
49
+ "third-party": "third-party";
50
+ undisclosed: "undisclosed";
51
+ }>;
52
+ instrument: z.ZodString;
53
+ readingsHash: z.ZodOptional<z.ZodString>;
54
+ }, z.core.$strict>;
55
+ }, z.core.$strict>;
56
+ export type Measured = z.infer<typeof MeasuredSchema>;
57
+ export declare const ClaimContentObject: z.ZodObject<{
58
+ sellerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
59
+ buyerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
60
+ assetType: z.ZodEnum<{
61
+ "gpu-hours": "gpu-hours";
62
+ storage: "storage";
63
+ "api-credits": "api-credits";
64
+ bandwidth: "bandwidth";
65
+ }>;
66
+ promisedSpec: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
67
+ delivered: z.ZodEnum<{
68
+ yes: "yes";
69
+ no: "no";
70
+ partial: "partial";
71
+ }>;
72
+ evidenceHash: z.ZodString;
73
+ settlementRef: z.ZodString;
74
+ timestamp: z.ZodString;
75
+ measured: z.ZodOptional<z.ZodObject<{
76
+ unit: z.ZodEnum<{
77
+ "gpu-second": "gpu-second";
78
+ byte: "byte";
79
+ "byte-second": "byte-second";
80
+ call: "call";
81
+ token: "token";
82
+ credit: "credit";
83
+ }>;
84
+ basis: z.ZodEnum<{
85
+ supplied: "supplied";
86
+ consumed: "consumed";
87
+ }>;
88
+ promisedAmount: z.ZodString;
89
+ deliveredAmount: z.ZodString;
90
+ period: z.ZodObject<{
91
+ start: z.ZodString;
92
+ end: z.ZodString;
93
+ }, z.core.$strict>;
94
+ method: z.ZodObject<{
95
+ attribution: z.ZodEnum<{
96
+ buyer: "buyer";
97
+ seller: "seller";
98
+ "third-party": "third-party";
99
+ undisclosed: "undisclosed";
100
+ }>;
101
+ instrument: z.ZodString;
102
+ readingsHash: z.ZodOptional<z.ZodString>;
103
+ }, z.core.$strict>;
104
+ }, z.core.$strict>>;
105
+ }, z.core.$strip>;
106
+ export declare const DeliveryClaimObject: z.ZodObject<{
107
+ sellerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
108
+ buyerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
109
+ assetType: z.ZodEnum<{
110
+ "gpu-hours": "gpu-hours";
111
+ storage: "storage";
112
+ "api-credits": "api-credits";
113
+ bandwidth: "bandwidth";
114
+ }>;
115
+ promisedSpec: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
116
+ delivered: z.ZodEnum<{
117
+ yes: "yes";
118
+ no: "no";
119
+ partial: "partial";
120
+ }>;
121
+ evidenceHash: z.ZodString;
122
+ settlementRef: z.ZodString;
123
+ timestamp: z.ZodString;
124
+ measured: z.ZodOptional<z.ZodObject<{
125
+ unit: z.ZodEnum<{
126
+ "gpu-second": "gpu-second";
127
+ byte: "byte";
128
+ "byte-second": "byte-second";
129
+ call: "call";
130
+ token: "token";
131
+ credit: "credit";
132
+ }>;
133
+ basis: z.ZodEnum<{
134
+ supplied: "supplied";
135
+ consumed: "consumed";
136
+ }>;
137
+ promisedAmount: z.ZodString;
138
+ deliveredAmount: z.ZodString;
139
+ period: z.ZodObject<{
140
+ start: z.ZodString;
141
+ end: z.ZodString;
142
+ }, z.core.$strict>;
143
+ method: z.ZodObject<{
144
+ attribution: z.ZodEnum<{
145
+ buyer: "buyer";
146
+ seller: "seller";
147
+ "third-party": "third-party";
148
+ undisclosed: "undisclosed";
149
+ }>;
150
+ instrument: z.ZodString;
151
+ readingsHash: z.ZodOptional<z.ZodString>;
152
+ }, z.core.$strict>;
153
+ }, z.core.$strict>>;
154
+ claimId: z.ZodString;
155
+ signature: z.ZodString;
156
+ }, z.core.$strip>;
6
157
  export declare const ClaimContentSchema: z.ZodObject<{
7
158
  sellerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
8
159
  buyerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
@@ -21,6 +172,36 @@ export declare const ClaimContentSchema: z.ZodObject<{
21
172
  evidenceHash: z.ZodString;
22
173
  settlementRef: z.ZodString;
23
174
  timestamp: z.ZodString;
175
+ measured: z.ZodOptional<z.ZodObject<{
176
+ unit: z.ZodEnum<{
177
+ "gpu-second": "gpu-second";
178
+ byte: "byte";
179
+ "byte-second": "byte-second";
180
+ call: "call";
181
+ token: "token";
182
+ credit: "credit";
183
+ }>;
184
+ basis: z.ZodEnum<{
185
+ supplied: "supplied";
186
+ consumed: "consumed";
187
+ }>;
188
+ promisedAmount: z.ZodString;
189
+ deliveredAmount: z.ZodString;
190
+ period: z.ZodObject<{
191
+ start: z.ZodString;
192
+ end: z.ZodString;
193
+ }, z.core.$strict>;
194
+ method: z.ZodObject<{
195
+ attribution: z.ZodEnum<{
196
+ buyer: "buyer";
197
+ seller: "seller";
198
+ "third-party": "third-party";
199
+ undisclosed: "undisclosed";
200
+ }>;
201
+ instrument: z.ZodString;
202
+ readingsHash: z.ZodOptional<z.ZodString>;
203
+ }, z.core.$strict>;
204
+ }, z.core.$strict>>;
24
205
  }, z.core.$strip>;
25
206
  export type ClaimContent = z.infer<typeof ClaimContentSchema>;
26
207
  /** The full, stored, signed claim — ClaimContent plus its content-address and signature. */
@@ -42,6 +223,36 @@ export declare const DeliveryClaimSchema: z.ZodObject<{
42
223
  evidenceHash: z.ZodString;
43
224
  settlementRef: z.ZodString;
44
225
  timestamp: z.ZodString;
226
+ measured: z.ZodOptional<z.ZodObject<{
227
+ unit: z.ZodEnum<{
228
+ "gpu-second": "gpu-second";
229
+ byte: "byte";
230
+ "byte-second": "byte-second";
231
+ call: "call";
232
+ token: "token";
233
+ credit: "credit";
234
+ }>;
235
+ basis: z.ZodEnum<{
236
+ supplied: "supplied";
237
+ consumed: "consumed";
238
+ }>;
239
+ promisedAmount: z.ZodString;
240
+ deliveredAmount: z.ZodString;
241
+ period: z.ZodObject<{
242
+ start: z.ZodString;
243
+ end: z.ZodString;
244
+ }, z.core.$strict>;
245
+ method: z.ZodObject<{
246
+ attribution: z.ZodEnum<{
247
+ buyer: "buyer";
248
+ seller: "seller";
249
+ "third-party": "third-party";
250
+ undisclosed: "undisclosed";
251
+ }>;
252
+ instrument: z.ZodString;
253
+ readingsHash: z.ZodOptional<z.ZodString>;
254
+ }, z.core.$strict>;
255
+ }, z.core.$strict>>;
45
256
  claimId: z.ZodString;
46
257
  signature: z.ZodString;
47
258
  }, z.core.$strip>;
@@ -53,6 +264,18 @@ export type DeliveryClaim = z.infer<typeof DeliveryClaimSchema>;
53
264
  * sorted.
54
265
  */
55
266
  export declare function canonicalize(value: unknown): string;
267
+ /**
268
+ * The EXACT bytes that get hashed for a claim, as a string.
269
+ *
270
+ * Exported because canonicalize() on its own is NOT the preimage, and that is
271
+ * the single most likely thing to get wrong when reimplementing this in
272
+ * another language: the preimage is `canonicalize(ClaimContentSchema.parse(content))`,
273
+ * not `canonicalize(content)`. The parse step is what lower-cases the two
274
+ * address fields and strips unknown top-level keys. Port only canonicalize()
275
+ * and you will silently produce wrong ids for any claim submitted with
276
+ * mixed-case addresses.
277
+ */
278
+ export declare function claimPreimage(content: ClaimContent): string;
56
279
  /**
57
280
  * Content-addressed id for a claim: sha256 of the canonical JSON of its
58
281
  * content fields (everything except claimId and signature themselves).
@@ -60,4 +283,106 @@ export declare function canonicalize(value: unknown): string;
60
283
  * over a shape that wouldn't itself pass ClaimContentSchema.
61
284
  */
62
285
  export declare function computeClaimId(content: ClaimContent): string;
286
+ /** ClaimContentSchema plus the ingest hardening of S-1..S-6. Used by recordDelivery(), never by computeClaimId(). */
287
+ export declare const StrictClaimContentSchema: z.ZodObject<{
288
+ sellerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
289
+ buyerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
290
+ assetType: z.ZodEnum<{
291
+ "gpu-hours": "gpu-hours";
292
+ storage: "storage";
293
+ "api-credits": "api-credits";
294
+ bandwidth: "bandwidth";
295
+ }>;
296
+ promisedSpec: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
297
+ delivered: z.ZodEnum<{
298
+ yes: "yes";
299
+ no: "no";
300
+ partial: "partial";
301
+ }>;
302
+ evidenceHash: z.ZodString;
303
+ settlementRef: z.ZodString;
304
+ timestamp: z.ZodString;
305
+ measured: z.ZodOptional<z.ZodObject<{
306
+ unit: z.ZodEnum<{
307
+ "gpu-second": "gpu-second";
308
+ byte: "byte";
309
+ "byte-second": "byte-second";
310
+ call: "call";
311
+ token: "token";
312
+ credit: "credit";
313
+ }>;
314
+ basis: z.ZodEnum<{
315
+ supplied: "supplied";
316
+ consumed: "consumed";
317
+ }>;
318
+ promisedAmount: z.ZodString;
319
+ deliveredAmount: z.ZodString;
320
+ period: z.ZodObject<{
321
+ start: z.ZodString;
322
+ end: z.ZodString;
323
+ }, z.core.$strict>;
324
+ method: z.ZodObject<{
325
+ attribution: z.ZodEnum<{
326
+ buyer: "buyer";
327
+ seller: "seller";
328
+ "third-party": "third-party";
329
+ undisclosed: "undisclosed";
330
+ }>;
331
+ instrument: z.ZodString;
332
+ readingsHash: z.ZodOptional<z.ZodString>;
333
+ }, z.core.$strict>;
334
+ }, z.core.$strict>>;
335
+ }, z.core.$strip>;
336
+ /** DeliveryClaimSchema plus the ingest hardening of S-1..S-6. This is what record_delivery validates against. */
337
+ export declare const StrictDeliveryClaimSchema: z.ZodObject<{
338
+ sellerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
339
+ buyerAddress: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
340
+ assetType: z.ZodEnum<{
341
+ "gpu-hours": "gpu-hours";
342
+ storage: "storage";
343
+ "api-credits": "api-credits";
344
+ bandwidth: "bandwidth";
345
+ }>;
346
+ promisedSpec: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>;
347
+ delivered: z.ZodEnum<{
348
+ yes: "yes";
349
+ no: "no";
350
+ partial: "partial";
351
+ }>;
352
+ evidenceHash: z.ZodString;
353
+ settlementRef: z.ZodString;
354
+ timestamp: z.ZodString;
355
+ measured: z.ZodOptional<z.ZodObject<{
356
+ unit: z.ZodEnum<{
357
+ "gpu-second": "gpu-second";
358
+ byte: "byte";
359
+ "byte-second": "byte-second";
360
+ call: "call";
361
+ token: "token";
362
+ credit: "credit";
363
+ }>;
364
+ basis: z.ZodEnum<{
365
+ supplied: "supplied";
366
+ consumed: "consumed";
367
+ }>;
368
+ promisedAmount: z.ZodString;
369
+ deliveredAmount: z.ZodString;
370
+ period: z.ZodObject<{
371
+ start: z.ZodString;
372
+ end: z.ZodString;
373
+ }, z.core.$strict>;
374
+ method: z.ZodObject<{
375
+ attribution: z.ZodEnum<{
376
+ buyer: "buyer";
377
+ seller: "seller";
378
+ "third-party": "third-party";
379
+ undisclosed: "undisclosed";
380
+ }>;
381
+ instrument: z.ZodString;
382
+ readingsHash: z.ZodOptional<z.ZodString>;
383
+ }, z.core.$strict>;
384
+ }, z.core.$strict>>;
385
+ claimId: z.ZodString;
386
+ signature: z.ZodString;
387
+ }, z.core.$strip>;
63
388
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,WAAW,+DAAgE,CAAC;AACzF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,eAAO,MAAM,gBAAgB,mCAAoC,CAAC;AAClE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAoD1D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;iBA6C7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;iBAS9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD;AA+BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAI5D"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,WAAW,+DAAgE,CAAC;AACzF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,eAAO,MAAM,gBAAgB,mCAAoC,CAAC;AAClE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAkF1D,eAAO,MAAM,cAAc,2EAA4E,CAAC;AACxG,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,qBAAqB,mCAAoC,CAAC;AACvE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AASnE,eAAO,MAAM,2BAA2B,4DAA6D,CAAC;AACtG,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAK1E,CAAC;AA4HF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkCzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAkEtD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyD7B,CAAC;AAWH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG9B,CAAC;AASH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA2D,CAAC;AAC3F,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA4D,CAAC;AAC7F,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD;AA+BD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAG5D;AAoLD,qHAAqH;AACrH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA6F,CAAC;AAEnI,iHAAiH;AACjH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA8F,CAAC"}
package/dist/schema.js CHANGED
@@ -16,6 +16,10 @@ export const ASSET_TYPES = ["gpu-hours", "storage", "api-credits", "bandwidth"];
16
16
  export const DELIVERED_VALUES = ["yes", "no", "partial"];
17
17
  const ETH_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
18
18
  const SHA256_HEX_RE = /^[0-9a-fA-F]{64}$/;
19
+ // Lower-case-only sha256 hex. Used for readingsHash (new in 0.2.0, so it can
20
+ // be strict from day one) and, at ingest only, for evidenceHash — see
21
+ // StrictClaimContentSchema below and the 0.1.3 section of CHANGELOG.md (S-3).
22
+ const LOWER_SHA256_HEX_RE = /^[0-9a-f]{64}$/;
19
23
  const CLAIM_ID_RE = /^0x[0-9a-fA-F]{64}$/;
20
24
  // 65-byte ECDSA signature (r ++ s ++ v), hex-encoded with 0x prefix — the
21
25
  // shape ethers.Signer#signMessage() / ethers.verifyMessage() produce.
@@ -64,7 +68,247 @@ function exceedsMaxDepth(value, maxDepth) {
64
68
  }
65
69
  return false;
66
70
  }
67
- export const ClaimContentSchema = z.object({
71
+ // ---------------------------------------------------------------------------
72
+ // `measured` — the optional quantitative block, added in 0.2.0.
73
+ //
74
+ // Full, language-neutral rules: the 0.1.3 section of CHANGELOG.md. The
75
+ // short version of the architecture, because it is the thing that is easy to
76
+ // break by accident:
77
+ //
78
+ // THE PREIMAGE FUNCTION IS FROZEN. canonicalize(), sortKeysDeep() and the
79
+ // sha256 step do not change. Everything that gets stricter is a REFUSAL AT
80
+ // INPUT, never a transformation on the hash route.
81
+ //
82
+ // `measured` is added to ClaimContentSchema (the schema computeClaimId()
83
+ // parses through) as exactly one `.optional()` key — no .default(), no
84
+ // .passthrough(), no .catchall(). A .default() would materialize the key and
85
+ // change the preimage of every already-recorded claim. Its validation lives
86
+ // here rather than only at ingest because it IS preimage-relevant: a
87
+ // non-canonical decimal must never be hashable.
88
+ //
89
+ // Its presence is the version marker; there is deliberately no `scheme`
90
+ // string inside the block. A 0.1.x node reading a 0.2 claim strips the
91
+ // unknown `measured` key, computes the v1 id, and answers claimId_mismatch —
92
+ // it refuses rather than silently accepting unverified measurement data,
93
+ // which is the safe failure direction and is the reason `measured` sits
94
+ // INSIDE the hashed content instead of next to it.
95
+ // ---------------------------------------------------------------------------
96
+ export const MEASURED_UNITS = ["gpu-second", "byte", "byte-second", "call", "token", "credit"];
97
+ export const MEASURED_BASIS_VALUES = ["supplied", "consumed"];
98
+ // Provenance of the number, and nothing else. This enum is deliberately NOT
99
+ // ranked: nowhere in this codebase or its docs does "third-party" mean
100
+ // "better than seller". There is no reliability/quality/trust field and there
101
+ // will not be one — every field in a claim is an assertion by the buyer.
102
+ // `undisclosed` exists because attribution is mandatory: without an escape
103
+ // hatch, someone unwilling to name the source would just pick an untrue
104
+ // value. Withholding should be visible, not silent.
105
+ export const MEASURED_ATTRIBUTION_VALUES = ["buyer", "seller", "third-party", "undisclosed"];
106
+ /**
107
+ * Which units are meaningful for which assetType. A literal 4-row table, not
108
+ * a derivation: there is nothing here to infer, and therefore nothing that
109
+ * can differ between reimplementations in other languages.
110
+ */
111
+ export const UNITS_BY_ASSET_TYPE = {
112
+ "gpu-hours": ["gpu-second"],
113
+ storage: ["byte", "byte-second"],
114
+ bandwidth: ["byte"],
115
+ "api-credits": ["call", "token", "credit"],
116
+ };
117
+ // CDEC — canonical decimal string. ASCII [0-9], never \d: Python's `re`
118
+ // matches \d on U+0664 (Arabic-Indic four) while JavaScript does not, so a
119
+ // spec written with \d is impossible to implement identically in both.
120
+ // No sign (quantities are non-negative, which also removes -0 entirely), no
121
+ // exponent, no leading zeros, integer part mandatory and at most 30 digits,
122
+ // optional fraction of 1..18 digits whose last digit is not 0. Exactly one
123
+ // legal string per value, in both directions.
124
+ const CDEC_RE = /^(0|[1-9][0-9]{0,29})(\.[0-9]{0,17}[1-9])?$/;
125
+ // CINST — canonical UTC instant, exactly 20 characters. No offsets (those are
126
+ // refused, not converted: converting would be a transformation on the hash
127
+ // route), no fractional seconds, no 24:00:00, no leap second :60, no
128
+ // date-only form. Every field is fixed-width and pinned to Z, so a plain
129
+ // lexicographic byte comparison of two CINST strings is identical to
130
+ // chronological ordering — which is why no time rule in this schema needs a
131
+ // date library.
132
+ const CINST_RE = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]Z$/;
133
+ // The form `timestamp` must have when `measured` is present (and, at ingest,
134
+ // the form it must have for every new claim — see S-2).
135
+ //
136
+ // EXACTLY three fractional digits, not one-to-nine. An earlier version of
137
+ // this rule allowed `(\.[0-9]{1,9})?`, which closed the four spellings named
138
+ // in the original defect report but left the whole family around them open:
139
+ // `…:00Z`, `…:00.0Z`, `…:00.00Z`, `…:00.000Z` and `…:00.000000000Z` are five
140
+ // spellings of one instant, and each hashed to its own claimId. That was
141
+ // demonstrated end to end, not theorised: one buyer, one seller, one
142
+ // settlementRef, one moment, five accepted ledger rows, and the duplicate
143
+ // check never fired because it keys on bytes the schema had not made
144
+ // canonical. A seller could inflate a delivery history tenfold without
145
+ // breaking a single rule. It is precisely the failure this file's own S-3
146
+ // message describes for evidence hashes ("upper-case hex mints a second
147
+ // claimId for the same evidence"), one field over.
148
+ //
149
+ // Three digits costs nothing: the only claim producer that has ever existed
150
+ // here is `new Date().toISOString()`, which always emits exactly three,
151
+ // including the real production claim in data-selftest/claims.jsonl
152
+ // (2026-08-31T18:06:48.102Z). One spelling per millisecond, no producer
153
+ // broken. `measured.period` already had this discipline via CINST; the
154
+ // claim's own timestamp did not.
155
+ const MEASURED_TIMESTAMP_RE = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.[0-9]{3}Z$/;
156
+ const MAX_INSTRUMENT_LENGTH = 200;
157
+ /**
158
+ * Real calendar check for a YYYY-MM-DD prefix. The regexes above still let
159
+ * 2026-02-30 through; this closes that without pulling in a date library, so
160
+ * a reimplementation in any language can copy these six lines verbatim.
161
+ */
162
+ function isRealCalendarDate(isoPrefix) {
163
+ const y = Number(isoPrefix.slice(0, 4));
164
+ const m = Number(isoPrefix.slice(5, 7));
165
+ const d = Number(isoPrefix.slice(8, 10));
166
+ const leap = (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;
167
+ const daysInMonth = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m - 1];
168
+ return d >= 1 && d <= daysInMonth;
169
+ }
170
+ /**
171
+ * True if `s` contains a C0 control character (U+0000-U+001F), U+007F, or a
172
+ * lone surrogate. Hygiene and log-injection safety, not a determinism
173
+ * requirement — the escape rules in the spec already cover determinism
174
+ * completely.
175
+ */
176
+ function hasForbiddenTextChars(s) {
177
+ for (let i = 0; i < s.length; i++) {
178
+ const c = s.charCodeAt(i);
179
+ if (c <= 0x1f || c === 0x7f)
180
+ return true;
181
+ if (c >= 0xd800 && c <= 0xdbff) {
182
+ const next = s.charCodeAt(i + 1);
183
+ if (!(next >= 0xdc00 && next <= 0xdfff))
184
+ return true;
185
+ i++; // valid surrogate pair — skip the low half
186
+ }
187
+ else if (c >= 0xdc00 && c <= 0xdfff) {
188
+ return true; // lone low surrogate
189
+ }
190
+ }
191
+ return false;
192
+ }
193
+ /**
194
+ * True if `s` contains a LONE surrogate: an unpaired U+D800..U+DFFF code
195
+ * unit. Deliberately NARROWER than hasForbiddenTextChars above, and used for
196
+ * a different reason.
197
+ *
198
+ * hasForbiddenTextChars is hygiene (log-injection safety). This is a
199
+ * PORTABILITY rule, and it is the only text property that makes a string
200
+ * genuinely unrepresentable outside JavaScript: a lone surrogate has no UTF-8
201
+ * encoding at all, so `Buffer.from(s, "utf8").toString("utf8") !== s` (this
202
+ * package measured that directly). JavaScript hides the problem because
203
+ * well-formed JSON.stringify escapes it to "\ud800" and JS strings are
204
+ * UTF-16, but a verifier written in Rust (`String` is UTF-8 by definition),
205
+ * Go, or Python cannot reconstruct the preimage bytes at all. That is the
206
+ * same failure mode S-5 closes for object KEYS, left open for string VALUES.
207
+ * See S-6 below.
208
+ */
209
+ function hasLoneSurrogate(s) {
210
+ for (let i = 0; i < s.length; i++) {
211
+ const c = s.charCodeAt(i);
212
+ if (c >= 0xd800 && c <= 0xdbff) {
213
+ const next = s.charCodeAt(i + 1);
214
+ if (!(next >= 0xdc00 && next <= 0xdfff))
215
+ return true;
216
+ i++; // valid surrogate pair — skip the low half
217
+ }
218
+ else if (c >= 0xdc00 && c <= 0xdfff) {
219
+ return true; // lone low surrogate
220
+ }
221
+ }
222
+ return false;
223
+ }
224
+ const CinstSchema = z
225
+ .string()
226
+ .regex(CINST_RE, "must be a canonical UTC instant: YYYY-MM-DDTHH:MM:SSZ, exactly 20 chars, no offset, no fractional seconds")
227
+ .refine(isRealCalendarDate, "must be a real calendar date (e.g. 2026-02-30 does not exist)");
228
+ const CdecSchema = z
229
+ .string()
230
+ .regex(CDEC_RE, "must be a canonical decimal string: no sign, no exponent, no leading zeros, at most 30 integer digits, optional 1..18 fraction digits not ending in 0");
231
+ /**
232
+ * The `measured` block. Strict: unknown keys are REFUSED, not stripped —
233
+ * stripping would let a producer believe it is sending data that silently
234
+ * falls out of the preimage. `readingsHash` is the only optional key in the
235
+ * block, because its absence itself carries meaning (there either is a pinned
236
+ * meter dump or there is not); making any other field optional would add a
237
+ * branch to the canonicalization without absence saying anything.
238
+ */
239
+ export const MeasuredSchema = z.strictObject({
240
+ unit: z.enum(MEASURED_UNITS).describe("Unit of the quantities below — must be in this assetType's row of UNITS_BY_ASSET_TYPE"),
241
+ basis: z
242
+ .enum(MEASURED_BASIS_VALUES)
243
+ .describe("Does the number count what the seller made available (`supplied`) or what the buyer actually drew (`consumed`)"),
244
+ promisedAmount: CdecSchema.refine((v) => v !== "0", 'promisedAmount must not be "0" — a promise of nothing is meaningless').describe("How much was promised, as a canonical decimal string"),
245
+ deliveredAmount: CdecSchema.describe("How much was measured, as a canonical decimal string"),
246
+ period: z
247
+ .strictObject({
248
+ start: CinstSchema.describe("Start of the closed measurement window, canonical UTC instant"),
249
+ end: CinstSchema.describe("End of the closed measurement window, canonical UTC instant"),
250
+ })
251
+ .refine((p) => p.start < p.end, "period.start must be strictly before period.end — a zero-length window is meaningless")
252
+ .describe("The closed window this measurement covers"),
253
+ method: z
254
+ .strictObject({
255
+ attribution: z
256
+ .enum(MEASURED_ATTRIBUTION_VALUES)
257
+ .describe("WHO produced the number — provenance only, never a quality or trust signal"),
258
+ instrument: z
259
+ .string()
260
+ .min(1, "instrument is required and must not be empty")
261
+ .max(MAX_INSTRUMENT_LENGTH)
262
+ .refine((v) => !hasForbiddenTextChars(v), "instrument must not contain C0 control characters, U+007F, or lone surrogates")
263
+ .describe('Free text about the measuring instrument, e.g. "nvidia-smi accounting, 10s polling"'),
264
+ readingsHash: z
265
+ .string()
266
+ .regex(LOWER_SHA256_HEX_RE, "readingsHash must be a lower-case sha256 hex digest (64 chars, no 0x prefix)")
267
+ .optional()
268
+ .describe("sha256 of the raw meter dump — the dump itself is not stored. Separate from evidenceHash, which is about delivery evidence"),
269
+ })
270
+ .describe("How the number was obtained"),
271
+ });
272
+ function checkMeasuredConsistency(content, ctx) {
273
+ const measured = content.measured;
274
+ if (!measured)
275
+ return;
276
+ // §5.2 — unit must sit in this assetType's row. Pure lookup.
277
+ const allowed = UNITS_BY_ASSET_TYPE[content.assetType];
278
+ if (!allowed.includes(measured.unit)) {
279
+ ctx.addIssue({
280
+ code: "custom",
281
+ path: ["measured", "unit"],
282
+ message: `unit "${measured.unit}" is not valid for assetType "${content.assetType}" (allowed: ${allowed.join(", ")})`,
283
+ });
284
+ }
285
+ // §5.3 — the period must be closed, i.e. it ended no later than the moment
286
+ // the claim was made. Two parts.
287
+ if (!MEASURED_TIMESTAMP_RE.test(content.timestamp) || !isRealCalendarDate(content.timestamp)) {
288
+ ctx.addIssue({
289
+ code: "custom",
290
+ path: ["timestamp"],
291
+ message: "when `measured` is present, timestamp must be a strict UTC instant YYYY-MM-DDTHH:MM:SS[.fff]Z with a real calendar date",
292
+ });
293
+ return;
294
+ }
295
+ // The 19-CHARACTER PREFIX RULE, and it has to be the prefix, not the whole
296
+ // string. Comparing full strings is wrong the moment `timestamp` carries
297
+ // fractional seconds inside the same second the period closed:
298
+ // "2026-09-01T08:00:00Z" <= "2026-09-01T08:00:00.102Z" is FALSE, because
299
+ // "." (0x2E) sorts before "Z" (0x5A). YYYY-MM-DDTHH:MM:SS is fixed-width
300
+ // and zero-padded, so prefix-lexicographic IS chronological, and truncating
301
+ // the fraction can only err conservatively (the fraction can only push the
302
+ // timestamp later).
303
+ if (measured.period.end.slice(0, 19) > content.timestamp.slice(0, 19)) {
304
+ ctx.addIssue({
305
+ code: "custom",
306
+ path: ["measured", "period", "end"],
307
+ message: "period.end must not be after timestamp (compared on the first 19 characters) — a claim covers a closed past window",
308
+ });
309
+ }
310
+ }
311
+ export const ClaimContentObject = z.object({
68
312
  // .transform(toLowerCase): a fuzz-and-benchmark audit found that
69
313
  // computeClaimId() hashed addresses exactly as submitted while every other
70
314
  // address comparison in this codebase (signature recovery, seller
@@ -108,20 +352,41 @@ export const ClaimContentSchema = z.object({
108
352
  .describe("x402 payment reference or on-chain tx hash for the settlement this claim is about"),
109
353
  timestamp: z
110
354
  .string()
355
+ // FROZEN, deliberately loose. Date.parse accepts "August 30, 2026" and
356
+ // date-only forms, which is far more permissive than the field's own
357
+ // documentation. It stays this way here so historical ledger lines remain
358
+ // recomputable; StrictClaimContentSchema (S-2) tightens it for everything
359
+ // new. This inconsistency is intentional and documented.
111
360
  .refine((v) => !Number.isNaN(Date.parse(v)), "timestamp must be a valid ISO-8601 date string")
112
361
  .describe("ISO-8601 timestamp of when this claim was made"),
362
+ // The one and only addition of 0.2.0. Optional, never defaulted: an absent
363
+ // key is absent from the preimage, so every claim recorded before 0.2.0
364
+ // hashes bit-for-bit identically (proven in schema.test.ts against the real
365
+ // production claim in data-selftest/claims.jsonl).
366
+ measured: MeasuredSchema.optional().describe("Optional quantitative record of how much was promised and how much was measured. Presence is the version marker; absence is the only encoding of 'not measured'"),
113
367
  });
114
- /** The full, stored, signed claim — ClaimContent plus its content-address and signature. */
115
- export const DeliveryClaimSchema = ClaimContentSchema.extend({
116
- claimId: z
117
- .string()
118
- .regex(CLAIM_ID_RE, "claimId must be a 0x-prefixed sha256 hex digest")
119
- .describe("Content-addressed id: sha256 of the canonical JSON of this claim's content fields — see computeClaimId()"),
120
- signature: z
121
- .string()
122
- .regex(SIGNATURE_RE, "signature must be a 0x-prefixed 65-byte ECDSA signature")
123
- .describe("Buyer's EIP-191 personal-sign signature over claimId"),
368
+ const claimIdField = z
369
+ .string()
370
+ .regex(CLAIM_ID_RE, "claimId must be a 0x-prefixed sha256 hex digest")
371
+ .describe("Content-addressed id: sha256 of the canonical JSON of this claim's content fields — see computeClaimId()");
372
+ const signatureField = z
373
+ .string()
374
+ .regex(SIGNATURE_RE, "signature must be a 0x-prefixed 65-byte ECDSA signature")
375
+ .describe("Buyer's EIP-191 personal-sign signature over claimId");
376
+ export const DeliveryClaimObject = ClaimContentObject.extend({
377
+ claimId: claimIdField,
378
+ signature: signatureField,
124
379
  });
380
+ // The cross-field checks are attached to each schema separately rather than
381
+ // inherited, because zod v4's .extend() DROPS checks from the schema it
382
+ // extends (measured directly: a .superRefine()'d object that is then
383
+ // .extend()ed no longer runs the refinement). Attaching per schema is the
384
+ // only shape that keeps ClaimContentSchema and DeliveryClaimSchema in
385
+ // agreement. Both keep a working `.shape` (index.ts's MCP tool registration
386
+ // depends on that), which .superRefine() on a ZodObject does preserve.
387
+ export const ClaimContentSchema = ClaimContentObject.superRefine(checkMeasuredConsistency);
388
+ /** The full, stored, signed claim — ClaimContent plus its content-address and signature. */
389
+ export const DeliveryClaimSchema = DeliveryClaimObject.superRefine(checkMeasuredConsistency);
125
390
  /**
126
391
  * Deterministic JSON stringify: object keys sorted recursively so hashing
127
392
  * and signing are stable regardless of the original key insertion order.
@@ -160,6 +425,20 @@ function sortKeysDeep(value, depth) {
160
425
  }
161
426
  return value;
162
427
  }
428
+ /**
429
+ * The EXACT bytes that get hashed for a claim, as a string.
430
+ *
431
+ * Exported because canonicalize() on its own is NOT the preimage, and that is
432
+ * the single most likely thing to get wrong when reimplementing this in
433
+ * another language: the preimage is `canonicalize(ClaimContentSchema.parse(content))`,
434
+ * not `canonicalize(content)`. The parse step is what lower-cases the two
435
+ * address fields and strips unknown top-level keys. Port only canonicalize()
436
+ * and you will silently produce wrong ids for any claim submitted with
437
+ * mixed-case addresses.
438
+ */
439
+ export function claimPreimage(content) {
440
+ return canonicalize(ClaimContentSchema.parse(content));
441
+ }
163
442
  /**
164
443
  * Content-addressed id for a claim: sha256 of the canonical JSON of its
165
444
  * content fields (everything except claimId and signature themselves).
@@ -167,8 +446,190 @@ function sortKeysDeep(value, depth) {
167
446
  * over a shape that wouldn't itself pass ClaimContentSchema.
168
447
  */
169
448
  export function computeClaimId(content) {
170
- const parsed = ClaimContentSchema.parse(content);
171
- const hash = createHash("sha256").update(canonicalize(parsed)).digest("hex");
449
+ const hash = createHash("sha256").update(claimPreimage(content)).digest("hex");
172
450
  return `0x${hash}`;
173
451
  }
452
+ // ---------------------------------------------------------------------------
453
+ // StrictClaimContentSchema — ingest hardening (S-1 .. S-6).
454
+ //
455
+ // None of this touches the preimage and none of it changes any existing
456
+ // claimId. These rules apply ONLY to newly submitted claims, via
457
+ // recordDelivery(). Historical ledger lines are always recomputed through the
458
+ // FROZEN ClaimContentSchema above and therefore stay verifiable even when
459
+ // they contain something (a float in promisedSpec, a loose timestamp) that
460
+ // S-1/S-2 now refuse for new claims.
461
+ //
462
+ // Second reason these are refusals rather than normalizations: if the schema
463
+ // guarantees the incoming bytes are already canonical, a verifier in Rust or
464
+ // Go needs no arithmetic at all — no decimal library, no date parser, no ICU.
465
+ // It hashes what it gets. The only transformation left anywhere on the hash
466
+ // route is the ASCII lower-casing of the two address fields, which is v1
467
+ // legacy.
468
+ // ---------------------------------------------------------------------------
469
+ const MAX_SAFE_SPEC_INT = Number.MAX_SAFE_INTEGER; // 2^53 - 1
470
+ /** True if `key` contains a surrogate code unit — i.e. a lone surrogate OR any astral character (S-5). */
471
+ function keyHasSurrogate(key) {
472
+ for (let i = 0; i < key.length; i++) {
473
+ const c = key.charCodeAt(i);
474
+ if (c >= 0xd800 && c <= 0xdfff)
475
+ return true;
476
+ }
477
+ return false;
478
+ }
479
+ function isPlainObject(v) {
480
+ const proto = Object.getPrototypeOf(v);
481
+ return proto === Object.prototype || proto === null;
482
+ }
483
+ /**
484
+ * S-1 + S-5 + S-6, walked iteratively (never recursively — same reasoning as
485
+ * exceedsMaxDepth above) over the object branch of promisedSpec.
486
+ *
487
+ * S-1 closes a REAL, MEASURED collision in 0.1.x, not a theoretical one:
488
+ * today NaN, Infinity, -Infinity and null in promisedSpec all produce the
489
+ * SAME claimId (JSON.stringify renders all four as `null`), and -0 and 0 do
490
+ * too. Allowed value types are therefore: string, boolean, null, array,
491
+ * plain object, and a number that is an INTEGER within [-(2^53-1), 2^53-1].
492
+ * Anything needing a fraction goes in as a decimal string.
493
+ *
494
+ * S-5 refuses object keys containing surrogate code units — lone surrogates
495
+ * and anything at or above U+10000. That kills the UTF-16-versus-code-point
496
+ * key-sorting divergence at the source for everything new: JavaScript sorts
497
+ * U+1F600 before U+FF01, while a code-point sort (Python `sorted()`, Go
498
+ * string ordering, Rust BTreeMap) gives the opposite. The sort rule stays
499
+ * normative for READING historical lines back.
500
+ *
501
+ * S-6 refuses LONE surrogates in promisedSpec STRINGS — both the string
502
+ * branch of the union and every string value inside the object branch. S-5
503
+ * closed this for keys only, which left the identical portability hole open
504
+ * one field over: a lone surrogate has no UTF-8 encoding, so a Rust/Go/Python
505
+ * verifier cannot reconstruct the preimage bytes even though JavaScript
506
+ * happily round-trips it. Note what S-6 does NOT do: astral characters
507
+ * (U+1F600 and friends) stay ALLOWED in string values, because they encode
508
+ * fine in UTF-8 and only KEY ordering was ever ambiguous; and C0 control
509
+ * characters stay ALLOWED in promisedSpec, unlike in settlementRef (S-4),
510
+ * because JSON.stringify escapes them deterministically, they cost nothing in
511
+ * portability, and promisedSpec is documented free text where a newline is a
512
+ * legitimate thing for a caller to write. Refusing them here would be
513
+ * unjustified scope creep with a real usability cost.
514
+ *
515
+ * Returns null when fine, or a human-readable reason.
516
+ */
517
+ const LONE_SURROGATE_PROBLEM = "promisedSpec strings must not contain lone surrogates — an unpaired UTF-16 half has no UTF-8 encoding, so a verifier in another language cannot reconstruct the preimage bytes";
518
+ function promisedSpecIngestProblem(spec) {
519
+ // The string branch: S-1/S-5 do not apply to it, but S-6 does.
520
+ if (typeof spec === "string")
521
+ return hasLoneSurrogate(spec) ? LONE_SURROGATE_PROBLEM : null;
522
+ // Depth AND visited tracking are both load-bearing, for a reason that is
523
+ // easy to miss: in zod v4 a failing `.refine()` is NON-ABORTING, so the
524
+ // MAX_DEPTH refine on promisedSpec does NOT stop this walker from also
525
+ // running on the same raw, already-rejected input. Without the bounds
526
+ // below, two ordinary inputs hang the process:
527
+ // - a cyclic object: infinite stack growth, RangeError after ~20s of a
528
+ // fully blocked event loop;
529
+ // - an acyclic DAG of just 41 objects at depth 40 (`let n={leaf:1};
530
+ // for(i<40) n={x:n,y:n}`): shared references get re-expanded once per
531
+ // path, so the walker explores ~2^40 nodes and never returns.
532
+ // Both were measured against a real build; the frozen route rejects the
533
+ // second in 4ms while this walker ran past 55 seconds. Bounding depth at
534
+ // MAX_DEPTH costs nothing (anything deeper is rejected anyway) and the
535
+ // visited set collapses shared references back to one visit each.
536
+ const stack = [{ v: spec, d: 0 }];
537
+ const visited = new Set();
538
+ while (stack.length > 0) {
539
+ const { v, d } = stack.pop();
540
+ if (d > MAX_DEPTH)
541
+ continue; // the frozen route's own depth refine reports this
542
+ if (v === null)
543
+ continue;
544
+ if (typeof v === "object") {
545
+ if (visited.has(v))
546
+ continue;
547
+ visited.add(v);
548
+ }
549
+ const t = typeof v;
550
+ if (t === "string") {
551
+ // S-6, for every string value at any depth.
552
+ if (hasLoneSurrogate(v))
553
+ return LONE_SURROGATE_PROBLEM;
554
+ continue;
555
+ }
556
+ if (t === "boolean")
557
+ continue;
558
+ if (t === "number") {
559
+ const n = v;
560
+ if (!Number.isFinite(n))
561
+ return "promisedSpec must not contain NaN or Infinity (all of NaN, Infinity, -Infinity and null hash identically)";
562
+ if (!Number.isInteger(n))
563
+ return "promisedSpec numbers must be integers — use a decimal string for fractional values";
564
+ if (Object.is(n, -0))
565
+ return "promisedSpec must not contain -0 (it hashes identically to 0)";
566
+ if (n > MAX_SAFE_SPEC_INT || n < -MAX_SAFE_SPEC_INT)
567
+ return "promisedSpec integers must be within [-(2^53-1), 2^53-1]";
568
+ continue;
569
+ }
570
+ if (Array.isArray(v)) {
571
+ for (const item of v)
572
+ stack.push({ v: item, d: d + 1 });
573
+ continue;
574
+ }
575
+ if (t === "object") {
576
+ const obj = v;
577
+ if (!isPlainObject(obj))
578
+ return "promisedSpec must contain only plain objects and arrays (no Date, Map, Set, RegExp or class instances)";
579
+ if (typeof obj.toJSON === "function")
580
+ return "promisedSpec must not contain an object with its own toJSON";
581
+ for (const key of Object.keys(obj)) {
582
+ if (keyHasSurrogate(key)) {
583
+ return "promisedSpec object keys must not contain surrogate code units (no lone surrogates and no characters at or above U+10000)";
584
+ }
585
+ stack.push({ v: obj[key], d: d + 1 });
586
+ }
587
+ continue;
588
+ }
589
+ return `promisedSpec must not contain a value of type ${t}`;
590
+ }
591
+ return null;
592
+ }
593
+ function checkIngestHardening(content, ctx) {
594
+ // S-1 + S-5 + S-6
595
+ const specProblem = promisedSpecIngestProblem(content.promisedSpec);
596
+ if (specProblem)
597
+ ctx.addIssue({ code: "custom", path: ["promisedSpec"], message: specProblem });
598
+ // S-2 — new claims must carry a strict UTC timestamp with a real calendar
599
+ // date. Closes the gap where "August 30, 2026" and date-only forms were
600
+ // accepted. Every producer in this codebase already emits
601
+ // new Date().toISOString(), which satisfies this unchanged.
602
+ if (!MEASURED_TIMESTAMP_RE.test(content.timestamp) || !isRealCalendarDate(content.timestamp)) {
603
+ ctx.addIssue({
604
+ code: "custom",
605
+ path: ["timestamp"],
606
+ message: "timestamp must be a strict UTC instant YYYY-MM-DDTHH:MM:SS[.fff]Z with a real calendar date",
607
+ });
608
+ }
609
+ // S-3 — hex case. evidenceHash in upper case produces a DIFFERENT claimId
610
+ // for the same evidence: exactly the duplicate-bypass that was closed for
611
+ // addresses on 2026-08-31 and left open for evidence. Closed here for new
612
+ // claims; the frozen schema still accepts either case so older lines keep
613
+ // recomputing.
614
+ if (!LOWER_SHA256_HEX_RE.test(content.evidenceHash)) {
615
+ ctx.addIssue({
616
+ code: "custom",
617
+ path: ["evidenceHash"],
618
+ message: "evidenceHash must be lower-case hex — upper-case hex mints a second claimId for the same evidence",
619
+ });
620
+ }
621
+ // S-4 — settlementRef hygiene (log-line injection); the fuzz suite already
622
+ // documented this gap.
623
+ if (hasForbiddenTextChars(content.settlementRef)) {
624
+ ctx.addIssue({
625
+ code: "custom",
626
+ path: ["settlementRef"],
627
+ message: "settlementRef must not contain C0 control characters, U+007F, or lone surrogates",
628
+ });
629
+ }
630
+ }
631
+ /** ClaimContentSchema plus the ingest hardening of S-1..S-6. Used by recordDelivery(), never by computeClaimId(). */
632
+ export const StrictClaimContentSchema = ClaimContentObject.superRefine(checkMeasuredConsistency).superRefine(checkIngestHardening);
633
+ /** DeliveryClaimSchema plus the ingest hardening of S-1..S-6. This is what record_delivery validates against. */
634
+ export const StrictDeliveryClaimSchema = DeliveryClaimObject.superRefine(checkMeasuredConsistency).superRefine(checkIngestHardening);
174
635
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAMA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAItE,MAAM,MAAM,oBAAoB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjG;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4BlF;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAG9F"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAMA,OAAO,EAA6B,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5E,MAAM,MAAM,oBAAoB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjG;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA8ClF;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAG9F"}
package/dist/tools.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // al-yad-mcp-server's companion-client.ts vs. index.ts). This lets tests
4
4
  // and examples/demo.ts call the real logic directly without spinning up a
5
5
  // stdio JSON-RPC transport.
6
- import { DeliveryClaimSchema } from "./schema.js";
6
+ import { StrictDeliveryClaimSchema } from "./schema.js";
7
7
  import { verifyClaim } from "./signing.js";
8
8
  import { appendClaim, claimsForSeller } from "./ledger.js";
9
9
  /**
@@ -18,7 +18,26 @@ import { appendClaim, claimsForSeller } from "./ledger.js";
18
18
  * exact read-check-write sequence the lock exists to make atomic.
19
19
  */
20
20
  export async function recordDelivery(input) {
21
- const parsed = DeliveryClaimSchema.safeParse(input);
21
+ // StrictDeliveryClaimSchema, not DeliveryClaimSchema: new claims must also
22
+ // pass the ingest hardening of S-1..S-5 (see schema.ts). That schema is a
23
+ // superset of the frozen one, so it never changes a claimId — it only
24
+ // refuses input the frozen schema would have accepted. Historical ledger
25
+ // lines are still read back through the FROZEN DeliveryClaimSchema in
26
+ // ledger.ts, so a claim recorded before 0.2.0 with (say) a float in
27
+ // promisedSpec stays readable and verifiable forever.
28
+ // safeParse() is wrapped for the same reason verifyClaim() below is: the
29
+ // ingest checks walk caller-supplied data, and hostile or merely odd input
30
+ // (a cyclic object, a shared-reference graph) has already been shown to
31
+ // throw from inside a zod check rather than return a failed parse. The
32
+ // tool's contract is {ok:false, reason}, never an uncaught exception, so
33
+ // every step that touches untrusted input belongs inside a try/catch.
34
+ let parsed;
35
+ try {
36
+ parsed = StrictDeliveryClaimSchema.safeParse(input);
37
+ }
38
+ catch (e) {
39
+ return { ok: false, reason: `invalid_claim: ${e.message}` };
40
+ }
22
41
  if (!parsed.success) {
23
42
  return { ok: false, reason: `invalid_claim: ${parsed.error.issues.map((i) => i.message).join("; ")}` };
24
43
  }
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,4BAA4B;AAE5B,OAAO,EAAE,mBAAmB,EAAsB,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAc;IACjD,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IACzG,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1B,IAAI,OAAuC,CAAC;IAC5C,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,uEAAuE;QACvE,mEAAmE;QACnE,qEAAqE;QACrE,oDAAoD;QACpD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAmB,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IACvE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IACrD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;AAC9C,CAAC;AAQD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,aAAqB;IAC5D,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;IACpD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,uEAAuE;AACvE,yEAAyE;AACzE,0EAA0E;AAC1E,4BAA4B;AAE5B,OAAO,EAAE,yBAAyB,EAAsB,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAc;IACjD,2EAA2E;IAC3E,0EAA0E;IAC1E,sEAAsE;IACtE,yEAAyE;IACzE,sEAAsE;IACtE,oEAAoE;IACpE,sDAAsD;IACtD,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,uEAAuE;IACvE,yEAAyE;IACzE,sEAAsE;IACtE,IAAI,MAA8D,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,GAAG,yBAAyB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAmB,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IACzG,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1B,IAAI,OAAuC,CAAC;IAC5C,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,uEAAuE;QACvE,mEAAmE;QACnE,qEAAqE;QACrE,oDAAoD;QACpD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAmB,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IACvE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IACrD,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;AAC9C,CAAC;AAQD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,aAAqB;IAC5D,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;IACpD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;AACzD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacity-attest",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server for capacity-delivery attestations: after an x402 payment for compute capacity (GPU-hours, storage, API credits, bandwidth), the paying agent leaves a signed, factual claim of what was actually delivered, so other agents can check a seller's delivery history before paying. No reputation score, no judgment, no financial instrument.",
5
5
  "keywords": [
6
6
  "mcp",