@gotgenes/pi-permission-system 10.0.0 → 10.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/CHANGELOG.md +26 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/agent-prep-session.ts +28 -0
- package/src/decision-reporter.ts +41 -0
- package/src/denial-messages.ts +11 -0
- package/src/forwarded-permissions/permission-forwarder.ts +549 -0
- package/src/forwarding-manager.ts +3 -7
- package/src/gate-handler-session.ts +13 -0
- package/src/gate-prompter.ts +14 -0
- package/src/handlers/before-agent-start.ts +2 -3
- package/src/handlers/gates/bash-command.ts +4 -18
- package/src/handlers/gates/bash-external-directory.ts +3 -15
- package/src/handlers/gates/bash-path.ts +3 -16
- package/src/handlers/gates/descriptor.ts +0 -28
- package/src/handlers/gates/path.ts +3 -15
- package/src/handlers/gates/runner.ts +142 -105
- package/src/handlers/gates/skill-input-gate-pipeline.ts +104 -0
- package/src/handlers/gates/skill-input.ts +44 -0
- package/src/handlers/gates/tool-call-gate-pipeline.ts +120 -0
- package/src/handlers/lifecycle.ts +9 -9
- package/src/handlers/permission-gate-handler.ts +34 -238
- package/src/index.ts +49 -69
- package/src/mcp-targets.ts +56 -46
- package/src/permission-prompter.ts +7 -58
- package/src/permission-resolver.ts +17 -0
- package/src/permission-session.ts +77 -9
- package/src/permissions-service.ts +53 -0
- package/src/service-lifecycle.ts +49 -0
- package/src/session-approval-recorder.ts +6 -0
- package/src/session-lifecycle-session.ts +24 -0
- package/src/tool-input-preview.ts +0 -62
- package/src/tool-input-prompt-formatters.ts +63 -0
- package/src/tool-preview-formatter.ts +6 -4
- package/test/decision-reporter.test.ts +112 -0
- package/test/denial-messages.test.ts +62 -0
- package/test/forwarding-manager.test.ts +26 -44
- package/test/handlers/before-agent-start.test.ts +45 -21
- package/test/handlers/external-directory-integration.test.ts +86 -22
- package/test/handlers/external-directory-session-dedup.test.ts +102 -55
- package/test/handlers/gates/bash-command.test.ts +49 -90
- package/test/handlers/gates/bash-external-directory.test.ts +54 -95
- package/test/handlers/gates/bash-path.test.ts +63 -148
- package/test/handlers/gates/path.test.ts +38 -105
- package/test/handlers/gates/runner.test.ts +150 -93
- package/test/handlers/gates/skill-input-gate-pipeline.test.ts +176 -0
- package/test/handlers/gates/skill-input.test.ts +128 -0
- package/test/handlers/gates/tool-call-gate-pipeline.test.ts +180 -0
- package/test/handlers/input.test.ts +1 -2
- package/test/handlers/lifecycle.test.ts +49 -33
- package/test/handlers/tool-call-events.test.ts +1 -1
- package/test/helpers/gate-fixtures.ts +147 -16
- package/test/helpers/handler-fixtures.ts +143 -27
- package/test/mcp-targets.test.ts +55 -0
- package/test/permission-forwarder.test.ts +295 -0
- package/test/permission-forwarding.test.ts +0 -282
- package/test/permission-prompter.test.ts +33 -44
- package/test/permission-session.test.ts +160 -27
- package/test/permissions-service.test.ts +151 -0
- package/test/runtime.test.ts +0 -4
- package/test/service-lifecycle.test.ts +162 -0
- package/test/tool-input-preview.test.ts +0 -111
- package/test/tool-input-prompt-formatters.test.ts +115 -0
- package/src/forwarded-permissions/polling.ts +0 -411
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { describe, expect, it
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type { GateDescriptor } from "#src/handlers/gates/descriptor";
|
|
4
4
|
import { isGateDescriptor } from "#src/handlers/gates/descriptor";
|
|
5
5
|
import { describePathGate } from "#src/handlers/gates/path";
|
|
6
6
|
import type { ToolCallContext } from "#src/handlers/gates/types";
|
|
7
|
-
import type { Rule } from "#src/rule";
|
|
8
|
-
import type { PermissionCheckResult } from "#src/types";
|
|
9
7
|
|
|
10
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
makeGateCheckResult as makeCheckResult,
|
|
10
|
+
makeResolver,
|
|
11
|
+
} from "#test/helpers/gate-fixtures";
|
|
11
12
|
|
|
12
13
|
// ── helpers ────────────────────────────────────────────────────────────────
|
|
13
14
|
|
|
@@ -23,53 +24,36 @@ function makeTcc(overrides: Partial<ToolCallContext> = {}): ToolCallContext {
|
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
type CheckPermissionFn = (
|
|
27
|
-
surface: string,
|
|
28
|
-
input: unknown,
|
|
29
|
-
agentName?: string,
|
|
30
|
-
sessionRules?: Rule[],
|
|
31
|
-
) => PermissionCheckResult;
|
|
32
|
-
|
|
33
27
|
// ── tests ──────────────────────────────────────────────────────────────────
|
|
34
28
|
|
|
35
29
|
describe("describePathGate", () => {
|
|
36
|
-
const getSessionRuleset = vi.fn<() => Rule[]>().mockReturnValue([]);
|
|
37
|
-
|
|
38
30
|
it("returns null for non-path-bearing tools", () => {
|
|
39
|
-
const
|
|
31
|
+
const resolver = makeResolver();
|
|
40
32
|
const result = describePathGate(
|
|
41
33
|
makeTcc({ toolName: "bash", input: { command: "ls" } }),
|
|
42
|
-
|
|
43
|
-
getSessionRuleset,
|
|
34
|
+
resolver,
|
|
44
35
|
);
|
|
45
36
|
expect(result).toBeNull();
|
|
46
|
-
expect(
|
|
37
|
+
expect(resolver.resolve).not.toHaveBeenCalled();
|
|
47
38
|
});
|
|
48
39
|
|
|
49
40
|
it("returns null when tool has no extractable path", () => {
|
|
50
|
-
const
|
|
41
|
+
const resolver = makeResolver();
|
|
51
42
|
const result = describePathGate(
|
|
52
43
|
makeTcc({ toolName: "read", input: {} }),
|
|
53
|
-
|
|
54
|
-
getSessionRuleset,
|
|
44
|
+
resolver,
|
|
55
45
|
);
|
|
56
46
|
expect(result).toBeNull();
|
|
57
47
|
});
|
|
58
48
|
|
|
59
49
|
it("returns null when path check result is allow", () => {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
.mockReturnValue(makeCheckResult({ state: "allow" }));
|
|
63
|
-
const result = describePathGate(
|
|
64
|
-
makeTcc(),
|
|
65
|
-
checkPermission,
|
|
66
|
-
getSessionRuleset,
|
|
67
|
-
);
|
|
50
|
+
const resolver = makeResolver(makeCheckResult({ state: "allow" }));
|
|
51
|
+
const result = describePathGate(makeTcc(), resolver);
|
|
68
52
|
expect(result).toBeNull();
|
|
69
53
|
});
|
|
70
54
|
|
|
71
55
|
it("returns null when matchedPattern is undefined (universal default)", () => {
|
|
72
|
-
const
|
|
56
|
+
const resolver = makeResolver(
|
|
73
57
|
makeCheckResult({
|
|
74
58
|
state: "ask",
|
|
75
59
|
matchedPattern: undefined,
|
|
@@ -77,16 +61,12 @@ describe("describePathGate", () => {
|
|
|
77
61
|
origin: "builtin",
|
|
78
62
|
}),
|
|
79
63
|
);
|
|
80
|
-
const result = describePathGate(
|
|
81
|
-
makeTcc(),
|
|
82
|
-
checkPermission,
|
|
83
|
-
getSessionRuleset,
|
|
84
|
-
);
|
|
64
|
+
const result = describePathGate(makeTcc(), resolver);
|
|
85
65
|
expect(result).toBeNull();
|
|
86
66
|
});
|
|
87
67
|
|
|
88
68
|
it("returns GateDescriptor when matchedPattern is defined (explicit path rule)", () => {
|
|
89
|
-
const
|
|
69
|
+
const resolver = makeResolver(
|
|
90
70
|
makeCheckResult({
|
|
91
71
|
state: "ask",
|
|
92
72
|
matchedPattern: "*.env",
|
|
@@ -94,27 +74,16 @@ describe("describePathGate", () => {
|
|
|
94
74
|
origin: "global",
|
|
95
75
|
}),
|
|
96
76
|
);
|
|
97
|
-
const result = describePathGate(
|
|
98
|
-
makeTcc(),
|
|
99
|
-
checkPermission,
|
|
100
|
-
getSessionRuleset,
|
|
101
|
-
);
|
|
77
|
+
const result = describePathGate(makeTcc(), resolver);
|
|
102
78
|
expect(result).not.toBeNull();
|
|
103
79
|
expect(isGateDescriptor(result)).toBe(true);
|
|
104
80
|
});
|
|
105
81
|
|
|
106
82
|
it("returns GateDescriptor when path check result is deny", () => {
|
|
107
|
-
const
|
|
108
|
-
makeCheckResult({
|
|
109
|
-
state: "deny",
|
|
110
|
-
matchedPattern: "*.env",
|
|
111
|
-
}),
|
|
112
|
-
);
|
|
113
|
-
const result = describePathGate(
|
|
114
|
-
makeTcc(),
|
|
115
|
-
checkPermission,
|
|
116
|
-
getSessionRuleset,
|
|
83
|
+
const resolver = makeResolver(
|
|
84
|
+
makeCheckResult({ state: "deny", matchedPattern: "*.env" }),
|
|
117
85
|
);
|
|
86
|
+
const result = describePathGate(makeTcc(), resolver);
|
|
118
87
|
expect(result).not.toBeNull();
|
|
119
88
|
expect(isGateDescriptor(result)).toBe(true);
|
|
120
89
|
const desc = result as GateDescriptor;
|
|
@@ -123,17 +92,10 @@ describe("describePathGate", () => {
|
|
|
123
92
|
});
|
|
124
93
|
|
|
125
94
|
it("returns GateDescriptor when path check result is ask", () => {
|
|
126
|
-
const
|
|
127
|
-
makeCheckResult({
|
|
128
|
-
state: "ask",
|
|
129
|
-
matchedPattern: "*.env",
|
|
130
|
-
}),
|
|
131
|
-
);
|
|
132
|
-
const result = describePathGate(
|
|
133
|
-
makeTcc(),
|
|
134
|
-
checkPermission,
|
|
135
|
-
getSessionRuleset,
|
|
95
|
+
const resolver = makeResolver(
|
|
96
|
+
makeCheckResult({ state: "ask", matchedPattern: "*.env" }),
|
|
136
97
|
);
|
|
98
|
+
const result = describePathGate(makeTcc(), resolver);
|
|
137
99
|
expect(result).not.toBeNull();
|
|
138
100
|
expect(isGateDescriptor(result)).toBe(true);
|
|
139
101
|
const desc = result as GateDescriptor;
|
|
@@ -142,13 +104,12 @@ describe("describePathGate", () => {
|
|
|
142
104
|
});
|
|
143
105
|
|
|
144
106
|
it("descriptor has correct session approval surface and pattern", () => {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
107
|
+
const resolver = makeResolver(
|
|
108
|
+
makeCheckResult({ state: "ask", matchedPattern: "*" }),
|
|
109
|
+
);
|
|
148
110
|
const result = describePathGate(
|
|
149
111
|
makeTcc({ input: { path: "/test/project/src/.env" } }),
|
|
150
|
-
|
|
151
|
-
getSessionRuleset,
|
|
112
|
+
resolver,
|
|
152
113
|
) as GateDescriptor;
|
|
153
114
|
expect(result.sessionApproval).toBeDefined();
|
|
154
115
|
expect(result.sessionApproval?.surface).toBe("path");
|
|
@@ -156,16 +117,10 @@ describe("describePathGate", () => {
|
|
|
156
117
|
});
|
|
157
118
|
|
|
158
119
|
it("descriptor denialContext references the file path and tool name", () => {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
);
|
|
164
|
-
const result = describePathGate(
|
|
165
|
-
makeTcc(),
|
|
166
|
-
checkPermission,
|
|
167
|
-
getSessionRuleset,
|
|
168
|
-
) as GateDescriptor;
|
|
120
|
+
const resolver = makeResolver(
|
|
121
|
+
makeCheckResult({ state: "deny", matchedPattern: "*.env" }),
|
|
122
|
+
);
|
|
123
|
+
const result = describePathGate(makeTcc(), resolver) as GateDescriptor;
|
|
169
124
|
expect(result.denialContext).toEqual({
|
|
170
125
|
kind: "path",
|
|
171
126
|
toolName: "read",
|
|
@@ -175,43 +130,21 @@ describe("describePathGate", () => {
|
|
|
175
130
|
});
|
|
176
131
|
|
|
177
132
|
it("descriptor decision uses surface 'path' and the file path as value", () => {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
);
|
|
183
|
-
const result = describePathGate(
|
|
184
|
-
makeTcc(),
|
|
185
|
-
checkPermission,
|
|
186
|
-
getSessionRuleset,
|
|
187
|
-
) as GateDescriptor;
|
|
133
|
+
const resolver = makeResolver(
|
|
134
|
+
makeCheckResult({ state: "deny", matchedPattern: "*.env" }),
|
|
135
|
+
);
|
|
136
|
+
const result = describePathGate(makeTcc(), resolver) as GateDescriptor;
|
|
188
137
|
expect(result.decision.surface).toBe("path");
|
|
189
138
|
expect(result.decision.value).toBe(".env");
|
|
190
139
|
});
|
|
191
140
|
|
|
192
|
-
it("
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
pattern: "/project/*",
|
|
197
|
-
action: "allow",
|
|
198
|
-
origin: "session",
|
|
199
|
-
},
|
|
200
|
-
];
|
|
201
|
-
const getSession = vi.fn<() => Rule[]>().mockReturnValue(sessionRules);
|
|
202
|
-
const checkPermission = vi
|
|
203
|
-
.fn<CheckPermissionFn>()
|
|
204
|
-
.mockReturnValue(makeCheckResult({ state: "allow" }));
|
|
205
|
-
describePathGate(
|
|
206
|
-
makeTcc({ agentName: "my-agent" }),
|
|
207
|
-
checkPermission,
|
|
208
|
-
getSession,
|
|
209
|
-
);
|
|
210
|
-
expect(checkPermission).toHaveBeenCalledWith(
|
|
141
|
+
it("resolves the path surface with the file path and agent name", () => {
|
|
142
|
+
const resolver = makeResolver(makeCheckResult({ state: "allow" }));
|
|
143
|
+
describePathGate(makeTcc({ agentName: "my-agent" }), resolver);
|
|
144
|
+
expect(resolver.resolve).toHaveBeenCalledWith(
|
|
211
145
|
"path",
|
|
212
146
|
{ path: ".env" },
|
|
213
147
|
"my-agent",
|
|
214
|
-
sessionRules,
|
|
215
148
|
);
|
|
216
149
|
});
|
|
217
150
|
});
|