@catp-protocol/cli 0.7.2 → 0.7.4
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/dist/audit/durable.d.ts +68 -0
- package/dist/audit/durable.d.ts.map +1 -0
- package/dist/audit/durable.js +214 -0
- package/dist/audit/durable.js.map +1 -0
- package/dist/audit/logger.d.ts +51 -5
- package/dist/audit/logger.d.ts.map +1 -1
- package/dist/audit/logger.js +99 -20
- package/dist/audit/logger.js.map +1 -1
- package/dist/audit/paths.d.ts +11 -0
- package/dist/audit/paths.d.ts.map +1 -1
- package/dist/audit/paths.js +19 -0
- package/dist/audit/paths.js.map +1 -1
- package/dist/audit/verifier.d.ts +9 -0
- package/dist/audit/verifier.d.ts.map +1 -1
- package/dist/audit/verifier.js +70 -18
- package/dist/audit/verifier.js.map +1 -1
- package/dist/cli.js +11 -11
- package/dist/cli.js.map +1 -1
- package/dist/commands/authorization.js +6 -0
- package/dist/commands/authorization.js.map +1 -1
- package/dist/commands/log.d.ts +41 -1
- package/dist/commands/log.d.ts.map +1 -1
- package/dist/commands/log.js +82 -22
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/receipt.d.ts +71 -1
- package/dist/commands/receipt.d.ts.map +1 -1
- package/dist/commands/receipt.js +344 -72
- package/dist/commands/receipt.js.map +1 -1
- package/dist/enforcement/core.d.ts +10 -4
- package/dist/enforcement/core.d.ts.map +1 -1
- package/dist/enforcement/core.js +40 -4
- package/dist/enforcement/core.js.map +1 -1
- package/dist/evidence/canonical.d.ts +22 -0
- package/dist/evidence/canonical.d.ts.map +1 -0
- package/dist/evidence/canonical.js +45 -0
- package/dist/evidence/canonical.js.map +1 -0
- package/dist/evidence/commitments.d.ts +46 -0
- package/dist/evidence/commitments.d.ts.map +1 -0
- package/dist/evidence/commitments.js +52 -0
- package/dist/evidence/commitments.js.map +1 -0
- package/dist/hook/post.d.ts +6 -0
- package/dist/hook/post.d.ts.map +1 -1
- package/dist/hook/post.js +1 -1
- package/dist/hook/post.js.map +1 -1
- package/dist/hook/pre.d.ts +6 -0
- package/dist/hook/pre.d.ts.map +1 -1
- package/dist/hook/pre.js +4 -1
- package/dist/hook/pre.js.map +1 -1
- package/dist/policy/engine.js +19 -1
- package/dist/policy/engine.js.map +1 -1
- package/dist/policy/types.d.ts +25 -2
- package/dist/policy/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrow filesystem seam used by the durable primitives. Production code binds
|
|
3
|
+
* this to node:fs; unit tests inject a fake to assert operation order and to
|
|
4
|
+
* inject failures without touching a real disk.
|
|
5
|
+
*/
|
|
6
|
+
export interface DurableFs {
|
|
7
|
+
existsSync(path: string): boolean;
|
|
8
|
+
mkdirSync(path: string, opts: {
|
|
9
|
+
recursive: boolean;
|
|
10
|
+
mode: number;
|
|
11
|
+
}): void;
|
|
12
|
+
openSync(path: string, flags: string, mode: number): number;
|
|
13
|
+
writeSync(fd: number, buffer: Uint8Array, offset: number, length: number, position: number | null): number;
|
|
14
|
+
fsyncSync(fd: number): void;
|
|
15
|
+
closeSync(fd: number): void;
|
|
16
|
+
readFileSync(path: string): Buffer;
|
|
17
|
+
renameSync(oldPath: string, newPath: string): void;
|
|
18
|
+
unlinkSync(path: string): void;
|
|
19
|
+
}
|
|
20
|
+
/** Production binding of {@link DurableFs} to node:fs. */
|
|
21
|
+
export declare const nodeFs: DurableFs;
|
|
22
|
+
/**
|
|
23
|
+
* Create `path` (and any missing ancestors) and make the new directory entries
|
|
24
|
+
* durable. Missing components are collected before creation, created with
|
|
25
|
+
* 0o700, then fsynced from the deepest component upward followed by the
|
|
26
|
+
* deepest pre-existing ancestor. If `path` already exists this is a no-op.
|
|
27
|
+
*/
|
|
28
|
+
export declare function ensureDirectoryDurable(path: string, fs?: DurableFs): void;
|
|
29
|
+
/**
|
|
30
|
+
* Durably append one line to a JSONL-style log file. Sequence: create parent
|
|
31
|
+
* directories, open append/create with 0o600, write the complete UTF-8 line
|
|
32
|
+
* plus exactly one newline, fsync the file, close it, and fsync the parent
|
|
33
|
+
* directory when the file was newly created.
|
|
34
|
+
*/
|
|
35
|
+
export declare function durableAppendLine(path: string, line: string, fs?: DurableFs): void;
|
|
36
|
+
/**
|
|
37
|
+
* Durably create an empty file (and its parent directories) if it does not
|
|
38
|
+
* already exist: open append/create with 0o600, fsync the new file, close it,
|
|
39
|
+
* then fsync the parent directory. An existing file is left untouched. This is
|
|
40
|
+
* used to materialize the audit log so a lock manager that resolves the target
|
|
41
|
+
* realpath never bypasses the new-file durability path.
|
|
42
|
+
*/
|
|
43
|
+
export declare function durableCreateEmptyFile(path: string, fs?: DurableFs): void;
|
|
44
|
+
/**
|
|
45
|
+
* Durably write content-addressed `bytes` to `path` via a same-directory temp
|
|
46
|
+
* file: create parents, write the temp with 0o600, fsync it, close, atomically
|
|
47
|
+
* rename onto the target, then fsync the parent directory.
|
|
48
|
+
*
|
|
49
|
+
* If the target already exists its bytes are compared: identical bytes are an
|
|
50
|
+
* idempotent success, differing bytes are reported as corruption. Descriptors
|
|
51
|
+
* are closed and the temp file removed on any failure while preserving the
|
|
52
|
+
* original exception.
|
|
53
|
+
*/
|
|
54
|
+
export declare function durableWriteContentAddressed(path: string, bytes: Uint8Array, fs?: DurableFs): void;
|
|
55
|
+
/**
|
|
56
|
+
* Storage seam threaded through the audit logger and hook options. It exists
|
|
57
|
+
* solely so tests can inject failures; CLI execution always uses
|
|
58
|
+
* {@link nodeAuditStorage}.
|
|
59
|
+
*/
|
|
60
|
+
export interface AuditStorage {
|
|
61
|
+
ensureDirectoryDurable(path: string): void;
|
|
62
|
+
createEmptyFile(path: string): void;
|
|
63
|
+
appendLine(path: string, line: string): void;
|
|
64
|
+
writeContentAddressed(path: string, bytes: Uint8Array): void;
|
|
65
|
+
}
|
|
66
|
+
/** Production {@link AuditStorage} backed by the fsync durable primitives. */
|
|
67
|
+
export declare const nodeAuditStorage: AuditStorage;
|
|
68
|
+
//# sourceMappingURL=durable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable.d.ts","sourceRoot":"","sources":["../../src/audit/durable.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5D,SAAS,CACP,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAAC;IACV,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,0DAA0D;AAC1D,eAAO,MAAM,MAAM,EAAE,SAqBpB,CAAC;AA+BF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAE,SAAkB,GAAG,IAAI,CAsBjF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAE,SAAkB,GAAG,IAAI,CA2B1F;AASD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAE,SAAkB,GAAG,IAAI,CAqBjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,UAAU,EACjB,EAAE,GAAE,SAAkB,GACrB,IAAI,CAuCN;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC9D;AAED,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,YAK9B,CAAC"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeSync, } from "node:fs";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
+
/** Production binding of {@link DurableFs} to node:fs. */
|
|
4
|
+
export const nodeFs = {
|
|
5
|
+
existsSync: (p) => existsSync(p),
|
|
6
|
+
mkdirSync: (p, opts) => {
|
|
7
|
+
mkdirSync(p, opts);
|
|
8
|
+
},
|
|
9
|
+
openSync: (p, flags, mode) => openSync(p, flags, mode),
|
|
10
|
+
writeSync: (fd, buffer, offset, length, position) => writeSync(fd, buffer, offset, length, position),
|
|
11
|
+
fsyncSync: (fd) => {
|
|
12
|
+
fsyncSync(fd);
|
|
13
|
+
},
|
|
14
|
+
closeSync: (fd) => {
|
|
15
|
+
closeSync(fd);
|
|
16
|
+
},
|
|
17
|
+
readFileSync: (p) => readFileSync(p),
|
|
18
|
+
renameSync: (o, n) => {
|
|
19
|
+
renameSync(o, n);
|
|
20
|
+
},
|
|
21
|
+
unlinkSync: (p) => {
|
|
22
|
+
unlinkSync(p);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const FILE_MODE = 0o600;
|
|
26
|
+
const DIR_MODE = 0o700;
|
|
27
|
+
/**
|
|
28
|
+
* Write every byte of `buffer`, looping until the whole buffer is consumed. A
|
|
29
|
+
* single writeSync call is not guaranteed to consume the entire buffer, so the
|
|
30
|
+
* returned count is advanced explicitly.
|
|
31
|
+
*/
|
|
32
|
+
function writeFull(fs, fd, buffer) {
|
|
33
|
+
let offset = 0;
|
|
34
|
+
while (offset < buffer.byteLength) {
|
|
35
|
+
const written = fs.writeSync(fd, buffer, offset, buffer.byteLength - offset, null);
|
|
36
|
+
if (written <= 0) {
|
|
37
|
+
throw new Error("durable write failed to make progress");
|
|
38
|
+
}
|
|
39
|
+
offset += written;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** fsync a directory so a newly created directory entry becomes durable. */
|
|
43
|
+
function fsyncDirectory(fs, dir) {
|
|
44
|
+
const fd = fs.openSync(dir, "r", DIR_MODE);
|
|
45
|
+
try {
|
|
46
|
+
fs.fsyncSync(fd);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
fs.closeSync(fd);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create `path` (and any missing ancestors) and make the new directory entries
|
|
54
|
+
* durable. Missing components are collected before creation, created with
|
|
55
|
+
* 0o700, then fsynced from the deepest component upward followed by the
|
|
56
|
+
* deepest pre-existing ancestor. If `path` already exists this is a no-op.
|
|
57
|
+
*/
|
|
58
|
+
export function ensureDirectoryDurable(path, fs = nodeFs) {
|
|
59
|
+
const target = resolve(path);
|
|
60
|
+
const missing = [];
|
|
61
|
+
let probe = target;
|
|
62
|
+
while (!fs.existsSync(probe)) {
|
|
63
|
+
missing.unshift(probe);
|
|
64
|
+
const parent = dirname(probe);
|
|
65
|
+
if (parent === probe)
|
|
66
|
+
break; // reached the filesystem root
|
|
67
|
+
probe = parent;
|
|
68
|
+
}
|
|
69
|
+
if (missing.length === 0)
|
|
70
|
+
return; // nothing created, nothing to flush
|
|
71
|
+
fs.mkdirSync(target, { recursive: true, mode: DIR_MODE });
|
|
72
|
+
for (let i = missing.length - 1; i >= 0; i--) {
|
|
73
|
+
fsyncDirectory(fs, missing[i]);
|
|
74
|
+
}
|
|
75
|
+
// Flush the pre-existing parent that now holds the shallowest new entry.
|
|
76
|
+
// Skip when the walk terminated at the filesystem root, in which case probe
|
|
77
|
+
// is itself one of the newly created components and was already flushed.
|
|
78
|
+
if (!missing.includes(probe)) {
|
|
79
|
+
fsyncDirectory(fs, probe);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Durably append one line to a JSONL-style log file. Sequence: create parent
|
|
84
|
+
* directories, open append/create with 0o600, write the complete UTF-8 line
|
|
85
|
+
* plus exactly one newline, fsync the file, close it, and fsync the parent
|
|
86
|
+
* directory when the file was newly created.
|
|
87
|
+
*/
|
|
88
|
+
export function durableAppendLine(path, line, fs = nodeFs) {
|
|
89
|
+
const dir = dirname(path);
|
|
90
|
+
ensureDirectoryDurable(dir, fs);
|
|
91
|
+
const existed = fs.existsSync(path);
|
|
92
|
+
const fd = fs.openSync(path, "a", FILE_MODE);
|
|
93
|
+
let closed = false;
|
|
94
|
+
try {
|
|
95
|
+
writeFull(fs, fd, Buffer.from(line + "\n", "utf8"));
|
|
96
|
+
fs.fsyncSync(fd);
|
|
97
|
+
fs.closeSync(fd);
|
|
98
|
+
closed = true;
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
// Close the descriptor without letting a secondary close error (POSIX can
|
|
102
|
+
// report a pending EIO on close after a failed fsync) mask the original
|
|
103
|
+
// write/fsync failure the caller must observe to fail closed.
|
|
104
|
+
if (!closed) {
|
|
105
|
+
try {
|
|
106
|
+
fs.closeSync(fd);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// preserve the original exception
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
throw err;
|
|
113
|
+
}
|
|
114
|
+
if (!existed) {
|
|
115
|
+
fsyncDirectory(fs, dir);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
let tempCounter = 0;
|
|
119
|
+
function uniqueTempPath(dir, base) {
|
|
120
|
+
tempCounter = (tempCounter + 1) % Number.MAX_SAFE_INTEGER;
|
|
121
|
+
return join(dir, `.${base}.${process.pid}.${Date.now()}.${tempCounter}.tmp`);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Durably create an empty file (and its parent directories) if it does not
|
|
125
|
+
* already exist: open append/create with 0o600, fsync the new file, close it,
|
|
126
|
+
* then fsync the parent directory. An existing file is left untouched. This is
|
|
127
|
+
* used to materialize the audit log so a lock manager that resolves the target
|
|
128
|
+
* realpath never bypasses the new-file durability path.
|
|
129
|
+
*/
|
|
130
|
+
export function durableCreateEmptyFile(path, fs = nodeFs) {
|
|
131
|
+
const dir = dirname(path);
|
|
132
|
+
ensureDirectoryDurable(dir, fs);
|
|
133
|
+
if (fs.existsSync(path))
|
|
134
|
+
return;
|
|
135
|
+
const fd = fs.openSync(path, "a", FILE_MODE);
|
|
136
|
+
let closed = false;
|
|
137
|
+
try {
|
|
138
|
+
fs.fsyncSync(fd);
|
|
139
|
+
fs.closeSync(fd);
|
|
140
|
+
closed = true;
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (!closed) {
|
|
144
|
+
try {
|
|
145
|
+
fs.closeSync(fd);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// preserve the original exception
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
fsyncDirectory(fs, dir);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Durably write content-addressed `bytes` to `path` via a same-directory temp
|
|
157
|
+
* file: create parents, write the temp with 0o600, fsync it, close, atomically
|
|
158
|
+
* rename onto the target, then fsync the parent directory.
|
|
159
|
+
*
|
|
160
|
+
* If the target already exists its bytes are compared: identical bytes are an
|
|
161
|
+
* idempotent success, differing bytes are reported as corruption. Descriptors
|
|
162
|
+
* are closed and the temp file removed on any failure while preserving the
|
|
163
|
+
* original exception.
|
|
164
|
+
*/
|
|
165
|
+
export function durableWriteContentAddressed(path, bytes, fs = nodeFs) {
|
|
166
|
+
const dir = dirname(path);
|
|
167
|
+
ensureDirectoryDurable(dir, fs);
|
|
168
|
+
if (fs.existsSync(path)) {
|
|
169
|
+
const existing = fs.readFileSync(path);
|
|
170
|
+
if (Buffer.compare(Buffer.from(bytes), existing) === 0)
|
|
171
|
+
return;
|
|
172
|
+
throw new Error(`content-addressed file already exists with different bytes: ${path}`);
|
|
173
|
+
}
|
|
174
|
+
const temp = uniqueTempPath(dir, basename(path));
|
|
175
|
+
const fd = fs.openSync(temp, "w", FILE_MODE);
|
|
176
|
+
let closed = false;
|
|
177
|
+
let renamed = false;
|
|
178
|
+
try {
|
|
179
|
+
writeFull(fs, fd, bytes);
|
|
180
|
+
fs.fsyncSync(fd);
|
|
181
|
+
fs.closeSync(fd);
|
|
182
|
+
closed = true;
|
|
183
|
+
fs.renameSync(temp, path);
|
|
184
|
+
renamed = true;
|
|
185
|
+
fsyncDirectory(fs, dir);
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
if (!closed) {
|
|
189
|
+
try {
|
|
190
|
+
fs.closeSync(fd);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// ignore close failure; preserve the original error
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (!renamed) {
|
|
197
|
+
try {
|
|
198
|
+
fs.unlinkSync(temp);
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
// best-effort temp cleanup; preserve the original error
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/** Production {@link AuditStorage} backed by the fsync durable primitives. */
|
|
208
|
+
export const nodeAuditStorage = {
|
|
209
|
+
ensureDirectoryDurable: (path) => ensureDirectoryDurable(path),
|
|
210
|
+
createEmptyFile: (path) => durableCreateEmptyFile(path),
|
|
211
|
+
appendLine: (path, line) => durableAppendLine(path, line),
|
|
212
|
+
writeContentAddressed: (path, bytes) => durableWriteContentAddressed(path, bytes),
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=durable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable.js","sourceRoot":"","sources":["../../src/audit/durable.ts"],"names":[],"mappings":"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"}
|
package/dist/audit/logger.d.ts
CHANGED
|
@@ -1,14 +1,60 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type CanonicalToolActionV1 } from "../evidence/commitments.js";
|
|
2
|
+
import { type AuditStorage } from "./durable.js";
|
|
3
|
+
import type { AuditEntry, AuditEntryV4, AuthorizationAction } from "../policy/types.js";
|
|
2
4
|
import type { ToolAction } from "../runtime/types.js";
|
|
3
5
|
import type { RuntimePhase } from "../runtime/types.js";
|
|
4
6
|
export declare function computeCommitment(tool: string, decision: "allow" | "deny", ts: string, prev?: string, ruleMatched?: string | null, inputSummary?: string, authorization?: AuthorizationAction, commitmentVersion?: 1 | 2 | 3, phase?: RuntimePhase): string;
|
|
5
7
|
export declare function summarizeInput(input: ToolAction): string;
|
|
8
|
+
export interface AuditEntryV4Fields {
|
|
9
|
+
phase: RuntimePhase;
|
|
10
|
+
tool: string;
|
|
11
|
+
decision: "allow" | "deny";
|
|
12
|
+
ts: string;
|
|
13
|
+
ruleMatched: string | null;
|
|
14
|
+
reason: string;
|
|
15
|
+
inputSummary: string;
|
|
16
|
+
policyCommitment: string;
|
|
17
|
+
actionCommitment: string;
|
|
18
|
+
authorization?: AuthorizationAction;
|
|
19
|
+
prev: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Version-4 entry commitment. Covers every security-relevant field with a
|
|
23
|
+
* domain separator: prev_commitment, phase, tool, decision, ts, rule, reason,
|
|
24
|
+
* the enforcement-time policy commitment, and the complete-action commitment.
|
|
25
|
+
* `inputSummary` is chained for display tamper-evidence only; the authoritative
|
|
26
|
+
* action binding is `actionCommitment`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeCommitmentV4(fields: AuditEntryV4Fields): string;
|
|
6
29
|
export declare function auditDir(agentId: string): string;
|
|
7
30
|
export declare function getLastCommitment(agentId: string): string;
|
|
8
|
-
export declare function appendAuditEntry(agentId: string, entry: AuditEntry): void;
|
|
31
|
+
export declare function appendAuditEntry(agentId: string, entry: AuditEntry, storage?: AuditStorage): void;
|
|
32
|
+
/**
|
|
33
|
+
* Append a v4 entry produced by `build`, persisting the complete canonical
|
|
34
|
+
* action as a content-addressed sidecar BEFORE the entry that references it.
|
|
35
|
+
*
|
|
36
|
+
* The sidecar write and the entry append both happen while holding the same
|
|
37
|
+
* per-log lock used to choose `prev_commitment`, so the ordering is atomic with
|
|
38
|
+
* respect to concurrent appends. A crash may leave an unreferenced sidecar, but
|
|
39
|
+
* never a committed entry whose action evidence was not flushed first. Any
|
|
40
|
+
* storage/fsync error propagates so the caller (pre-hook) can fail closed.
|
|
41
|
+
*/
|
|
9
42
|
export declare function appendChainedAuditEntry<T extends {
|
|
10
|
-
auditEntry:
|
|
11
|
-
|
|
12
|
-
|
|
43
|
+
auditEntry: AuditEntryV4;
|
|
44
|
+
action: CanonicalToolActionV1;
|
|
45
|
+
}>(agentId: string, build: (prevCommitment: string) => T, storage?: AuditStorage): T;
|
|
46
|
+
export interface AuditEntryBindings {
|
|
47
|
+
reason: string;
|
|
48
|
+
policyCommitment: string;
|
|
49
|
+
actionCommitment: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a version-4 audit entry that binds the decision to the exact
|
|
53
|
+
* enforcement-time policy commitment and complete-action commitment. The caller
|
|
54
|
+
* (enforcement core) computes both commitments from the normalized policy and
|
|
55
|
+
* canonical action used for the decision; this function never recomputes them
|
|
56
|
+
* from mutable files.
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildEntry(input: ToolAction, decision: "allow" | "deny", ruleMatched: string | null, prevCommitment: string, bindings: AuditEntryBindings): AuditEntryV4;
|
|
13
59
|
export declare function extractAuthorizationAction(input: ToolAction): AuthorizationAction | undefined;
|
|
14
60
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAMA,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACjG,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAexD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,GAAG,MAAM,EAC1B,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,MAAY,EAClB,WAAW,GAAE,MAAM,GAAG,IAAW,EACjC,YAAY,GAAE,MAAW,EACzB,aAAa,CAAC,EAAE,mBAAmB,EACnC,iBAAiB,GAAE,CAAC,GAAG,CAAC,GAAG,CAAK,EAChC,KAAK,CAAC,EAAE,YAAY,GACnB,MAAM,CASR;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGxD;AAQD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAetE;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIzD;AAsCD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,YAA+B,GACvC,IAAI,CAGN;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,CAAC,SAAS;IAAE,UAAU,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAA;CAAE,EAErE,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,CAAC,EACpC,OAAO,GAAE,YAA+B,GACvC,CAAC,CAoBH;AAwCD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,OAAO,GAAG,MAAM,EAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,kBAAkB,GAC3B,YAAY,CAmCd;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,UAAU,GAAG,mBAAmB,GAAG,SAAS,CAsB7F"}
|
package/dist/audit/logger.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { closeSync, existsSync, openSync, readSync, statSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { lockSync } from "proper-lockfile";
|
|
5
|
-
import { auditDirForDate } from "./paths.js";
|
|
5
|
+
import { actionSidecarPath, auditDirForDate } from "./paths.js";
|
|
6
|
+
import { sha256Hex, stableStringify } from "../evidence/canonical.js";
|
|
7
|
+
import { computeActionCommitment } from "../evidence/commitments.js";
|
|
8
|
+
import { nodeAuditStorage } from "./durable.js";
|
|
6
9
|
const AUDIT_LOCK_STALE_MS = 5_000;
|
|
7
10
|
const AUDIT_LOCK_WAIT_MS = 2_000;
|
|
8
11
|
const AUDIT_LOCK_RETRY_MS = 10;
|
|
@@ -29,6 +32,34 @@ export function summarizeInput(input) {
|
|
|
29
32
|
const raw = JSON.stringify(input.toolInput);
|
|
30
33
|
return raw.length > 200 ? raw.slice(0, 200) + "…" : raw;
|
|
31
34
|
}
|
|
35
|
+
// Domain separator for version-4 audit-entry commitments. v4 is a NEW format
|
|
36
|
+
// with no backward-compatibility constraint, so it uses the shared canonical
|
|
37
|
+
// serializer and an explicit domain string. Legacy v1--v3 commitments above are
|
|
38
|
+
// left byte-for-byte unchanged.
|
|
39
|
+
const AUDIT_ENTRY_V4_DOMAIN = "catp:audit-entry:v4\n";
|
|
40
|
+
/**
|
|
41
|
+
* Version-4 entry commitment. Covers every security-relevant field with a
|
|
42
|
+
* domain separator: prev_commitment, phase, tool, decision, ts, rule, reason,
|
|
43
|
+
* the enforcement-time policy commitment, and the complete-action commitment.
|
|
44
|
+
* `inputSummary` is chained for display tamper-evidence only; the authoritative
|
|
45
|
+
* action binding is `actionCommitment`.
|
|
46
|
+
*/
|
|
47
|
+
export function computeCommitmentV4(fields) {
|
|
48
|
+
const payload = {
|
|
49
|
+
phase: fields.phase,
|
|
50
|
+
tool: fields.tool,
|
|
51
|
+
decision: fields.decision,
|
|
52
|
+
ts: fields.ts,
|
|
53
|
+
ruleMatched: fields.ruleMatched,
|
|
54
|
+
reason: fields.reason,
|
|
55
|
+
inputSummary: fields.inputSummary,
|
|
56
|
+
policyCommitment: fields.policyCommitment,
|
|
57
|
+
actionCommitment: fields.actionCommitment,
|
|
58
|
+
authorization: fields.authorization ?? null,
|
|
59
|
+
prev: fields.prev,
|
|
60
|
+
};
|
|
61
|
+
return sha256Hex(AUDIT_ENTRY_V4_DOMAIN + stableStringify(payload));
|
|
62
|
+
}
|
|
32
63
|
export function auditDir(agentId) {
|
|
33
64
|
const date = new Date().toISOString().slice(0, 10);
|
|
34
65
|
return auditDirForDate(agentId, date);
|
|
@@ -75,27 +106,51 @@ function readLastAuditLine(file) {
|
|
|
75
106
|
closeSync(fd);
|
|
76
107
|
}
|
|
77
108
|
}
|
|
78
|
-
export function appendAuditEntry(agentId, entry) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
const file = join(dir, "actions.jsonl");
|
|
82
|
-
withAuditLock(file, () => appendEntryToFile(file, entry));
|
|
109
|
+
export function appendAuditEntry(agentId, entry, storage = nodeAuditStorage) {
|
|
110
|
+
const file = join(auditDir(agentId), "actions.jsonl");
|
|
111
|
+
withAuditLock(file, storage, () => appendEntryToFile(file, entry, storage));
|
|
83
112
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Append a v4 entry produced by `build`, persisting the complete canonical
|
|
115
|
+
* action as a content-addressed sidecar BEFORE the entry that references it.
|
|
116
|
+
*
|
|
117
|
+
* The sidecar write and the entry append both happen while holding the same
|
|
118
|
+
* per-log lock used to choose `prev_commitment`, so the ordering is atomic with
|
|
119
|
+
* respect to concurrent appends. A crash may leave an unreferenced sidecar, but
|
|
120
|
+
* never a committed entry whose action evidence was not flushed first. Any
|
|
121
|
+
* storage/fsync error propagates so the caller (pre-hook) can fail closed.
|
|
122
|
+
*/
|
|
123
|
+
export function appendChainedAuditEntry(agentId, build, storage = nodeAuditStorage) {
|
|
124
|
+
// Compute the date once so the log file and its action sidecars always land
|
|
125
|
+
// in the same daily directory even across a midnight boundary.
|
|
126
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
127
|
+
const dir = auditDirForDate(agentId, date);
|
|
87
128
|
const file = join(dir, "actions.jsonl");
|
|
88
|
-
return withAuditLock(file, () => {
|
|
129
|
+
return withAuditLock(file, storage, () => {
|
|
89
130
|
const result = build(getLastCommitmentFromFile(file));
|
|
90
|
-
|
|
131
|
+
const entry = result.auditEntry;
|
|
132
|
+
// Re-check the binding at the persistence boundary so a mismatched
|
|
133
|
+
// entry/action pair can never be durably recorded.
|
|
134
|
+
if (computeActionCommitment(result.action) !== entry.action_commitment) {
|
|
135
|
+
throw new Error("internal error: action evidence does not match audit entry binding");
|
|
136
|
+
}
|
|
137
|
+
const sidecar = actionSidecarPath(agentId, date, entry.action_commitment);
|
|
138
|
+
storage.writeContentAddressed(sidecar, Buffer.from(stableStringify(result.action), "utf8"));
|
|
139
|
+
appendEntryToFile(file, entry, storage);
|
|
91
140
|
return result;
|
|
92
141
|
});
|
|
93
142
|
}
|
|
94
|
-
|
|
95
|
-
|
|
143
|
+
// `input_summary` is capped for operator readability and is NON-AUTHORITATIVE:
|
|
144
|
+
// the security binding is the content-addressed action sidecar plus the entry's
|
|
145
|
+
// action_commitment, never this display string.
|
|
146
|
+
function appendEntryToFile(file, entry, storage) {
|
|
147
|
+
storage.appendLine(file, JSON.stringify(entry));
|
|
96
148
|
}
|
|
97
|
-
function withAuditLock(file, operation) {
|
|
98
|
-
|
|
149
|
+
function withAuditLock(file, storage, operation) {
|
|
150
|
+
// Durably materialize the log file (fsync new file + parent) before
|
|
151
|
+
// proper-lockfile resolves its realpath, so lock setup cannot bypass the
|
|
152
|
+
// new-file durability path.
|
|
153
|
+
storage.createEmptyFile(file);
|
|
99
154
|
const release = acquireAuditLock(file);
|
|
100
155
|
try {
|
|
101
156
|
return operation();
|
|
@@ -122,18 +177,42 @@ function acquireAuditLock(file) {
|
|
|
122
177
|
}
|
|
123
178
|
}
|
|
124
179
|
}
|
|
125
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Build a version-4 audit entry that binds the decision to the exact
|
|
182
|
+
* enforcement-time policy commitment and complete-action commitment. The caller
|
|
183
|
+
* (enforcement core) computes both commitments from the normalized policy and
|
|
184
|
+
* canonical action used for the decision; this function never recomputes them
|
|
185
|
+
* from mutable files.
|
|
186
|
+
*/
|
|
187
|
+
export function buildEntry(input, decision, ruleMatched, prevCommitment, bindings) {
|
|
126
188
|
const ts = new Date().toISOString();
|
|
127
189
|
const inputSummary = summarizeInput(input);
|
|
128
190
|
const authorization = extractAuthorizationAction(input);
|
|
191
|
+
const phase = input.phase;
|
|
192
|
+
const commitment = computeCommitmentV4({
|
|
193
|
+
phase,
|
|
194
|
+
tool: input.toolName,
|
|
195
|
+
decision,
|
|
196
|
+
ts,
|
|
197
|
+
ruleMatched,
|
|
198
|
+
reason: bindings.reason,
|
|
199
|
+
inputSummary,
|
|
200
|
+
policyCommitment: bindings.policyCommitment,
|
|
201
|
+
actionCommitment: bindings.actionCommitment,
|
|
202
|
+
authorization,
|
|
203
|
+
prev: prevCommitment,
|
|
204
|
+
});
|
|
129
205
|
const entry = {
|
|
130
|
-
commitment_version:
|
|
131
|
-
phase
|
|
206
|
+
commitment_version: 4,
|
|
207
|
+
phase,
|
|
132
208
|
ts,
|
|
133
209
|
tool: input.toolName,
|
|
134
210
|
decision,
|
|
135
211
|
rule_matched: ruleMatched,
|
|
136
|
-
|
|
212
|
+
reason: bindings.reason,
|
|
213
|
+
policy_commitment: bindings.policyCommitment,
|
|
214
|
+
action_commitment: bindings.actionCommitment,
|
|
215
|
+
commitment,
|
|
137
216
|
input_summary: inputSummary,
|
|
138
217
|
};
|
|
139
218
|
if (authorization) {
|
package/dist/audit/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/audit/paths.d.ts
CHANGED
|
@@ -2,4 +2,15 @@ export declare function catpHome(): string;
|
|
|
2
2
|
export declare function validateAgentId(agentId: string): string;
|
|
3
3
|
export declare function auditRoot(agentId: string): string;
|
|
4
4
|
export declare function auditDirForDate(agentId: string, date: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Directory holding the content-addressed canonical action sidecars for a given
|
|
7
|
+
* agent/day: `$CATP_HOME/audit/<agent>/<YYYY-MM-DD>/actions`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function actionsDirForDate(agentId: string, date: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Absolute path of the durable sidecar storing the complete canonical action
|
|
12
|
+
* whose digest is `actionCommitment`. The commitment must be a 64-character
|
|
13
|
+
* lowercase hex digest so it can never escape the actions directory.
|
|
14
|
+
*/
|
|
15
|
+
export declare function actionSidecarPath(agentId: string, date: string, actionCommitment: string): string;
|
|
5
16
|
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/audit/paths.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/audit/paths.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvE;AAID;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAKR"}
|
package/dist/audit/paths.js
CHANGED
|
@@ -15,4 +15,23 @@ export function auditRoot(agentId) {
|
|
|
15
15
|
export function auditDirForDate(agentId, date) {
|
|
16
16
|
return join(auditRoot(agentId), date);
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Directory holding the content-addressed canonical action sidecars for a given
|
|
20
|
+
* agent/day: `$CATP_HOME/audit/<agent>/<YYYY-MM-DD>/actions`.
|
|
21
|
+
*/
|
|
22
|
+
export function actionsDirForDate(agentId, date) {
|
|
23
|
+
return join(auditDirForDate(agentId, date), "actions");
|
|
24
|
+
}
|
|
25
|
+
const ACTION_COMMITMENT_HEX64 = /^[0-9a-f]{64}$/;
|
|
26
|
+
/**
|
|
27
|
+
* Absolute path of the durable sidecar storing the complete canonical action
|
|
28
|
+
* whose digest is `actionCommitment`. The commitment must be a 64-character
|
|
29
|
+
* lowercase hex digest so it can never escape the actions directory.
|
|
30
|
+
*/
|
|
31
|
+
export function actionSidecarPath(agentId, date, actionCommitment) {
|
|
32
|
+
if (!ACTION_COMMITMENT_HEX64.test(actionCommitment)) {
|
|
33
|
+
throw new Error("action commitment must be a 64-character lowercase hex digest");
|
|
34
|
+
}
|
|
35
|
+
return join(actionsDirForDate(agentId, date), `${actionCommitment}.json`);
|
|
36
|
+
}
|
|
18
37
|
//# sourceMappingURL=paths.js.map
|
package/dist/audit/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/audit/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,IAAY;IAC3D,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC"}
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/audit/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,IAAY;IAC3D,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAY;IAC7D,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,IAAY,EACZ,gBAAwB;IAExB,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,GAAG,gBAAgB,OAAO,CAAC,CAAC;AAC5E,CAAC"}
|