@gotgenes/pi-permission-system 5.9.0 → 5.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 +15 -0
- package/package.json +1 -1
- package/src/handlers/before-agent-start.ts +19 -32
- package/src/handlers/input.ts +5 -5
- package/src/handlers/lifecycle.ts +17 -33
- package/src/handlers/tool-call.ts +11 -18
- package/src/handlers/types.ts +11 -38
- package/src/index.ts +14 -17
- package/src/permission-session.ts +252 -0
- package/src/runtime.ts +5 -30
- package/src/skill-prompt-sanitizer.ts +15 -4
- package/tests/handlers/before-agent-start.test.ts +79 -110
- package/tests/handlers/input-events.test.ts +19 -31
- package/tests/handlers/input.test.ts +41 -73
- package/tests/handlers/lifecycle.test.ts +61 -179
- package/tests/handlers/tool-call-events.test.ts +66 -92
- package/tests/handlers/tool-call.test.ts +40 -61
- package/tests/permission-session.test.ts +546 -0
- package/tests/runtime.test.ts +2 -77
|
@@ -9,8 +9,8 @@ import { handleToolCall } from "../../src/handlers/tool-call";
|
|
|
9
9
|
import type { HandlerDeps } from "../../src/handlers/types";
|
|
10
10
|
import type { PermissionDecisionEvent } from "../../src/permission-events";
|
|
11
11
|
import { PERMISSIONS_DECISION_CHANNEL } from "../../src/permission-events";
|
|
12
|
-
import type {
|
|
13
|
-
import type { PermissionCheckResult } from "../../src/types";
|
|
12
|
+
import type { PermissionSession } from "../../src/permission-session";
|
|
13
|
+
import type { PermissionCheckResult, PermissionState } from "../../src/types";
|
|
14
14
|
|
|
15
15
|
// ── helpers ────────────────────────────────────────────────────────────────
|
|
16
16
|
|
|
@@ -67,42 +67,35 @@ function makeCheckResult(
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
function makeSession(
|
|
70
|
+
function makeSession(
|
|
71
|
+
overrides: Partial<Record<keyof PermissionSession, unknown>> = {},
|
|
72
|
+
): PermissionSession {
|
|
71
73
|
return {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
} as unknown as SessionState["sessionRules"],
|
|
74
|
+
logger: { debug: vi.fn(), review: vi.fn(), warn: vi.fn() },
|
|
75
|
+
activate: vi.fn(),
|
|
76
|
+
resolveAgentName: vi.fn().mockReturnValue(null),
|
|
77
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("allow")),
|
|
78
|
+
getToolPermission: vi.fn().mockReturnValue("allow" as PermissionState),
|
|
79
|
+
getSessionRuleset: vi.fn().mockReturnValue([]),
|
|
80
|
+
approveSessionRule: vi.fn(),
|
|
81
|
+
getActiveSkillEntries: vi.fn().mockReturnValue([]),
|
|
82
|
+
getInfrastructureDirs: vi
|
|
83
|
+
.fn()
|
|
84
|
+
.mockReturnValue(["/test/agent", "/test/agent/git"]),
|
|
85
|
+
getInfrastructureReadPaths: vi.fn().mockReturnValue([]),
|
|
85
86
|
...overrides,
|
|
86
|
-
};
|
|
87
|
+
} as unknown as PermissionSession;
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
function makeDeps(overrides: Partial<HandlerDeps> = {}): HandlerDeps {
|
|
90
91
|
return {
|
|
91
92
|
session: makeSession(),
|
|
92
|
-
logger: { debug: vi.fn(), review: vi.fn(), warn: vi.fn() },
|
|
93
|
-
piInfrastructureDirs: ["/test/agent", "/test/agent/git"],
|
|
94
|
-
getPiInfrastructureReadPaths: vi.fn().mockReturnValue([]),
|
|
95
93
|
events: makeEvents(),
|
|
96
|
-
createPermissionManagerForCwd: vi.fn(),
|
|
97
|
-
refreshExtensionConfig: vi.fn(),
|
|
98
|
-
logResolvedConfigPaths: vi.fn(),
|
|
99
|
-
resolveAgentName: vi.fn().mockReturnValue(null),
|
|
100
94
|
canRequestPermissionConfirmation: vi.fn().mockReturnValue(true),
|
|
101
95
|
promptPermission: vi
|
|
102
96
|
.fn()
|
|
103
97
|
.mockResolvedValue({ approved: true, state: "approved" }),
|
|
104
98
|
createPermissionRequestId: vi.fn().mockReturnValue("req-id"),
|
|
105
|
-
forwarding: { start: vi.fn(), stop: vi.fn() },
|
|
106
99
|
stopPermissionRpcHandlers: vi.fn(),
|
|
107
100
|
getAllTools: vi.fn().mockReturnValue([{ name: "read" }, { name: "bash" }]),
|
|
108
101
|
setActiveTools: vi.fn(),
|
|
@@ -122,18 +115,15 @@ function getDecisionEvents(deps: HandlerDeps): PermissionDecisionEvent[] {
|
|
|
122
115
|
|
|
123
116
|
describe("handleToolCall decision events — policy_allow", () => {
|
|
124
117
|
it("emits allow with policy_allow when checkPermission returns allow", async () => {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}),
|
|
133
|
-
),
|
|
134
|
-
} as unknown as SessionState["permissionManager"],
|
|
135
|
-
}),
|
|
118
|
+
const session = makeSession({
|
|
119
|
+
checkPermission: vi.fn().mockReturnValue(
|
|
120
|
+
makeCheckResult("allow", {
|
|
121
|
+
origin: "global",
|
|
122
|
+
matchedPattern: "*",
|
|
123
|
+
}),
|
|
124
|
+
),
|
|
136
125
|
});
|
|
126
|
+
const deps = makeDeps({ session });
|
|
137
127
|
|
|
138
128
|
await handleToolCall(deps, makeToolCallEvent("read"), makeCtx());
|
|
139
129
|
|
|
@@ -153,18 +143,15 @@ describe("handleToolCall decision events — policy_allow", () => {
|
|
|
153
143
|
|
|
154
144
|
describe("handleToolCall decision events — policy_deny", () => {
|
|
155
145
|
it("emits deny with policy_deny when checkPermission returns deny", async () => {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}),
|
|
164
|
-
),
|
|
165
|
-
} as unknown as SessionState["permissionManager"],
|
|
166
|
-
}),
|
|
146
|
+
const session = makeSession({
|
|
147
|
+
checkPermission: vi.fn().mockReturnValue(
|
|
148
|
+
makeCheckResult("deny", {
|
|
149
|
+
origin: "project",
|
|
150
|
+
matchedPattern: "read",
|
|
151
|
+
}),
|
|
152
|
+
),
|
|
167
153
|
});
|
|
154
|
+
const deps = makeDeps({ session });
|
|
168
155
|
|
|
169
156
|
await handleToolCall(deps, makeToolCallEvent("read"), makeCtx());
|
|
170
157
|
|
|
@@ -182,18 +169,15 @@ describe("handleToolCall decision events — policy_deny", () => {
|
|
|
182
169
|
|
|
183
170
|
describe("handleToolCall decision events — session_approved", () => {
|
|
184
171
|
it("emits allow with session_approved when checkPermission returns source:session", async () => {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}),
|
|
193
|
-
),
|
|
194
|
-
} as unknown as SessionState["permissionManager"],
|
|
195
|
-
}),
|
|
172
|
+
const session = makeSession({
|
|
173
|
+
checkPermission: vi.fn().mockReturnValue(
|
|
174
|
+
makeCheckResult("allow", {
|
|
175
|
+
source: "session",
|
|
176
|
+
matchedPattern: "git *",
|
|
177
|
+
}),
|
|
178
|
+
),
|
|
196
179
|
});
|
|
180
|
+
const deps = makeDeps({ session });
|
|
197
181
|
|
|
198
182
|
await handleToolCall(
|
|
199
183
|
deps,
|
|
@@ -215,12 +199,11 @@ describe("handleToolCall decision events — session_approved", () => {
|
|
|
215
199
|
|
|
216
200
|
describe("handleToolCall decision events — user_approved", () => {
|
|
217
201
|
it("emits allow with user_approved when state=ask and user approves once", async () => {
|
|
202
|
+
const session = makeSession({
|
|
203
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
204
|
+
});
|
|
218
205
|
const deps = makeDeps({
|
|
219
|
-
session
|
|
220
|
-
permissionManager: {
|
|
221
|
-
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
222
|
-
} as unknown as SessionState["permissionManager"],
|
|
223
|
-
}),
|
|
206
|
+
session,
|
|
224
207
|
promptPermission: vi
|
|
225
208
|
.fn()
|
|
226
209
|
.mockResolvedValue({ approved: true, state: "approved" }),
|
|
@@ -237,12 +220,11 @@ describe("handleToolCall decision events — user_approved", () => {
|
|
|
237
220
|
});
|
|
238
221
|
|
|
239
222
|
it("emits allow with user_approved_for_session when user approves for session", async () => {
|
|
223
|
+
const session = makeSession({
|
|
224
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
225
|
+
});
|
|
240
226
|
const deps = makeDeps({
|
|
241
|
-
session
|
|
242
|
-
permissionManager: {
|
|
243
|
-
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
244
|
-
} as unknown as SessionState["permissionManager"],
|
|
245
|
-
}),
|
|
227
|
+
session,
|
|
246
228
|
promptPermission: vi
|
|
247
229
|
.fn()
|
|
248
230
|
.mockResolvedValue({ approved: true, state: "approved_for_session" }),
|
|
@@ -263,12 +245,11 @@ describe("handleToolCall decision events — user_approved", () => {
|
|
|
263
245
|
|
|
264
246
|
describe("handleToolCall decision events — user_denied", () => {
|
|
265
247
|
it("emits deny with user_denied when state=ask and user denies", async () => {
|
|
248
|
+
const session = makeSession({
|
|
249
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
250
|
+
});
|
|
266
251
|
const deps = makeDeps({
|
|
267
|
-
session
|
|
268
|
-
permissionManager: {
|
|
269
|
-
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
270
|
-
} as unknown as SessionState["permissionManager"],
|
|
271
|
-
}),
|
|
252
|
+
session,
|
|
272
253
|
promptPermission: vi
|
|
273
254
|
.fn()
|
|
274
255
|
.mockResolvedValue({ approved: false, state: "denied" }),
|
|
@@ -289,12 +270,11 @@ describe("handleToolCall decision events — user_denied", () => {
|
|
|
289
270
|
|
|
290
271
|
describe("handleToolCall decision events — confirmation_unavailable", () => {
|
|
291
272
|
it("emits deny with confirmation_unavailable when state=ask but no UI", async () => {
|
|
273
|
+
const session = makeSession({
|
|
274
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
275
|
+
});
|
|
292
276
|
const deps = makeDeps({
|
|
293
|
-
session
|
|
294
|
-
permissionManager: {
|
|
295
|
-
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
296
|
-
} as unknown as SessionState["permissionManager"],
|
|
297
|
-
}),
|
|
277
|
+
session,
|
|
298
278
|
canRequestPermissionConfirmation: vi.fn().mockReturnValue(false),
|
|
299
279
|
});
|
|
300
280
|
|
|
@@ -318,14 +298,11 @@ describe("handleToolCall decision events — confirmation_unavailable", () => {
|
|
|
318
298
|
describe("handleToolCall decision events — infrastructure_auto_allowed", () => {
|
|
319
299
|
it("emits allow with infrastructure_auto_allowed for Pi infra reads", async () => {
|
|
320
300
|
const infraDir = "/test/agent";
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
permissionManager: {
|
|
325
|
-
checkPermission: vi.fn().mockReturnValue(makeCheckResult("allow")),
|
|
326
|
-
} as unknown as SessionState["permissionManager"],
|
|
327
|
-
}),
|
|
301
|
+
const session = makeSession({
|
|
302
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("allow")),
|
|
303
|
+
getInfrastructureDirs: vi.fn().mockReturnValue([infraDir]),
|
|
328
304
|
});
|
|
305
|
+
const deps = makeDeps({ session });
|
|
329
306
|
|
|
330
307
|
const event = makeToolCallEvent("read", {
|
|
331
308
|
input: { path: `${infraDir}/some-file.json` },
|
|
@@ -333,7 +310,6 @@ describe("handleToolCall decision events — infrastructure_auto_allowed", () =>
|
|
|
333
310
|
await handleToolCall(deps, event, makeCtx());
|
|
334
311
|
|
|
335
312
|
const events = getDecisionEvents(deps);
|
|
336
|
-
// One infrastructure_auto_allowed event + one policy_allow for the normal gate
|
|
337
313
|
const infraEvents = events.filter(
|
|
338
314
|
(e) => e.resolution === "infrastructure_auto_allowed",
|
|
339
315
|
);
|
|
@@ -349,13 +325,11 @@ describe("handleToolCall decision events — infrastructure_auto_allowed", () =>
|
|
|
349
325
|
|
|
350
326
|
describe("handleToolCall decision events — auto_approved", () => {
|
|
351
327
|
it("emits allow with auto_approved when promptPermission returns autoApproved:true", async () => {
|
|
328
|
+
const session = makeSession({
|
|
329
|
+
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
330
|
+
});
|
|
352
331
|
const deps = makeDeps({
|
|
353
|
-
session
|
|
354
|
-
permissionManager: {
|
|
355
|
-
checkPermission: vi.fn().mockReturnValue(makeCheckResult("ask")),
|
|
356
|
-
} as unknown as SessionState["permissionManager"],
|
|
357
|
-
}),
|
|
358
|
-
// Simulate what PermissionPrompter returns in yolo mode
|
|
332
|
+
session,
|
|
359
333
|
promptPermission: vi.fn().mockResolvedValue({
|
|
360
334
|
approved: true,
|
|
361
335
|
state: "approved",
|
|
@@ -3,8 +3,8 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
3
3
|
|
|
4
4
|
import { getEventInput, handleToolCall } from "../../src/handlers/tool-call";
|
|
5
5
|
import type { HandlerDeps } from "../../src/handlers/types";
|
|
6
|
-
import type {
|
|
7
|
-
import type { PermissionCheckResult } from "../../src/types";
|
|
6
|
+
import type { PermissionSession } from "../../src/permission-session";
|
|
7
|
+
import type { PermissionCheckResult, PermissionState } from "../../src/types";
|
|
8
8
|
|
|
9
9
|
// ── SDK stubs ──────────────────────────────────────────────────────────────
|
|
10
10
|
vi.mock("@mariozechner/pi-coding-agent", async (importOriginal) => {
|
|
@@ -55,42 +55,35 @@ function makePermissionResult(
|
|
|
55
55
|
return { state, toolName: "read", source: "tool", origin: "builtin" };
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function makeSession(
|
|
58
|
+
function makeSession(
|
|
59
|
+
overrides: Partial<Record<keyof PermissionSession, unknown>> = {},
|
|
60
|
+
): PermissionSession {
|
|
59
61
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} as unknown as SessionState["sessionRules"],
|
|
62
|
+
logger: { debug: vi.fn(), review: vi.fn(), warn: vi.fn() },
|
|
63
|
+
activate: vi.fn(),
|
|
64
|
+
resolveAgentName: vi.fn().mockReturnValue(null),
|
|
65
|
+
checkPermission: vi.fn().mockReturnValue(makePermissionResult("allow")),
|
|
66
|
+
getToolPermission: vi.fn().mockReturnValue("allow" as PermissionState),
|
|
67
|
+
getSessionRuleset: vi.fn().mockReturnValue([]),
|
|
68
|
+
approveSessionRule: vi.fn(),
|
|
69
|
+
getActiveSkillEntries: vi.fn().mockReturnValue([]),
|
|
70
|
+
getInfrastructureDirs: vi
|
|
71
|
+
.fn()
|
|
72
|
+
.mockReturnValue(["/test/agent", "/test/agent/git"]),
|
|
73
|
+
getInfrastructureReadPaths: vi.fn().mockReturnValue([]),
|
|
73
74
|
...overrides,
|
|
74
|
-
};
|
|
75
|
+
} as unknown as PermissionSession;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
function makeDeps(overrides: Partial<HandlerDeps> = {}): HandlerDeps {
|
|
78
79
|
return {
|
|
79
80
|
session: makeSession(),
|
|
80
|
-
|
|
81
|
-
piInfrastructureDirs: ["/test/agent", "/test/agent/git"],
|
|
82
|
-
getPiInfrastructureReadPaths: vi.fn().mockReturnValue([]),
|
|
83
|
-
createPermissionManagerForCwd: vi.fn(),
|
|
84
|
-
refreshExtensionConfig: vi.fn(),
|
|
85
|
-
logResolvedConfigPaths: vi.fn(),
|
|
86
|
-
resolveAgentName: vi.fn().mockReturnValue(null),
|
|
81
|
+
events: { emit: vi.fn(), on: vi.fn().mockReturnValue(() => undefined) },
|
|
87
82
|
canRequestPermissionConfirmation: vi.fn().mockReturnValue(true),
|
|
88
83
|
promptPermission: vi
|
|
89
84
|
.fn()
|
|
90
85
|
.mockResolvedValue({ approved: true, state: "approved" }),
|
|
91
86
|
createPermissionRequestId: vi.fn().mockReturnValue("req-id"),
|
|
92
|
-
events: { emit: vi.fn(), on: vi.fn().mockReturnValue(() => undefined) },
|
|
93
|
-
forwarding: { start: vi.fn(), stop: vi.fn() },
|
|
94
87
|
stopPermissionRpcHandlers: vi.fn(),
|
|
95
88
|
getAllTools: vi.fn().mockReturnValue([{ name: "read" }, { name: "bash" }]),
|
|
96
89
|
setActiveTools: vi.fn(),
|
|
@@ -127,23 +120,15 @@ describe("getEventInput", () => {
|
|
|
127
120
|
// ── handleToolCall ─────────────────────────────────────────────────────────
|
|
128
121
|
|
|
129
122
|
describe("handleToolCall", () => {
|
|
130
|
-
it("
|
|
131
|
-
const ctx = makeCtx();
|
|
132
|
-
const deps = makeDeps();
|
|
133
|
-
await handleToolCall(deps, makeToolCallEvent("read"), ctx);
|
|
134
|
-
expect(deps.session.runtimeContext).toBe(ctx);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("starts forwarded permission polling", async () => {
|
|
123
|
+
it("activates session with ctx", async () => {
|
|
138
124
|
const ctx = makeCtx();
|
|
139
125
|
const deps = makeDeps();
|
|
140
126
|
await handleToolCall(deps, makeToolCallEvent("read"), ctx);
|
|
141
|
-
expect(deps.
|
|
127
|
+
expect(deps.session.activate).toHaveBeenCalledWith(ctx);
|
|
142
128
|
});
|
|
143
129
|
|
|
144
130
|
it("blocks when tool name cannot be resolved", async () => {
|
|
145
131
|
const deps = makeDeps();
|
|
146
|
-
// An event with no recognisable name field
|
|
147
132
|
const result = await handleToolCall(deps, { type: "tool_call" }, makeCtx());
|
|
148
133
|
expect(result).toEqual({
|
|
149
134
|
block: true,
|
|
@@ -164,7 +149,6 @@ describe("handleToolCall", () => {
|
|
|
164
149
|
});
|
|
165
150
|
|
|
166
151
|
it("returns empty object when tool is allowed", async () => {
|
|
167
|
-
// default makeRuntime() has checkPermission → "allow"
|
|
168
152
|
const deps = makeDeps();
|
|
169
153
|
const result = await handleToolCall(
|
|
170
154
|
deps,
|
|
@@ -175,15 +159,10 @@ describe("handleToolCall", () => {
|
|
|
175
159
|
});
|
|
176
160
|
|
|
177
161
|
it("blocks when tool is denied by policy", async () => {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
permissionManager: {
|
|
181
|
-
checkPermission: vi
|
|
182
|
-
.fn()
|
|
183
|
-
.mockReturnValue(makePermissionResult("deny")),
|
|
184
|
-
} as unknown as SessionState["permissionManager"],
|
|
185
|
-
}),
|
|
162
|
+
const session = makeSession({
|
|
163
|
+
checkPermission: vi.fn().mockReturnValue(makePermissionResult("deny")),
|
|
186
164
|
});
|
|
165
|
+
const deps = makeDeps({ session });
|
|
187
166
|
const result = await handleToolCall(
|
|
188
167
|
deps,
|
|
189
168
|
makeToolCallEvent("read"),
|
|
@@ -205,8 +184,11 @@ describe("handleToolCall — skill-read gate", () => {
|
|
|
205
184
|
normalizedLocation: "/skills/librarian/SKILL.md",
|
|
206
185
|
normalizedBaseDir: "/skills/librarian",
|
|
207
186
|
};
|
|
187
|
+
const session = makeSession({
|
|
188
|
+
getActiveSkillEntries: vi.fn().mockReturnValue([skillEntry]),
|
|
189
|
+
});
|
|
208
190
|
const deps = makeDeps({
|
|
209
|
-
session
|
|
191
|
+
session,
|
|
210
192
|
getAllTools: vi.fn().mockReturnValue([{ toolName: "read" }]),
|
|
211
193
|
});
|
|
212
194
|
const event = {
|
|
@@ -228,8 +210,11 @@ describe("handleToolCall — skill-read gate", () => {
|
|
|
228
210
|
normalizedLocation: "/skills/librarian/SKILL.md",
|
|
229
211
|
normalizedBaseDir: "/skills/librarian",
|
|
230
212
|
};
|
|
213
|
+
const session = makeSession({
|
|
214
|
+
getActiveSkillEntries: vi.fn().mockReturnValue([skillEntry]),
|
|
215
|
+
});
|
|
231
216
|
const deps = makeDeps({
|
|
232
|
-
session
|
|
217
|
+
session,
|
|
233
218
|
getAllTools: vi.fn().mockReturnValue([{ toolName: "read" }]),
|
|
234
219
|
});
|
|
235
220
|
const event = {
|
|
@@ -247,14 +232,11 @@ describe("handleToolCall — skill-read gate", () => {
|
|
|
247
232
|
|
|
248
233
|
describe("handleToolCall — external-directory gate", () => {
|
|
249
234
|
it("blocks a read of a path outside cwd when policy is deny", async () => {
|
|
235
|
+
const session = makeSession({
|
|
236
|
+
checkPermission: vi.fn().mockReturnValue(makePermissionResult("deny")),
|
|
237
|
+
});
|
|
250
238
|
const deps = makeDeps({
|
|
251
|
-
session
|
|
252
|
-
permissionManager: {
|
|
253
|
-
checkPermission: vi
|
|
254
|
-
.fn()
|
|
255
|
-
.mockReturnValue(makePermissionResult("deny")),
|
|
256
|
-
} as unknown as SessionState["permissionManager"],
|
|
257
|
-
}),
|
|
239
|
+
session,
|
|
258
240
|
getAllTools: vi.fn().mockReturnValue([{ name: "read" }]),
|
|
259
241
|
});
|
|
260
242
|
const event = {
|
|
@@ -272,14 +254,11 @@ describe("handleToolCall — external-directory gate", () => {
|
|
|
272
254
|
|
|
273
255
|
describe("handleToolCall — bash external-directory gate", () => {
|
|
274
256
|
it("blocks a bash command referencing an external path when policy is deny", async () => {
|
|
257
|
+
const session = makeSession({
|
|
258
|
+
checkPermission: vi.fn().mockReturnValue(makePermissionResult("deny")),
|
|
259
|
+
});
|
|
275
260
|
const deps = makeDeps({
|
|
276
|
-
session
|
|
277
|
-
permissionManager: {
|
|
278
|
-
checkPermission: vi
|
|
279
|
-
.fn()
|
|
280
|
-
.mockReturnValue(makePermissionResult("deny")),
|
|
281
|
-
} as unknown as SessionState["permissionManager"],
|
|
282
|
-
}),
|
|
261
|
+
session,
|
|
283
262
|
getAllTools: vi.fn().mockReturnValue([{ name: "bash" }]),
|
|
284
263
|
});
|
|
285
264
|
const event = {
|