agentfootprint 6.17.0 → 6.18.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,559 @@
1
+ "use strict";
2
+ /**
3
+ * auditExport — tamper-evident audit bundle (backlog #20, compliance
4
+ * wedge item 2; pairs with #19's `otelObservability` GenAI spans).
5
+ *
6
+ * Consumes the typed `agentfootprint.*` event stream and accumulates an
7
+ * append-only, HASH-CHAINED record log: every record carries the SHA-256
8
+ * of its own canonical serialization plus the hash of the previous
9
+ * record. Flipping a single byte anywhere in an exported bundle makes
10
+ * `verifyAuditBundle` name the exact record that broke — the
11
+ * record-keeping shape EU AI Act Art. 12 asks for (events the system
12
+ * logged, in order, demonstrably unmodified since capture).
13
+ *
14
+ * Pattern: Observability strategy (one purpose — chain accumulation)
15
+ * + pure offline verifier.
16
+ * Role: Outer ring (Hexagonal). Attach via
17
+ * `agent.enable.observability({ strategy: auditExport() })`.
18
+ * Emits: nothing — terminal sink.
19
+ *
20
+ * ## What lands in the chain
21
+ *
22
+ * One record per typed event, in dispatch order: decisions
23
+ * (`agent.route_decided`, `composition.route_decided` incl. decide()
24
+ * evidence), tool calls (`stream.tool_start/_end`), validation
25
+ * rejections (#9), permission verdicts and halts, credential lifecycle,
26
+ * costs, errors, skill/memory/context activity. Each new `meta.runId`
27
+ * is anchored by a GENESIS record (`audit.genesis`) carrying the runId,
28
+ * the agent identity, and library versions — runs chain back-to-back in
29
+ * one log, so silently DROPPING a whole run breaks the chain too.
30
+ *
31
+ * High-volume content deltas (`stream.token`, `stream.thinking_delta`)
32
+ * are excluded by default (`includeTokenEvents: true` to include).
33
+ *
34
+ * ## Record / bundle schema
35
+ *
36
+ * ```
37
+ * AuditRecord = { seq, timestamp, eventType, payload, meta, prevHash, hash }
38
+ * hash = SHA-256 hex over canonicalJson(record minus `hash`)
39
+ * prevHash = previous record's `hash` (ZERO_HASH at chain start)
40
+ * AuditBundle = { header, records, finalHash }
41
+ * header = { format, hashAlgorithm, canonicalization, chainHead,
42
+ * firstSeq, recordCount, exportedAt, library }
43
+ * ```
44
+ *
45
+ * Canonicalization is `afp-cjson/1` (see `lib/canonicalJson.ts` — those
46
+ * rules ARE the contract; the header names them so independent
47
+ * verifiers can re-implement byte-exactly).
48
+ *
49
+ * ## Persistence + long runs
50
+ *
51
+ * Persistence is the CONSUMER's job — the bundle is plain JSON
52
+ * (`JSON.stringify(strategy.bundle())`, store anywhere). For long runs,
53
+ * `drain()` returns the records accumulated since the last drain while
54
+ * keeping the chain intact ACROSS drains: each segment's
55
+ * `header.chainHead` equals the previous segment's `finalHash`, so
56
+ * `verifyAuditBundle([seg1, seg2, ...])` re-verifies the concatenation
57
+ * end-to-end.
58
+ *
59
+ * ## PII discipline (mirrors #19's otelObservability)
60
+ *
61
+ * Payloads enter records through a bounding layer — by default
62
+ * (`payloadMode: 'bounded'`) record payloads NEVER carry raw runtime
63
+ * values that can echo PII:
64
+ *
65
+ * - tool args → `'[keys: …]'` (top-level key NAMES only)
66
+ * - tool results → `'[type: …]'` (typeof only)
67
+ * - userPrompt / LLM content / thinking blocks / history
68
+ * → `'[N chars]'` / `'[N messages]'` markers
69
+ * - content PREVIEWS (`contentSummary` on context/memory events,
70
+ * `rawContent`, `resultSummary`, `droppedSummaries`) → markers
71
+ * (for short content a preview IS the content; `contentHash`
72
+ * stays — it links identical content without echoing it)
73
+ * - error MESSAGE strings (`error`, `errorMessage`, `lastError`,
74
+ * `rawOutput`) → `'[N chars]'` (messages can echo values)
75
+ * - free-form Records (`questionPayload`, `resumeInput`, risk/eval
76
+ * `evidence`, memory `scoreEvidence`) → `'[keys: …]'`
77
+ *
78
+ * Everything else is embedded as the registry payload (sanitized:
79
+ * strings capped at 256 chars, lists at 32 items, cycles broken) —
80
+ * those payloads are bounded by construction: identifiers, counts,
81
+ * enums, decide() evidence (engine-bounded + redaction-aware),
82
+ * validation issues (paths/TYPES per #9), credential events (no
83
+ * secrets by contract).
84
+ *
85
+ * `payloadMode: 'verbatim'` embeds full payloads (still
86
+ * JSON-sanitized). For Art. 12 completeness on an access-controlled
87
+ * store that is often the point — but the bundle then carries prompts,
88
+ * tool args/results and model output. Treat it as PII-bearing, and
89
+ * remember the Agent sets NO footprintjs RedactionPolicy by default
90
+ * (policies you do set redact the emit channel UPSTREAM of this
91
+ * strategy, so redacted events arrive here already redacted).
92
+ *
93
+ * ## Tamper-EVIDENT, not tamper-PROOF (honest threat model)
94
+ *
95
+ * The chain proves INTERNAL consistency: any partial modification —
96
+ * edit, insert, delete, reorder, drop-a-run — is detected and named.
97
+ * It does NOT prove provenance: an adversary holding the only copy can
98
+ * recompute every hash from the mutation onward and present a
99
+ * self-consistent forgery. For non-repudiation, anchor `finalHash`
100
+ * externally as part of your retention process (write-once/WORM store,
101
+ * signed log, RFC 3161 timestamping, or simply a second party) — then
102
+ * a whole-suffix recomputation no longer matches the anchor.
103
+ *
104
+ * ## Runtime requirements
105
+ *
106
+ * Hashing uses `node:crypto` (`createHash('sha256')`) — zero new
107
+ * dependencies, imported lazily at first use (same gating as the
108
+ * optional vendor SDKs in this folder, so merely importing this module
109
+ * stays browser-safe). `auditExport` and `verifyAuditBundle` therefore
110
+ * run anywhere `node:crypto` exists: Node ≥ 20, Bun, Deno,
111
+ * edge runtimes with Node compat (e.g. Cloudflare `nodejs_compat`).
112
+ * In a browser there is no SYNC SHA-256 (WebCrypto is async-only), so
113
+ * both throw a descriptive error — verify server-side, or re-implement
114
+ * verification from the documented contract (it is pure: recompute
115
+ * SHA-256 over `afp-cjson/1` canonicalization and walk the chain).
116
+ *
117
+ * @example Capture → export → verify
118
+ * ```ts
119
+ * import { auditExport, verifyAuditBundle } from 'agentfootprint/observability-providers';
120
+ *
121
+ * const audit = auditExport({ agent: 'loan-officer' });
122
+ * const stop = agent.enable.observability({ strategy: audit });
123
+ * await agent.run({ message: 'assess application A-17' });
124
+ * stop();
125
+ *
126
+ * const bundle = audit.bundle(); // JSON-serializable
127
+ * await fs.writeFile('run.audit.json', JSON.stringify(bundle));
128
+ *
129
+ * const check = verifyAuditBundle(bundle); // offline — no agent needed
130
+ * // check.valid === true; tamper with one byte → { valid: false, brokenAt: <seq> }
131
+ * ```
132
+ */
133
+ Object.defineProperty(exports, "__esModule", { value: true });
134
+ exports.verifyAuditBundle = exports.auditExport = exports.AUDIT_BUNDLE_FORMAT = exports.AUDIT_GENESIS_EVENT_TYPE = exports.AUDIT_ZERO_HASH = void 0;
135
+ const canonicalJson_js_1 = require("../../lib/canonicalJson.js");
136
+ const lazyRequire_js_1 = require("../../lib/lazyRequire.js");
137
+ // ─── Public types ─────────────────────────────────────────────────────
138
+ /** SHA-256 of "nothing" — the `prevHash` of the first record in a
139
+ * chain and the `chainHead` of a chain's first segment. */
140
+ exports.AUDIT_ZERO_HASH = '0'.repeat(64);
141
+ /** `eventType` of the per-run genesis record. Deliberately OUTSIDE the
142
+ * `agentfootprint.*` registry namespace — it is a chain-level record,
143
+ * not a dispatched event (#20 ships zero new typed events). */
144
+ exports.AUDIT_GENESIS_EVENT_TYPE = 'audit.genesis';
145
+ /** Format identifier carried on every bundle header. */
146
+ exports.AUDIT_BUNDLE_FORMAT = 'agentfootprint.audit/1';
147
+ let cryptoModule;
148
+ function resolveCrypto() {
149
+ if (cryptoModule)
150
+ return cryptoModule;
151
+ try {
152
+ cryptoModule = (0, lazyRequire_js_1.lazyRequire)('node:crypto');
153
+ }
154
+ catch {
155
+ throw new Error('auditExport/verifyAuditBundle require `node:crypto` for synchronous SHA-256 ' +
156
+ '(available in Node ≥ 20, Bun, Deno, and edge runtimes with Node compat). ' +
157
+ 'Browsers expose only async WebCrypto — capture/verify audit bundles server-side.');
158
+ }
159
+ if (typeof cryptoModule.createHash !== 'function') {
160
+ throw new Error('auditExport: `node:crypto` resolved but `createHash` is missing.');
161
+ }
162
+ return cryptoModule;
163
+ }
164
+ function sha256Hex(text) {
165
+ return resolveCrypto().createHash('sha256').update(text, 'utf8').digest('hex');
166
+ }
167
+ /** Best-effort library version for header + genesis.
168
+ *
169
+ * Tries the package self-reference first (`exports["./package.json"]`
170
+ * — resolves from source and the CJS build), then relative paths to
171
+ * the root manifest (the ESM build sits under `dist/esm/`, whose
172
+ * type-stamp `package.json` has no `name`, which breaks Node's
173
+ * self-reference scope; relative specifiers resolve from
174
+ * `lib/lazyRequire` — `../../` from `src//dist/lib`, `../../../`
175
+ * from `dist/esm/lib`). The `name` guard rejects any manifest that
176
+ * isn't actually ours. 'unknown' where nothing resolves (bundlers). */
177
+ function libraryVersion() {
178
+ for (const specifier of [
179
+ 'agentfootprint/package.json',
180
+ '../../package.json',
181
+ '../../../package.json',
182
+ ]) {
183
+ try {
184
+ const pkg = (0, lazyRequire_js_1.lazyRequire)(specifier);
185
+ if (pkg.name === 'agentfootprint' && typeof pkg.version === 'string')
186
+ return pkg.version;
187
+ }
188
+ catch {
189
+ /* try the next candidate */
190
+ }
191
+ }
192
+ return 'unknown';
193
+ }
194
+ // ─── JSON sanitization (both modes) ──────────────────────────────────
195
+ /** Caps mirror otel.ts's bounding discipline (defense-in-depth — the
196
+ * registry payloads are mostly bounded upstream). */
197
+ const MAX_STRING_CHARS = 256;
198
+ const MAX_LIST_ITEMS = 32;
199
+ const MAX_DEPTH = 8;
200
+ /**
201
+ * Convert any value to a JSON-safe, size-bounded tree:
202
+ * strings capped, arrays capped with an overflow marker, cycles
203
+ * broken, depth capped, Date → ISO, bigint → string, non-finite →
204
+ * null, functions/symbols/undefined dropped (objects) or null
205
+ * (arrays). Output always canonicalizes without throwing.
206
+ */
207
+ function sanitizeJson(value, depth = 0, seen = new Set()) {
208
+ if (value === null)
209
+ return null;
210
+ switch (typeof value) {
211
+ case 'string':
212
+ return value.length > MAX_STRING_CHARS ? `${value.slice(0, MAX_STRING_CHARS - 1)}…` : value;
213
+ case 'number':
214
+ return Number.isFinite(value) ? value : null;
215
+ case 'boolean':
216
+ return value;
217
+ case 'bigint':
218
+ return String(value);
219
+ case 'undefined':
220
+ case 'function':
221
+ case 'symbol':
222
+ return undefined;
223
+ default:
224
+ break;
225
+ }
226
+ const obj = value;
227
+ if (obj instanceof Date)
228
+ return obj.toISOString();
229
+ if (depth >= MAX_DEPTH)
230
+ return '[truncated: depth]';
231
+ if (seen.has(obj))
232
+ return '[circular]';
233
+ seen.add(obj);
234
+ try {
235
+ if (Array.isArray(obj)) {
236
+ const capped = obj.slice(0, MAX_LIST_ITEMS).map((item) => {
237
+ const sanitized = sanitizeJson(item, depth + 1, seen);
238
+ return sanitized === undefined ? null : sanitized;
239
+ });
240
+ if (obj.length > MAX_LIST_ITEMS)
241
+ capped.push(`…+${obj.length - MAX_LIST_ITEMS} more`);
242
+ return capped;
243
+ }
244
+ const out = {};
245
+ for (const [key, entry] of Object.entries(obj)) {
246
+ const sanitized = sanitizeJson(entry, depth + 1, seen);
247
+ if (sanitized !== undefined)
248
+ out[key] = sanitized;
249
+ }
250
+ return out;
251
+ }
252
+ finally {
253
+ seen.delete(obj);
254
+ }
255
+ }
256
+ // ─── Bounding layer (payloadMode: 'bounded') ─────────────────────────
257
+ /** `'[23 chars]'` — length evidence without content. */
258
+ function charsMarker(value) {
259
+ return typeof value === 'string' ? `[${value.length} chars]` : `[type: ${typeofOf(value)}]`;
260
+ }
261
+ /** `'[keys: a, b, c]'` — shape evidence for free-form Records. */
262
+ function keysMarker(value) {
263
+ if (value === null || typeof value !== 'object')
264
+ return `[type: ${typeofOf(value)}]`;
265
+ const keys = Object.keys(value).slice(0, MAX_LIST_ITEMS);
266
+ return `[keys: ${keys.join(', ')}]`;
267
+ }
268
+ function typeofOf(value) {
269
+ return value === null ? 'null' : typeof value;
270
+ }
271
+ /**
272
+ * Content-bearing fields per event type → bounded replacement.
273
+ * Only fields that can echo raw runtime values appear here; everything
274
+ * else passes through `sanitizeJson` untouched (see module docs for
275
+ * the per-domain verbatim/summarized table).
276
+ */
277
+ const BOUND_FIELDS = {
278
+ 'agentfootprint.agent.turn_start': { userPrompt: charsMarker },
279
+ 'agentfootprint.agent.turn_end': { finalContent: charsMarker },
280
+ 'agentfootprint.agent.iteration_end': {
281
+ history: (v) => (Array.isArray(v) ? `[${v.length} messages]` : charsMarker(v)),
282
+ },
283
+ 'agentfootprint.agent.output_schema_validation_failed': { rawOutput: charsMarker },
284
+ 'agentfootprint.stream.llm_end': { content: charsMarker },
285
+ 'agentfootprint.stream.token': { content: charsMarker },
286
+ 'agentfootprint.stream.thinking_delta': { content: charsMarker },
287
+ 'agentfootprint.stream.thinking_end': {
288
+ blocks: (v) => (Array.isArray(v) ? `[${v.length} blocks]` : charsMarker(v)),
289
+ },
290
+ 'agentfootprint.stream.tool_start': { args: keysMarker },
291
+ 'agentfootprint.stream.tool_end': { result: (v) => `[type: ${typeofOf(v)}]` },
292
+ // contentSummary is a raw-content PREVIEW (not a redacted summary) —
293
+ // for short content it IS the content, so it is bounded like content.
294
+ // `contentHash` stays verbatim: it links identical injections across
295
+ // records without echoing a byte of them.
296
+ 'agentfootprint.context.injected': { rawContent: charsMarker, contentSummary: charsMarker },
297
+ 'agentfootprint.context.slot_composed': {
298
+ droppedSummaries: (v) => (Array.isArray(v) ? `[${v.length} summaries]` : charsMarker(v)),
299
+ },
300
+ 'agentfootprint.composition.merge_end': { resultSummary: charsMarker },
301
+ 'agentfootprint.memory.attached': { contentSummary: charsMarker },
302
+ 'agentfootprint.memory.written': { contentSummary: charsMarker },
303
+ 'agentfootprint.pause.request': { questionPayload: keysMarker },
304
+ 'agentfootprint.pause.resume': { resumeInput: keysMarker },
305
+ 'agentfootprint.risk.flagged': { evidence: keysMarker },
306
+ 'agentfootprint.eval.score': { evidence: keysMarker },
307
+ 'agentfootprint.memory.strategy_applied': { scoreEvidence: keysMarker },
308
+ };
309
+ /** Error-MESSAGE field names — bounded in EVERY event (messages can
310
+ * echo runtime values; mirrors #19's "stage + scope only" rule). The
311
+ * classifier fields (`errorName`, `errorKind`) stay verbatim. */
312
+ const ERROR_MESSAGE_FIELDS = new Set(['error', 'errorMessage', 'lastError']);
313
+ function boundPayload(eventType, payload) {
314
+ if (payload === null || typeof payload !== 'object' || Array.isArray(payload)) {
315
+ return sanitizeJson(payload);
316
+ }
317
+ const fieldRules = BOUND_FIELDS[eventType];
318
+ const out = {};
319
+ for (const [key, value] of Object.entries(payload)) {
320
+ const rule = fieldRules?.[key];
321
+ if (rule !== undefined) {
322
+ out[key] = rule(value);
323
+ continue;
324
+ }
325
+ if (ERROR_MESSAGE_FIELDS.has(key) && typeof value === 'string') {
326
+ out[key] = charsMarker(value);
327
+ continue;
328
+ }
329
+ const sanitized = sanitizeJson(value);
330
+ if (sanitized !== undefined)
331
+ out[key] = sanitized;
332
+ }
333
+ return out;
334
+ }
335
+ // ─── Strategy factory ────────────────────────────────────────────────
336
+ /** Excluded by default — high-volume content deltas. */
337
+ const TOKEN_EVENT_TYPES = new Set([
338
+ 'agentfootprint.stream.token',
339
+ 'agentfootprint.stream.thinking_delta',
340
+ ]);
341
+ function auditExport(opts = {}) {
342
+ const payloadMode = opts.payloadMode ?? 'bounded';
343
+ const includeTokenEvents = opts.includeTokenEvents === true;
344
+ const version = libraryVersion();
345
+ // Chain state — survives drains; one chain per strategy instance.
346
+ let nextSeq = 0;
347
+ let lastHash = exports.AUDIT_ZERO_HASH;
348
+ let segmentHead = exports.AUDIT_ZERO_HASH;
349
+ let segmentFirstSeq = 0;
350
+ let retained = [];
351
+ const seenRunIds = new Set();
352
+ let stopped = false;
353
+ function append(eventType, timestamp, payload, meta) {
354
+ const preimage = { seq: nextSeq, timestamp, eventType, payload, meta, prevHash: lastHash };
355
+ const hash = sha256Hex((0, canonicalJson_js_1.canonicalJson)(preimage));
356
+ retained.push({ ...preimage, hash });
357
+ lastHash = hash;
358
+ nextSeq += 1;
359
+ }
360
+ function appendGenesis(runId, timestamp) {
361
+ append(exports.AUDIT_GENESIS_EVENT_TYPE, timestamp, {
362
+ runId,
363
+ ...(opts.agent !== undefined && { agent: opts.agent }),
364
+ library: { name: 'agentfootprint', version },
365
+ ...(opts.versions !== undefined && { versions: sanitizeJson(opts.versions) }),
366
+ payloadMode,
367
+ }, { runId });
368
+ }
369
+ function makeBundle() {
370
+ return {
371
+ header: {
372
+ format: exports.AUDIT_BUNDLE_FORMAT,
373
+ hashAlgorithm: 'sha-256',
374
+ canonicalization: canonicalJson_js_1.CANONICAL_JSON_VERSION,
375
+ chainHead: segmentHead,
376
+ firstSeq: segmentFirstSeq,
377
+ recordCount: retained.length,
378
+ exportedAt: Date.now(),
379
+ library: { name: 'agentfootprint', version },
380
+ },
381
+ records: [...retained],
382
+ finalHash: lastHash,
383
+ };
384
+ }
385
+ return {
386
+ name: 'audit',
387
+ capabilities: { events: true },
388
+ /** Attach-time check (the `validate()` contract) — fail fast where
389
+ * `node:crypto` is unavailable instead of on the first event. */
390
+ validate() {
391
+ resolveCrypto();
392
+ },
393
+ exportEvent(event) {
394
+ if (stopped)
395
+ return;
396
+ if (!includeTokenEvents && TOKEN_EVENT_TYPES.has(event.type))
397
+ return;
398
+ // Real dispatcher envelopes carry meta (bridge/eventMeta.ts).
399
+ // Hand-fed events without it are still recorded — an audit sink
400
+ // must never silently drop — under the 'unattributed' run anchor.
401
+ const meta = event.meta;
402
+ const runId = typeof meta?.runId === 'string' ? meta.runId : 'unattributed';
403
+ const timestamp = typeof meta?.wallClockMs === 'number' ? meta.wallClockMs : Date.now();
404
+ if (!seenRunIds.has(runId)) {
405
+ seenRunIds.add(runId);
406
+ appendGenesis(runId, timestamp);
407
+ }
408
+ // wallClockMs lives on `timestamp`; the rest of the meta rides
409
+ // along sanitized (runtimeStageId, paths, turn/iter indices, …).
410
+ const { wallClockMs: _lifted, ...metaRest } = meta ?? {};
411
+ void _lifted;
412
+ const recordMeta = {
413
+ ...sanitizeJson(metaRest),
414
+ runId,
415
+ };
416
+ const payload = payloadMode === 'bounded'
417
+ ? boundPayload(event.type, event.payload)
418
+ : sanitizeJson(event.payload);
419
+ append(event.type, timestamp, payload, recordMeta);
420
+ },
421
+ flush() {
422
+ // In-memory sink — nothing to flush. Export via bundle()/drain().
423
+ },
424
+ stop() {
425
+ // Stop OBSERVING; never destroy collected evidence — consumers
426
+ // drain/bundle after stop.
427
+ stopped = true;
428
+ },
429
+ bundle() {
430
+ return makeBundle();
431
+ },
432
+ drain() {
433
+ const segment = makeBundle();
434
+ segmentHead = lastHash;
435
+ segmentFirstSeq = nextSeq;
436
+ retained = [];
437
+ return segment;
438
+ },
439
+ recordCount() {
440
+ return retained.length;
441
+ },
442
+ };
443
+ }
444
+ exports.auditExport = auditExport;
445
+ // ─── Offline verification (pure — no agent, no strategy) ─────────────
446
+ /**
447
+ * Recompute the hash chain of a bundle (or of consecutive drained
448
+ * segments, in order) and report the exact record where integrity
449
+ * breaks. Pure function over JSON data — runs offline, long after the
450
+ * run, with no agent and no strategy instance.
451
+ *
452
+ * Checks, in order, per segment:
453
+ * 1. header format / algorithm / canonicalization are supported
454
+ * 2. `recordCount` matches `records.length`
455
+ * 3. segment continuity (`chainHead`/`firstSeq` extend the previous
456
+ * segment's `finalHash`/seq range)
457
+ * 4. per record: `seq` is contiguous, `prevHash` links the previous
458
+ * record, and SHA-256 over the canonical preimage (the record
459
+ * minus `hash` — so ADDED fields are caught too) matches `hash`
460
+ * 5. `finalHash` equals the last record's hash
461
+ */
462
+ function verifyAuditBundle(input) {
463
+ const segments = Array.isArray(input)
464
+ ? input
465
+ : [input];
466
+ let recordsChecked = 0;
467
+ let expectedChainHead;
468
+ let expectedFirstSeq;
469
+ const fail = (reason, brokenAt) => ({
470
+ valid: false,
471
+ recordsChecked,
472
+ ...(brokenAt !== undefined && { brokenAt }),
473
+ reason,
474
+ });
475
+ if (segments.length === 0)
476
+ return fail('no bundles supplied');
477
+ for (let s = 0; s < segments.length; s++) {
478
+ const segment = segments[s];
479
+ const where = segments.length > 1 ? ` (segment ${s})` : '';
480
+ if (segment === undefined || typeof segment !== 'object') {
481
+ return fail(`bundle is not an object${where}`);
482
+ }
483
+ const { header, records, finalHash } = segment;
484
+ if (header === undefined || !Array.isArray(records) || typeof finalHash !== 'string') {
485
+ return fail(`bundle missing header/records/finalHash${where}`);
486
+ }
487
+ if (header.format !== exports.AUDIT_BUNDLE_FORMAT) {
488
+ return fail(`unsupported format '${String(header.format)}'${where}`);
489
+ }
490
+ if (header.hashAlgorithm !== 'sha-256') {
491
+ return fail(`unsupported hashAlgorithm '${String(header.hashAlgorithm)}'${where}`);
492
+ }
493
+ if (header.canonicalization !== canonicalJson_js_1.CANONICAL_JSON_VERSION) {
494
+ return fail(`unsupported canonicalization '${String(header.canonicalization)}'${where}`);
495
+ }
496
+ if (header.recordCount !== records.length) {
497
+ return fail(`recordCount ${String(header.recordCount)} does not match ${records.length} records${where}`);
498
+ }
499
+ if (expectedChainHead !== undefined && header.chainHead !== expectedChainHead) {
500
+ return fail(`segment discontinuity — chainHead does not match previous segment's finalHash${where}`, header.firstSeq);
501
+ }
502
+ if (expectedFirstSeq !== undefined && header.firstSeq !== expectedFirstSeq) {
503
+ return fail(`segment discontinuity — firstSeq ${String(header.firstSeq)}, expected ${expectedFirstSeq}${where}`, expectedFirstSeq);
504
+ }
505
+ // Head-truncation invariant (adversarial-review finding): a segment
506
+ // claiming to be the chain START (firstSeq 0) MUST anchor on the zero
507
+ // hash, and a segment anchored on the zero hash MUST claim seq 0 —
508
+ // both directions. Without this, an attacker could drop the first K
509
+ // records (genesis included — agent identity, versions, payload-mode
510
+ // declaration) and forge `chainHead` from the survivor's prevHash;
511
+ // `finalHash` is untouched by that attack, so external finalHash
512
+ // anchoring alone would NOT catch it. With the invariant, a head-
513
+ // truncated forgery must declare firstSeq > 0 — visibly NOT a chain
514
+ // start — and auditors reject leading segments missing seq 0.
515
+ if (header.firstSeq === 0 && header.chainHead !== exports.AUDIT_ZERO_HASH) {
516
+ return fail(`head-truncation guard — firstSeq 0 requires chainHead to be the zero hash${where}`, 0);
517
+ }
518
+ if (header.chainHead === exports.AUDIT_ZERO_HASH && header.firstSeq !== 0) {
519
+ return fail(`head-truncation guard — zero-hash chainHead requires firstSeq 0, got ${String(header.firstSeq)}${where}`, header.firstSeq);
520
+ }
521
+ let prevHash = header.chainHead;
522
+ for (let i = 0; i < records.length; i++) {
523
+ const record = records[i];
524
+ const expectedSeq = header.firstSeq + i;
525
+ if (record === null || typeof record !== 'object') {
526
+ return fail(`record at seq ${expectedSeq} is not an object`, expectedSeq);
527
+ }
528
+ if (record.seq !== expectedSeq) {
529
+ return fail(`sequence mismatch — record carries seq ${String(record.seq)}, expected ${expectedSeq}`, expectedSeq);
530
+ }
531
+ if (record.prevHash !== prevHash) {
532
+ return fail(`chain broken — prevHash does not match the preceding record's hash`, expectedSeq);
533
+ }
534
+ let recomputed;
535
+ try {
536
+ const { hash: _stored, ...preimage } = record;
537
+ void _stored;
538
+ recomputed = sha256Hex((0, canonicalJson_js_1.canonicalJson)(preimage));
539
+ }
540
+ catch (err) {
541
+ return fail(`record not canonicalizable (${err instanceof Error ? err.message : String(err)})`, expectedSeq);
542
+ }
543
+ if (recomputed !== record.hash) {
544
+ return fail(`hash mismatch — record content does not match its hash (tampered or corrupted)`, expectedSeq);
545
+ }
546
+ prevHash = record.hash;
547
+ recordsChecked += 1;
548
+ }
549
+ if (finalHash !== prevHash) {
550
+ const lastSeq = header.firstSeq + records.length - 1;
551
+ return fail(`finalHash does not match the last record's hash${where}`, records.length > 0 ? lastSeq : header.firstSeq);
552
+ }
553
+ expectedChainHead = finalHash;
554
+ expectedFirstSeq = header.firstSeq + records.length;
555
+ }
556
+ return { valid: true, recordsChecked };
557
+ }
558
+ exports.verifyAuditBundle = verifyAuditBundle;
559
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/adapters/observability/audit.ts"],"names":[],"mappings":"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"}