@ziffer-io/verify 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/cbor.d.ts +87 -0
- package/dist/cbor.d.ts.map +1 -0
- package/dist/cbor.js +326 -0
- package/dist/cbor.js.map +1 -0
- package/dist/chain.d.ts +142 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +430 -0
- package/dist/chain.js.map +1 -0
- package/dist/clauses.d.ts +70 -0
- package/dist/clauses.d.ts.map +1 -1
- package/dist/clauses.js +77 -0
- package/dist/clauses.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/quorum.d.ts +245 -0
- package/dist/quorum.d.ts.map +1 -0
- package/dist/quorum.js +566 -0
- package/dist/quorum.js.map +1 -0
- package/dist/sig.d.ts +57 -0
- package/dist/sig.d.ts.map +1 -0
- package/dist/sig.js +127 -0
- package/dist/sig.js.map +1 -0
- package/dist/testkeys.d.ts +33 -0
- package/dist/testkeys.d.ts.map +1 -1
- package/dist/testkeys.js +100 -0
- package/dist/testkeys.js.map +1 -1
- package/dist/verify.d.ts +44 -20
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +55 -146
- package/dist/verify.js.map +1 -1
- package/dist/webauthn.d.ts +148 -0
- package/dist/webauthn.d.ts.map +1 -0
- package/dist/webauthn.js +414 -0
- package/dist/webauthn.js.map +1 -0
- package/dist/wire.d.ts +44 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +90 -0
- package/dist/wire.js.map +1 -0
- package/package.json +2 -2
package/dist/chain.js
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The audit chain export verifier (ACP-428) -- the TypeScript reader of the
|
|
3
|
+
* file the console's "Download the audit chain for this window" link gives.
|
|
4
|
+
*
|
|
5
|
+
* The link said the file was verifiable offline and nothing a customer held
|
|
6
|
+
* verified it. The Python SDK's `verify_chain` and this function are that
|
|
7
|
+
* verifier, and they are held to ONE verdict per file by the shared corpus in
|
|
8
|
+
* `fixtures/chain-export/` -- the same refusal name at the same record, the
|
|
9
|
+
* same recomputed last hash, the same report of what the anchors cover. The
|
|
10
|
+
* check order below is the Python reader's, step for step, because on a file
|
|
11
|
+
* with two defects the order decides which one is named.
|
|
12
|
+
*
|
|
13
|
+
* # What is recomputed, and what is only reported
|
|
14
|
+
*
|
|
15
|
+
* Every `chain_hash` is RECOMPUTED -- `sha256:` over the canonical bytes of the
|
|
16
|
+
* record (the first record of the chain) or of `{prev, record}` (every later
|
|
17
|
+
* one), the audit service's own link -- and the file's value is compared,
|
|
18
|
+
* never used. Every `previous_hash` after the first row is compared against
|
|
19
|
+
* the hash just recomputed. The first row's `previous_hash`, in a file that
|
|
20
|
+
* starts after the beginning of the chain, is the one link this file cannot
|
|
21
|
+
* recompute; it is reported as `startsAfter`, and it is checked only when an
|
|
22
|
+
* anchor names exactly that position.
|
|
23
|
+
*
|
|
24
|
+
* # The anchor key never comes from the file
|
|
25
|
+
*
|
|
26
|
+
* Every anchor entry carries an `anchor_identity` beside it. Reading the key
|
|
27
|
+
* from there would accept any file whose author signed their own anchors and
|
|
28
|
+
* wrote their own key next to them -- the party under verification supplying
|
|
29
|
+
* the value it is verified with. So the key is a parameter, from a file the
|
|
30
|
+
* customer holds, and with no key every anchor is reported `unchecked`: never
|
|
31
|
+
* passed, and never dropped from the report.
|
|
32
|
+
*
|
|
33
|
+
* # Numbers: the file's TEXT is read, not only its parsed values
|
|
34
|
+
*
|
|
35
|
+
* `JSON.parse` reads `1.0` as the integer 1. The record the writer hashed said
|
|
36
|
+
* `1.0`, so hashing `1` would compare bytes nobody wrote and name the wrong
|
|
37
|
+
* defect. The parser's reviver sees each number's source text (Node 22 and
|
|
38
|
+
* later), and a number written with a fraction or an exponent becomes a value
|
|
39
|
+
* the canonical encoder refuses -- `RecordNotCanonical` inside a record,
|
|
40
|
+
* `ExportMalformed` in the file's own fields, exactly where the Python reader
|
|
41
|
+
* says so. On a runtime whose parser does not hand the reviver the source
|
|
42
|
+
* text, that one case would be named `ChainHashMismatch` instead; the file is
|
|
43
|
+
* refused either way.
|
|
44
|
+
*/
|
|
45
|
+
import { createHash } from 'node:crypto';
|
|
46
|
+
import { canon } from './canon.js';
|
|
47
|
+
import { ed25519IsSmallOrder } from './ed25519.js';
|
|
48
|
+
import { MLDSA65_PK_LEN, verifyUnderSuite } from './sig.js';
|
|
49
|
+
import { isRecord } from './wire.js';
|
|
50
|
+
/** The one suite an audit anchor is signed under here, and the only one an anchor key may name. */
|
|
51
|
+
export const ANCHOR_SUITE = 'hybrid-ed25519-mldsa65';
|
|
52
|
+
const ANCHOR_VERSION = 1;
|
|
53
|
+
const HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
54
|
+
const ED25519_PK_BYTES = 32;
|
|
55
|
+
/** A refusal of an export, by name, at the first record or anchor that broke. */
|
|
56
|
+
export class ChainRefusal extends Error {
|
|
57
|
+
/** The refusal name, identical to the Python reader's `ChainRefused.name`. */
|
|
58
|
+
refusal;
|
|
59
|
+
seq;
|
|
60
|
+
anchor;
|
|
61
|
+
constructor(refusal, detail, where = {}) {
|
|
62
|
+
super(`${refusal}: ${detail}`);
|
|
63
|
+
this.name = 'ChainRefusal';
|
|
64
|
+
this.refusal = refusal;
|
|
65
|
+
this.seq = where.seq ?? null;
|
|
66
|
+
this.anchor = where.anchor ?? null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** An anchor key file that cannot be used, by name. A defect in the caller's own file, not a verdict. */
|
|
70
|
+
export class AnchorKeyRefusal extends Error {
|
|
71
|
+
refusal;
|
|
72
|
+
constructor(refusal, detail) {
|
|
73
|
+
super(`${refusal}: ${detail}`);
|
|
74
|
+
this.name = 'AnchorKeyRefusal';
|
|
75
|
+
this.refusal = refusal;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// A number the source spelled with a fraction or an exponent. A symbol, so the
|
|
79
|
+
// canonical encoder refuses it wherever it lands and no field check mistakes it
|
|
80
|
+
// for an integer.
|
|
81
|
+
const NOT_AN_INTEGER = Symbol('a number written with a fraction or an exponent');
|
|
82
|
+
function reviver(_key, value, context) {
|
|
83
|
+
if (typeof value === 'number' && typeof context?.source === 'string' && /[.eE]/.test(context.source)) {
|
|
84
|
+
return NOT_AN_INTEGER;
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
function isInt(v) {
|
|
89
|
+
return typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;
|
|
90
|
+
}
|
|
91
|
+
// Half of a UTF-16 surrogate pair on its own: the Python reader cannot encode
|
|
92
|
+
// one at all, and JSON.stringify would escape it into bytes nobody wrote.
|
|
93
|
+
const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
94
|
+
function canonicalValue(v) {
|
|
95
|
+
if (v === null || typeof v === 'boolean')
|
|
96
|
+
return true;
|
|
97
|
+
if (typeof v === 'number')
|
|
98
|
+
return Number.isSafeInteger(v);
|
|
99
|
+
if (typeof v === 'string')
|
|
100
|
+
return !LONE_SURROGATE.test(v);
|
|
101
|
+
if (Array.isArray(v))
|
|
102
|
+
return v.every(canonicalValue);
|
|
103
|
+
if (isRecord(v))
|
|
104
|
+
return Object.entries(v).every(([k, x]) => !LONE_SURROGATE.test(k) && canonicalValue(x));
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
function sha256Hex(bytes) {
|
|
108
|
+
return createHash('sha256').update(bytes).digest('hex');
|
|
109
|
+
}
|
|
110
|
+
/** The audit service's link: `sha256:` over the canonical bytes. */
|
|
111
|
+
function link(value) {
|
|
112
|
+
return `sha256:${sha256Hex(canon(value))}`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* RFC 4648 section 4 base64 with padding, in its one spelling: a value that
|
|
116
|
+
* does not re-encode to itself is refused, so two spellings of one signature
|
|
117
|
+
* are not two accepted signatures.
|
|
118
|
+
*/
|
|
119
|
+
function b64Strict(value) {
|
|
120
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
121
|
+
return null;
|
|
122
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value) || value.length % 4 !== 0)
|
|
123
|
+
return null;
|
|
124
|
+
const raw = Uint8Array.from(Buffer.from(value, 'base64'));
|
|
125
|
+
return Buffer.from(raw).toString('base64') === value ? raw : null;
|
|
126
|
+
}
|
|
127
|
+
function parseText(file) {
|
|
128
|
+
let text;
|
|
129
|
+
if (typeof file === 'string') {
|
|
130
|
+
text = file;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
try {
|
|
134
|
+
// ignoreBOM keeps a byte-order mark in the text, where JSON.parse refuses
|
|
135
|
+
// it -- as the Python reader's parser does.
|
|
136
|
+
text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(file);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
throw new ChainRefusal('ExportMalformed', 'the file is not UTF-8');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const parsed = JSON.parse(text, reviver);
|
|
144
|
+
return parsed;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
throw new ChainRefusal('ExportMalformed', 'the file is not JSON');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Read the audit anchor identity's public document -- `{alg, classical, pq,
|
|
152
|
+
* fingerprint}`, the halves in base64 -- checking every redundant field: the
|
|
153
|
+
* fingerprint is recomputed over both halves and compared, and a small-order
|
|
154
|
+
* Ed25519 half is refused, because under one a single signature verifies every
|
|
155
|
+
* message.
|
|
156
|
+
*/
|
|
157
|
+
export function parseAnchorKey(file) {
|
|
158
|
+
let doc;
|
|
159
|
+
try {
|
|
160
|
+
doc = JSON.parse(typeof file === 'string' ? file : new TextDecoder('utf-8', { fatal: true }).decode(file));
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
throw new AnchorKeyRefusal('AnchorKeyMalformed', 'the anchor key file is not JSON');
|
|
164
|
+
}
|
|
165
|
+
if (!isRecord(doc)) {
|
|
166
|
+
throw new AnchorKeyRefusal('AnchorKeyMalformed', 'the anchor key document is not a JSON object');
|
|
167
|
+
}
|
|
168
|
+
if ('ed25519_pk_hex' in doc || 'identity' in doc) {
|
|
169
|
+
throw new AnchorKeyRefusal('AnchorKeyMalformed', 'this is a receipt trust anchor (the document `ziffer pubkey` writes), not the audit anchor identity');
|
|
170
|
+
}
|
|
171
|
+
if (doc['alg'] !== ANCHOR_SUITE) {
|
|
172
|
+
throw new AnchorKeyRefusal('AnchorKeyUnsupported', `audit anchors are verified under ${ANCHOR_SUITE} only`);
|
|
173
|
+
}
|
|
174
|
+
const classical = b64Strict(doc['classical']);
|
|
175
|
+
const pq = b64Strict(doc['pq']);
|
|
176
|
+
if (classical === null || classical.length !== ED25519_PK_BYTES || pq === null || pq.length !== MLDSA65_PK_LEN) {
|
|
177
|
+
throw new AnchorKeyRefusal('AnchorKeyMalformed', '`classical` must be 32 bytes and `pq` 1952 bytes, each in padded base64');
|
|
178
|
+
}
|
|
179
|
+
if (ed25519IsSmallOrder(classical)) {
|
|
180
|
+
throw new AnchorKeyRefusal('AnchorKeyMalformed', 'the Ed25519 half is a small-order point');
|
|
181
|
+
}
|
|
182
|
+
const both = new Uint8Array(classical.length + pq.length);
|
|
183
|
+
both.set(classical, 0);
|
|
184
|
+
both.set(pq, classical.length);
|
|
185
|
+
const fingerprint = `sha256:${sha256Hex(both)}`;
|
|
186
|
+
if (doc['fingerprint'] !== fingerprint) {
|
|
187
|
+
throw new AnchorKeyRefusal('AnchorKeyMalformed', 'the fingerprint is not the fingerprint of the document’s own keys; it was edited after it was written');
|
|
188
|
+
}
|
|
189
|
+
return { alg: ANCHOR_SUITE, classical, pq, fingerprint };
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Both halves of the hybrid signature over the bytes the audit service signed:
|
|
193
|
+
* the canonical encoding of the anchor's `alg`, `heads`, `period_end` and `v`.
|
|
194
|
+
* Conjunctive, over exactly {classical, pq}.
|
|
195
|
+
*/
|
|
196
|
+
function anchorSignatureOk(key, signed) {
|
|
197
|
+
const sig = signed['sig'];
|
|
198
|
+
if (!isRecord(sig))
|
|
199
|
+
return false;
|
|
200
|
+
const names = Object.keys(sig).sort();
|
|
201
|
+
if (names.length !== 2 || names[0] !== 'classical' || names[1] !== 'pq')
|
|
202
|
+
return false;
|
|
203
|
+
const classical = b64Strict(sig['classical']);
|
|
204
|
+
const pq = b64Strict(sig['pq']);
|
|
205
|
+
if (classical === null || pq === null)
|
|
206
|
+
return false;
|
|
207
|
+
const body = canon({
|
|
208
|
+
alg: signed['alg'],
|
|
209
|
+
heads: signed['heads'],
|
|
210
|
+
period_end: signed['period_end'],
|
|
211
|
+
v: signed['v'],
|
|
212
|
+
});
|
|
213
|
+
const parts = [
|
|
214
|
+
{ primitive: 'classical', bytes: classical },
|
|
215
|
+
{ primitive: 'pq', bytes: pq },
|
|
216
|
+
];
|
|
217
|
+
return verifyUnderSuite(ANCHOR_SUITE, key, body, parts) === null;
|
|
218
|
+
}
|
|
219
|
+
function isHead(h) {
|
|
220
|
+
return (Array.isArray(h) && h.length === 3 && typeof h[0] === 'string' && isInt(h[1]) && typeof h[2] === 'string');
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Verify an audit chain export, from the file's bytes or text.
|
|
224
|
+
*
|
|
225
|
+
* Throws {@link ChainRefusal} at the first break: `ExportMalformed`,
|
|
226
|
+
* `ExportEmpty`, `ChainSeqGap`, `RecordOutOfPlace`, `ChainLinkBroken`,
|
|
227
|
+
* `RecordNotCanonical`, `ChainHashMismatch`, `AnchorMalformed`,
|
|
228
|
+
* `AnchorSuiteNotEnrolled`, `AnchorSignatureInvalid`, `AnchorHeadMismatch`.
|
|
229
|
+
*
|
|
230
|
+
* NOT checked, on purpose, as in the Python reader: whether each record's
|
|
231
|
+
* fields are the set its kind of event carries, the transparency-log entry and
|
|
232
|
+
* timestamp stored beside each anchor, and whether the file holds EVERY record
|
|
233
|
+
* of its window -- a file cut short at the end verifies, and `unanchoredFrom`
|
|
234
|
+
* says how much of it nothing yet commits to.
|
|
235
|
+
*/
|
|
236
|
+
export function verifyChain(file, anchorKey) {
|
|
237
|
+
const doc = parseText(file);
|
|
238
|
+
if (!isRecord(doc))
|
|
239
|
+
throw new ChainRefusal('ExportMalformed', 'the file is not a JSON object');
|
|
240
|
+
const tenant = doc['tenant'];
|
|
241
|
+
const chain = doc['chain'];
|
|
242
|
+
const anchors = doc['anchors'];
|
|
243
|
+
if (typeof tenant !== 'string' || !Array.isArray(chain) || !Array.isArray(anchors)) {
|
|
244
|
+
throw new ChainRefusal('ExportMalformed', 'the file carries no `tenant`, `chain` and `anchors`');
|
|
245
|
+
}
|
|
246
|
+
if (chain.length === 0)
|
|
247
|
+
throw new ChainRefusal('ExportEmpty', 'the file holds no records');
|
|
248
|
+
// ---- the chain: every link recomputed, in order -------------------------
|
|
249
|
+
const recomputed = [];
|
|
250
|
+
let firstSeq = 0;
|
|
251
|
+
let startsAfter = null;
|
|
252
|
+
for (let i = 0; i < chain.length; i += 1) {
|
|
253
|
+
const row = chain[i];
|
|
254
|
+
if (!isRecord(row) ||
|
|
255
|
+
!isInt(row['seq']) ||
|
|
256
|
+
typeof row['chain_hash'] !== 'string' ||
|
|
257
|
+
!('previous_hash' in row) ||
|
|
258
|
+
!(row['previous_hash'] === null || typeof row['previous_hash'] === 'string') ||
|
|
259
|
+
!isRecord(row['record'])) {
|
|
260
|
+
throw new ChainRefusal('ExportMalformed', `row ${i} is not {seq, previous_hash, chain_hash, record}`);
|
|
261
|
+
}
|
|
262
|
+
const seq = row['seq'];
|
|
263
|
+
const record = row['record'];
|
|
264
|
+
const previous = row['previous_hash'];
|
|
265
|
+
if (i === 0) {
|
|
266
|
+
firstSeq = seq;
|
|
267
|
+
}
|
|
268
|
+
else if (seq !== firstSeq + i) {
|
|
269
|
+
throw new ChainRefusal('ChainSeqGap', `follows record ${firstSeq + i - 1}; a chain has no gaps`, { seq });
|
|
270
|
+
}
|
|
271
|
+
const recordSeq = record['seq'];
|
|
272
|
+
if (record['tenant_id'] !== tenant || (seq > 0 && !(isInt(recordSeq) && recordSeq === seq))) {
|
|
273
|
+
throw new ChainRefusal('RecordOutOfPlace', 'the record names another tenant or another position', { seq });
|
|
274
|
+
}
|
|
275
|
+
let prev;
|
|
276
|
+
if (i === 0) {
|
|
277
|
+
if (seq === 0 && previous !== null) {
|
|
278
|
+
throw new ChainRefusal('ChainLinkBroken', 'the first record of a chain has no predecessor', { seq });
|
|
279
|
+
}
|
|
280
|
+
if (seq > 0) {
|
|
281
|
+
if (typeof previous !== 'string' || !HASH_PATTERN.test(previous)) {
|
|
282
|
+
throw new ChainRefusal('ChainLinkBroken', 'the file starts after the chain’s beginning and does not say which hash it continues from', { seq });
|
|
283
|
+
}
|
|
284
|
+
startsAfter = previous;
|
|
285
|
+
}
|
|
286
|
+
prev = typeof previous === 'string' ? previous : null;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
const before = recomputed[i - 1] ?? null;
|
|
290
|
+
if (previous !== before) {
|
|
291
|
+
throw new ChainRefusal('ChainLinkBroken', 'does not continue from the record before it', { seq });
|
|
292
|
+
}
|
|
293
|
+
prev = before;
|
|
294
|
+
}
|
|
295
|
+
if (!canonicalValue(record)) {
|
|
296
|
+
throw new ChainRefusal('RecordNotCanonical', 'the record holds a fraction or an integer too large to encode one way', { seq });
|
|
297
|
+
}
|
|
298
|
+
const hash = seq === 0 ? link(record) : link({ prev, record });
|
|
299
|
+
if (hash !== row['chain_hash']) {
|
|
300
|
+
throw new ChainRefusal('ChainHashMismatch', `the record hashes to ${hash}`, { seq });
|
|
301
|
+
}
|
|
302
|
+
recomputed.push(hash);
|
|
303
|
+
}
|
|
304
|
+
const lastSeq = firstSeq + chain.length - 1;
|
|
305
|
+
// ---- the anchors: each signature under YOUR key, each head against the chain
|
|
306
|
+
const results = [];
|
|
307
|
+
let anchoredThrough = null;
|
|
308
|
+
for (let j = 0; j < anchors.length; j += 1) {
|
|
309
|
+
const entry = anchors[j];
|
|
310
|
+
const signed = isRecord(entry) ? entry['anchor'] : undefined;
|
|
311
|
+
if (!isRecord(signed) ||
|
|
312
|
+
typeof signed['alg'] !== 'string' ||
|
|
313
|
+
!isInt(signed['v']) ||
|
|
314
|
+
signed['v'] !== ANCHOR_VERSION ||
|
|
315
|
+
!isInt(signed['period_end']) ||
|
|
316
|
+
!Array.isArray(signed['heads']) ||
|
|
317
|
+
!signed['heads'].every(isHead) ||
|
|
318
|
+
!('sig' in signed)) {
|
|
319
|
+
throw new ChainRefusal('AnchorMalformed', 'not {alg, heads, period_end, sig, v} with three-part heads', {
|
|
320
|
+
anchor: j,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
const periodEnd = signed['period_end'];
|
|
324
|
+
const heads = signed['heads'];
|
|
325
|
+
const mine = heads.filter(isHead).filter((h) => h[0] === tenant);
|
|
326
|
+
if (mine.length > 1) {
|
|
327
|
+
throw new ChainRefusal('AnchorMalformed', `names this tenant ${mine.length} times`, { anchor: j });
|
|
328
|
+
}
|
|
329
|
+
let status = 'unchecked';
|
|
330
|
+
if (anchorKey !== undefined) {
|
|
331
|
+
if (signed['alg'] !== anchorKey.alg) {
|
|
332
|
+
throw new ChainRefusal('AnchorSuiteNotEnrolled', 'signed under a suite your anchor key is not', {
|
|
333
|
+
anchor: j,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
if (!anchorSignatureOk(anchorKey, signed)) {
|
|
337
|
+
throw new ChainRefusal('AnchorSignatureInvalid', 'the anchor’s signature does not verify under your anchor key -- both halves must', { anchor: j });
|
|
338
|
+
}
|
|
339
|
+
status = 'verified';
|
|
340
|
+
}
|
|
341
|
+
let placement = 'no_head';
|
|
342
|
+
let headSeq = null;
|
|
343
|
+
const head = mine[0];
|
|
344
|
+
if (head !== undefined) {
|
|
345
|
+
const [, hSeq, hHash] = head;
|
|
346
|
+
headSeq = hSeq;
|
|
347
|
+
let expected = null;
|
|
348
|
+
if (firstSeq <= hSeq && hSeq <= lastSeq) {
|
|
349
|
+
placement = 'in_file';
|
|
350
|
+
expected = recomputed[hSeq - firstSeq] ?? null;
|
|
351
|
+
}
|
|
352
|
+
else if (hSeq === firstSeq - 1 && startsAfter !== null) {
|
|
353
|
+
placement = 'window_floor';
|
|
354
|
+
expected = startsAfter;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
placement = hSeq < firstSeq ? 'before_file' : 'after_file';
|
|
358
|
+
}
|
|
359
|
+
// Compared with or without a key, as in the Python reader: a file whose
|
|
360
|
+
// anchors disagree with its own recomputed chain is refused either way.
|
|
361
|
+
if (expected !== null && hHash !== expected) {
|
|
362
|
+
throw new ChainRefusal('AnchorHeadMismatch', `the chain recomputes to ${expected} at this position`, {
|
|
363
|
+
seq: hSeq,
|
|
364
|
+
anchor: j,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (status === 'verified' && (placement === 'in_file' || placement === 'window_floor')) {
|
|
368
|
+
anchoredThrough = anchoredThrough === null ? hSeq : Math.max(anchoredThrough, hSeq);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
results.push({ index: j, status, placement, headSeq, periodEnd });
|
|
372
|
+
}
|
|
373
|
+
let unanchoredFrom;
|
|
374
|
+
if (anchoredThrough === null)
|
|
375
|
+
unanchoredFrom = firstSeq;
|
|
376
|
+
else if (anchoredThrough < lastSeq)
|
|
377
|
+
unanchoredFrom = anchoredThrough + 1;
|
|
378
|
+
else
|
|
379
|
+
unanchoredFrom = null;
|
|
380
|
+
const lastChainHash = recomputed[recomputed.length - 1];
|
|
381
|
+
if (lastChainHash === undefined)
|
|
382
|
+
throw new ChainRefusal('ExportEmpty', 'the file holds no records');
|
|
383
|
+
return {
|
|
384
|
+
tenant,
|
|
385
|
+
firstSeq,
|
|
386
|
+
lastSeq,
|
|
387
|
+
records: chain.length,
|
|
388
|
+
lastChainHash,
|
|
389
|
+
startsAfter,
|
|
390
|
+
anchorsChecked: anchorKey !== undefined,
|
|
391
|
+
anchors: results,
|
|
392
|
+
anchoredThrough,
|
|
393
|
+
unanchoredFrom,
|
|
394
|
+
unanchoredCount: unanchoredFrom === null ? 0 : lastSeq - unanchoredFrom + 1,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
/** {@link verifyChain}'s answer, or its refusal, as one corpus-shaped object. */
|
|
398
|
+
export function chainVerdict(file, anchorKey) {
|
|
399
|
+
let v;
|
|
400
|
+
try {
|
|
401
|
+
v = verifyChain(file, anchorKey);
|
|
402
|
+
}
|
|
403
|
+
catch (e) {
|
|
404
|
+
if (e instanceof ChainRefusal) {
|
|
405
|
+
return { verdict: 'refused', refusal: e.refusal, seq: e.seq, anchor: e.anchor };
|
|
406
|
+
}
|
|
407
|
+
throw e;
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
verdict: 'verified',
|
|
411
|
+
tenant: v.tenant,
|
|
412
|
+
first_seq: v.firstSeq,
|
|
413
|
+
last_seq: v.lastSeq,
|
|
414
|
+
records: v.records,
|
|
415
|
+
last_chain_hash: v.lastChainHash,
|
|
416
|
+
starts_after: v.startsAfter,
|
|
417
|
+
anchors_checked: v.anchorsChecked,
|
|
418
|
+
anchors: v.anchors.map((a) => ({
|
|
419
|
+
index: a.index,
|
|
420
|
+
status: a.status,
|
|
421
|
+
placement: a.placement,
|
|
422
|
+
head_seq: a.headSeq,
|
|
423
|
+
period_end: a.periodEnd,
|
|
424
|
+
})),
|
|
425
|
+
anchored_through: v.anchoredThrough,
|
|
426
|
+
unanchored_from: v.unanchoredFrom,
|
|
427
|
+
unanchored_count: v.unanchoredCount,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
//# sourceMappingURL=chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain.js","sourceRoot":"","sources":["../src/chain.ts"],"names":[],"mappings":"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"}
|
package/dist/clauses.d.ts
CHANGED
|
@@ -50,4 +50,74 @@ export declare const CLAUSE_WIRE_TYPE = "WE-4";
|
|
|
50
50
|
* refusal carries the field's (ACP-88/ACP-89).
|
|
51
51
|
*/
|
|
52
52
|
export declare const CLAUSE_RECEIPT_NONCE_SIZE = "L-17";
|
|
53
|
+
/** Rust `quorum::CLAUSE_NO_ATTESTATIONS` -- INV-1-HIGH, a receipt commits to
|
|
54
|
+
* attestations and none arrived. */
|
|
55
|
+
export declare const CLAUSE_NO_ATTESTATIONS = "INV-1-HIGH";
|
|
56
|
+
/** Rust `quorum::CLAUSE_NO_OBJECT` -- AT-8, an entry carrying no Attestation
|
|
57
|
+
* Object (the pre-v1.3.3 form, where only the id travelled). */
|
|
58
|
+
export declare const CLAUSE_NO_OBJECT = "AT-8";
|
|
59
|
+
/** Rust `quorum::CLAUSE_OBJECT_SCHEMA` -- AT-8b, the object's field set is not
|
|
60
|
+
* exactly AT-1's. CLOSED: an unknown field is refused, a missing one never
|
|
61
|
+
* defaulted (Z4). */
|
|
62
|
+
export declare const CLAUSE_OBJECT_SCHEMA = "AT-8b";
|
|
63
|
+
/** Rust `quorum::CLAUSE_NONCE_SIZE` -- AT-1, `att_nonce` is well-formed but is
|
|
64
|
+
* not 128-bit. The ATTESTATION nonce's own size clause, never L-17 (which sizes
|
|
65
|
+
* the receipt's): one number, two clauses, and the refusal carries the field's. */
|
|
66
|
+
export declare const CLAUSE_ATT_NONCE_SIZE = "AT-1";
|
|
67
|
+
/** Rust `quorum::CLAUSE_ATTESTATION_SUITE` -- CR-4. An UNKNOWN suite refuses
|
|
68
|
+
* here under CR-4 and not CR-1, matching `Bundle.suite_ok`, which returns False
|
|
69
|
+
* for a name it does not know; the receipt path spells the same condition CR-1
|
|
70
|
+
* and the differential compares names, so the reference wins. */
|
|
71
|
+
export declare const CLAUSE_ATTESTATION_SUITE = "CR-4";
|
|
72
|
+
/** Rust `quorum::CLAUSE_ATTESTER_SIG` -- §9.3 step 7b(i). */
|
|
73
|
+
export declare const CLAUSE_ATTESTER_SIG = "9.3-7b-i";
|
|
74
|
+
/** Rust `quorum::CLAUSE_BINDING` -- §9.3 step 7b(ii), the object binds a
|
|
75
|
+
* DIFFERENT proposal. This is Y1: a genuine quorum raised for P1 attached to a
|
|
76
|
+
* receipt for P2. */
|
|
77
|
+
export declare const CLAUSE_BINDING = "9.3-7b-ii";
|
|
78
|
+
/** Rust `quorum::CLAUSE_POLICY_BASIS` -- §9.3 step 7b(iii), policy basis or
|
|
79
|
+
* object freshness. */
|
|
80
|
+
export declare const CLAUSE_POLICY_BASIS = "9.3-7b-iii";
|
|
81
|
+
/** Rust `quorum::CLAUSE_OPERATOR_DISAGREE` -- §9.3 step 7b(iii-a), the objects
|
|
82
|
+
* disagree on who the operator is (Y4). */
|
|
83
|
+
export declare const CLAUSE_OPERATOR_DISAGREE = "9.3-7b-iii-a";
|
|
84
|
+
/** Rust `quorum::CLAUSE_CONSENT` -- AT-9's SECOND requirement: an attester
|
|
85
|
+
* signed for a quorum other than the bundle's. A CONSENT check, not a threshold
|
|
86
|
+
* one; deleting it cannot lower a quorum. */
|
|
87
|
+
export declare const CLAUSE_CONSENT = "AT-9";
|
|
88
|
+
/** Rust `quorum::CLAUSE_DERIVED_ID` -- Y1b, a transmitted `attestation_id`
|
|
89
|
+
* differing from the derived one. */
|
|
90
|
+
export declare const CLAUSE_DERIVED_ID = "Y1b";
|
|
91
|
+
/** Rust `quorum::CLAUSE_MEMBERSHIP` -- AB-1, the entry digest binding: entry
|
|
92
|
+
* schema, digest-list type, or membership. */
|
|
93
|
+
export declare const CLAUSE_MEMBERSHIP = "AB-1";
|
|
94
|
+
/** Rust `quorum::CLAUSE_DIGEST_ORDER` -- AB-2, `attestation_digests` is not in
|
|
95
|
+
* the one canonical ordering. */
|
|
96
|
+
export declare const CLAUSE_DIGEST_ORDER = "AB-2";
|
|
97
|
+
/** Rust `quorum::CLAUSE_DIGEST_DUP` -- AB-3, a repeated digest. */
|
|
98
|
+
export declare const CLAUSE_DIGEST_DUP = "AB-3";
|
|
99
|
+
/** Rust `quorum::CLAUSE_CARDINALITY` -- AB-4, entry count and signed digest
|
|
100
|
+
* count disagree. Fewer is withholding, more is injection. */
|
|
101
|
+
export declare const CLAUSE_CARDINALITY = "AB-4";
|
|
102
|
+
/** Rust `quorum::CLAUSE_ASSURANCE` -- AT-10, an identity enrolled below the
|
|
103
|
+
* registry's assurance floor. */
|
|
104
|
+
export declare const CLAUSE_ASSURANCE = "AT-10";
|
|
105
|
+
/** Rust `quorum::CLAUSE_QUORUM` -- AT-3, fewer distinct approvals than the
|
|
106
|
+
* threshold recomputed from the bundle. */
|
|
107
|
+
export declare const CLAUSE_QUORUM = "AT-3";
|
|
108
|
+
/** Rust `quorum::CLAUSE_OPERATOR_SELF` -- AT-2, the operator counted toward
|
|
109
|
+
* their own quorum. */
|
|
110
|
+
export declare const CLAUSE_OPERATOR_SELF = "AT-2";
|
|
111
|
+
/** Rust `quorum::CLAUSE_WEBAUTHN_ALG` -- HM-3. The object's declared `alg` and
|
|
112
|
+
* the registry's disagree about what KIND of key this identity holds. Either
|
|
113
|
+
* side alone decides nothing; the DISAGREEMENT is the refusal, raised before a
|
|
114
|
+
* byte of the assertion is parsed. */
|
|
115
|
+
export declare const CLAUSE_WEBAUTHN_ALG = "WebauthnAlgMismatch";
|
|
116
|
+
/** Rust `quorum::CLAUSE_WEBAUTHN_COUNTER` -- HM-4 (f). A regression is a CLONED
|
|
117
|
+
* AUTHENTICATOR, not a retry. */
|
|
118
|
+
export declare const CLAUSE_WEBAUTHN_COUNTER = "WebauthnCounter";
|
|
119
|
+
/** Rust `quorum::CLAUSE_MALFORMED` -- the entry's `sig`, the assertion or the
|
|
120
|
+
* credential is not the shape §8.6c declares. Not a statement about a
|
|
121
|
+
* signature. */
|
|
122
|
+
export declare const CLAUSE_MALFORMED = "Malformed";
|
|
53
123
|
//# sourceMappingURL=clauses.d.ts.map
|
package/dist/clauses.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../src/clauses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,sFAAsF;AACtF,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,8FAA8F;AAC9F,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC,gGAAgG;AAChG,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,4EAA4E;AAC5E,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAC/C,qGAAqG;AACrG,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../src/clauses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,sFAAsF;AACtF,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,8FAA8F;AAC9F,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC,gGAAgG;AAChG,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,4EAA4E;AAC5E,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAC/C,qGAAqG;AACrG,eAAO,MAAM,eAAe,UAAU,CAAC;AACvC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAUhD;oCACoC;AACpC,eAAO,MAAM,sBAAsB,eAAe,CAAC;AACnD;gEACgE;AAChE,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC;;qBAEqB;AACrB,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAC5C;;mFAEmF;AACnF,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAC5C;;;iEAGiE;AACjE,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAC/C,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C;;qBAEqB;AACrB,eAAO,MAAM,cAAc,cAAc,CAAC;AAC1C;uBACuB;AACvB,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAChD;2CAC2C;AAC3C,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AACvD;;6CAE6C;AAC7C,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC;qCACqC;AACrC,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AACvC;8CAC8C;AAC9C,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC;iCACiC;AACjC,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAC1C,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC;8DAC8D;AAC9D,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC;iCACiC;AACjC,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC;2CAC2C;AAC3C,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC;uBACuB;AACvB,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C;;;sCAGsC;AACtC,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD;iCACiC;AACjC,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD;;gBAEgB;AAChB,eAAO,MAAM,gBAAgB,cAAc,CAAC"}
|
package/dist/clauses.js
CHANGED
|
@@ -50,4 +50,81 @@ export const CLAUSE_WIRE_TYPE = 'WE-4';
|
|
|
50
50
|
* refusal carries the field's (ACP-88/ACP-89).
|
|
51
51
|
*/
|
|
52
52
|
export const CLAUSE_RECEIPT_NONCE_SIZE = 'L-17';
|
|
53
|
+
// ------------------------------------------------------------------ step 7b
|
|
54
|
+
//
|
|
55
|
+
// The AT-* quorum and §8.6b's AB-*, spelled as `crates/acp-decision/src/quorum.rs`
|
|
56
|
+
// and `reference/src/acp_executor.py` spell them. Several are literals at the
|
|
57
|
+
// refusal site in Rust and named here; the VALUE is the contract either way, and
|
|
58
|
+
// the Rust constant name is kept beside each one so a reader diffing the two
|
|
59
|
+
// files sees one table rather than two vocabularies.
|
|
60
|
+
/** Rust `quorum::CLAUSE_NO_ATTESTATIONS` -- INV-1-HIGH, a receipt commits to
|
|
61
|
+
* attestations and none arrived. */
|
|
62
|
+
export const CLAUSE_NO_ATTESTATIONS = 'INV-1-HIGH';
|
|
63
|
+
/** Rust `quorum::CLAUSE_NO_OBJECT` -- AT-8, an entry carrying no Attestation
|
|
64
|
+
* Object (the pre-v1.3.3 form, where only the id travelled). */
|
|
65
|
+
export const CLAUSE_NO_OBJECT = 'AT-8';
|
|
66
|
+
/** Rust `quorum::CLAUSE_OBJECT_SCHEMA` -- AT-8b, the object's field set is not
|
|
67
|
+
* exactly AT-1's. CLOSED: an unknown field is refused, a missing one never
|
|
68
|
+
* defaulted (Z4). */
|
|
69
|
+
export const CLAUSE_OBJECT_SCHEMA = 'AT-8b';
|
|
70
|
+
/** Rust `quorum::CLAUSE_NONCE_SIZE` -- AT-1, `att_nonce` is well-formed but is
|
|
71
|
+
* not 128-bit. The ATTESTATION nonce's own size clause, never L-17 (which sizes
|
|
72
|
+
* the receipt's): one number, two clauses, and the refusal carries the field's. */
|
|
73
|
+
export const CLAUSE_ATT_NONCE_SIZE = 'AT-1';
|
|
74
|
+
/** Rust `quorum::CLAUSE_ATTESTATION_SUITE` -- CR-4. An UNKNOWN suite refuses
|
|
75
|
+
* here under CR-4 and not CR-1, matching `Bundle.suite_ok`, which returns False
|
|
76
|
+
* for a name it does not know; the receipt path spells the same condition CR-1
|
|
77
|
+
* and the differential compares names, so the reference wins. */
|
|
78
|
+
export const CLAUSE_ATTESTATION_SUITE = 'CR-4';
|
|
79
|
+
/** Rust `quorum::CLAUSE_ATTESTER_SIG` -- §9.3 step 7b(i). */
|
|
80
|
+
export const CLAUSE_ATTESTER_SIG = '9.3-7b-i';
|
|
81
|
+
/** Rust `quorum::CLAUSE_BINDING` -- §9.3 step 7b(ii), the object binds a
|
|
82
|
+
* DIFFERENT proposal. This is Y1: a genuine quorum raised for P1 attached to a
|
|
83
|
+
* receipt for P2. */
|
|
84
|
+
export const CLAUSE_BINDING = '9.3-7b-ii';
|
|
85
|
+
/** Rust `quorum::CLAUSE_POLICY_BASIS` -- §9.3 step 7b(iii), policy basis or
|
|
86
|
+
* object freshness. */
|
|
87
|
+
export const CLAUSE_POLICY_BASIS = '9.3-7b-iii';
|
|
88
|
+
/** Rust `quorum::CLAUSE_OPERATOR_DISAGREE` -- §9.3 step 7b(iii-a), the objects
|
|
89
|
+
* disagree on who the operator is (Y4). */
|
|
90
|
+
export const CLAUSE_OPERATOR_DISAGREE = '9.3-7b-iii-a';
|
|
91
|
+
/** Rust `quorum::CLAUSE_CONSENT` -- AT-9's SECOND requirement: an attester
|
|
92
|
+
* signed for a quorum other than the bundle's. A CONSENT check, not a threshold
|
|
93
|
+
* one; deleting it cannot lower a quorum. */
|
|
94
|
+
export const CLAUSE_CONSENT = 'AT-9';
|
|
95
|
+
/** Rust `quorum::CLAUSE_DERIVED_ID` -- Y1b, a transmitted `attestation_id`
|
|
96
|
+
* differing from the derived one. */
|
|
97
|
+
export const CLAUSE_DERIVED_ID = 'Y1b';
|
|
98
|
+
/** Rust `quorum::CLAUSE_MEMBERSHIP` -- AB-1, the entry digest binding: entry
|
|
99
|
+
* schema, digest-list type, or membership. */
|
|
100
|
+
export const CLAUSE_MEMBERSHIP = 'AB-1';
|
|
101
|
+
/** Rust `quorum::CLAUSE_DIGEST_ORDER` -- AB-2, `attestation_digests` is not in
|
|
102
|
+
* the one canonical ordering. */
|
|
103
|
+
export const CLAUSE_DIGEST_ORDER = 'AB-2';
|
|
104
|
+
/** Rust `quorum::CLAUSE_DIGEST_DUP` -- AB-3, a repeated digest. */
|
|
105
|
+
export const CLAUSE_DIGEST_DUP = 'AB-3';
|
|
106
|
+
/** Rust `quorum::CLAUSE_CARDINALITY` -- AB-4, entry count and signed digest
|
|
107
|
+
* count disagree. Fewer is withholding, more is injection. */
|
|
108
|
+
export const CLAUSE_CARDINALITY = 'AB-4';
|
|
109
|
+
/** Rust `quorum::CLAUSE_ASSURANCE` -- AT-10, an identity enrolled below the
|
|
110
|
+
* registry's assurance floor. */
|
|
111
|
+
export const CLAUSE_ASSURANCE = 'AT-10';
|
|
112
|
+
/** Rust `quorum::CLAUSE_QUORUM` -- AT-3, fewer distinct approvals than the
|
|
113
|
+
* threshold recomputed from the bundle. */
|
|
114
|
+
export const CLAUSE_QUORUM = 'AT-3';
|
|
115
|
+
/** Rust `quorum::CLAUSE_OPERATOR_SELF` -- AT-2, the operator counted toward
|
|
116
|
+
* their own quorum. */
|
|
117
|
+
export const CLAUSE_OPERATOR_SELF = 'AT-2';
|
|
118
|
+
/** Rust `quorum::CLAUSE_WEBAUTHN_ALG` -- HM-3. The object's declared `alg` and
|
|
119
|
+
* the registry's disagree about what KIND of key this identity holds. Either
|
|
120
|
+
* side alone decides nothing; the DISAGREEMENT is the refusal, raised before a
|
|
121
|
+
* byte of the assertion is parsed. */
|
|
122
|
+
export const CLAUSE_WEBAUTHN_ALG = 'WebauthnAlgMismatch';
|
|
123
|
+
/** Rust `quorum::CLAUSE_WEBAUTHN_COUNTER` -- HM-4 (f). A regression is a CLONED
|
|
124
|
+
* AUTHENTICATOR, not a retry. */
|
|
125
|
+
export const CLAUSE_WEBAUTHN_COUNTER = 'WebauthnCounter';
|
|
126
|
+
/** Rust `quorum::CLAUSE_MALFORMED` -- the entry's `sig`, the assertion or the
|
|
127
|
+
* credential is not the shape §8.6c declares. Not a statement about a
|
|
128
|
+
* signature. */
|
|
129
|
+
export const CLAUSE_MALFORMED = 'Malformed';
|
|
53
130
|
//# sourceMappingURL=clauses.js.map
|
package/dist/clauses.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clauses.js","sourceRoot":"","sources":["../src/clauses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,8FAA8F;AAC9F,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AACvC,gGAAgG;AAChG,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAC3C,oGAAoG;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAC/C,qGAAqG;AACrG,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AACvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"clauses.js","sourceRoot":"","sources":["../src/clauses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,8FAA8F;AAC9F,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AACvC,gGAAgG;AAChG,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAC3C,oGAAoG;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,OAAO,CAAC;AAC/C,qGAAqG;AACrG,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AACvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,6EAA6E;AAC7E,EAAE;AACF,mFAAmF;AACnF,8EAA8E;AAC9E,iFAAiF;AACjF,6EAA6E;AAC7E,qDAAqD;AAErD;oCACoC;AACpC,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AACnD;gEACgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AACvC;;qBAEqB;AACrB,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAC5C;;mFAEmF;AACnF,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC5C;;;iEAGiE;AACjE,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAC/C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAC9C;;qBAEqB;AACrB,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC;AAC1C;uBACuB;AACvB,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAChD;2CAC2C;AAC3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CAAC;AACvD;;6CAE6C;AAC7C,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC;qCACqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC;8CAC8C;AAC9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC;iCACiC;AACjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAC1C,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC;8DAC8D;AAC9D,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AACzC;iCACiC;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC;2CAC2C;AAC3C,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AACpC;uBACuB;AACvB,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAC3C;;;sCAGsC;AACtC,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AACzD;iCACiC;AACjC,MAAM,CAAC,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AACzD;;gBAEgB;AAChB,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @ziffer-io/verify -- the third receipt-verifier implementation (ACP-197 §5).
|
|
3
3
|
*
|
|
4
|
-
* `verifyReceipt` is the API
|
|
4
|
+
* `verifyReceipt` is the API for a receipt and `verifyChain` for an exported
|
|
5
|
+
* audit chain (ACP-428); everything else is exported so the pieces are
|
|
5
6
|
* individually testable and so `@ziffer-io/client` can re-export ONE verify (the
|
|
6
7
|
* client adds no verification logic of its own -- one home per rule).
|
|
7
8
|
*/
|
|
8
9
|
export { canon, compareCodePoints, type Json } from './canon.js';
|
|
10
|
+
export { ANCHOR_SUITE, AnchorKeyRefusal, ChainRefusal, chainVerdict, parseAnchorKey, verifyChain, type AnchorKey, type AnchorResult, type ChainVerdict, type ChainVerified, } from './chain.js';
|
|
11
|
+
export { CborError, cborAsBytes, cborEncode, cborGetInt, cborGetText, cborIsMap, cborKeys, decodeCanonical, type Cbor, type CborMap, } from './cbor.js';
|
|
12
|
+
export { CLAUSE_ASSURANCE, CLAUSE_ATTESTATION_SUITE, CLAUSE_ATTESTER_SIG, CLAUSE_ATT_NONCE_SIZE, CLAUSE_BINDING, CLAUSE_CARDINALITY, CLAUSE_CONSENT, CLAUSE_DERIVED_ID, CLAUSE_DIGEST_DUP, CLAUSE_DIGEST_ORDER, CLAUSE_MALFORMED, CLAUSE_MEMBERSHIP, CLAUSE_NO_ATTESTATIONS, CLAUSE_NO_OBJECT, CLAUSE_OBJECT_SCHEMA, CLAUSE_OPERATOR_DISAGREE, CLAUSE_OPERATOR_SELF, CLAUSE_POLICY_BASIS, CLAUSE_QUORUM, CLAUSE_WEBAUTHN_ALG, CLAUSE_WEBAUTHN_COUNTER, } from './clauses.js';
|
|
13
|
+
export { AT1_FIELDS, attestationId, entryDigest, verifyQuorum, type AttesterCredential, type DecisionBasis, type HybridAttester, type QuorumOutcome, type QuorumPolicy, type WebauthnAttester, } from './quorum.js';
|
|
14
|
+
export { ASSERTION_FIELDS, MALFORMED, REGISTRY_KEY_WEAK, WEBAUTHN_ALGS, WEBAUTHN_AUTHENTICATOR_DATA, WEBAUTHN_CHALLENGE, WEBAUTHN_ORIGIN, WEBAUTHN_PRIMITIVE, WEBAUTHN_SIGNATURE, WEBAUTHN_TYPE, WebauthnRefusal, coseKeyParse, decodeAssertion, verifyWebauthn, webauthnChallenge, type Assertion, type CredentialKey, } from './webauthn.js';
|
|
15
|
+
export { b64Decode } from './wire.js';
|
|
9
16
|
export { CLAUSE_BODY_SIZE, CLAUSE_CANONICAL, CLAUSE_DECISION, CLAUSE_PROPOSAL_BINDING, CLAUSE_RECEIPT_NONCE_SIZE, CLAUSE_SIGNATURE, CLAUSE_SUITE_FLOOR, CLAUSE_TEMPORAL, CLAUSE_UNKNOWN_SUITE, CLAUSE_VALIDITY_WINDOW, CLAUSE_VERSION, CLAUSE_WIRE_TYPE, } from './clauses.js';
|
|
10
17
|
export { ED25519_PK_LEN, ED25519_SIG_LEN, ed25519IsSmallOrder, verifyEd25519Strict, } from './ed25519.js';
|
|
11
18
|
export { parseInstant } from './instant.js';
|