@mcp-audit-gateway/core 0.2.0 → 0.4.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.
Files changed (64) hide show
  1. package/.github/workflows/ci.yml +37 -0
  2. package/README.md +31 -3
  3. package/dist/attestation/audit-log.d.ts +34 -3
  4. package/dist/attestation/audit-log.d.ts.map +1 -1
  5. package/dist/attestation/audit-log.js +286 -10
  6. package/dist/attestation/audit-log.js.map +1 -1
  7. package/dist/attestation/checkpoint.test.d.ts +2 -0
  8. package/dist/attestation/checkpoint.test.d.ts.map +1 -0
  9. package/dist/attestation/checkpoint.test.js +870 -0
  10. package/dist/attestation/checkpoint.test.js.map +1 -0
  11. package/dist/attestation/signer.d.ts +24 -9
  12. package/dist/attestation/signer.d.ts.map +1 -1
  13. package/dist/attestation/signer.js +145 -11
  14. package/dist/attestation/signer.js.map +1 -1
  15. package/dist/attestation/signer.test.js +11 -0
  16. package/dist/attestation/signer.test.js.map +1 -1
  17. package/dist/attestation/verify.d.ts +23 -2
  18. package/dist/attestation/verify.d.ts.map +1 -1
  19. package/dist/attestation/verify.js +219 -2
  20. package/dist/attestation/verify.js.map +1 -1
  21. package/dist/integration.test.js +1 -0
  22. package/dist/integration.test.js.map +1 -1
  23. package/dist/proxy/gateway.d.ts +4 -0
  24. package/dist/proxy/gateway.d.ts.map +1 -1
  25. package/dist/proxy/gateway.js +4 -1
  26. package/dist/proxy/gateway.js.map +1 -1
  27. package/dist/proxy/gateway.test.js +19 -0
  28. package/dist/proxy/gateway.test.js.map +1 -1
  29. package/dist/proxy/mcp-server-adapter.d.ts +1 -0
  30. package/dist/proxy/mcp-server-adapter.d.ts.map +1 -1
  31. package/dist/proxy/mcp-server-adapter.js +28 -1
  32. package/dist/proxy/mcp-server-adapter.js.map +1 -1
  33. package/dist/proxy/mcp-server-adapter.test.js +1 -0
  34. package/dist/proxy/mcp-server-adapter.test.js.map +1 -1
  35. package/dist/types.d.ts +74 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/types.js +13 -0
  38. package/dist/types.js.map +1 -1
  39. package/dist/wrap/proxy.test.js +2 -2
  40. package/dist/wrap/proxy.test.js.map +1 -1
  41. package/docs/BACKLOG.md +33 -0
  42. package/docs/SECURITY-DESIGN.md +126 -0
  43. package/docs/v0.4.0-patch-audit.md +115 -0
  44. package/package.json +1 -1
  45. package/src/attestation/audit-log.ts +336 -15
  46. package/src/attestation/checkpoint.test.ts +956 -0
  47. package/src/attestation/signer.test.ts +14 -0
  48. package/src/attestation/signer.ts +152 -19
  49. package/src/attestation/verify.ts +270 -4
  50. package/src/integration.test.ts +1 -0
  51. package/src/proxy/gateway.test.ts +18 -0
  52. package/src/proxy/gateway.ts +4 -0
  53. package/src/proxy/mcp-server-adapter.test.ts +1 -0
  54. package/src/proxy/mcp-server-adapter.ts +26 -0
  55. package/src/types.ts +48 -0
  56. package/src/wrap/proxy.test.ts +2 -2
  57. package/test/vectors/aps-action-ref-v1-vectors.json +351 -0
  58. package/test/vectors/aps-action-ref-v1.mjs +145 -0
  59. package/test/vectors/canonicalization.json +182 -0
  60. package/test/vectors/checkpoint.json +450 -0
  61. package/test/vectors/verify-checkpoint.mjs +344 -0
  62. package/test/vectors/verify-checkpoint.py +358 -0
  63. package/test/vectors/verify.mjs +74 -1
  64. package/test/vectors/verify.py +78 -1
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ node-version: [20, 22]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-node@v4
18
+ with:
19
+ node-version: ${{ matrix.node-version }}
20
+ - run: npm ci
21
+ - run: npm run build
22
+ - run: npm test
23
+
24
+ vectors:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-node@v4
29
+ with:
30
+ node-version: 20
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.12"
34
+ - run: npm ci
35
+ - run: node test/vectors/verify-checkpoint.mjs
36
+ - run: python3 test/vectors/verify-checkpoint.py
37
+ - run: node test/vectors/aps-action-ref-v1.mjs
package/README.md CHANGED
@@ -137,18 +137,46 @@ See [gateway configuration](gateway.config.example.json) for the full schema.
137
137
  ## Install
138
138
 
139
139
  ```bash
140
- npm install -g @mcp-gateway/audit
140
+ npm install -g @mcp-audit-gateway/core
141
141
  ```
142
142
 
143
143
  This installs the `mcp-audit` CLI globally. Or use without installing:
144
144
  ```bash
145
- npx @mcp-gateway/audit wrap -- <your mcp server command>
145
+ npx @mcp-audit-gateway/core wrap -- <your mcp server command>
146
146
  ```
147
147
 
148
+ ## Attestation layer
149
+
150
+ The signing and verification subsystem goes beyond per-record HMAC. It provides tamper-evidence across log rotation, crash recovery, and multi-file chains.
151
+
152
+ Checkpoint records let a consumer detect tail truncation by stashing a single hash externally. The chain carries forward across file rotations (no silent resets). Forced restarts emit signed `chain_break` records instead of quietly starting fresh.
153
+
154
+ The canonical form is type-tagged and injective, avoids JCS's float-formatting problem by rejecting unsafe numbers entirely, and has proven cross-language parity via 46 conformance vectors (JS + Python). See [SECURITY-DESIGN.md](docs/SECURITY-DESIGN.md) for the full specification and threat model.
155
+
156
+ ## Conformance
157
+
158
+ This implementation satisfies the following properties (verified by cross-language conformance vectors and unit tests):
159
+
160
+ - Injective canonical form (no cross-type digest collisions)
161
+ - Cross-language sort equivalence (UTF-16 code-unit order)
162
+ - Unpaired surrogate rejection
163
+ - Hash chain continuity across log rotation
164
+ - Planted state detection on startup
165
+ - No false-positive after legitimate chain break
166
+ - Fail-closed on corrupt or oversized input
167
+ - Segmented monotonicity at chain_break boundaries
168
+ - Consumer-anchored completeness via checkpoint records
169
+ - Memory-bounded init (1MB cap)
170
+
171
+ APS action-ref-v1 conformance: 51/51 vectors passing (JCS recomputation + fail-closed digest comparison).
172
+
148
173
  ## Testing
149
174
 
150
175
  ```bash
151
- npm test # 96 tests across 12 test files
176
+ npm test # 149 unit tests
177
+ node test/vectors/verify-checkpoint.mjs # 46 JS conformance vectors
178
+ python3 test/vectors/verify-checkpoint.py # 46 Python conformance vectors
179
+ node test/vectors/aps-action-ref-v1.mjs # 51 APS vectors
152
180
  ```
153
181
 
154
182
  ## License
@@ -1,6 +1,12 @@
1
- import type { AuditRecord } from "../types.js";
1
+ import type { AuditRecord, CheckpointRecord, ChainBreakRecord } from "../types.js";
2
2
  import type { Signer } from "./signer.js";
3
- export declare function hashRecord(record: AuditRecord): string;
3
+ export declare function hashRecord(record: AuditRecord | CheckpointRecord | ChainBreakRecord): string;
4
+ export interface CheckpointConfig {
5
+ enabled: boolean;
6
+ intervalRecords: number;
7
+ intervalSeconds: number;
8
+ trigger: "records" | "time" | "whichever_first";
9
+ }
4
10
  export declare class AuditLog {
5
11
  private path;
6
12
  private signer;
@@ -8,7 +14,13 @@ export declare class AuditLog {
8
14
  private currentSize;
9
15
  private lastHash;
10
16
  private writeQueue;
17
+ private recordsSinceCheckpoint;
18
+ private lastCheckpointTime;
19
+ private checkpointSequence;
20
+ private totalRecordCount;
21
+ private checkpointConfig;
11
22
  constructor(path: string, signer: Signer, rotateAfterBytes: number);
23
+ enableCheckpoints(config: CheckpointConfig): void;
12
24
  record(method: string, opts: {
13
25
  toolName?: string;
14
26
  namespace?: string;
@@ -18,9 +30,28 @@ export declare class AuditLog {
18
30
  success: boolean;
19
31
  errorCode?: number;
20
32
  decisionContextDigest?: string;
33
+ aiInvocation?: {
34
+ turnId?: string;
35
+ invocationReason?: string;
36
+ model?: string;
37
+ };
21
38
  }): Promise<AuditRecord>;
22
39
  private writeRecord;
40
+ private shouldEmitCheckpoint;
41
+ private writeCheckpoint;
42
+ emitCheckpoint(): Promise<CheckpointRecord>;
43
+ getLastHash(): string;
44
+ getCheckpointSequence(): number;
45
+ getRecordCount(): number;
23
46
  private rotate;
24
- init(): Promise<void>;
47
+ private rotationBoundaryHash;
48
+ private persistState;
49
+ private persistChainState;
50
+ private recoverState;
51
+ init(opts?: {
52
+ forceNewChain?: boolean;
53
+ }): Promise<void>;
54
+ private emitChainBreak;
55
+ forceNewChain(reason: string): Promise<ChainBreakRecord>;
25
56
  }
26
57
  //# sourceMappingURL=audit-log.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../src/attestation/audit-log.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAsB1C,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAGtD;AAED,qBAAa,QAAQ;IAMjB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,gBAAgB;IAP1B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,UAAU,CAAoC;gBAG5C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM;IAG5B,MAAM,CACV,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;QACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,GACA,OAAO,CAAC,WAAW,CAAC;YAaT,WAAW;YAqCX,MAAM;IAUd,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAmC5B"}
1
+ {"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../src/attestation/audit-log.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAiC,MAAM,aAAa,CAAC;AAElH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA6B1C,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,MAAM,CAG5F;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG,iBAAiB,CAAC;CACjD;AAED,qBAAa,QAAQ;IAWjB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,gBAAgB;IAZ1B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,gBAAgB,CAAiC;gBAG/C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM;IAGlC,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAI3C,MAAM,CACV,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;QACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,YAAY,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/E,GACA,OAAO,CAAC,WAAW,CAAC;YAaT,WAAW;IA8CzB,OAAO,CAAC,oBAAoB;YAWd,eAAe;IAyBvB,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAajD,WAAW,IAAI,MAAM;IAIrB,qBAAqB,IAAI,MAAM;IAI/B,cAAc,IAAI,MAAM;YAIV,MAAM;IAapB,OAAO,CAAC,oBAAoB,CAAqB;YAEnC,YAAY;YAaZ,iBAAiB;YAajB,YAAY;IAsBpB,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAqK/C,cAAc;IA+BtB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAY/D"}
@@ -1,11 +1,12 @@
1
- import { appendFile, stat, rename, open } from "node:fs/promises";
1
+ import { appendFile, stat, rename, open, writeFile as fsWriteFile } from "node:fs/promises";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
+ import { isCheckpoint } from "../types.js";
3
4
  const GATEWAY_WITNESSED_FIELDS = [
4
5
  "id", "timestamp", "method", "toolName", "namespace",
5
6
  "upstream", "principal", "durationMs", "success", "errorCode",
6
7
  "previousHash",
7
8
  ];
8
- function buildParties(hasDecisionContext) {
9
+ function buildParties(hasDecisionContext, hasAiInvocation) {
9
10
  const parties = [
10
11
  { party: "gateway", role: "witness", scope: GATEWAY_WITNESSED_FIELDS },
11
12
  ];
@@ -16,6 +17,13 @@ function buildParties(hasDecisionContext) {
16
17
  scope: ["decisionContextDigest"],
17
18
  });
18
19
  }
20
+ if (hasAiInvocation) {
21
+ parties.push({
22
+ party: "client",
23
+ role: "asserter",
24
+ scope: ["aiInvocation"],
25
+ });
26
+ }
19
27
  return parties;
20
28
  }
21
29
  export function hashRecord(record) {
@@ -29,11 +37,19 @@ export class AuditLog {
29
37
  currentSize = 0;
30
38
  lastHash = "genesis";
31
39
  writeQueue = Promise.resolve();
40
+ recordsSinceCheckpoint = 0;
41
+ lastCheckpointTime = Date.now();
42
+ checkpointSequence = 0;
43
+ totalRecordCount = 0;
44
+ checkpointConfig = null;
32
45
  constructor(path, signer, rotateAfterBytes) {
33
46
  this.path = path;
34
47
  this.signer = signer;
35
48
  this.rotateAfterBytes = rotateAfterBytes;
36
49
  }
50
+ enableCheckpoints(config) {
51
+ this.checkpointConfig = config;
52
+ }
37
53
  async record(method, opts) {
38
54
  return new Promise((resolve, reject) => {
39
55
  this.writeQueue = this.writeQueue.then(async () => {
@@ -48,12 +64,14 @@ export class AuditLog {
48
64
  });
49
65
  }
50
66
  async writeRecord(method, opts) {
67
+ const { aiInvocation, ...rest } = opts;
51
68
  const record = {
52
69
  id: randomUUID(),
53
70
  timestamp: new Date().toISOString(),
54
71
  method,
55
- ...opts,
56
- parties: buildParties(opts.decisionContextDigest != null),
72
+ ...rest,
73
+ ...(aiInvocation ? { aiInvocation } : {}),
74
+ parties: buildParties(opts.decisionContextDigest != null, aiInvocation != null),
57
75
  previousHash: this.lastHash,
58
76
  };
59
77
  record.attestation = await this.signer.sign(record);
@@ -61,54 +79,312 @@ export class AuditLog {
61
79
  await appendFile(this.path, line);
62
80
  this.currentSize += Buffer.byteLength(line);
63
81
  this.lastHash = hashRecord(record);
82
+ this.totalRecordCount++;
83
+ this.recordsSinceCheckpoint++;
84
+ if (this.shouldEmitCheckpoint()) {
85
+ await this.writeCheckpoint();
86
+ }
64
87
  if (this.currentSize >= this.rotateAfterBytes) {
65
88
  await this.rotate();
66
89
  }
67
90
  return record;
68
91
  }
92
+ shouldEmitCheckpoint() {
93
+ if (!this.checkpointConfig?.enabled)
94
+ return false;
95
+ const { trigger, intervalRecords, intervalSeconds } = this.checkpointConfig;
96
+ const recordsHit = this.recordsSinceCheckpoint >= intervalRecords;
97
+ const timeHit = (Date.now() - this.lastCheckpointTime) >= intervalSeconds * 1000;
98
+ if (trigger === "records")
99
+ return recordsHit;
100
+ if (trigger === "time")
101
+ return timeHit;
102
+ return recordsHit || timeHit;
103
+ }
104
+ async writeCheckpoint() {
105
+ this.checkpointSequence++;
106
+ const checkpoint = {
107
+ id: `ckpt_${randomUUID()}`,
108
+ type: "checkpoint",
109
+ timestamp: new Date().toISOString(),
110
+ sequence: this.checkpointSequence,
111
+ recordCount: this.totalRecordCount,
112
+ previousHash: this.lastHash,
113
+ parties: [{ party: "gateway", role: "witness", scope: ["sequence", "recordCount", "previousHash"] }],
114
+ };
115
+ checkpoint.attestation = await this.signer.sign(checkpoint);
116
+ const line = JSON.stringify(checkpoint) + "\n";
117
+ await appendFile(this.path, line);
118
+ this.currentSize += Buffer.byteLength(line);
119
+ this.lastHash = hashRecord(checkpoint);
120
+ this.recordsSinceCheckpoint = 0;
121
+ this.lastCheckpointTime = Date.now();
122
+ return checkpoint;
123
+ }
124
+ async emitCheckpoint() {
125
+ return new Promise((resolve, reject) => {
126
+ this.writeQueue = this.writeQueue.then(async () => {
127
+ try {
128
+ const result = await this.writeCheckpoint();
129
+ resolve(result);
130
+ }
131
+ catch (err) {
132
+ reject(err);
133
+ }
134
+ });
135
+ });
136
+ }
137
+ getLastHash() {
138
+ return this.lastHash;
139
+ }
140
+ getCheckpointSequence() {
141
+ return this.checkpointSequence;
142
+ }
143
+ getRecordCount() {
144
+ return this.totalRecordCount;
145
+ }
69
146
  async rotate() {
70
147
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
71
148
  const rotatedPath = this.path.replace(/\.jsonl$/, `-${ts}.jsonl`);
72
149
  try {
73
150
  await rename(this.path, rotatedPath);
74
151
  this.currentSize = 0;
75
- this.lastHash = "genesis";
152
+ // Chain-global: lastHash, sequence, recordCount survive rotation.
153
+ // The first record in the new file chains to the last hash of the
154
+ // previous file. Resetting to "genesis" would allow truncation-via-rotation.
155
+ await this.persistState();
76
156
  }
77
157
  catch { }
78
158
  }
79
- async init() {
159
+ rotationBoundaryHash = "genesis";
160
+ async persistState() {
161
+ const statePath = this.path.replace(/\.jsonl$/, ".state.json");
162
+ const tmpPath = statePath + ".tmp";
163
+ const state = {
164
+ lastHash: this.lastHash,
165
+ rotationBoundaryHash: this.lastHash,
166
+ checkpointSequence: this.checkpointSequence,
167
+ totalRecordCount: this.totalRecordCount,
168
+ };
169
+ await fsWriteFile(tmpPath, JSON.stringify(state));
170
+ await rename(tmpPath, statePath);
171
+ }
172
+ async persistChainState() {
173
+ const statePath = this.path.replace(/\.jsonl$/, ".state.json");
174
+ const tmpPath = statePath + ".tmp";
175
+ const state = {
176
+ lastHash: this.lastHash,
177
+ rotationBoundaryHash: this.rotationBoundaryHash,
178
+ checkpointSequence: this.checkpointSequence,
179
+ totalRecordCount: this.totalRecordCount,
180
+ };
181
+ await fsWriteFile(tmpPath, JSON.stringify(state));
182
+ await rename(tmpPath, statePath);
183
+ }
184
+ async recoverState() {
185
+ const statePath = this.path.replace(/\.jsonl$/, ".state.json");
186
+ try {
187
+ const { readFile } = await import("node:fs/promises");
188
+ const raw = await readFile(statePath, "utf-8");
189
+ const state = JSON.parse(raw);
190
+ if (typeof state.lastHash !== "string" || typeof state.checkpointSequence !== "number" ||
191
+ typeof state.rotationBoundaryHash !== "string") {
192
+ return "corrupt";
193
+ }
194
+ this.lastHash = state.lastHash;
195
+ this.rotationBoundaryHash = state.rotationBoundaryHash;
196
+ this.checkpointSequence = state.checkpointSequence ?? 0;
197
+ this.totalRecordCount = state.totalRecordCount ?? 0;
198
+ return "found";
199
+ }
200
+ catch (err) {
201
+ const code = err?.code;
202
+ if (code === "ENOENT")
203
+ return "not_found";
204
+ return "corrupt";
205
+ }
206
+ }
207
+ async init(opts) {
208
+ const stateResult = await this.recoverState();
209
+ let logExists = false;
80
210
  let s;
81
211
  try {
82
212
  s = await stat(this.path);
213
+ logExists = true;
83
214
  }
84
215
  catch {
216
+ logExists = false;
217
+ }
218
+ // Three-way startup:
219
+ // (a) No state file, no log → genuine first run
220
+ if (stateResult === "not_found" && !logExists) {
221
+ this.currentSize = 0;
222
+ return;
223
+ }
224
+ // (c) State file corrupt or exists but unparseable → refuse unless forced
225
+ if (stateResult === "corrupt") {
226
+ if (opts?.forceNewChain) {
227
+ await this.emitChainBreak("state_file_corrupt");
228
+ return;
229
+ }
230
+ throw new Error("[audit-log] state file corrupt or inconsistent. " +
231
+ "Use --force-new-chain to start a new chain (emits a signed chain_break record).");
232
+ }
233
+ // (b) State file present and parseable → base+delta resume
234
+ if (!logExists) {
85
235
  this.currentSize = 0;
86
236
  return;
87
237
  }
88
238
  this.currentSize = s.size;
89
239
  if (s.size > 0) {
90
- const tailSize = Math.min(s.size, 8192);
240
+ const boundaryHash = stateResult === "found" ? this.rotationBoundaryHash : undefined;
91
241
  const fh = await open(this.path, "r");
92
242
  try {
243
+ let headBuf = Buffer.alloc(0);
244
+ let offset = 0;
245
+ const chunkSize = 4096;
246
+ const maxFirstLine = 1024 * 1024;
247
+ let firstLine = null;
248
+ while (offset < s.size) {
249
+ if (headBuf.length >= maxFirstLine) {
250
+ if (opts?.forceNewChain) {
251
+ await this.emitChainBreak("log_first_record_oversize");
252
+ return;
253
+ }
254
+ throw new Error("[audit-log] first record exceeds 1MB cap (no newline found within limit). " +
255
+ "Use --force-new-chain to start a new chain.");
256
+ }
257
+ const readSize = Math.min(chunkSize, s.size - offset);
258
+ const chunk = Buffer.alloc(readSize);
259
+ await fh.read(chunk, 0, readSize, offset);
260
+ headBuf = Buffer.concat([headBuf, chunk]);
261
+ const text = headBuf.toString("utf-8");
262
+ const nlIdx = text.indexOf("\n");
263
+ if (nlIdx !== -1) {
264
+ firstLine = text.slice(0, nlIdx);
265
+ break;
266
+ }
267
+ offset += readSize;
268
+ }
269
+ if (firstLine === null) {
270
+ const text = headBuf.toString("utf-8").trim();
271
+ if (text.length === 0) {
272
+ if (opts?.forceNewChain) {
273
+ await this.emitChainBreak("log_empty_no_newline");
274
+ return;
275
+ }
276
+ throw new Error("[audit-log] log file exists but contains no parseable content. " +
277
+ "Use --force-new-chain to start a new chain.");
278
+ }
279
+ firstLine = text;
280
+ }
281
+ // Parse first record — if it doesn't parse, the log is corrupt
282
+ let firstRecordPrevHash;
283
+ let firstRecordIsBreak = false;
284
+ try {
285
+ const firstRecord = JSON.parse(firstLine);
286
+ if (firstRecord.type === "chain_break") {
287
+ firstRecordIsBreak = true;
288
+ firstRecordPrevHash = firstRecord.priorHead;
289
+ }
290
+ else {
291
+ firstRecordPrevHash = firstRecord.previousHash;
292
+ }
293
+ }
294
+ catch {
295
+ if (opts?.forceNewChain) {
296
+ await this.emitChainBreak("log_first_record_corrupt");
297
+ return;
298
+ }
299
+ throw new Error("[audit-log] first record in log is corrupt (unparseable JSON). " +
300
+ "Use --force-new-chain to start a new chain.");
301
+ }
302
+ // Read tail: recover chain head and checkpoint state
303
+ const tailSize = Math.min(s.size, 8192);
93
304
  const buf = Buffer.alloc(tailSize);
94
305
  await fh.read(buf, 0, tailSize, s.size - tailSize);
95
306
  const tail = buf.toString("utf-8");
96
307
  const lines = tail.trimEnd().split("\n");
308
+ let foundLast = false;
309
+ let recordCountFromTail = 0;
310
+ let tailMaxSequence = 0;
97
311
  for (let i = lines.length - 1; i >= 0; i--) {
98
312
  try {
99
- const record = JSON.parse(lines[i]);
100
- this.lastHash = hashRecord(record);
101
- return;
313
+ const parsed = JSON.parse(lines[i]);
314
+ recordCountFromTail++;
315
+ if (!foundLast) {
316
+ this.lastHash = hashRecord(parsed);
317
+ foundLast = true;
318
+ }
319
+ if (isCheckpoint(parsed)) {
320
+ if (parsed.sequence > tailMaxSequence) {
321
+ tailMaxSequence = parsed.sequence;
322
+ }
323
+ }
102
324
  }
103
325
  catch {
104
326
  process.stderr.write(`[audit-log] warning: corrupt record in tail, skipping\n`);
105
327
  }
106
328
  }
329
+ if (tailMaxSequence > this.checkpointSequence) {
330
+ this.checkpointSequence = tailMaxSequence;
331
+ }
332
+ if (boundaryHash !== undefined && firstRecordPrevHash !== undefined &&
333
+ firstRecordPrevHash !== boundaryHash) {
334
+ if (opts?.forceNewChain) {
335
+ await this.emitChainBreak("state_log_inconsistent");
336
+ return;
337
+ }
338
+ throw new Error("[audit-log] state file inconsistent with log: first record does not " +
339
+ "chain from rotationBoundaryHash. Use --force-new-chain to start a new chain.");
340
+ }
341
+ if (stateResult === "not_found") {
342
+ this.totalRecordCount = recordCountFromTail;
343
+ }
107
344
  }
108
345
  finally {
109
346
  await fh.close();
110
347
  }
111
348
  }
112
349
  }
350
+ async emitChainBreak(reason) {
351
+ const record = {
352
+ id: `break_${randomUUID()}`,
353
+ type: "chain_break",
354
+ timestamp: new Date().toISOString(),
355
+ reason,
356
+ priorHead: this.lastHash !== "genesis" ? this.lastHash : undefined,
357
+ priorSequence: this.checkpointSequence > 0 ? this.checkpointSequence : undefined,
358
+ priorRecordCount: this.totalRecordCount > 0 ? this.totalRecordCount : undefined,
359
+ };
360
+ record.attestation = await this.signer.sign(record);
361
+ const line = JSON.stringify(record) + "\n";
362
+ await appendFile(this.path, line);
363
+ this.currentSize += Buffer.byteLength(line);
364
+ // Reset chain state — this is a new chain.
365
+ // rotationBoundaryHash is NOT updated: it tracks the file boundary,
366
+ // not the chain boundary. The linkage check compares the first record
367
+ // of a file against rotationBoundaryHash, so mid-file breaks must not
368
+ // overwrite it.
369
+ this.lastHash = hashRecord(record);
370
+ this.checkpointSequence = 0;
371
+ this.totalRecordCount = 0;
372
+ this.recordsSinceCheckpoint = 0;
373
+ await this.persistChainState();
374
+ return record;
375
+ }
376
+ async forceNewChain(reason) {
377
+ return new Promise((resolve, reject) => {
378
+ this.writeQueue = this.writeQueue.then(async () => {
379
+ try {
380
+ const result = await this.emitChainBreak(reason);
381
+ resolve(result);
382
+ }
383
+ catch (err) {
384
+ reject(err);
385
+ }
386
+ });
387
+ });
388
+ }
113
389
  }
114
390
  //# sourceMappingURL=audit-log.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit-log.js","sourceRoot":"","sources":["../../src/attestation/audit-log.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audit-log.js","sourceRoot":"","sources":["../../src/attestation/audit-log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,YAAY,EAAgB,MAAM,aAAa,CAAC;AAGzD,MAAM,wBAAwB,GAAG;IAC/B,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW;IACpD,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW;IAC7D,cAAc;CACf,CAAC;AAEF,SAAS,YAAY,CAAC,kBAA2B,EAAE,eAAwB;IACzE,MAAM,OAAO,GAAuB;QAClC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,wBAAwB,EAAE;KACvE,CAAC;IACF,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,eAAe;YACtB,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,CAAC,uBAAuB,CAAC;SACjC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,CAAC,cAAc,CAAC;SACxB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyD;IAClF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AASD,MAAM,OAAO,QAAQ;IAWT;IACA;IACA;IAZF,WAAW,GAAG,CAAC,CAAC;IAChB,QAAQ,GAAW,SAAS,CAAC;IAC7B,UAAU,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAC9C,sBAAsB,GAAG,CAAC,CAAC;IAC3B,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,kBAAkB,GAAG,CAAC,CAAC;IACvB,gBAAgB,GAAG,CAAC,CAAC;IACrB,gBAAgB,GAA4B,IAAI,CAAC;IAEzD,YACU,IAAY,EACZ,MAAc,EACd,gBAAwB;QAFxB,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QACd,qBAAgB,GAAhB,gBAAgB,CAAQ;IAC/B,CAAC;IAEJ,iBAAiB,CAAC,MAAwB;QACxC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,MAAM,CACV,MAAc,EACd,IAUC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBAChD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBACpD,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,WAAW,CACvB,MAAc,EACd,IAUC;QAED,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACvC,MAAM,MAAM,GAAgB;YAC1B,EAAE,EAAE,UAAU,EAAE;YAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM;YACN,GAAG,IAAI;YACP,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,qBAAqB,IAAI,IAAI,EAAE,YAAY,IAAI,IAAI,CAAC;YAC/E,YAAY,EAAE,IAAI,CAAC,QAAQ;SAC5B,CAAC;QAEF,MAAM,CAAC,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;QAE3C,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAE9B,IAAI,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAChC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/B,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC9C,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,oBAAoB;QAC1B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO;YAAE,OAAO,KAAK,CAAC;QAClD,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC5E,MAAM,UAAU,GAAG,IAAI,CAAC,sBAAsB,IAAI,eAAe,CAAC;QAClE,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,eAAe,GAAG,IAAI,CAAC;QAEjF,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,UAAU,CAAC;QAC7C,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO,OAAO,CAAC;QACvC,OAAO,UAAU,IAAI,OAAO,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAqB;YACnC,EAAE,EAAE,QAAQ,UAAU,EAAE,EAAE;YAC1B,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,QAAQ,EAAE,IAAI,CAAC,kBAAkB;YACjC,WAAW,EAAE,IAAI,CAAC,gBAAgB;YAClC,YAAY,EAAE,IAAI,CAAC,QAAQ;YAC3B,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC;SACrG,CAAC;QAEF,UAAU,CAAC,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;QAE/C,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAErC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBAChD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC5C,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,qBAAqB;QACnB,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,MAAM;QAClB,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YACrC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,kEAAkE;YAClE,kEAAkE;YAClE,6EAA6E;YAC7E,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAEO,oBAAoB,GAAW,SAAS,CAAC;IAEzC,KAAK,CAAC,YAAY;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;QACnC,MAAM,KAAK,GAAG;YACZ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,oBAAoB,EAAE,IAAI,CAAC,QAAQ;YACnC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;SACxC,CAAC;QACF,MAAM,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;QACnC,MAAM,KAAK,GAAG;YACZ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;YAC/C,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;SACxC,CAAC;QACF,MAAM,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAC/D,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;YACtD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,kBAAkB,KAAK,QAAQ;gBAClF,OAAO,KAAK,CAAC,oBAAoB,KAAK,QAAQ,EAAE,CAAC;gBACnD,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC/B,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,CAAC;YACvD,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,IAAI,CAAC,CAAC;YACxD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,IAAI,CAAC,CAAC;YACpD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,IAAI,GAAI,GAA6B,EAAE,IAAI,CAAC;YAClD,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,WAAW,CAAC;YAC1C,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAkC;QAC3C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAE9C,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,CAAC;QACN,IAAI,CAAC;YACH,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;QAED,qBAAqB;QACrB,gDAAgD;QAChD,IAAI,WAAW,KAAK,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC;YAC9C,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,IAAI,EAAE,aAAa,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,MAAM,IAAI,KAAK,CACb,kDAAkD;gBAClD,iFAAiF,CAClF,CAAC;QACJ,CAAC;QAED,2DAA2D;QAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,CAAE,CAAC,IAAI,CAAC;QAE3B,IAAI,CAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAChB,MAAM,YAAY,GAAG,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC;YACrF,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACtC,IAAI,CAAC;gBACH,IAAI,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC9B,IAAI,MAAM,GAAG,CAAC,CAAC;gBACf,MAAM,SAAS,GAAG,IAAI,CAAC;gBACvB,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;gBACjC,IAAI,SAAS,GAAkB,IAAI,CAAC;gBACpC,OAAO,MAAM,GAAG,CAAE,CAAC,IAAI,EAAE,CAAC;oBACxB,IAAI,OAAO,CAAC,MAAM,IAAI,YAAY,EAAE,CAAC;wBACnC,IAAI,IAAI,EAAE,aAAa,EAAE,CAAC;4BACxB,MAAM,IAAI,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC;4BACvD,OAAO;wBACT,CAAC;wBACD,MAAM,IAAI,KAAK,CACb,4EAA4E;4BAC5E,6CAA6C,CAC9C,CAAC;oBACJ,CAAC;oBACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAE,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;oBACvD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBACrC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;oBAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBACjC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;wBACjB,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;wBACjC,MAAM;oBACR,CAAC;oBACD,MAAM,IAAI,QAAQ,CAAC;gBACrB,CAAC;gBACD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;oBACvB,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACtB,IAAI,IAAI,EAAE,aAAa,EAAE,CAAC;4BACxB,MAAM,IAAI,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC;4BAClD,OAAO;wBACT,CAAC;wBACD,MAAM,IAAI,KAAK,CACb,iEAAiE;4BACjE,6CAA6C,CAC9C,CAAC;oBACJ,CAAC;oBACD,SAAS,GAAG,IAAI,CAAC;gBACnB,CAAC;gBAED,+DAA+D;gBAC/D,IAAI,mBAAuC,CAAC;gBAC5C,IAAI,kBAAkB,GAAG,KAAK,CAAC;gBAC/B,IAAI,CAAC;oBACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;oBAC1C,IAAI,WAAW,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;wBACvC,kBAAkB,GAAG,IAAI,CAAC;wBAC1B,mBAAmB,GAAG,WAAW,CAAC,SAAS,CAAC;oBAC9C,CAAC;yBAAM,CAAC;wBACN,mBAAmB,GAAG,WAAW,CAAC,YAAY,CAAC;oBACjD,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,IAAI,IAAI,EAAE,aAAa,EAAE,CAAC;wBACxB,MAAM,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC,CAAC;wBACtD,OAAO;oBACT,CAAC;oBACD,MAAM,IAAI,KAAK,CACb,iEAAiE;wBACjE,6CAA6C,CAC9C,CAAC;gBACJ,CAAC;gBAED,qDAAqD;gBACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACzC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACnC,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAE,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;gBACpD,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACnC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACzC,IAAI,SAAS,GAAG,KAAK,CAAC;gBACtB,IAAI,mBAAmB,GAAG,CAAC,CAAC;gBAC5B,IAAI,eAAe,GAAG,CAAC,CAAC;gBAExB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3C,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;wBACpC,mBAAmB,EAAE,CAAC;wBAEtB,IAAI,CAAC,SAAS,EAAE,CAAC;4BACf,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;4BACnC,SAAS,GAAG,IAAI,CAAC;wBACnB,CAAC;wBAED,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;4BACzB,IAAI,MAAM,CAAC,QAAQ,GAAG,eAAe,EAAE,CAAC;gCACtC,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC;4BACpC,CAAC;wBACH,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,yDAAyD,CAC1D,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAED,IAAI,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBAC9C,IAAI,CAAC,kBAAkB,GAAG,eAAe,CAAC;gBAC5C,CAAC;gBAED,IAAI,YAAY,KAAK,SAAS,IAAI,mBAAmB,KAAK,SAAS;oBAC/D,mBAAmB,KAAK,YAAY,EAAE,CAAC;oBACzC,IAAI,IAAI,EAAE,aAAa,EAAE,CAAC;wBACxB,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;wBACpD,OAAO;oBACT,CAAC;oBACD,MAAM,IAAI,KAAK,CACb,sEAAsE;wBACtE,8EAA8E,CAC/E,CAAC;gBACJ,CAAC;gBAED,IAAI,WAAW,KAAK,WAAW,EAAE,CAAC;oBAChC,IAAI,CAAC,gBAAgB,GAAG,mBAAmB,CAAC;gBAC9C,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,MAAc;QACzC,MAAM,MAAM,GAAqB;YAC/B,EAAE,EAAE,SAAS,UAAU,EAAE,EAAE;YAC3B,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM;YACN,SAAS,EAAE,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YAClE,aAAa,EAAE,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS;YAChF,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;SAChF,CAAC;QAEF,MAAM,CAAC,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;QAE3C,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAE5C,2CAA2C;QAC3C,oEAAoE;QACpE,sEAAsE;QACtE,sEAAsE;QACtE,gBAAgB;QAChB,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;QAEhC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAc;QAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBAChD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;oBACjD,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=checkpoint.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.test.d.ts","sourceRoot":"","sources":["../../src/attestation/checkpoint.test.ts"],"names":[],"mappings":""}