@gotgenes/pi-permission-system 3.8.0 → 3.10.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/CHANGELOG.md +37 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/defaults.ts +60 -0
- package/src/handlers/lifecycle.ts +1 -1
- package/src/handlers/tool-call.ts +16 -12
- package/src/index.ts +1 -4
- package/src/normalize.ts +70 -0
- package/src/permission-manager.ts +127 -254
- package/src/rule.ts +7 -23
- package/src/runtime.ts +3 -3
- package/src/session-rules.ts +54 -0
- package/src/types.ts +13 -18
- package/tests/defaults.test.ts +105 -0
- package/tests/handlers/before-agent-start.test.ts +4 -5
- package/tests/handlers/input.test.ts +3 -4
- package/tests/handlers/lifecycle.test.ts +7 -8
- package/tests/handlers/tool-call.test.ts +27 -19
- package/tests/normalize.test.ts +121 -0
- package/tests/permission-system.test.ts +11 -39
- package/tests/rule.test.ts +24 -42
- package/tests/runtime.test.ts +5 -4
- package/tests/session-rules.test.ts +225 -0
- package/tests/session-start.test.ts +2 -2
- package/src/bash-filter.ts +0 -51
- package/src/session-approval-cache.ts +0 -81
- package/tests/bash-filter.test.ts +0 -142
- package/tests/session-approval-cache.test.ts +0 -131
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
// Mock node:os so tilde-expansion is deterministic across platforms.
|
|
4
|
-
vi.mock("node:os", () => {
|
|
5
|
-
const homedir = vi.fn(() => "/mock/home");
|
|
6
|
-
return {
|
|
7
|
-
homedir,
|
|
8
|
-
default: { homedir },
|
|
9
|
-
};
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
deriveApprovalPrefix,
|
|
14
|
-
SessionApprovalCache,
|
|
15
|
-
} from "../src/session-approval-cache";
|
|
16
|
-
|
|
17
|
-
describe("SessionApprovalCache", () => {
|
|
18
|
-
describe("approve and has", () => {
|
|
19
|
-
it("returns false when no approvals exist", () => {
|
|
20
|
-
const cache = new SessionApprovalCache();
|
|
21
|
-
expect(cache.has("external_directory", "/some/path")).toBe(false);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("returns true for a path under an approved prefix", () => {
|
|
25
|
-
const cache = new SessionApprovalCache();
|
|
26
|
-
cache.approve("external_directory", "/other/project/src/");
|
|
27
|
-
expect(cache.has("external_directory", "/other/project/src/foo.ts")).toBe(
|
|
28
|
-
true,
|
|
29
|
-
);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("returns true for the exact approved prefix path", () => {
|
|
33
|
-
const cache = new SessionApprovalCache();
|
|
34
|
-
cache.approve("external_directory", "/other/project/src/");
|
|
35
|
-
expect(cache.has("external_directory", "/other/project/src/")).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("returns false for a path outside the approved prefix", () => {
|
|
39
|
-
const cache = new SessionApprovalCache();
|
|
40
|
-
cache.approve("external_directory", "/other/project/src/");
|
|
41
|
-
expect(cache.has("external_directory", "/other/project/lib/foo.ts")).toBe(
|
|
42
|
-
false,
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("returns false for a sibling directory that shares a string prefix", () => {
|
|
47
|
-
const cache = new SessionApprovalCache();
|
|
48
|
-
cache.approve("external_directory", "/other/project/");
|
|
49
|
-
// /other/project-b/ should NOT match /other/project/
|
|
50
|
-
expect(cache.has("external_directory", "/other/project-b/foo.ts")).toBe(
|
|
51
|
-
false,
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("handles multiple approved prefixes for the same surface", () => {
|
|
56
|
-
const cache = new SessionApprovalCache();
|
|
57
|
-
cache.approve("external_directory", "/other/project-a/");
|
|
58
|
-
cache.approve("external_directory", "/other/project-b/");
|
|
59
|
-
expect(cache.has("external_directory", "/other/project-a/foo.ts")).toBe(
|
|
60
|
-
true,
|
|
61
|
-
);
|
|
62
|
-
expect(cache.has("external_directory", "/other/project-b/bar.ts")).toBe(
|
|
63
|
-
true,
|
|
64
|
-
);
|
|
65
|
-
expect(cache.has("external_directory", "/other/project-c/baz.ts")).toBe(
|
|
66
|
-
false,
|
|
67
|
-
);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("does not duplicate identical prefixes", () => {
|
|
71
|
-
const cache = new SessionApprovalCache();
|
|
72
|
-
cache.approve("external_directory", "/other/project/");
|
|
73
|
-
cache.approve("external_directory", "/other/project/");
|
|
74
|
-
// Set semantics — just verify it still works
|
|
75
|
-
expect(cache.has("external_directory", "/other/project/foo.ts")).toBe(
|
|
76
|
-
true,
|
|
77
|
-
);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
describe("surface isolation", () => {
|
|
82
|
-
it("does not match across different surface types", () => {
|
|
83
|
-
const cache = new SessionApprovalCache();
|
|
84
|
-
cache.approve("external_directory", "/other/project/");
|
|
85
|
-
expect(cache.has("some_other_surface", "/other/project/foo.ts")).toBe(
|
|
86
|
-
false,
|
|
87
|
-
);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe("clear", () => {
|
|
92
|
-
it("removes all approvals", () => {
|
|
93
|
-
const cache = new SessionApprovalCache();
|
|
94
|
-
cache.approve("external_directory", "/other/project/");
|
|
95
|
-
cache.approve("some_surface", "/another/path/");
|
|
96
|
-
cache.clear();
|
|
97
|
-
expect(cache.has("external_directory", "/other/project/foo.ts")).toBe(
|
|
98
|
-
false,
|
|
99
|
-
);
|
|
100
|
-
expect(cache.has("some_surface", "/another/path/file")).toBe(false);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe("deriveApprovalPrefix", () => {
|
|
106
|
-
it("returns parent directory with trailing separator for a file path", () => {
|
|
107
|
-
expect(deriveApprovalPrefix("/other/project/src/foo.ts")).toBe(
|
|
108
|
-
"/other/project/src/",
|
|
109
|
-
);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("returns the directory itself with trailing separator for a directory path", () => {
|
|
113
|
-
expect(deriveApprovalPrefix("/other/project/src/")).toBe(
|
|
114
|
-
"/other/project/src/",
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("returns the directory itself when path has no trailing separator", () => {
|
|
119
|
-
// For a path like /other/project/src (directory), dirname gives /other/project
|
|
120
|
-
// but we can't distinguish dir from file without stat. dirname is the safe choice.
|
|
121
|
-
expect(deriveApprovalPrefix("/other/project/src")).toBe("/other/project/");
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("handles root path", () => {
|
|
125
|
-
expect(deriveApprovalPrefix("/")).toBe("/");
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("handles single-level path", () => {
|
|
129
|
-
expect(deriveApprovalPrefix("/foo")).toBe("/");
|
|
130
|
-
});
|
|
131
|
-
});
|