Parent directory

static-permissions.test.ts

2701 bytes
 1import { expect, test } from "bun:test";
 2import { mkdtempSync, rmSync } from "node:fs";
 3import { tmpdir } from "node:os";
 4import { join } from "node:path";
 5import { checkStaticPermission } from "../../src/pi/static-permissions";
 6import type { PiPolicyEngineConfig } from "../../src/pi/config";
 7
 8test("explicit deny wins before external path handling", async () => {
 9  const cwd = mkdtempSync(join(tmpdir(), "policy-engine-cwd-"));
10  try {
11    const decision = await checkStaticPermission(
12      "write",
13      { path: join(tmpdir(), "policy-engine-external-file") },
14      cwd,
15      { reviewer: { kind: "none" }, tools: { write: "deny" }, externalDirectories: [] },
16    );
17    expect(decision).toMatchObject({ decision: "deny" });
18  } finally {
19    rmSync(cwd, { recursive: true, force: true });
20  }
21});
22
23test("allows unconfigured tools and checks configured tools", async () => {
24  const config: PiPolicyEngineConfig = { reviewer: { kind: "none" }, tools: {}, externalDirectories: [] };
25  await expect(checkStaticPermission("my_extension_tool", {}, process.cwd(), config)).resolves.toMatchObject({
26    decision: "allow",
27  });
28  await expect(
29    checkStaticPermission("my_extension_tool", {}, process.cwd(), {
30      ...config,
31      tools: { my_extension_tool: "check" },
32    }),
33  ).resolves.toBeUndefined();
34});
35
36test("asks before changing a policy engine configuration", async () => {
37  const cwd = mkdtempSync(join(tmpdir(), "policy-engine-cwd-"));
38  try {
39    const config: PiPolicyEngineConfig = {
40      reviewer: { kind: "none" },
41      tools: { edit: "allow", write: "allow" },
42      externalDirectories: [],
43    };
44    for (const toolType of ["edit", "write"]) {
45      await expect(
46        checkStaticPermission(toolType, { path: ".pi/policy-engine.json" }, cwd, config),
47      ).resolves.toMatchObject({
48        decision: "ask",
49      });
50    }
51  } finally {
52    rmSync(cwd, { recursive: true, force: true });
53  }
54});
55
56test("allows external paths only inside configured directories", async () => {
57  const root = mkdtempSync(join(tmpdir(), "policy-engine-external-"));
58  const cwd = join(root, "cwd");
59  const external = join(root, "shared");
60  const nested = join(external, "nested", "file.txt");
61  const sibling = join(root, "shared-sibling", "file.txt");
62  try {
63    const config = { reviewer: { kind: "none" } as const, tools: {}, externalDirectories: [external] };
64    await expect(checkStaticPermission("read", { path: nested }, cwd, config)).resolves.toMatchObject({
65      decision: "allow",
66    });
67    await expect(checkStaticPermission("read", { path: sibling }, cwd, config)).resolves.toBeUndefined();
68  } finally {
69    rmSync(root, { recursive: true, force: true });
70  }
71});