@catp-protocol/cli 0.1.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/dist/audit/logger.d.ts +8 -0
- package/dist/audit/logger.d.ts.map +1 -0
- package/dist/audit/logger.js +56 -0
- package/dist/audit/logger.js.map +1 -0
- package/dist/audit/verifier.d.ts +8 -0
- package/dist/audit/verifier.d.ts.map +1 -0
- package/dist/audit/verifier.js +42 -0
- package/dist/audit/verifier.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +47 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +42 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/log.d.ts +8 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +64 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/validate.d.ts +4 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +17 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/hook/post.d.ts +2 -0
- package/dist/hook/post.d.ts.map +1 -0
- package/dist/hook/post.js +42 -0
- package/dist/hook/post.js.map +1 -0
- package/dist/hook/pre.d.ts +2 -0
- package/dist/hook/pre.d.ts.map +1 -0
- package/dist/hook/pre.js +52 -0
- package/dist/hook/pre.js.map +1 -0
- package/dist/policy/engine.d.ts +8 -0
- package/dist/policy/engine.d.ts.map +1 -0
- package/dist/policy/engine.js +52 -0
- package/dist/policy/engine.js.map +1 -0
- package/dist/policy/loader.d.ts +4 -0
- package/dist/policy/loader.d.ts.map +1 -0
- package/dist/policy/loader.js +69 -0
- package/dist/policy/loader.js.map +1 -0
- package/dist/policy/types.d.ts +30 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +2 -0
- package/dist/policy/types.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AuditEntry, HookInput } from "../policy/types.js";
|
|
2
|
+
export declare function computeCommitment(tool: string, decision: "allow" | "deny", ts: string, prev?: string): string;
|
|
3
|
+
export declare function summarizeInput(input: HookInput): string;
|
|
4
|
+
export declare function auditDir(agentId: string): string;
|
|
5
|
+
export declare function getLastCommitment(agentId: string): string;
|
|
6
|
+
export declare function appendAuditEntry(agentId: string, entry: AuditEntry): void;
|
|
7
|
+
export declare function buildEntry(input: HookInput, decision: "allow" | "deny", ruleMatched: string | null, prevCommitment?: string): AuditEntry;
|
|
8
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAMhE,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,GAAG,MAAM,EAC1B,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,MAAY,GACjB,MAAM,CAOR;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAGvD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAIzE;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,EAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,cAAc,GAAE,MAAY,GAC3B,UAAU,CAUZ"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { appendFileSync, mkdirSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
// Phase 0: SHA-256 commitment placeholder.
|
|
6
|
+
// Chains on fields stored in the log (tool, decision, ts, prev) so the chain
|
|
7
|
+
// is verifiable from the JSONL file alone without replaying tool_input.
|
|
8
|
+
// Phase 1 replaces this with a Poseidon hash over the full action witness via WASM.
|
|
9
|
+
export function computeCommitment(tool, decision, ts, prev = "0") {
|
|
10
|
+
return createHash("sha256")
|
|
11
|
+
.update(tool)
|
|
12
|
+
.update(decision)
|
|
13
|
+
.update(ts)
|
|
14
|
+
.update(prev)
|
|
15
|
+
.digest("hex");
|
|
16
|
+
}
|
|
17
|
+
export function summarizeInput(input) {
|
|
18
|
+
const raw = JSON.stringify(input.tool_input);
|
|
19
|
+
return raw.length > 200 ? raw.slice(0, 200) + "…" : raw;
|
|
20
|
+
}
|
|
21
|
+
export function auditDir(agentId) {
|
|
22
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
23
|
+
return join(homedir(), ".catp", "audit", agentId, date);
|
|
24
|
+
}
|
|
25
|
+
export function getLastCommitment(agentId) {
|
|
26
|
+
const dir = auditDir(agentId);
|
|
27
|
+
const file = join(dir, "actions.jsonl");
|
|
28
|
+
try {
|
|
29
|
+
const content = readFileSync(file, "utf8").trimEnd();
|
|
30
|
+
if (!content)
|
|
31
|
+
return "0";
|
|
32
|
+
const lastLine = content.split("\n").pop() ?? "";
|
|
33
|
+
const entry = JSON.parse(lastLine);
|
|
34
|
+
return entry.commitment;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return "0";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function appendAuditEntry(agentId, entry) {
|
|
41
|
+
const dir = auditDir(agentId);
|
|
42
|
+
mkdirSync(dir, { recursive: true });
|
|
43
|
+
appendFileSync(join(dir, "actions.jsonl"), JSON.stringify(entry) + "\n", "utf8");
|
|
44
|
+
}
|
|
45
|
+
export function buildEntry(input, decision, ruleMatched, prevCommitment = "0") {
|
|
46
|
+
const ts = new Date().toISOString();
|
|
47
|
+
return {
|
|
48
|
+
ts,
|
|
49
|
+
tool: input.tool_name,
|
|
50
|
+
decision,
|
|
51
|
+
rule_matched: ruleMatched,
|
|
52
|
+
commitment: computeCommitment(input.tool_name, decision, ts, prevCommitment),
|
|
53
|
+
input_summary: summarizeInput(input),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/audit/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/audit/verifier.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA6BxE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
import { computeCommitment } from "./logger.js";
|
|
4
|
+
export async function verifyChain(logFile) {
|
|
5
|
+
const lines = await readLines(logFile);
|
|
6
|
+
if (lines.length === 0) {
|
|
7
|
+
return { ok: true, checked: 0, broken_at: null, message: "empty log" };
|
|
8
|
+
}
|
|
9
|
+
let prev = "0";
|
|
10
|
+
for (let i = 0; i < lines.length; i++) {
|
|
11
|
+
let entry;
|
|
12
|
+
try {
|
|
13
|
+
entry = JSON.parse(lines[i]);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return { ok: false, checked: i, broken_at: i, message: `line ${i + 1}: invalid JSON` };
|
|
17
|
+
}
|
|
18
|
+
const decision = entry.decision;
|
|
19
|
+
const expected = computeCommitment(entry.tool, decision, entry.ts, prev);
|
|
20
|
+
if (entry.commitment !== expected) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
checked: i,
|
|
24
|
+
broken_at: i,
|
|
25
|
+
message: `line ${i + 1}: commitment mismatch (chain broken or tampered)`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
prev = entry.commitment;
|
|
29
|
+
}
|
|
30
|
+
return { ok: true, checked: lines.length, broken_at: null, message: "chain intact" };
|
|
31
|
+
}
|
|
32
|
+
async function readLines(file) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const lines = [];
|
|
35
|
+
const rl = createInterface({ input: createReadStream(file), crlfDelay: Infinity });
|
|
36
|
+
rl.on("line", (l) => { if (l.trim())
|
|
37
|
+
lines.push(l); });
|
|
38
|
+
rl.on("close", () => resolve(lines));
|
|
39
|
+
rl.on("error", reject);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../src/audit/verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUhD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe;IAC/C,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACzE,CAAC;IAED,IAAI,IAAI,GAAG,GAAG,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAiB,CAAC;QACtB,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAe,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACzF,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,QAA4B,CAAC;QACpD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAClC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,CAAC;gBACV,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,kDAAkD;aACzE,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC;IAC1B,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;AACvF,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACnF,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACrC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { runPreHook } from "./hook/pre.js";
|
|
4
|
+
import { runPostHook } from "./hook/post.js";
|
|
5
|
+
import { cmdInit } from "./commands/init.js";
|
|
6
|
+
import { cmdValidate } from "./commands/validate.js";
|
|
7
|
+
import { cmdLogShow, cmdLogVerify } from "./commands/log.js";
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name("catp")
|
|
11
|
+
.description("CATP enforcement plugin — policy enforcement and audit for AI agents")
|
|
12
|
+
.version("0.1.0");
|
|
13
|
+
program
|
|
14
|
+
.command("init")
|
|
15
|
+
.description("Scaffold a catp-policy.toml in the current directory")
|
|
16
|
+
.action(cmdInit);
|
|
17
|
+
program
|
|
18
|
+
.command("validate")
|
|
19
|
+
.description("Validate catp-policy.toml syntax")
|
|
20
|
+
.option("-f, --file <path>", "path to policy file (default: auto-discover)")
|
|
21
|
+
.action(cmdValidate);
|
|
22
|
+
const hook = program.command("hook").description("Hook handlers called by agent frameworks");
|
|
23
|
+
hook
|
|
24
|
+
.command("pre")
|
|
25
|
+
.description("PreToolUse handler — reads stdin JSON, allows or blocks")
|
|
26
|
+
.action(() => { runPreHook().catch(() => process.exit(0)); });
|
|
27
|
+
hook
|
|
28
|
+
.command("post")
|
|
29
|
+
.description("PostToolUse handler — reads stdin JSON, records to audit log")
|
|
30
|
+
.action(() => { runPostHook().catch(() => process.exit(0)); });
|
|
31
|
+
const log = program.command("log").description("Audit log commands");
|
|
32
|
+
log
|
|
33
|
+
.command("show")
|
|
34
|
+
.description("Display recent audit log entries")
|
|
35
|
+
.option("-n, --lines <n>", "number of lines to show", "50")
|
|
36
|
+
.option("--agent <id>", "agent id (default: from policy file)")
|
|
37
|
+
.action(cmdLogShow);
|
|
38
|
+
log
|
|
39
|
+
.command("verify")
|
|
40
|
+
.description("Verify commitment chain integrity")
|
|
41
|
+
.option("--agent <id>", "agent id (default: from policy file)")
|
|
42
|
+
.action(cmdLogVerify);
|
|
43
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
44
|
+
process.stderr.write(`catp: ${err.message}\n`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,sEAAsE,CAAC;KACnF,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,OAAO,CAAC,CAAC;AAEnB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,mBAAmB,EAAE,8CAA8C,CAAC;KAC3E,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,0CAA0C,CAAC,CAAC;AAE7F,IAAI;KACD,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhE,IAAI;KACD,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjE,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC;AAErE,GAAG;KACA,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,iBAAiB,EAAE,yBAAyB,EAAE,IAAI,CAAC;KAC1D,MAAM,CAAC,cAAc,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,UAAU,CAAC,CAAC;AAEtB,GAAG;KACA,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,cAAc,EAAE,sCAAsC,CAAC;KAC9D,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAU,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA+BA,wBAAgB,OAAO,IAAI,IAAI,CAa9B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { writeFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const TEMPLATE = `[agent]
|
|
4
|
+
id = "my-agent"
|
|
5
|
+
version = "1"
|
|
6
|
+
|
|
7
|
+
# Rules are evaluated top-to-bottom; first match wins.
|
|
8
|
+
# Omit pattern/path fields to match any invocation of that tool.
|
|
9
|
+
|
|
10
|
+
[[rules]]
|
|
11
|
+
tool = "Bash"
|
|
12
|
+
allow = false
|
|
13
|
+
pattern = ["rm -rf*", "*--force*", "*git push*prod*"]
|
|
14
|
+
reason = "Destructive or production-affecting shell commands are blocked"
|
|
15
|
+
|
|
16
|
+
[[rules]]
|
|
17
|
+
tool = "Bash"
|
|
18
|
+
allow = true
|
|
19
|
+
|
|
20
|
+
[[rules]]
|
|
21
|
+
tool = "Write"
|
|
22
|
+
allow = true
|
|
23
|
+
path_allowlist = ["./src/**", "./tests/**", "./docs/**"]
|
|
24
|
+
|
|
25
|
+
[[rules]]
|
|
26
|
+
tool = "WebFetch"
|
|
27
|
+
allow = false
|
|
28
|
+
reason = "External network calls require explicit approval"
|
|
29
|
+
`;
|
|
30
|
+
export function cmdInit() {
|
|
31
|
+
const dest = join(process.cwd(), "catp-policy.toml");
|
|
32
|
+
if (existsSync(dest)) {
|
|
33
|
+
process.stdout.write("catp-policy.toml already exists — skipping.\n");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
writeFileSync(dest, TEMPLATE, "utf8");
|
|
37
|
+
process.stdout.write("Created catp-policy.toml\n\nNext steps:\n" +
|
|
38
|
+
" 1. Edit catp-policy.toml to match your agent's requirements\n" +
|
|
39
|
+
" 2. Run: catp validate\n" +
|
|
40
|
+
" 3. Add CATP hooks to ~/.claude/settings.json (see README)\n");
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BhB,CAAC;AAEF,MAAM,UAAU,OAAO;IACrB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2CAA2C;QAC3C,iEAAiE;QACjE,2BAA2B;QAC3B,+DAA+D,CAChE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"AAyBA,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAuBxE;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAe1E"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { findPolicyFile, loadPolicy } from "../policy/loader.js";
|
|
5
|
+
import { verifyChain } from "../audit/verifier.js";
|
|
6
|
+
function resolveAgentId(opts) {
|
|
7
|
+
if (opts.agent)
|
|
8
|
+
return opts.agent;
|
|
9
|
+
const policyPath = findPolicyFile();
|
|
10
|
+
if (!policyPath) {
|
|
11
|
+
process.stderr.write("catp: no --agent id and no catp-policy.toml found\n");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
return loadPolicy(policyPath).agent.id;
|
|
15
|
+
}
|
|
16
|
+
function latestLogFile(agentId) {
|
|
17
|
+
const base = join(homedir(), ".catp", "audit", agentId);
|
|
18
|
+
if (!existsSync(base))
|
|
19
|
+
return null;
|
|
20
|
+
const dates = readdirSync(base).sort().reverse();
|
|
21
|
+
if (dates.length === 0)
|
|
22
|
+
return null;
|
|
23
|
+
return join(base, dates[0], "actions.jsonl");
|
|
24
|
+
}
|
|
25
|
+
export function cmdLogShow(opts) {
|
|
26
|
+
const agentId = resolveAgentId(opts);
|
|
27
|
+
const logFile = latestLogFile(agentId);
|
|
28
|
+
if (!logFile || !existsSync(logFile)) {
|
|
29
|
+
process.stdout.write(`No audit log found for agent "${agentId}"\n`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const lines = readFileSync(logFile, "utf8").trim().split("\n").filter(Boolean);
|
|
33
|
+
const n = Math.min(parseInt(opts.lines, 10) || 50, lines.length);
|
|
34
|
+
const recent = lines.slice(-n);
|
|
35
|
+
for (const line of recent) {
|
|
36
|
+
try {
|
|
37
|
+
const e = JSON.parse(line);
|
|
38
|
+
const icon = e.decision === "allow" ? "✓" : "✗";
|
|
39
|
+
const rule = e.rule_matched ? ` [${e.rule_matched}]` : "";
|
|
40
|
+
process.stdout.write(`${icon} ${e.ts} ${e.tool}${rule}\n ${e.input_summary}\n`);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
process.stdout.write(`? ${line}\n`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
process.stdout.write(`\n${recent.length} entries from ${logFile}\n`);
|
|
47
|
+
}
|
|
48
|
+
export async function cmdLogVerify(opts) {
|
|
49
|
+
const agentId = resolveAgentId(opts);
|
|
50
|
+
const logFile = latestLogFile(agentId);
|
|
51
|
+
if (!logFile || !existsSync(logFile)) {
|
|
52
|
+
process.stdout.write(`No audit log found for agent "${agentId}"\n`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const result = await verifyChain(logFile);
|
|
56
|
+
if (result.ok) {
|
|
57
|
+
process.stdout.write(`✓ Chain intact — ${result.checked} entries verified\n`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
process.stderr.write(`✗ Chain broken at entry ${result.broken_at}: ${result.message}\n`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/commands/log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgBzD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { findPolicyFile, loadPolicy } from "../policy/loader.js";
|
|
2
|
+
export function cmdValidate(opts) {
|
|
3
|
+
const policyPath = opts.file ?? findPolicyFile();
|
|
4
|
+
if (!policyPath) {
|
|
5
|
+
process.stderr.write("catp: no catp-policy.toml found in current directory or any parent\n");
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
const policy = loadPolicy(policyPath);
|
|
10
|
+
process.stdout.write(`✓ ${policyPath}\n agent: ${policy.agent.id} v${policy.agent.version}\n rules: ${policy.rules.length}\n`);
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
process.stderr.write(`✗ ${policyPath}\n ${err.message}\n`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjE,MAAM,UAAU,WAAW,CAAC,IAAuB;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,IAAI,cAAc,EAAE,CAAC;IACjD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;QACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,UAAU,cAAc,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,cAAc,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAC3G,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,UAAU,OAAQ,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../src/hook/post.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA6BjD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { findPolicyFile, loadPolicy } from "../policy/loader.js";
|
|
2
|
+
import { buildEntry, appendAuditEntry, getLastCommitment } from "../audit/logger.js";
|
|
3
|
+
export async function runPostHook() {
|
|
4
|
+
const raw = await readStdin();
|
|
5
|
+
let input;
|
|
6
|
+
try {
|
|
7
|
+
input = JSON.parse(raw);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
const policyPath = findPolicyFile();
|
|
13
|
+
if (!policyPath)
|
|
14
|
+
process.exit(0);
|
|
15
|
+
let policy;
|
|
16
|
+
try {
|
|
17
|
+
policy = loadPolicy(policyPath);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
// PostToolUse always records allow — the action already executed
|
|
23
|
+
const prev = getLastCommitment(policy.agent.id);
|
|
24
|
+
const entry = buildEntry(input, "allow", null, prev);
|
|
25
|
+
try {
|
|
26
|
+
appendAuditEntry(policy.agent.id, entry);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Audit log failure must not block the agent
|
|
30
|
+
}
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
async function readStdin() {
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
let data = "";
|
|
36
|
+
process.stdin.setEncoding("utf8");
|
|
37
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
38
|
+
process.stdin.on("end", () => resolve(data));
|
|
39
|
+
process.stdin.on("error", () => resolve(""));
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=post.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post.js","sourceRoot":"","sources":["../../src/hook/post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGrF,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;IAC9B,IAAI,KAAgB,CAAC;IACrB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,IAAI,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEjC,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,iEAAiE;IACjE,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,6CAA6C;IAC/C,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre.d.ts","sourceRoot":"","sources":["../../src/hook/pre.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA2ChD"}
|
package/dist/hook/pre.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { findPolicyFile, loadPolicy } from "../policy/loader.js";
|
|
2
|
+
import { evaluate } from "../policy/engine.js";
|
|
3
|
+
import { buildEntry, appendAuditEntry, getLastCommitment } from "../audit/logger.js";
|
|
4
|
+
export async function runPreHook() {
|
|
5
|
+
const raw = await readStdin();
|
|
6
|
+
let input;
|
|
7
|
+
try {
|
|
8
|
+
input = JSON.parse(raw);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
const policyPath = findPolicyFile();
|
|
14
|
+
if (!policyPath) {
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
let policy;
|
|
18
|
+
try {
|
|
19
|
+
policy = loadPolicy(policyPath);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
process.stderr.write(`catp: policy error: ${err.message}\n`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
const decision = evaluate(policy, input);
|
|
26
|
+
const ruleName = decision.rule
|
|
27
|
+
? `${decision.rule.tool}:${decision.rule.allow ? "allow" : "deny"}`
|
|
28
|
+
: null;
|
|
29
|
+
const prev = getLastCommitment(policy.agent.id);
|
|
30
|
+
const entry = buildEntry(input, decision.allow ? "allow" : "deny", ruleName, prev);
|
|
31
|
+
try {
|
|
32
|
+
appendAuditEntry(policy.agent.id, entry);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Audit log failure must not block the agent
|
|
36
|
+
}
|
|
37
|
+
if (!decision.allow) {
|
|
38
|
+
process.stdout.write(JSON.stringify({ decision: "block", reason: decision.reason }) + "\n");
|
|
39
|
+
process.exit(2);
|
|
40
|
+
}
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
async function readStdin() {
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
let data = "";
|
|
46
|
+
process.stdin.setEncoding("utf8");
|
|
47
|
+
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
48
|
+
process.stdin.on("end", () => resolve(data));
|
|
49
|
+
process.stdin.on("error", () => resolve(""));
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=pre.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre.js","sourceRoot":"","sources":["../../src/hook/pre.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CatpPolicy, Rule, HookInput } from "./types.js";
|
|
2
|
+
export interface Decision {
|
|
3
|
+
allow: boolean;
|
|
4
|
+
rule: Rule | null;
|
|
5
|
+
reason: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function evaluate(policy: CatpPolicy, input: HookInput): Decision;
|
|
8
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/policy/engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,CAiBvE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import micromatch from "micromatch";
|
|
2
|
+
export function evaluate(policy, input) {
|
|
3
|
+
const toolRules = policy.rules.filter((r) => r.tool === "*" || r.tool === input.tool_name);
|
|
4
|
+
for (const rule of toolRules) {
|
|
5
|
+
if (matchesRule(rule, input)) {
|
|
6
|
+
return {
|
|
7
|
+
allow: rule.allow,
|
|
8
|
+
rule,
|
|
9
|
+
reason: rule.reason ?? (rule.allow ? "allowed by policy" : "denied by policy"),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
// Default allow if no rule matches
|
|
14
|
+
return { allow: true, rule: null, reason: "no matching rule — default allow" };
|
|
15
|
+
}
|
|
16
|
+
function matchesRule(rule, input) {
|
|
17
|
+
if (rule.pattern && rule.pattern.length > 0) {
|
|
18
|
+
const command = extractCommand(input);
|
|
19
|
+
if (command === null)
|
|
20
|
+
return false;
|
|
21
|
+
return rule.pattern.some((p) => micromatch.isMatch(command, p) || command.includes(p));
|
|
22
|
+
}
|
|
23
|
+
if (rule.path_allowlist || rule.path_denylist) {
|
|
24
|
+
const filePath = extractPath(input);
|
|
25
|
+
if (filePath === null)
|
|
26
|
+
return false;
|
|
27
|
+
if (rule.path_denylist && rule.path_denylist.length > 0) {
|
|
28
|
+
if (micromatch.isMatch(filePath, rule.path_denylist))
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
if (rule.path_allowlist && rule.path_allowlist.length > 0) {
|
|
32
|
+
return !micromatch.isMatch(filePath, rule.path_allowlist);
|
|
33
|
+
}
|
|
34
|
+
// path condition present but file didn't match denylist and no allowlist — no match
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
// No pattern/path conditions — matches any invocation of this tool
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
function extractCommand(input) {
|
|
41
|
+
const cmd = input.tool_input["command"];
|
|
42
|
+
return typeof cmd === "string" ? cmd : null;
|
|
43
|
+
}
|
|
44
|
+
function extractPath(input) {
|
|
45
|
+
for (const key of ["file_path", "path", "filePath"]) {
|
|
46
|
+
const v = input.tool_input[key];
|
|
47
|
+
if (typeof v === "string")
|
|
48
|
+
return v;
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/policy/engine.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AASpC,MAAM,UAAU,QAAQ,CAAC,MAAkB,EAAE,KAAgB;IAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,SAAS,CACpD,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,IAAI;gBACJ,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB,CAAC;aAC/E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;AACjF,CAAC;AAED,SAAS,WAAW,CAAC,IAAU,EAAE,KAAgB;IAC/C,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAEpC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxD,IAAI,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC;gBAAE,OAAO,IAAI,CAAC;QACpE,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC5D,CAAC;QACD,oFAAoF;QACpF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mEAAmE;IACnE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,KAAgB;IACtC,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACxC,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED,SAAS,WAAW,CAAC,KAAgB;IACnC,KAAK,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QACpD,MAAM,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/policy/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAS9E;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAIzD"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parse } from "smol-toml";
|
|
4
|
+
const POLICY_FILENAME = "catp-policy.toml";
|
|
5
|
+
export function findPolicyFile(startDir = process.cwd()) {
|
|
6
|
+
let dir = startDir;
|
|
7
|
+
while (true) {
|
|
8
|
+
const candidate = join(dir, POLICY_FILENAME);
|
|
9
|
+
if (existsSync(candidate))
|
|
10
|
+
return candidate;
|
|
11
|
+
const parent = join(dir, "..");
|
|
12
|
+
if (parent === dir)
|
|
13
|
+
return null;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function loadPolicy(policyPath) {
|
|
18
|
+
const raw = readFileSync(policyPath, "utf8");
|
|
19
|
+
const parsed = parse(raw);
|
|
20
|
+
return validate(parsed, policyPath);
|
|
21
|
+
}
|
|
22
|
+
function validate(raw, path) {
|
|
23
|
+
if (typeof raw !== "object" || raw === null) {
|
|
24
|
+
throw new Error(`${path}: policy must be a TOML object`);
|
|
25
|
+
}
|
|
26
|
+
const obj = raw;
|
|
27
|
+
if (!obj.agent || typeof obj.agent !== "object") {
|
|
28
|
+
throw new Error(`${path}: missing [agent] section`);
|
|
29
|
+
}
|
|
30
|
+
const agent = obj.agent;
|
|
31
|
+
if (typeof agent.id !== "string" || !agent.id) {
|
|
32
|
+
throw new Error(`${path}: agent.id must be a non-empty string`);
|
|
33
|
+
}
|
|
34
|
+
if (typeof agent.version !== "string" || !agent.version) {
|
|
35
|
+
throw new Error(`${path}: agent.version must be a non-empty string`);
|
|
36
|
+
}
|
|
37
|
+
if (!Array.isArray(obj.rules)) {
|
|
38
|
+
throw new Error(`${path}: [[rules]] must be an array`);
|
|
39
|
+
}
|
|
40
|
+
const rules = obj.rules.map((r, i) => {
|
|
41
|
+
if (typeof r !== "object" || r === null) {
|
|
42
|
+
throw new Error(`${path}: rules[${i}] must be an object`);
|
|
43
|
+
}
|
|
44
|
+
const rule = r;
|
|
45
|
+
if (typeof rule.tool !== "string" || !rule.tool) {
|
|
46
|
+
throw new Error(`${path}: rules[${i}].tool must be a non-empty string`);
|
|
47
|
+
}
|
|
48
|
+
if (typeof rule.allow !== "boolean") {
|
|
49
|
+
throw new Error(`${path}: rules[${i}].allow must be a boolean`);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
tool: rule.tool,
|
|
53
|
+
allow: rule.allow,
|
|
54
|
+
pattern: toStringArray(rule.pattern),
|
|
55
|
+
path_allowlist: toStringArray(rule.path_allowlist),
|
|
56
|
+
path_denylist: toStringArray(rule.path_denylist),
|
|
57
|
+
reason: typeof rule.reason === "string" ? rule.reason : undefined,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
return { agent: { id: agent.id, version: agent.version }, rules };
|
|
61
|
+
}
|
|
62
|
+
function toStringArray(v) {
|
|
63
|
+
if (v === undefined || v === null)
|
|
64
|
+
return undefined;
|
|
65
|
+
if (!Array.isArray(v))
|
|
66
|
+
return undefined;
|
|
67
|
+
return v.filter((x) => typeof x === "string");
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/policy/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface AgentMeta {
|
|
2
|
+
id: string;
|
|
3
|
+
version: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Rule {
|
|
6
|
+
tool: string;
|
|
7
|
+
allow: boolean;
|
|
8
|
+
pattern?: string[];
|
|
9
|
+
path_allowlist?: string[];
|
|
10
|
+
path_denylist?: string[];
|
|
11
|
+
reason?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CatpPolicy {
|
|
14
|
+
agent: AgentMeta;
|
|
15
|
+
rules: Rule[];
|
|
16
|
+
}
|
|
17
|
+
export interface HookInput {
|
|
18
|
+
session_id?: string;
|
|
19
|
+
tool_name: string;
|
|
20
|
+
tool_input: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
export interface AuditEntry {
|
|
23
|
+
ts: string;
|
|
24
|
+
tool: string;
|
|
25
|
+
decision: "allow" | "deny";
|
|
26
|
+
rule_matched: string | null;
|
|
27
|
+
commitment: string;
|
|
28
|
+
input_summary: string;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/policy/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@catp-protocol/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Cryptographic Agent Trust Protocol — local enforcement plugin for Claude Code with TOML policy and tamper-evident audit log",
|
|
5
|
+
"keywords": ["claude-code", "ai-agents", "policy", "audit", "hooks", "trust", "zk"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/lfzkoala/catp#readme",
|
|
8
|
+
"bugs": "https://github.com/lfzkoala/catp/issues",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/lfzkoala/catp.git"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"bin": {
|
|
15
|
+
"catp": "./dist/cli.js"
|
|
16
|
+
},
|
|
17
|
+
"files": ["dist"],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=20"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
25
|
+
"test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage --ci"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"commander": "^12.0.0",
|
|
29
|
+
"micromatch": "^4.0.5",
|
|
30
|
+
"smol-toml": "^1.3.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/micromatch": "^4.0.6",
|
|
34
|
+
"@types/node": "^20.0.0",
|
|
35
|
+
"jest": "^29.0.0",
|
|
36
|
+
"ts-jest": "^29.0.0",
|
|
37
|
+
"typescript": "^5.4.0"
|
|
38
|
+
}
|
|
39
|
+
}
|