@atrib/verify 0.4.0 → 0.5.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.
@@ -0,0 +1,94 @@
1
+ import { type AtribRecord, type ProofBundle } from '@atrib/mcp';
2
+ import type { RecordVerificationResult } from './verify-record.js';
3
+ export type HandoffRejectionReason = 'record_missing' | 'record_hash_mismatch' | 'record_invalid' | 'signature_invalid' | 'wrong_signer' | 'wrong_context' | 'stale' | 'body_missing' | 'body_commitment_missing' | 'body_hash_mismatch' | 'proof_missing' | 'proof_invalid';
4
+ export interface HandoffClaimInput {
5
+ record_hash: string;
6
+ record?: AtribRecord;
7
+ body?: unknown;
8
+ args?: unknown;
9
+ result?: unknown;
10
+ proof?: ProofBundle;
11
+ trusted_creator_keys?: string[];
12
+ allowed_context_ids?: string[];
13
+ max_age_ms?: number;
14
+ }
15
+ export interface VerifyHandoffClaimsOptions {
16
+ trusted_creator_keys?: string[];
17
+ allowed_context_ids?: string[];
18
+ require_body?: boolean;
19
+ require_body_commitment?: boolean;
20
+ require_log_inclusion?: boolean;
21
+ log_public_key?: Uint8Array;
22
+ now_ms?: number;
23
+ max_age_ms?: number;
24
+ }
25
+ export interface HandoffBodyVerification {
26
+ args_hash_present: boolean;
27
+ args_hash_ok: boolean | null;
28
+ result_hash_present: boolean;
29
+ result_hash_ok: boolean | null;
30
+ }
31
+ export interface HandoffProofVerification {
32
+ present: boolean;
33
+ inclusion_ok: boolean | null;
34
+ checkpoint_signature_ok: boolean | null;
35
+ error?: string;
36
+ }
37
+ export interface HandoffClaimVerification {
38
+ record_hash: string;
39
+ accepted: boolean;
40
+ rejection_reasons: HandoffRejectionReason[];
41
+ warnings: string[];
42
+ record?: AtribRecord;
43
+ verification?: RecordVerificationResult;
44
+ signature_ok: boolean | null;
45
+ computed_record_hash: string | null;
46
+ signer_trusted: boolean | null;
47
+ context_allowed: boolean | null;
48
+ body?: HandoffBodyVerification;
49
+ proof?: HandoffProofVerification;
50
+ }
51
+ export interface HandoffVerificationResult {
52
+ accepted: HandoffClaimVerification[];
53
+ rejected: HandoffClaimVerification[];
54
+ accepted_record_hashes: string[];
55
+ all_accepted: boolean;
56
+ }
57
+ export interface HandoffEvidenceEntry {
58
+ record_hash?: string;
59
+ record?: AtribRecord;
60
+ body?: unknown;
61
+ args?: unknown;
62
+ result?: unknown;
63
+ proof?: ProofBundle | null;
64
+ _local?: {
65
+ content?: unknown;
66
+ body?: unknown;
67
+ args?: unknown;
68
+ result?: unknown;
69
+ producer?: string;
70
+ [key: string]: unknown;
71
+ } | null;
72
+ [key: string]: unknown;
73
+ }
74
+ export interface HandoffEvidencePacket {
75
+ kind?: string;
76
+ records?: HandoffEvidenceEntry[];
77
+ claims?: HandoffEvidenceEntry[];
78
+ record_hashes?: string[];
79
+ required_record_hashes?: string[];
80
+ trusted_creator_keys?: string[];
81
+ allowed_context_ids?: string[];
82
+ max_age_ms?: number;
83
+ archive_refs?: unknown[];
84
+ [key: string]: unknown;
85
+ }
86
+ export interface HandoffClaimsFromEvidenceOptions {
87
+ required_record_hashes?: string[];
88
+ trusted_creator_keys?: string[];
89
+ allowed_context_ids?: string[];
90
+ max_age_ms?: number;
91
+ }
92
+ export declare function handoffClaimsFromEvidencePacket(packet: HandoffEvidencePacket | HandoffEvidenceEntry[], options?: HandoffClaimsFromEvidenceOptions): HandoffClaimInput[];
93
+ export declare function verifyHandoffClaims(claims: HandoffClaimInput[], options?: VerifyHandoffClaimsOptions): Promise<HandoffVerificationResult>;
94
+ //# sourceMappingURL=handoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../src/handoff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,371 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import canonicalize from 'canonicalize';
3
+ import * as ed from '@noble/ed25519';
4
+ import { sha512 } from '@noble/hashes/sha2.js';
5
+ import { base64urlDecode, canonicalRecord, hexEncode, leafHash, serializeEntry, sha256, verifyInclusion, } from '@atrib/mcp';
6
+ import { verifyRecord } from './verify-record.js';
7
+ ed.hashes.sha512 = sha512;
8
+ ed.hashes.sha512Async = (message) => Promise.resolve(sha512(message));
9
+ function recordHash(record) {
10
+ return `sha256:${hexEncode(sha256(canonicalRecord(record)))}`;
11
+ }
12
+ function hashPlainJson(value) {
13
+ try {
14
+ const encoded = canonicalize(value);
15
+ if (encoded === undefined)
16
+ return null;
17
+ return `sha256:${hexEncode(sha256(new TextEncoder().encode(encoded)))}`;
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ function hashSaltedJson(value, salt) {
24
+ try {
25
+ const encoded = canonicalize(value);
26
+ if (encoded === undefined)
27
+ return null;
28
+ const saltBytes = base64urlDecode(salt);
29
+ const bodyBytes = new TextEncoder().encode(encoded);
30
+ const input = new Uint8Array(saltBytes.length + bodyBytes.length);
31
+ input.set(saltBytes, 0);
32
+ input.set(bodyBytes, saltBytes.length);
33
+ return `sha256:${hexEncode(sha256(input))}`;
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ function hashMaterial(value, salt) {
40
+ return salt === undefined ? hashPlainJson(value) : hashSaltedJson(value, salt);
41
+ }
42
+ function hasMaterial(value) {
43
+ return value !== undefined;
44
+ }
45
+ function isObject(value) {
46
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
47
+ }
48
+ function isAtribRecordLike(value) {
49
+ if (!isObject(value))
50
+ return false;
51
+ return (typeof value.spec_version === 'string' &&
52
+ typeof value.event_type === 'string' &&
53
+ typeof value.context_id === 'string' &&
54
+ typeof value.creator_key === 'string' &&
55
+ typeof value.chain_root === 'string' &&
56
+ typeof value.content_id === 'string' &&
57
+ typeof value.signature === 'string');
58
+ }
59
+ function proofOrUndefined(value) {
60
+ if (value === null || value === undefined)
61
+ return undefined;
62
+ return value;
63
+ }
64
+ function localSidecar(value) {
65
+ return isObject(value) ? value : undefined;
66
+ }
67
+ function evidenceEntries(packet) {
68
+ if (Array.isArray(packet))
69
+ return packet;
70
+ const entries = [];
71
+ if (Array.isArray(packet.records))
72
+ entries.push(...packet.records);
73
+ if (Array.isArray(packet.claims))
74
+ entries.push(...packet.claims);
75
+ return entries;
76
+ }
77
+ function requiredHashes(packet, options) {
78
+ const values = new Set();
79
+ if (!Array.isArray(packet)) {
80
+ for (const hash of packet.required_record_hashes ?? [])
81
+ values.add(hash);
82
+ for (const hash of packet.record_hashes ?? [])
83
+ values.add(hash);
84
+ }
85
+ for (const hash of options.required_record_hashes ?? [])
86
+ values.add(hash);
87
+ return [...values];
88
+ }
89
+ function claimFromEvidenceEntry(entry, packet, options) {
90
+ const envelope = isObject(entry) ? entry : {};
91
+ const record = isAtribRecordLike(envelope.record)
92
+ ? envelope.record
93
+ : isAtribRecordLike(entry)
94
+ ? entry
95
+ : undefined;
96
+ const local = localSidecar(envelope._local);
97
+ const claimHash = typeof envelope.record_hash === 'string'
98
+ ? envelope.record_hash
99
+ : record
100
+ ? recordHash(record)
101
+ : undefined;
102
+ if (claimHash === undefined)
103
+ return null;
104
+ const trustedCreatorKeys = options.trusted_creator_keys ??
105
+ (!Array.isArray(packet) ? packet.trusted_creator_keys : undefined);
106
+ const allowedContextIds = options.allowed_context_ids ?? (!Array.isArray(packet) ? packet.allowed_context_ids : undefined);
107
+ const maxAgeMs = options.max_age_ms ?? (!Array.isArray(packet) ? packet.max_age_ms : undefined);
108
+ const claim = { record_hash: claimHash };
109
+ if (record)
110
+ claim.record = record;
111
+ const body = envelope.body ?? local?.body ?? local?.content;
112
+ const args = envelope.args ?? local?.args;
113
+ const result = envelope.result ?? local?.result;
114
+ if (body !== undefined)
115
+ claim.body = body;
116
+ if (args !== undefined)
117
+ claim.args = args;
118
+ if (result !== undefined)
119
+ claim.result = result;
120
+ const proof = proofOrUndefined(envelope.proof);
121
+ if (proof !== undefined)
122
+ claim.proof = proof;
123
+ if (trustedCreatorKeys !== undefined)
124
+ claim.trusted_creator_keys = trustedCreatorKeys;
125
+ if (allowedContextIds !== undefined)
126
+ claim.allowed_context_ids = allowedContextIds;
127
+ if (maxAgeMs !== undefined)
128
+ claim.max_age_ms = maxAgeMs;
129
+ return claim;
130
+ }
131
+ export function handoffClaimsFromEvidencePacket(packet, options = {}) {
132
+ const claims = [];
133
+ const seen = new Set();
134
+ for (const entry of evidenceEntries(packet)) {
135
+ const claim = claimFromEvidenceEntry(entry, packet, options);
136
+ if (!claim)
137
+ continue;
138
+ claims.push(claim);
139
+ seen.add(claim.record_hash);
140
+ }
141
+ for (const hash of requiredHashes(packet, options)) {
142
+ if (!seen.has(hash))
143
+ claims.push({ record_hash: hash });
144
+ }
145
+ return claims;
146
+ }
147
+ function verifyBody(claim, record, requireBody, requireBodyCommitment, reasons) {
148
+ const body = {
149
+ args_hash_present: record.args_hash !== undefined,
150
+ args_hash_ok: null,
151
+ result_hash_present: record.result_hash !== undefined,
152
+ result_hash_ok: null,
153
+ };
154
+ const argsMaterial = claim.args ?? claim.body;
155
+ const resultMaterial = claim.result;
156
+ const anyMaterial = hasMaterial(argsMaterial) || hasMaterial(resultMaterial);
157
+ const anyCommitment = record.args_hash !== undefined || record.result_hash !== undefined;
158
+ if (requireBody && !anyMaterial) {
159
+ reasons.push('body_missing');
160
+ }
161
+ if (requireBodyCommitment && !anyCommitment) {
162
+ reasons.push('body_commitment_missing');
163
+ }
164
+ if (record.args_hash !== undefined && hasMaterial(argsMaterial)) {
165
+ body.args_hash_ok = hashMaterial(argsMaterial, record.args_salt) === record.args_hash;
166
+ if (!body.args_hash_ok)
167
+ reasons.push('body_hash_mismatch');
168
+ }
169
+ if (record.result_hash !== undefined && hasMaterial(resultMaterial)) {
170
+ body.result_hash_ok = hashMaterial(resultMaterial, record.result_salt) === record.result_hash;
171
+ if (!body.result_hash_ok)
172
+ reasons.push('body_hash_mismatch');
173
+ }
174
+ return body;
175
+ }
176
+ function verifyFreshness(record, nowMs, maxAgeMs, reasons) {
177
+ if (maxAgeMs === undefined)
178
+ return;
179
+ const ageMs = nowMs - record.timestamp;
180
+ if (ageMs < 0 || ageMs > maxAgeMs)
181
+ reasons.push('stale');
182
+ }
183
+ async function verifyProofPresence(claim, record, computedRecordHash, requireLogInclusion, logPublicKey, reasons) {
184
+ if (claim.proof === undefined) {
185
+ if (requireLogInclusion)
186
+ reasons.push('proof_missing');
187
+ return requireLogInclusion
188
+ ? { present: false, inclusion_ok: null, checkpoint_signature_ok: null }
189
+ : undefined;
190
+ }
191
+ const verification = await verifyProofBundle(record, computedRecordHash, claim.proof, logPublicKey);
192
+ if (verification.inclusion_ok !== true)
193
+ reasons.push('proof_invalid');
194
+ if (logPublicKey !== undefined && verification.checkpoint_signature_ok !== true) {
195
+ reasons.push('proof_invalid');
196
+ }
197
+ return verification;
198
+ }
199
+ function decodeBase64Bytes(value, expectedLength) {
200
+ const decoded = new Uint8Array(Buffer.from(value, 'base64'));
201
+ if (decoded.length !== expectedLength) {
202
+ throw new Error(`expected ${expectedLength} bytes, got ${decoded.length}`);
203
+ }
204
+ return decoded;
205
+ }
206
+ function bytesEqual(left, right) {
207
+ if (left.length !== right.length)
208
+ return false;
209
+ let diff = 0;
210
+ for (let i = 0; i < left.length; i++) {
211
+ diff |= left[i] ^ right[i];
212
+ }
213
+ return diff === 0;
214
+ }
215
+ function checkpointBody(checkpoint) {
216
+ const body = checkpoint.split('\n\n')[0];
217
+ if (body === undefined || body.length === 0)
218
+ throw new Error('checkpoint body missing');
219
+ return body.endsWith('\n') ? body : `${body}\n`;
220
+ }
221
+ function parseCheckpointRoot(checkpoint) {
222
+ const body = checkpointBody(checkpoint);
223
+ const lines = body.trimEnd().split('\n');
224
+ if (lines.length !== 3)
225
+ throw new Error('checkpoint body must have three lines');
226
+ const treeSize = Number(lines[1]);
227
+ if (!Number.isSafeInteger(treeSize) || treeSize < 0) {
228
+ throw new Error('checkpoint tree size is invalid');
229
+ }
230
+ return {
231
+ treeSize,
232
+ rootHash: decodeBase64Bytes(lines[2], 32),
233
+ };
234
+ }
235
+ async function verifyCheckpointSignature(checkpoint, logPublicKey) {
236
+ const parts = checkpoint.split('\n\n');
237
+ const body = checkpointBody(checkpoint);
238
+ const sigLine = parts[1]?.trim();
239
+ if (sigLine === undefined || sigLine.length === 0)
240
+ return false;
241
+ const match = sigLine.match(/^\S+ \S+ (\S+)\s*$/);
242
+ if (match === null)
243
+ return false;
244
+ const decoded = decodeBase64Bytes(match[1], 68);
245
+ const signature = decoded.slice(4);
246
+ return ed.verifyAsync(signature, new TextEncoder().encode(body), logPublicKey);
247
+ }
248
+ function expectedLeafHash(record, computedRecordHash) {
249
+ const recordHashHex = computedRecordHash.slice('sha256:'.length);
250
+ const entry = serializeEntry({
251
+ record_hash_hex: recordHashHex,
252
+ creator_key_b64url: record.creator_key,
253
+ context_id: record.context_id,
254
+ timestamp: record.timestamp,
255
+ event_type: record.event_type,
256
+ });
257
+ return leafHash(entry);
258
+ }
259
+ async function verifyProofBundle(record, computedRecordHash, proof, logPublicKey) {
260
+ try {
261
+ const checkpoint = parseCheckpointRoot(proof.checkpoint);
262
+ const leaf = decodeBase64Bytes(proof.leaf_hash, 32);
263
+ const expectedLeaf = expectedLeafHash(record, computedRecordHash);
264
+ if (!bytesEqual(leaf, expectedLeaf)) {
265
+ return {
266
+ present: true,
267
+ inclusion_ok: false,
268
+ checkpoint_signature_ok: null,
269
+ error: 'proof leaf hash does not match record entry',
270
+ };
271
+ }
272
+ const proofHashes = proof.inclusion_proof.map((item) => decodeBase64Bytes(item, 32));
273
+ const checkpointSignatureOk = logPublicKey === undefined
274
+ ? null
275
+ : await verifyCheckpointSignature(proof.checkpoint, logPublicKey);
276
+ return {
277
+ present: true,
278
+ inclusion_ok: verifyInclusion(proof.log_index, checkpoint.treeSize, leaf, proofHashes, checkpoint.rootHash),
279
+ checkpoint_signature_ok: checkpointSignatureOk,
280
+ };
281
+ }
282
+ catch (error) {
283
+ return {
284
+ present: true,
285
+ inclusion_ok: false,
286
+ checkpoint_signature_ok: null,
287
+ error: error instanceof Error ? error.message : 'proof verification failed',
288
+ };
289
+ }
290
+ }
291
+ function verifyTrustedSigner(record, trustedCreatorKeys, reasons) {
292
+ if (trustedCreatorKeys === undefined || trustedCreatorKeys.length === 0)
293
+ return null;
294
+ const trusted = trustedCreatorKeys.includes(record.creator_key);
295
+ if (!trusted)
296
+ reasons.push('wrong_signer');
297
+ return trusted;
298
+ }
299
+ function verifyAllowedContext(record, allowedContextIds, reasons) {
300
+ if (allowedContextIds === undefined || allowedContextIds.length === 0)
301
+ return null;
302
+ const allowed = allowedContextIds.includes(record.context_id);
303
+ if (!allowed)
304
+ reasons.push('wrong_context');
305
+ return allowed;
306
+ }
307
+ async function verifyOneClaim(claim, options) {
308
+ const reasons = [];
309
+ const warnings = [];
310
+ const nowMs = options.now_ms ?? Date.now();
311
+ const trustedCreatorKeys = claim.trusted_creator_keys ?? options.trusted_creator_keys;
312
+ const allowedContextIds = claim.allowed_context_ids ?? options.allowed_context_ids;
313
+ const maxAgeMs = claim.max_age_ms ?? options.max_age_ms;
314
+ if (claim.record === undefined) {
315
+ reasons.push('record_missing');
316
+ return {
317
+ record_hash: claim.record_hash,
318
+ accepted: false,
319
+ rejection_reasons: reasons,
320
+ warnings,
321
+ signature_ok: null,
322
+ computed_record_hash: null,
323
+ signer_trusted: null,
324
+ context_allowed: null,
325
+ };
326
+ }
327
+ const computed = recordHash(claim.record);
328
+ if (computed !== claim.record_hash) {
329
+ reasons.push('record_hash_mismatch');
330
+ }
331
+ const verification = await verifyRecord(claim.record);
332
+ if (!verification.signatureOk)
333
+ reasons.push('signature_invalid');
334
+ if (!verification.valid)
335
+ reasons.push('record_invalid');
336
+ warnings.push(...verification.warnings);
337
+ const signerTrusted = verifyTrustedSigner(claim.record, trustedCreatorKeys, reasons);
338
+ const contextAllowed = verifyAllowedContext(claim.record, allowedContextIds, reasons);
339
+ verifyFreshness(claim.record, nowMs, maxAgeMs, reasons);
340
+ const proof = await verifyProofPresence(claim, claim.record, computed, options.require_log_inclusion === true, options.log_public_key, reasons);
341
+ const body = verifyBody(claim, claim.record, options.require_body === true, options.require_body_commitment === true, reasons);
342
+ const uniqueReasons = Array.from(new Set(reasons));
343
+ const result = {
344
+ record_hash: claim.record_hash,
345
+ accepted: uniqueReasons.length === 0,
346
+ rejection_reasons: uniqueReasons,
347
+ warnings,
348
+ record: claim.record,
349
+ verification,
350
+ signature_ok: verification.signatureOk,
351
+ computed_record_hash: computed,
352
+ signer_trusted: signerTrusted,
353
+ context_allowed: contextAllowed,
354
+ body,
355
+ };
356
+ if (proof !== undefined)
357
+ result.proof = proof;
358
+ return result;
359
+ }
360
+ export async function verifyHandoffClaims(claims, options = {}) {
361
+ const checked = await Promise.all(claims.map((claim) => verifyOneClaim(claim, options)));
362
+ const accepted = checked.filter((claim) => claim.accepted);
363
+ const rejected = checked.filter((claim) => !claim.accepted);
364
+ return {
365
+ accepted,
366
+ rejected,
367
+ accepted_record_hashes: accepted.map((claim) => claim.record_hash),
368
+ all_accepted: rejected.length === 0,
369
+ };
370
+ }
371
+ //# sourceMappingURL=handoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff.js","sourceRoot":"","sources":["../src/handoff.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ export { AtribVerifier } from './verifier.js';
2
2
  export type { AtribVerifierOptions, CalculateOptions, VerifyRecommendationOptions, } from './verifier.js';
3
3
  export { verifyRecord } from './verify-record.js';
4
4
  export type { RecordVerificationResult, ProvenanceAnnotation, VerifyRecordOptions, CrossAttestationAnnotation, } from './verify-record.js';
5
+ export { handoffClaimsFromEvidencePacket, verifyHandoffClaims } from './handoff.js';
6
+ export type { HandoffBodyVerification, HandoffClaimsFromEvidenceOptions, HandoffClaimInput, HandoffClaimVerification, HandoffEvidenceEntry, HandoffEvidencePacket, HandoffProofVerification, HandoffRejectionReason, HandoffVerificationResult, VerifyHandoffClaimsOptions, } from './handoff.js';
5
7
  export { calculate, DEFAULT_POLICY, isValidPolicy } from './calculate.js';
6
8
  export { signRecommendation, verifyRecommendationSignature, recommendationSigningInput, distributionsMatch, } from './recommendation.js';
7
9
  export { buildPolicy, policyFrom } from './policy-builder.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,eAAe,CAAA;AAKtB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAGzE,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAG7D,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAG5F,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAC3E,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGxF,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,wBAAwB,EACxB,mBAAmB,EACnB,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,8BAA8B,EAC9B,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EACzB,cAAc,EACd,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,MAAM,GACP,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,kBAAkB,GACnB,MAAM,uBAAuB,CAAA;AAG9B,YAAY,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,SAAS,EACT,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,eAAe,CAAA;AAKtB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAK3B,OAAO,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACnF,YAAY,EACV,uBAAuB,EACvB,gCAAgC,EAChC,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAGzE,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAG7D,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAG5F,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAC3E,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAGxF,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,wBAAwB,EACxB,mBAAmB,EACnB,6BAA6B,EAC7B,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,8BAA8B,EAC9B,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,yBAAyB,EACzB,cAAc,EACd,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,MAAM,GACP,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EACV,kBAAkB,EAClB,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,kBAAkB,GACnB,MAAM,uBAAuB,CAAA;AAG9B,YAAY,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,SAAS,EACT,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -6,6 +6,10 @@ export { AtribVerifier } from './verifier.js';
6
6
  // AtribVerifier.verify which operates on a settlement RecommendationDocument.
7
7
  // Surfaces the implemented D044, D041, D045, D051, D052, and D094 annotations.
8
8
  export { verifyRecord } from './verify-record.js';
9
+ // Cross-agent handoff claim verification. Used when one agent receives a
10
+ // record_hash claim plus private body material from another agent and must
11
+ // decide whether to link its next record through informed_by.
12
+ export { handoffClaimsFromEvidencePacket, verifyHandoffClaims } from './handoff.js';
9
13
  // Calculation algorithm (§4.6). pure function, exported for direct use
10
14
  export { calculate, DEFAULT_POLICY, isValidPolicy } from './calculate.js';
11
15
  // Recommendation document signing/verification (§4.7)
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,+CAA+C;AAE/C,4BAA4B;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAO7C,8DAA8D;AAC9D,8EAA8E;AAC9E,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAQjD,uEAAuE;AACvE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEzE,sDAAsD;AACtD,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAE5B,mDAAmD;AACnD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE7D,+BAA+B;AAC/B,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE5F,6BAA6B;AAC7B,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAG3E,6EAA6E;AAC7E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA;AA6B7B,0DAA0D;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAgCvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,+CAA+C;AAE/C,4BAA4B;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAO7C,8DAA8D;AAC9D,8EAA8E;AAC9E,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAQjD,yEAAyE;AACzE,2EAA2E;AAC3E,8DAA8D;AAC9D,OAAO,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAcnF,uEAAuE;AACvE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEzE,sDAAsD;AACtD,OAAO,EACL,kBAAkB,EAClB,6BAA6B,EAC7B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAE5B,mDAAmD;AACnD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE7D,+BAA+B;AAC/B,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAE5F,6BAA6B;AAC7B,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAG3E,6EAA6E;AAC7E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA;AA6B7B,0DAA0D;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAgCvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAA"}
@@ -120,9 +120,10 @@ export interface CrossAttestationAnnotation {
120
120
  */
121
121
  signers_count: number;
122
122
  /**
123
- * Number of signers whose Ed25519 signature successfully verifies
124
- * against the cross-attestation canonical bytes (JCS form with
125
- * `signers: []` and `signature` omitted, per §1.7.6).
123
+ * Number of distinct creator keys with at least one Ed25519 signature
124
+ * that successfully verifies against the cross-attestation canonical
125
+ * bytes (JCS form with `signers: []` and `signature` omitted, per
126
+ * §1.7.6). Duplicate entries from one key do not inflate this count.
126
127
  */
127
128
  signers_valid: number;
128
129
  /**
@@ -231,8 +232,8 @@ export interface RecordVerificationResult {
231
232
  * Cross-attestation annotation per §1.7.6 (D052). Populated ONLY for
232
233
  * transaction records (`event_type = https://atrib.dev/v1/types/transaction`).
233
234
  * Surfaces signers_count, signers_valid, and missing (true when fewer
234
- * than 2 signers verified). Per §1.7.6 verifiers MUST flag missing
235
- * cross-attestation; consumers decide policy.
235
+ * than 2 distinct signer keys verify). Per §1.7.6 verifiers MUST flag
236
+ * missing cross-attestation; consumers decide policy.
236
237
  */
237
238
  cross_attestation?: CrossAttestationAnnotation;
238
239
  /**
@@ -335,7 +336,8 @@ declare function resolveCapabilityCheck(record: AtribRecord, claim: ResolvedIden
335
336
  * For each entry in `record.signers`, verify the Ed25519 signature
336
337
  * against the cross-attestation canonical bytes (JCS form with
337
338
  * `signers: []` and the top-level `signature` field omitted). Count
338
- * valid signatures; flag `missing: true` when fewer than 2 verify.
339
+ * distinct valid signer keys; flag `missing: true` when fewer than 2
340
+ * independent keys verify.
339
341
  *
340
342
  * Per §1.7.6 mismatches are SIGNALS, not invalidation: missing
341
343
  * cross-attestation does NOT push to `warnings[]` (which would flip
@@ -1 +1 @@
1
- {"version":3,"file":"verify-record.d.ts","sourceRoot":"","sources":["../src/verify-record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"verify-record.d.ts","sourceRoot":"","sources":["../src/verify-record.ts"],"names":[],"mappings":"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"}
@@ -257,7 +257,8 @@ function resolveCapabilityCheck(record, claim, _warnings) {
257
257
  * For each entry in `record.signers`, verify the Ed25519 signature
258
258
  * against the cross-attestation canonical bytes (JCS form with
259
259
  * `signers: []` and the top-level `signature` field omitted). Count
260
- * valid signatures; flag `missing: true` when fewer than 2 verify.
260
+ * distinct valid signer keys; flag `missing: true` when fewer than 2
261
+ * independent keys verify.
261
262
  *
262
263
  * Per §1.7.6 mismatches are SIGNALS, not invalidation: missing
263
264
  * cross-attestation does NOT push to `warnings[]` (which would flip
@@ -283,7 +284,7 @@ async function resolveCrossAttestation(record) {
283
284
  // if it does, treat all signers as unverifiable.
284
285
  return { signers_count, signers_valid: 0, missing: true };
285
286
  }
286
- let signers_valid = 0;
287
+ const validSignerKeys = new Set();
287
288
  for (const entry of signers) {
288
289
  if (typeof entry?.creator_key !== 'string' || typeof entry?.signature !== 'string')
289
290
  continue;
@@ -292,12 +293,13 @@ async function resolveCrossAttestation(record) {
292
293
  const sig = base64urlDecode(entry.signature);
293
294
  const ok = await ed.verifyAsync(sig, canonicalBytes, pubKey);
294
295
  if (ok)
295
- signers_valid++;
296
+ validSignerKeys.add(entry.creator_key);
296
297
  }
297
298
  catch {
298
299
  // Malformed key/sig bytes: skip without counting.
299
300
  }
300
301
  }
302
+ const signers_valid = validSignerKeys.size;
301
303
  return {
302
304
  signers_count,
303
305
  signers_valid,
@@ -306,14 +308,24 @@ async function resolveCrossAttestation(record) {
306
308
  }
307
309
  async function verifyCreatorSignerSignature(record) {
308
310
  const signers = Array.isArray(record.signers) ? record.signers : [];
309
- const creatorSigner = signers.find((entry) => entry.creator_key === record.creator_key);
310
- if (!creatorSigner)
311
+ const creatorSigners = signers.filter((entry) => entry.creator_key === record.creator_key);
312
+ if (creatorSigners.length === 0)
311
313
  return false;
312
- const pubKey = base64urlDecode(creatorSigner.creator_key);
313
- const sig = base64urlDecode(creatorSigner.signature);
314
- if (pubKey.length !== 32 || sig.length !== 64)
315
- return false;
316
- return ed.verifyAsync(sig, canonicalCrossAttestationInput(record), pubKey);
314
+ const verifyInput = canonicalCrossAttestationInput(record);
315
+ for (const creatorSigner of creatorSigners) {
316
+ try {
317
+ const pubKey = base64urlDecode(creatorSigner.creator_key);
318
+ const sig = base64urlDecode(creatorSigner.signature);
319
+ if (pubKey.length !== 32 || sig.length !== 64)
320
+ continue;
321
+ if (await ed.verifyAsync(sig, verifyInput, pubKey))
322
+ return true;
323
+ }
324
+ catch {
325
+ // Try the next matching signer entry.
326
+ }
327
+ }
328
+ return false;
317
329
  }
318
330
  function detectPosture(record, warnings) {
319
331
  const declared = record.timestamp_granularity;