aqta-verify-receipt 1.0.8 → 1.0.10
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/README.md +12 -8
- package/dist/cli.js +117 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +111 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ Same algorithm on npm and PyPI. Reference implementation, not a platform SDK.
|
|
|
18
18
|
## 30-second check
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
npx aqta-verify-receipt
|
|
22
|
-
--key
|
|
21
|
+
npx aqta-verify-receipt receipt.json \
|
|
22
|
+
--key 9Y3Eiq6V8QjRDUM5nPqSwKIOPQaoEU4SbagfYFdvWa4
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Default output is one compact line (words carry meaning; colour is optional):
|
|
@@ -37,7 +37,7 @@ Invalid:
|
|
|
37
37
|
Optional flourish (never the proof):
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
npx aqta-verify-receipt
|
|
40
|
+
npx aqta-verify-receipt receipt.json --key <pinned> --pretty
|
|
41
41
|
# …
|
|
42
42
|
◈ seal intact · verified offline
|
|
43
43
|
```
|
|
@@ -45,8 +45,8 @@ npx aqta-verify-receipt@1.0.8 receipt.json --key <pinned> --pretty
|
|
|
45
45
|
Automation:
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
npx aqta-verify-receipt
|
|
49
|
-
npx aqta-verify-receipt
|
|
48
|
+
npx aqta-verify-receipt receipt.json --key <pinned> --json
|
|
49
|
+
npx aqta-verify-receipt receipt.json --key <pinned> -q; echo $?
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
| Exit | Meaning |
|
|
@@ -57,13 +57,17 @@ npx aqta-verify-receipt@1.0.8 receipt.json --key <pinned> -q; echo $?
|
|
|
57
57
|
|
|
58
58
|
Production public key (also at
|
|
59
59
|
[`/v1/attestation/public-key`](https://api.aqta.ai/v1/attestation/public-key),
|
|
60
|
-
key id `aqta-att-
|
|
60
|
+
key id `aqta-att-01269bb4b6a7d950`):
|
|
61
61
|
|
|
62
62
|
```
|
|
63
|
-
|
|
63
|
+
9Y3Eiq6V8QjRDUM5nPqSwKIOPQaoEU4SbagfYFdvWa4
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
Pin that string
|
|
66
|
+
Pin that string; do not re-fetch it inside a verify loop. Keys rotate and
|
|
67
|
+
receipts do not: a receipt verifies against the key current when it was
|
|
68
|
+
signed, and the permanent key record (with retired keys and their validity
|
|
69
|
+
windows) is at
|
|
70
|
+
[`app.aqta.ai/security/issuer-keys.txt`](https://app.aqta.ai/security/issuer-keys.txt).
|
|
67
71
|
|
|
68
72
|
## Install
|
|
69
73
|
|
package/dist/cli.js
CHANGED
|
@@ -46,6 +46,7 @@ Usage:
|
|
|
46
46
|
Options:
|
|
47
47
|
--key <key> pin the issuer public key (required for counsel-grade)
|
|
48
48
|
--integrity-only check signature vs embedded key only (anyone can self-sign)
|
|
49
|
+
--envelope <name> opt in to a non-ATTESTATION-v1 envelope (e.g. anchor-v1)
|
|
49
50
|
--no-strict allow unknown top-level fields
|
|
50
51
|
--json machine JSON on stdout (one object)
|
|
51
52
|
--pretty optional human flourish after the compact line
|
|
@@ -70,14 +71,31 @@ function compactLine(valid, outcome, id, trustOrReason) {
|
|
|
70
71
|
}
|
|
71
72
|
return `${paint('31', `${no} invalid`)} ${trustOrReason} ${mid(id)}`;
|
|
72
73
|
}
|
|
73
|
-
|
|
74
|
+
/**
|
|
75
|
+
* The optional human lines under the compact verdict.
|
|
76
|
+
*
|
|
77
|
+
* Says what was established and what was not, because a receipt that verifies
|
|
78
|
+
* still does not prove which model ran, and someone reading this at the end of
|
|
79
|
+
* an audit should not have to already know that. Never changes the exit code.
|
|
80
|
+
*
|
|
81
|
+
* Must stay word-for-word identical to _pretty_extra in the Python CLI.
|
|
82
|
+
*/
|
|
83
|
+
function prettyExtra(valid, keySource) {
|
|
74
84
|
const utf8 = useUtf8();
|
|
75
85
|
const mark = utf8 ? '◈' : '*';
|
|
76
86
|
const dot = utf8 ? '·' : '-';
|
|
77
|
-
if (valid) {
|
|
78
|
-
return `${mark} seal
|
|
87
|
+
if (!valid) {
|
|
88
|
+
return (`${mark} seal broken ${dot} do not rely on this receipt\n` +
|
|
89
|
+
' these bytes are not what the issuer signed');
|
|
90
|
+
}
|
|
91
|
+
if (keySource !== 'pinned') {
|
|
92
|
+
return (`${mark} signature checks out, against a key this receipt supplied itself\n` +
|
|
93
|
+
' anyone can self-sign, so this shows only that the file is internally consistent\n' +
|
|
94
|
+
' pin the issuer key with --key before you rely on it');
|
|
79
95
|
}
|
|
80
|
-
return `${mark} seal
|
|
96
|
+
return (`${mark} seal intact ${dot} checked offline, nothing was sent to Aqta\n` +
|
|
97
|
+
' the issuer signed these exact bytes and no one has altered them since\n' +
|
|
98
|
+
' it does not prove which model actually ran');
|
|
81
99
|
}
|
|
82
100
|
function main() {
|
|
83
101
|
const args = process.argv.slice(2);
|
|
@@ -86,6 +104,7 @@ function main() {
|
|
|
86
104
|
let file = '';
|
|
87
105
|
let trustedKey;
|
|
88
106
|
let integrityOnly = false;
|
|
107
|
+
let envelope;
|
|
89
108
|
let strict = true;
|
|
90
109
|
let quiet = false;
|
|
91
110
|
let asJson = false;
|
|
@@ -100,6 +119,11 @@ function main() {
|
|
|
100
119
|
else if (a === '--integrity-only') {
|
|
101
120
|
integrityOnly = true;
|
|
102
121
|
}
|
|
122
|
+
else if (a === '--envelope') {
|
|
123
|
+
envelope = args[++i];
|
|
124
|
+
if (!envelope)
|
|
125
|
+
usage();
|
|
126
|
+
}
|
|
103
127
|
else if (a === '--no-strict') {
|
|
104
128
|
strict = false;
|
|
105
129
|
}
|
|
@@ -149,9 +173,29 @@ function main() {
|
|
|
149
173
|
process.stderr.write('aqta-verify-receipt: input is not valid JSON\n');
|
|
150
174
|
process.exit(2);
|
|
151
175
|
}
|
|
176
|
+
// Bare `null` parses fine and then crashed the display code below with an
|
|
177
|
+
// uncaught TypeError and a Node stack trace, including on the documented
|
|
178
|
+
// `curl ... | aqta-verify-receipt -` path. Matches the Python message and
|
|
179
|
+
// exit code.
|
|
180
|
+
if (typeof receipt !== 'object' || receipt === null || Array.isArray(receipt)) {
|
|
181
|
+
process.stderr.write('aqta-verify-receipt: receipt must be a JSON object\n');
|
|
182
|
+
process.exit(2);
|
|
183
|
+
}
|
|
184
|
+
// ATTESTATION-v1 canonicalises a parsed object, so a receipt carrying the same
|
|
185
|
+
// member name twice has no single canonical payload: a parser keeping the first
|
|
186
|
+
// value and one keeping the last compute different signed bytes from identical
|
|
187
|
+
// input. RFC 8259 leaves that choice to the implementation, so the format
|
|
188
|
+
// rejects the receipt. JSON.parse silently keeps the last value, so the check
|
|
189
|
+
// has to run over the raw text.
|
|
190
|
+
const duplicate = findDuplicateMemberName(raw);
|
|
191
|
+
if (duplicate !== null) {
|
|
192
|
+
process.stderr.write(`aqta-verify-receipt: duplicate member name: ${duplicate}\n`);
|
|
193
|
+
process.exit(2);
|
|
194
|
+
}
|
|
152
195
|
const result = (0, index_1.verifyReceipt)(receipt, {
|
|
153
196
|
trustedPublicKey: trustedKey,
|
|
154
197
|
allowUntrustedEmbeddedKey: integrityOnly,
|
|
198
|
+
envelope,
|
|
155
199
|
strictFields: strict,
|
|
156
200
|
});
|
|
157
201
|
const id = typeof receipt.attestation_id === 'string' ? receipt.attestation_id : '?';
|
|
@@ -166,18 +210,85 @@ function main() {
|
|
|
166
210
|
outcome,
|
|
167
211
|
attestation_id: id,
|
|
168
212
|
key_source: result.keySource ?? null,
|
|
213
|
+
envelope: result.envelope ?? null,
|
|
169
214
|
reason: result.valid ? null : result.reason ?? 'verification failed',
|
|
170
215
|
}) + '\n');
|
|
171
216
|
}
|
|
172
217
|
else {
|
|
173
|
-
|
|
218
|
+
let detail = result.valid ? trust : result.reason ?? 'verification failed';
|
|
219
|
+
// Name the envelope when it is not the default, so a valid line never
|
|
220
|
+
// leaves the reader assuming ATTESTATION-v1 rules were applied.
|
|
221
|
+
if (result.valid && result.envelope && result.envelope !== 'ATTESTATION-v1') {
|
|
222
|
+
detail = `${detail}, envelope ${result.envelope}`;
|
|
223
|
+
}
|
|
174
224
|
process.stdout.write(compactLine(result.valid, outcome, id, detail) + '\n');
|
|
175
225
|
if (pretty) {
|
|
176
|
-
process.stdout.write(prettyExtra(result.valid) + '\n');
|
|
226
|
+
process.stdout.write(prettyExtra(result.valid, result.keySource) + '\n');
|
|
177
227
|
}
|
|
178
228
|
}
|
|
179
229
|
}
|
|
180
230
|
process.exit(result.valid ? 0 : 1);
|
|
181
231
|
}
|
|
182
232
|
main();
|
|
233
|
+
/**
|
|
234
|
+
* Returns the first member name that appears twice within the same object, or
|
|
235
|
+
* null. Walks the raw text because JSON.parse has already collapsed duplicates
|
|
236
|
+
* by the time a reviver runs.
|
|
237
|
+
*/
|
|
238
|
+
function findDuplicateMemberName(raw) {
|
|
239
|
+
const stack = [];
|
|
240
|
+
let i = 0;
|
|
241
|
+
const readString = () => {
|
|
242
|
+
let out = '';
|
|
243
|
+
i += 1; // opening quote
|
|
244
|
+
while (i < raw.length) {
|
|
245
|
+
const ch = raw[i];
|
|
246
|
+
if (ch === '\\') {
|
|
247
|
+
out += raw.slice(i, i + 2);
|
|
248
|
+
i += 2;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (ch === '"') {
|
|
252
|
+
i += 1;
|
|
253
|
+
// Decode escapes before comparing. Comparing raw source spelling made
|
|
254
|
+
// the check escape-blind, so "outcome" was not seen as a duplicate
|
|
255
|
+
// of "outcome" and the ambiguous receipt verified here while Python
|
|
256
|
+
// rejected it. `out` is a valid JSON string body by construction.
|
|
257
|
+
try {
|
|
258
|
+
return JSON.parse('"' + out + '"');
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
out += ch;
|
|
265
|
+
i += 1;
|
|
266
|
+
}
|
|
267
|
+
return out;
|
|
268
|
+
};
|
|
269
|
+
while (i < raw.length) {
|
|
270
|
+
const ch = raw[i];
|
|
271
|
+
if (ch === '"') {
|
|
272
|
+
const value = readString();
|
|
273
|
+
// A string is a member name only if the next non-space character is a colon
|
|
274
|
+
// and we are directly inside an object.
|
|
275
|
+
let j = i;
|
|
276
|
+
while (j < raw.length && /\s/.test(raw[j]))
|
|
277
|
+
j += 1;
|
|
278
|
+
if (raw[j] === ':' && stack.length > 0) {
|
|
279
|
+
const names = stack[stack.length - 1];
|
|
280
|
+
if (names.has(value))
|
|
281
|
+
return value;
|
|
282
|
+
names.add(value);
|
|
283
|
+
}
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (ch === '{')
|
|
287
|
+
stack.push(new Set());
|
|
288
|
+
else if (ch === '}')
|
|
289
|
+
stack.pop();
|
|
290
|
+
i += 1;
|
|
291
|
+
}
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
183
294
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA;;;;;;;;;;;;;;GAcG;AACH,2BAAkC;AAClC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,14 @@ export interface VerifyOptions {
|
|
|
43
43
|
* top-level fields."
|
|
44
44
|
*/
|
|
45
45
|
strictFields?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Name of a non-ATTESTATION-v1 envelope the caller is deliberately
|
|
48
|
+
* verifying. Foreign envelopes carry their own field sets, so none of
|
|
49
|
+
* ATTESTATION-v1's structural or semantic rules apply; naming one here is
|
|
50
|
+
* how a caller says it understands that. Without it, a foreign envelope is
|
|
51
|
+
* rejected rather than silently verified under weaker rules.
|
|
52
|
+
*/
|
|
53
|
+
envelope?: EnvelopeFormat;
|
|
46
54
|
}
|
|
47
55
|
export type KeySource = 'pinned' | 'untrusted';
|
|
48
56
|
export interface VerifyResult {
|
|
@@ -67,7 +75,7 @@ export interface VerifyResult {
|
|
|
67
75
|
*
|
|
68
76
|
* @example
|
|
69
77
|
* const result = verifyReceipt(receipt, {
|
|
70
|
-
* trustedPublicKey: '
|
|
78
|
+
* trustedPublicKey: '9Y3Eiq6V8QjRDUM5nPqSwKIOPQaoEU4SbagfYFdvWa4',
|
|
71
79
|
* });
|
|
72
80
|
* if (!result.valid) throw new Error(`Receipt invalid: ${result.reason}`);
|
|
73
81
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,8DAA8D;AAC9D,MAAM,WAAW,kBAAkB;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IACzD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAEpC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,8DAA8D;AAC9D,MAAM,WAAW,kBAAkB;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IACzD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAEpC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAmGD;;;;;;;;;;;;;;;;;GAiBG;AACH;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,WAAW,CAAC;AAO5D,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAUtE;AAmFD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,aAAkB,GAC1B,YAAY,CAuJd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,SAA4C,GAC9C,OAAO,CAAC,MAAM,CAAC,CAMjB"}
|
package/dist/index.js
CHANGED
|
@@ -53,13 +53,18 @@ function base64urlDecode(s) {
|
|
|
53
53
|
* array values). It is NOT a general-purpose canonical-JSON library.
|
|
54
54
|
*/
|
|
55
55
|
function canonicalise(payload) {
|
|
56
|
-
|
|
57
|
-
const parts = [];
|
|
58
|
-
for (const k of keys) {
|
|
59
|
-
parts.push(`${JSON.stringify(k)}:${canonicalValue(payload[k])}`);
|
|
60
|
-
}
|
|
61
|
-
return new TextEncoder().encode('{' + parts.join(',') + '}');
|
|
56
|
+
return new TextEncoder().encode(canonicalValue(payload));
|
|
62
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* RFC 3339 with an explicit offset, range-checked without Date.
|
|
60
|
+
*
|
|
61
|
+
* Must stay character-for-character identical to _RFC3339_OFFSET in the Python
|
|
62
|
+
* verifier; the two implementations agreeing on what a timestamp is is the
|
|
63
|
+
* whole point of having two.
|
|
64
|
+
*/
|
|
65
|
+
const RFC3339_OFFSET = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])[Tt ]([01]\d|2[0-3]):[0-5]\d:([0-5]\d|60)(\.\d+)?([Zz]|[+-]([01]\d|2[0-3]):[0-5]\d)$/;
|
|
66
|
+
/** Matches an unpaired surrogate, which has no UTF-8 encoding. */
|
|
67
|
+
const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
63
68
|
function canonicalValue(v) {
|
|
64
69
|
if (v === null || v === undefined) {
|
|
65
70
|
return 'null';
|
|
@@ -68,17 +73,38 @@ function canonicalValue(v) {
|
|
|
68
73
|
return '[' + v.map(canonicalValue).join(',') + ']';
|
|
69
74
|
}
|
|
70
75
|
if (typeof v === 'number') {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
|
|
76
|
+
if (!Number.isFinite(v))
|
|
77
|
+
throw new Error('non-finite number');
|
|
78
|
+
// JSON.stringify implements ECMA-262 Number::toString, which is exactly
|
|
79
|
+
// the number grammar RFC 8785 (JCS) 3.2.2.3 specifies. Python's default
|
|
80
|
+
// float repr does not agree with it below 1e-4, so the Python verifier
|
|
81
|
+
// implements this algorithm rather than the reverse.
|
|
82
|
+
return JSON.stringify(v);
|
|
83
|
+
}
|
|
84
|
+
if (typeof v === 'string') {
|
|
85
|
+
// JSON.stringify escapes a lone surrogate to \uXXXX and would happily sign
|
|
86
|
+
// it, while a UTF-8 encoder cannot represent it at all. Rejecting in both
|
|
87
|
+
// implementations is the only way they agree on such a receipt.
|
|
88
|
+
if (LONE_SURROGATE.test(v))
|
|
89
|
+
throw new Error('string contains an unpaired surrogate');
|
|
78
90
|
return JSON.stringify(v);
|
|
79
91
|
}
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
if (typeof v === 'boolean') {
|
|
93
|
+
return JSON.stringify(v);
|
|
94
|
+
}
|
|
95
|
+
if (typeof v === 'object') {
|
|
96
|
+
// Nested objects sort too. No conformant receipt nests, but Python sorted
|
|
97
|
+
// recursively and this did not, so the two would have diverged the moment
|
|
98
|
+
// a field ever did.
|
|
99
|
+
const o = v;
|
|
100
|
+
return ('{' +
|
|
101
|
+
Object.keys(o)
|
|
102
|
+
.sort()
|
|
103
|
+
.map((k) => `${JSON.stringify(k)}:${canonicalValue(o[k])}`)
|
|
104
|
+
.join(',') +
|
|
105
|
+
'}');
|
|
106
|
+
}
|
|
107
|
+
throw new Error(`not canonicalisable: ${typeof v}`);
|
|
82
108
|
}
|
|
83
109
|
const ENVELOPE_FIELDS = {
|
|
84
110
|
'ATTESTATION-v1': { signature: 'signature', publicKey: 'public_key' },
|
|
@@ -97,6 +123,24 @@ function detectEnvelope(receipt) {
|
|
|
97
123
|
}
|
|
98
124
|
return null;
|
|
99
125
|
}
|
|
126
|
+
/** The Ed25519 group order L, RFC 8032 section 5.1. */
|
|
127
|
+
const ED25519_L = 7237005577332262213973186563042994240857116359379907606001950938285454250989n;
|
|
128
|
+
/**
|
|
129
|
+
* RFC 8032 5.1.7 requires the signature scalar S to decode in [0, L).
|
|
130
|
+
*
|
|
131
|
+
* tweetnacl omits this check, so 16 byte-distinct signatures verified for any
|
|
132
|
+
* one receipt: S, S+L, ... S+15L. No forgery, since producing any of them
|
|
133
|
+
* needs a genuine signature over unchanged content, but the two published
|
|
134
|
+
* verifiers returned different verdicts on identical bytes, and a transparency
|
|
135
|
+
* log that keys a leaf on receipt bytes would see 16 distinct leaves for one
|
|
136
|
+
* decision.
|
|
137
|
+
*/
|
|
138
|
+
function canonicalScalar(sig) {
|
|
139
|
+
let s = 0n;
|
|
140
|
+
for (let i = 63; i >= 32; i--)
|
|
141
|
+
s = (s << 8n) | BigInt(sig[i]);
|
|
142
|
+
return s < ED25519_L;
|
|
143
|
+
}
|
|
100
144
|
/**
|
|
101
145
|
* Signature check shared by every envelope.
|
|
102
146
|
*
|
|
@@ -135,6 +179,9 @@ function verifySignedEnvelope(r, envelope, options) {
|
|
|
135
179
|
return { valid: false, reason: 'signature length != 64 bytes' };
|
|
136
180
|
if (pub.length !== 32)
|
|
137
181
|
return { valid: false, reason: 'public key length != 32 bytes' };
|
|
182
|
+
if (!canonicalScalar(sig)) {
|
|
183
|
+
return { valid: false, reason: 'non-canonical signature scalar' };
|
|
184
|
+
}
|
|
138
185
|
if (!tweetnacl_1.default.sign.detached.verify(canonical, sig, pub)) {
|
|
139
186
|
return { valid: false, reason: 'signature check failed' };
|
|
140
187
|
}
|
|
@@ -162,7 +209,20 @@ function verifyReceipt(receipt, options = {}) {
|
|
|
162
209
|
}
|
|
163
210
|
// Other issuers' envelopes carry their own field sets, so only the signature
|
|
164
211
|
// is checked. The structural rules below are ATTESTATION-v1's alone.
|
|
212
|
+
//
|
|
213
|
+
// Which is why it has to be opted into. Detecting a foreign envelope purely
|
|
214
|
+
// by field name meant any object naming its fields signature_b64 and
|
|
215
|
+
// public_key_b64 skipped every structural and semantic rule: a payload with
|
|
216
|
+
// v:99, outcome:"MAYBE" and request_hash:"nope" verified, and so did an
|
|
217
|
+
// object that was not a receipt at all. Exit 0 then answered "were these
|
|
218
|
+
// bytes signed by that key" rather than "is this a conformant receipt".
|
|
165
219
|
if (envelope !== 'ATTESTATION-v1') {
|
|
220
|
+
if (options.envelope !== envelope) {
|
|
221
|
+
return {
|
|
222
|
+
valid: false,
|
|
223
|
+
reason: `envelope ${envelope} requires explicit opt-in (pass envelope: '${envelope}'); ATTESTATION-v1 rules do not apply to it`,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
166
226
|
return verifySignedEnvelope(r, envelope, options);
|
|
167
227
|
}
|
|
168
228
|
// Structural checks
|
|
@@ -191,6 +251,39 @@ function verifyReceipt(receipt, options = {}) {
|
|
|
191
251
|
if (typeof r.request_hash !== 'string' || !/^[0-9a-f]{64}$/.test(r.request_hash)) {
|
|
192
252
|
return { valid: false, reason: 'request_hash must be 64 lowercase hex chars' };
|
|
193
253
|
}
|
|
254
|
+
// The remaining §7 semantic checks. The Python verifier has always applied
|
|
255
|
+
// these; this one did not, so the two reference implementations returned
|
|
256
|
+
// different answers for the same receipt. A format whose verifiers disagree
|
|
257
|
+
// cannot settle a dispute, so they are enforced identically in both.
|
|
258
|
+
if (!r.policy_applied.every((p) => typeof p === 'string')) {
|
|
259
|
+
return { valid: false, reason: 'policy_applied must contain only strings' };
|
|
260
|
+
}
|
|
261
|
+
const sorted = [...r.policy_applied].sort();
|
|
262
|
+
if (r.policy_applied.some((p, i) => p !== sorted[i])) {
|
|
263
|
+
return { valid: false, reason: 'policy_applied must be in lexicographic order' };
|
|
264
|
+
}
|
|
265
|
+
if (typeof r.cost_prevented_eur !== 'number' || !Number.isFinite(r.cost_prevented_eur)) {
|
|
266
|
+
return { valid: false, reason: 'cost_prevented_eur must be a number' };
|
|
267
|
+
}
|
|
268
|
+
if (r.cost_prevented_eur < 0) {
|
|
269
|
+
return { valid: false, reason: 'cost_prevented_eur must be non-negative' };
|
|
270
|
+
}
|
|
271
|
+
// Well-formedness only. Freshness stays informative per CONFORMANCE.md, so
|
|
272
|
+
// an old receipt still verifies offline; a timestamp that is not a datetime
|
|
273
|
+
// with an explicit offset is a malformed field, not a stale one.
|
|
274
|
+
//
|
|
275
|
+
// The range checks live in the pattern rather than in Date.parse. Deferring
|
|
276
|
+
// to V8 made this verifier reject "2016-12-31T23:59:60Z", a real leap second
|
|
277
|
+
// and legal RFC 3339, while still accepting February 30th because V8 rolls it
|
|
278
|
+
// forward. Python had no such clause, so the two disagreed on both. This
|
|
279
|
+
// pattern is character-for-character the one in the Python verifier.
|
|
280
|
+
if (typeof r.timestamp !== 'string' ||
|
|
281
|
+
!RFC3339_OFFSET.test(r.timestamp)) {
|
|
282
|
+
return {
|
|
283
|
+
valid: false,
|
|
284
|
+
reason: 'timestamp must be an RFC 3339 datetime with an explicit offset',
|
|
285
|
+
};
|
|
286
|
+
}
|
|
194
287
|
const pinned = options.trustedPublicKey;
|
|
195
288
|
const allowUntrusted = options.allowUntrustedEmbeddedKey === true;
|
|
196
289
|
if (pinned === undefined && !allowUntrusted) {
|
|
@@ -226,6 +319,9 @@ function verifyReceipt(receipt, options = {}) {
|
|
|
226
319
|
if (pub.length !== 32) {
|
|
227
320
|
return { valid: false, reason: 'public key length != 32 bytes' };
|
|
228
321
|
}
|
|
322
|
+
if (!canonicalScalar(sig)) {
|
|
323
|
+
return { valid: false, reason: 'non-canonical signature scalar' };
|
|
324
|
+
}
|
|
229
325
|
const ok = tweetnacl_1.default.sign.detached.verify(canonical, sig, pub);
|
|
230
326
|
if (!ok) {
|
|
231
327
|
return { valid: false, reason: 'signature check failed' };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;AAsMH,wCAUC;AAmFD,sCA0JC;AAsBD,0DAQC;AAzdD,0DAA6B;AAC7B,oEAAsC;AA+DtC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IACpD,SAAS;IACT,SAAS;IACT,YAAY;IACZ,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC;IACnD,GAAG;IACH,gBAAgB;IAChB,UAAU;IACV,QAAQ;IACR,cAAc;IACd,OAAO;IACP,SAAS;IACT,gBAAgB;IAChB,oBAAoB;IACpB,WAAW;IACX,YAAY;IACZ,WAAW;CACZ,CAAC,CAAC;AAEH,gEAAgE;AAChE,SAAS,eAAe,CAAC,CAAS;IAChC,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzD,OAAO,wBAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,OAAgC;IACpD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,cAAc,GAClB,kIAAkI,CAAC;AAErI,kEAAkE;AAClE,MAAM,cAAc,GAAG,wEAAwE,CAAC;AAEhG,SAAS,cAAc,CAAC,CAAU;IAChC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACrD,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC9D,wEAAwE;QACxE,wEAAwE;QACxE,uEAAuE;QACvE,qDAAqD;QACrD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,2EAA2E;QAC3E,0EAA0E;QAC1E,gEAAgE;QAChE,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,0EAA0E;QAC1E,0EAA0E;QAC1E,oBAAoB;QACpB,MAAM,CAAC,GAAG,CAA4B,CAAC;QACvC,OAAO,CACL,GAAG;YACH,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;iBACX,IAAI,EAAE;iBACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC1D,IAAI,CAAC,GAAG,CAAC;YACZ,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,EAAE,CAAC,CAAC;AACtD,CAAC;AA+BD,MAAM,eAAe,GAAqE;IACxF,gBAAgB,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE;IACrE,WAAW,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,gBAAgB,EAAE;CACzE,CAAC;AAEF,mFAAmF;AACnF,SAAgB,cAAc,CAAC,OAAgB;IAC7C,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjE,MAAM,CAAC,GAAG,OAAkC,CAAC;IAC7C,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACxE,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QAChF,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,uDAAuD;AACvD,MAAM,SAAS,GACb,6EAA6E,CAAC;AAEhF;;;;;;;;;GASG;AACH,SAAS,eAAe,CAAC,GAAe;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;QAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,SAAS,CAAC;AACvB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAC3B,CAA0B,EAC1B,QAAwB,EACxB,OAAsB;IAEtB,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IACxC,MAAM,cAAc,GAAG,OAAO,CAAC,yBAAyB,KAAK,IAAI,CAAC;IAElE,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EACJ,+EAA+E;SAClF,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,SAAS,CAAW,CAAC;IAClD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,uCAAuC,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,OAAO,GAA4B,EAAE,GAAG,CAAC,EAAE,CAAC;IAClD,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEjC,IAAI,SAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1E,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAW,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;QACzC,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;QACvF,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;QACxF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,mBAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,QAAQ;YACR,SAAS,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW;SACzD,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1E,CAAC;AACH,CAAC;AAED,SAAgB,aAAa,CAC3B,OAAgB,EAChB,UAAyB,EAAE;IAE3B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC;IAC9D,CAAC;IACD,MAAM,CAAC,GAAG,OAAkC,CAAC;IAE7C,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EACJ,sFAAsF;SACzF,CAAC;IACJ,CAAC;IACD,6EAA6E;IAC7E,qEAAqE;IACrE,EAAE;IACF,4EAA4E;IAC5E,qEAAqE;IACrE,4EAA4E;IAC5E,wEAAwE;IACxE,yEAAyE;IACzE,wEAAwE;IACxE,IAAI,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QAClC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,YAAY,QAAQ,8CAA8C,QAAQ,6CAA6C;aAChI,CAAC;QACJ,CAAC;QACD,OAAO,oBAAoB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,oBAAoB;IACpB,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;QACpC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,KAAK,EAAE,EAAE,CAAC;QACtE,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,KAAK,KAAK,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,4BAA4B,CAAC,EAAE,EAAE,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QACd,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;IAC3E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;QACjF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,6CAA6C,EAAE,CAAC;IACjF,CAAC;IACD,2EAA2E;IAC3E,yEAAyE;IACzE,4EAA4E;IAC5E,qEAAqE;IACrE,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACnE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,0CAA0C,EAAE,CAAC;IAC9E,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAI,CAAC,CAAC,cAA2B,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAK,CAAC,CAAC,cAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,+CAA+C,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,OAAO,CAAC,CAAC,kBAAkB,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACvF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,qCAAqC,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,CAAC,kBAAkB,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC;IAC7E,CAAC;IACD,2EAA2E;IAC3E,4EAA4E;IAC5E,iEAAiE;IACjE,EAAE;IACF,4EAA4E;IAC5E,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,qEAAqE;IACrE,IACE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;QAC/B,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EACjC,CAAC;QACD,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,gEAAgE;SACzE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IACxC,MAAM,cAAc,GAAG,OAAO,CAAC,yBAAyB,KAAK,IAAI,CAAC;IAElE,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EACJ,+EAA+E;SAClF,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;QACpD,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,uCAAuC;SAChD,CAAC;IACJ,CAAC;IAED,kDAAkD;IAClD,MAAM,OAAO,GAA4B,EAAE,GAAG,CAAC,EAAE,CAAC;IAClD,OAAO,OAAO,CAAC,SAAS,CAAC;IAEzB,IAAI,SAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1E,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,CAAC,SAAmB,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,CAAC,UAAoB,CAAC,CAAC;QACpD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;QAClE,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,+BAA+B,EAAE,CAAC;QACnE,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAAC;QACpE,CAAC;QACD,MAAM,EAAE,GAAG,mBAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1D,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,gBAAgB;YAC1B,SAAS,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW;SACzD,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1E,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,uBAAuB,CAC3C,GAAG,GAAG,yCAAyC;IAE/C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACnC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aqta-verify-receipt",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Offline CLI and library for Seal ATTESTATION-v1 receipts. Ed25519 check of a signed model call; no account, no Aqta server required.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "tsc",
|
|
25
|
-
"test": "node --test dist/index.test.js",
|
|
25
|
+
"test": "node --test dist/index.test.js dist/envelope.test.js",
|
|
26
26
|
"prepublishOnly": "npm run build"
|
|
27
27
|
},
|
|
28
28
|
"keywords": [
|