|
1 | 1 | import { describe, expect, it } from "bun:test"; |
2 | | -import { mkdtempSync, mkdirSync, rmSync } from "node:fs"; |
| 2 | +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; |
3 | 3 | import { tmpdir } from "node:os"; |
4 | 4 | import { join } from "node:path"; |
5 | 5 | import { evaluateToolGuard } from "./index"; |
6 | 6 |
|
7 | | -describe("pi-command-policy-bridge jj behavior", () => { |
8 | | - it("blocks git add in jj repos with remediation", () => { |
9 | | - const dir = mkdtempSync(join(tmpdir(), "pi-jj-test-")); |
10 | | - mkdirSync(join(dir, ".jj")); |
11 | | - const decision = evaluateToolGuard({ |
12 | | - toolName: "bash", |
13 | | - input: { command: "git add ." }, |
14 | | - workingDirectory: dir, |
15 | | - }); |
16 | | - rmSync(dir, { recursive: true, force: true }); |
17 | | - expect(decision.kind).toBe("deny"); |
18 | | - if (decision.kind !== "deny") return; |
19 | | - expect(decision.reason).toContain("jj snapshots automatically"); |
| 7 | +describe("pi-command-policy-bridge", () => { |
| 8 | + it("does not block git commands", () => { |
| 9 | + const decision = evaluateToolGuard({ |
| 10 | + toolName: "bash", |
| 11 | + input: { command: "git add ." }, |
20 | 12 | }); |
| 13 | + expect(decision.kind).toBe("allow"); |
| 14 | + }); |
21 | 15 |
|
22 | | - it("does not block git add outside jj repos", () => { |
23 | | - const decision = evaluateToolGuard({ |
24 | | - toolName: "bash", |
25 | | - input: { command: "git add ." }, |
26 | | - workingDirectory: "/tmp", |
27 | | - }); |
28 | | - expect(decision.kind).toBe("allow"); |
| 16 | + it("allows jj_vcs align_push without prompting", () => { |
| 17 | + const decision = evaluateToolGuard({ |
| 18 | + toolName: "jj_vcs", |
| 19 | + input: { action: "align_push" }, |
| 20 | + workingDirectory: process.cwd(), |
29 | 21 | }); |
| 22 | + expect(decision.kind).toBe("allow"); |
| 23 | + }); |
30 | 24 |
|
31 | | - it("requires approval for jj_vcs align_push", () => { |
32 | | - const decision = evaluateToolGuard({ |
33 | | - toolName: "jj_vcs", |
34 | | - input: { action: "align_push" }, |
35 | | - workingDirectory: process.cwd(), |
36 | | - }); |
37 | | - expect(decision.kind).toBe("ask"); |
38 | | - }); |
| 25 | + it("allows commands with no readable bash policy", () => { |
| 26 | + const dir = mkdtempSync(join(tmpdir(), "pi-missing-policy-test-")); |
| 27 | + const previous = process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR; |
| 28 | + process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR = dir; |
39 | 29 |
|
40 | | - it("allows jj_vcs status", () => { |
41 | | - const decision = evaluateToolGuard({ |
42 | | - toolName: "jj_vcs", |
43 | | - input: { action: "status" }, |
44 | | - workingDirectory: process.cwd(), |
45 | | - }); |
46 | | - expect(decision.kind).toBe("allow"); |
47 | | - }); |
| 30 | + try { |
| 31 | + const decision = evaluateToolGuard({ |
| 32 | + toolName: "bash", |
| 33 | + input: { command: "echo safe" }, |
| 34 | + }); |
| 35 | + expect(decision.kind).toBe("allow"); |
| 36 | + } finally { |
| 37 | + if (previous === undefined) { |
| 38 | + delete process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR; |
| 39 | + } else { |
| 40 | + process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR = previous; |
| 41 | + } |
| 42 | + rmSync(dir, { recursive: true, force: true }); |
| 43 | + } |
| 44 | + }); |
| 45 | + |
| 46 | + it("allows bash policy ask rules without prompting", () => { |
| 47 | + const dir = mkdtempSync(join(tmpdir(), "pi-policy-test-")); |
| 48 | + const previous = process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR; |
| 49 | + process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR = dir; |
| 50 | + writeFileSync(join(dir, "pi-permissions.jsonc"), '{ "bash": { "*": "ask" } }'); |
| 51 | + |
| 52 | + try { |
| 53 | + const decision = evaluateToolGuard({ |
| 54 | + toolName: "bash", |
| 55 | + input: { command: "echo safe" }, |
| 56 | + }); |
| 57 | + expect(decision.kind).toBe("allow"); |
| 58 | + } finally { |
| 59 | + if (previous === undefined) { |
| 60 | + delete process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR; |
| 61 | + } else { |
| 62 | + process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR = previous; |
| 63 | + } |
| 64 | + rmSync(dir, { recursive: true, force: true }); |
| 65 | + } |
| 66 | + }); |
| 67 | + |
| 68 | + it("denies explicit bash policy deny rules", () => { |
| 69 | + const dir = mkdtempSync(join(tmpdir(), "pi-deny-policy-test-")); |
| 70 | + const previous = process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR; |
| 71 | + process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR = dir; |
| 72 | + writeFileSync( |
| 73 | + join(dir, "pi-permissions.jsonc"), |
| 74 | + '{ "bash": { "*": "allow", "*brew install*": "deny" } }' |
| 75 | + ); |
| 76 | + |
| 77 | + try { |
| 78 | + const decision = evaluateToolGuard({ |
| 79 | + toolName: "bash", |
| 80 | + input: { command: "brew install foo" }, |
| 81 | + }); |
| 82 | + expect(decision.kind).toBe("deny"); |
| 83 | + } finally { |
| 84 | + if (previous === undefined) { |
| 85 | + delete process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR; |
| 86 | + } else { |
| 87 | + process.env.PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR = previous; |
| 88 | + } |
| 89 | + rmSync(dir, { recursive: true, force: true }); |
| 90 | + } |
| 91 | + }); |
48 | 92 | }); |
0 commit comments