@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.
- package/.github/workflows/ci.yml +37 -0
- package/README.md +31 -3
- package/dist/attestation/audit-log.d.ts +34 -3
- package/dist/attestation/audit-log.d.ts.map +1 -1
- package/dist/attestation/audit-log.js +286 -10
- package/dist/attestation/audit-log.js.map +1 -1
- package/dist/attestation/checkpoint.test.d.ts +2 -0
- package/dist/attestation/checkpoint.test.d.ts.map +1 -0
- package/dist/attestation/checkpoint.test.js +870 -0
- package/dist/attestation/checkpoint.test.js.map +1 -0
- package/dist/attestation/signer.d.ts +24 -9
- package/dist/attestation/signer.d.ts.map +1 -1
- package/dist/attestation/signer.js +145 -11
- package/dist/attestation/signer.js.map +1 -1
- package/dist/attestation/signer.test.js +11 -0
- package/dist/attestation/signer.test.js.map +1 -1
- package/dist/attestation/verify.d.ts +23 -2
- package/dist/attestation/verify.d.ts.map +1 -1
- package/dist/attestation/verify.js +219 -2
- package/dist/attestation/verify.js.map +1 -1
- package/dist/integration.test.js +1 -0
- package/dist/integration.test.js.map +1 -1
- package/dist/proxy/gateway.d.ts +4 -0
- package/dist/proxy/gateway.d.ts.map +1 -1
- package/dist/proxy/gateway.js +4 -1
- package/dist/proxy/gateway.js.map +1 -1
- package/dist/proxy/gateway.test.js +19 -0
- package/dist/proxy/gateway.test.js.map +1 -1
- package/dist/proxy/mcp-server-adapter.d.ts +1 -0
- package/dist/proxy/mcp-server-adapter.d.ts.map +1 -1
- package/dist/proxy/mcp-server-adapter.js +28 -1
- package/dist/proxy/mcp-server-adapter.js.map +1 -1
- package/dist/proxy/mcp-server-adapter.test.js +1 -0
- package/dist/proxy/mcp-server-adapter.test.js.map +1 -1
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -1
- package/dist/wrap/proxy.test.js +2 -2
- package/dist/wrap/proxy.test.js.map +1 -1
- package/docs/BACKLOG.md +33 -0
- package/docs/SECURITY-DESIGN.md +126 -0
- package/docs/v0.4.0-patch-audit.md +115 -0
- package/package.json +1 -1
- package/src/attestation/audit-log.ts +336 -15
- package/src/attestation/checkpoint.test.ts +956 -0
- package/src/attestation/signer.test.ts +14 -0
- package/src/attestation/signer.ts +152 -19
- package/src/attestation/verify.ts +270 -4
- package/src/integration.test.ts +1 -0
- package/src/proxy/gateway.test.ts +18 -0
- package/src/proxy/gateway.ts +4 -0
- package/src/proxy/mcp-server-adapter.test.ts +1 -0
- package/src/proxy/mcp-server-adapter.ts +26 -0
- package/src/types.ts +48 -0
- package/src/wrap/proxy.test.ts +2 -2
- package/test/vectors/aps-action-ref-v1-vectors.json +351 -0
- package/test/vectors/aps-action-ref-v1.mjs +145 -0
- package/test/vectors/canonicalization.json +182 -0
- package/test/vectors/checkpoint.json +450 -0
- package/test/vectors/verify-checkpoint.mjs +344 -0
- package/test/vectors/verify-checkpoint.py +358 -0
- package/test/vectors/verify.mjs +74 -1
- 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/
|
|
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/
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
...
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
100
|
-
|
|
101
|
-
|
|
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":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.test.d.ts","sourceRoot":"","sources":["../../src/attestation/checkpoint.test.ts"],"names":[],"mappings":""}
|