@gotgenes/pi-permission-system 10.4.0 → 10.5.1

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +1 -1
  3. package/src/handlers/before-agent-start.ts +11 -6
  4. package/src/handlers/gates/bash-command.ts +2 -2
  5. package/src/handlers/gates/bash-external-directory.ts +2 -2
  6. package/src/handlers/gates/bash-path.ts +2 -2
  7. package/src/handlers/gates/path.ts +2 -2
  8. package/src/handlers/gates/runner.ts +2 -2
  9. package/src/handlers/gates/tool-call-gate-pipeline.ts +10 -9
  10. package/src/handlers/lifecycle.ts +7 -4
  11. package/src/handlers/permission-gate-handler.ts +3 -3
  12. package/src/index.ts +13 -4
  13. package/src/permission-resolver.ts +66 -2
  14. package/src/permission-session.ts +8 -72
  15. package/src/session-rules.ts +3 -2
  16. package/src/skill-prompt-sanitizer.ts +1 -1
  17. package/test/handlers/before-agent-start.test.ts +56 -86
  18. package/test/handlers/external-directory-session-dedup.test.ts +80 -160
  19. package/test/handlers/gates/bash-external-directory.test.ts +2 -2
  20. package/test/handlers/gates/bash-path.test.ts +2 -2
  21. package/test/handlers/gates/tool-call-gate-pipeline.test.ts +30 -21
  22. package/test/handlers/input.test.ts +5 -4
  23. package/test/handlers/lifecycle.test.ts +79 -85
  24. package/test/handlers/tool-call.test.ts +3 -2
  25. package/test/helpers/gate-fixtures.ts +5 -9
  26. package/test/helpers/handler-fixtures.ts +100 -107
  27. package/test/helpers/session-fixtures.ts +192 -0
  28. package/test/permission-resolver.test.ts +196 -0
  29. package/test/permission-session.test.ts +14 -266
  30. package/test/session-rules.test.ts +13 -5
  31. package/src/agent-prep-session.ts +0 -28
  32. package/src/gate-handler-session.ts +0 -13
  33. package/src/session-lifecycle-session.ts +0 -24
@@ -1,15 +1,16 @@
1
1
  /**
2
2
  * Shared handler-level test fixtures for PermissionGateHandler tests.
3
3
  *
4
- * All factories use override bags so callers can specialize any field
5
- * without constructing the full object from scratch.
4
+ * `makeHandler` builds a real PermissionSession + PermissionResolver and wires
5
+ * them into the handler and pipelines exactly as `index.ts` does.
6
+ * Call-site overrides for permission results flow through
7
+ * `permissionManager.checkPermission`; session state overrides are applied
8
+ * via vi.spyOn on the real session instance.
6
9
  */
7
10
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
8
11
  import { vi } from "vitest";
9
12
 
10
13
  import { GateDecisionReporter } from "#src/decision-reporter";
11
- import { DEFAULT_EXTENSION_CONFIG } from "#src/extension-config";
12
- import type { GateHandlerSession } from "#src/gate-handler-session";
13
14
  import type { GatePrompter } from "#src/gate-prompter";
14
15
  import { GateRunner } from "#src/handlers/gates/runner";
15
16
  import {
@@ -24,32 +25,33 @@ import { PermissionGateHandler } from "#src/handlers/permission-gate-handler";
24
25
  import type { PermissionDecisionEvent } from "#src/permission-events";
25
26
  import { PERMISSIONS_DECISION_CHANNEL } from "#src/permission-events";
26
27
  import type { Rule } from "#src/rule";
27
- import type { SessionApprovalRecorder } from "#src/session-approval-recorder";
28
28
  import type { SessionLogger } from "#src/session-logger";
29
- import { resolveToolPreviewLimits } from "#src/tool-preview-formatter";
29
+ import { SessionRules } from "#src/session-rules";
30
30
  import type { ToolRegistry } from "#src/tool-registry";
31
31
  import type { PermissionCheckResult, PermissionState } from "#src/types";
32
+ import {
33
+ makeRealResolver,
34
+ makeRealSession,
35
+ } from "#test/helpers/session-fixtures";
36
+
37
+ // ── MockGateHandlerSession ────────────────────────────────────────────────
32
38
 
33
39
  /**
34
- * Precise mock boundary for PermissionGateHandler integration tests.
40
+ * Mock type for gate-pipeline inputs (ToolCallGateInputs + SkillInputGateInputs).
35
41
  *
36
- * Intersection of every role the handler and its collaborators require.
37
- * Prompting is not included here — it moved to `PromptingGateway` (#339).
38
- * Pass a `prompter` override to `makeHandler` to steer GateRunner's prompting
39
- * role; `makeHandler` creates a clean default prompter when none is supplied.
42
+ * Used by `makeSurfaceCheck`, `makeBashCommandCheck`, and the `session`
43
+ * override bag in `makeHandler`. The `GateHandlerSession` role (activate +
44
+ * resolveAgentName) is now satisfied by the real `PermissionSession`; this
45
+ * type covers only the pipeline input surface.
40
46
  *
41
- * The 4-arg `checkPermission` overrides the 3-arg version from
42
- * GateHandlerSession so the `resolve` delegation can forward session rules.
47
+ * The 4-arg `checkPermission` is a superset of `SkillInputGateInputs` —
48
+ * it routes through `permissionManager.checkPermission` in production.
43
49
  */
44
50
  export type MockGateHandlerSession = ToolCallGateInputs &
45
- SkillInputGateInputs &
46
- SessionApprovalRecorder &
47
- GateHandlerSession & {
48
- /** Logger source for the reporter the fixture builds. */
51
+ SkillInputGateInputs & {
52
+ /** Logger shape expected by GateDecisionReporter. */
49
53
  logger: SessionLogger;
50
- /** Session-rule accessor used by the resolve delegation. */
51
- getSessionRuleset(): Rule[];
52
- /** 4-arg form so the resolve delegation can pass rules. */
54
+ /** 4-arg form so surface-check mocks can receive optional rules. */
53
55
  checkPermission(
54
56
  surface: string,
55
57
  input: unknown,
@@ -58,6 +60,8 @@ export type MockGateHandlerSession = ToolCallGateInputs &
58
60
  ): PermissionCheckResult;
59
61
  };
60
62
 
63
+ // ── Small utility factories ───────────────────────────────────────────────
64
+
61
65
  export function makeEvents() {
62
66
  return {
63
67
  emit: vi.fn(),
@@ -117,73 +121,6 @@ export function makeCheckResult(
117
121
  };
118
122
  }
119
123
 
120
- /**
121
- * Full-intersection session stub.
122
- *
123
- * Uses per-field `??` selection (no spread) so TypeScript verifies every
124
- * field against `MockGateHandlerSession` individually — a missing field fails
125
- * `pnpm run check` instead of failing silently at runtime.
126
- *
127
- * The `resolve` delegation is inlined as a closure that reads `session` at
128
- * call time, so overriding `checkPermission` or `getSessionRuleset`
129
- * automatically steers it without extra guards.
130
- *
131
- * Prompting is not part of this mock — pass `prompter` to `makeHandler`.
132
- */
133
- export function makeSession(
134
- overrides: Partial<MockGateHandlerSession> = {},
135
- ): MockGateHandlerSession {
136
- const session: MockGateHandlerSession = {
137
- logger: overrides.logger ?? {
138
- debug: vi.fn(),
139
- review: vi.fn(),
140
- warn: vi.fn(),
141
- },
142
- activate: overrides.activate ?? vi.fn<MockGateHandlerSession["activate"]>(),
143
- resolveAgentName:
144
- overrides.resolveAgentName ??
145
- vi.fn<MockGateHandlerSession["resolveAgentName"]>().mockReturnValue(null),
146
- checkPermission:
147
- overrides.checkPermission ??
148
- vi
149
- .fn<MockGateHandlerSession["checkPermission"]>()
150
- .mockReturnValue(makeCheckResult()),
151
- getSessionRuleset:
152
- overrides.getSessionRuleset ??
153
- vi.fn<MockGateHandlerSession["getSessionRuleset"]>().mockReturnValue([]),
154
- recordSessionApproval:
155
- overrides.recordSessionApproval ??
156
- vi.fn<MockGateHandlerSession["recordSessionApproval"]>(),
157
- getActiveSkillEntries:
158
- overrides.getActiveSkillEntries ??
159
- vi
160
- .fn<MockGateHandlerSession["getActiveSkillEntries"]>()
161
- .mockReturnValue([]),
162
- getInfrastructureReadDirs:
163
- overrides.getInfrastructureReadDirs ??
164
- vi
165
- .fn<MockGateHandlerSession["getInfrastructureReadDirs"]>()
166
- .mockReturnValue(["/test/agent", "/test/agent/git"]),
167
- getToolPreviewLimits:
168
- overrides.getToolPreviewLimits ??
169
- vi
170
- .fn<MockGateHandlerSession["getToolPreviewLimits"]>()
171
- .mockReturnValue(resolveToolPreviewLimits(DEFAULT_EXTENSION_CONFIG)),
172
- // Resolve delegation — closure reads `session` at call time so overrides win.
173
- resolve:
174
- overrides.resolve ??
175
- vi.fn<MockGateHandlerSession["resolve"]>((surface, input, agentName) =>
176
- session.checkPermission(
177
- surface,
178
- input,
179
- agentName,
180
- session.getSessionRuleset(),
181
- ),
182
- ),
183
- };
184
- return session;
185
- }
186
-
187
124
  export function makeToolRegistry(
188
125
  overrides: Partial<ToolRegistry> = {},
189
126
  ): ToolRegistry {
@@ -194,14 +131,14 @@ export function makeToolRegistry(
194
131
  };
195
132
  }
196
133
 
134
+ // ── Surface-check factories ────────────────────────────────────────────────
135
+
197
136
  /**
198
137
  * Surface-dispatching `checkPermission` mock.
199
138
  *
200
- * Builds a `vi.fn()` that returns a `PermissionCheckResult` for each surface,
201
- * using `bySurface[surface]` when matched and `defaultResult` otherwise.
202
- * Default fields: `toolName` = the surface string, `source: "tool"`,
203
- * `origin: "builtin"` — callers override by including the field in the
204
- * per-surface or default partial (e.g. `{ path: { state: "allow", source: "special" } }`).
139
+ * Returns the matching per-surface result or `defaultResult`.
140
+ * Pass the returned function as `session.checkPermission` in a `makeHandler`
141
+ * override bag it is applied to `permissionManager.checkPermission`.
205
142
  *
206
143
  * Return type is intentionally unannotated so callers retain full `vi.fn()`
207
144
  * mock access (`mock.calls`, `toHaveBeenCalledWith`, etc.).
@@ -231,9 +168,8 @@ export function makeSurfaceCheck(
231
168
  /**
232
169
  * Bash-surface `checkPermission` mock that dispatches on a command regex.
233
170
  *
234
- * For the `bash` surface: returns a deny result when `opts.deny` matches the
235
- * command, and an allow result otherwise. For all other surfaces, returns a
236
- * plain allow result.
171
+ * Pass the returned function as `session.checkPermission` in a `makeHandler`
172
+ * override bag it is applied to `permissionManager.checkPermission`.
237
173
  *
238
174
  * Return type is intentionally unannotated so callers retain full `vi.fn()`
239
175
  * mock access.
@@ -266,24 +202,68 @@ export function makeBashCommandCheck(opts: {
266
202
  });
267
203
  }
268
204
 
205
+ // ── makeHandler ────────────────────────────────────────────────────────────
206
+
269
207
  /**
270
- * Constructs a PermissionGateHandler with mocked collaborators.
208
+ * Constructs a PermissionGateHandler wired with real collaborators.
271
209
  *
272
- * Returns all collaborators so each test file can destructure only what
273
- * it needs handler, events, session, toolRegistry, and prompter are all available.
210
+ * The `session` override bag maps to the real collaborators:
211
+ * - `checkPermission` applied to `permissionManager.checkPermission`
212
+ * - `getActiveSkillEntries`, `getInfrastructureReadDirs`, `getToolPreviewLimits`
213
+ * → applied as vi.spyOn overrides on the real session
214
+ * - `resolveAgentName` → applied as a vi.spyOn override on the real session
274
215
  *
275
- * The default prompter approves all requests. Pass `prompter` explicitly to
276
- * steer canConfirm/prompt behavior for the test.
216
+ * Returns `{ handler, events, session, toolRegistry, prompter, recorder,
217
+ * permissionManager, forwarding }` so each test file can destructure only
218
+ * what it needs.
219
+ * `session.activate` is not a mock — use `forwarding.start` to assert it
220
+ * was called.
277
221
  */
278
222
  export function makeHandler(overrides?: {
279
- session?: Partial<MockGateHandlerSession>;
223
+ session?: Partial<MockGateHandlerSession> & {
224
+ resolveAgentName?: (
225
+ ctx: ExtensionContext,
226
+ systemPrompt?: string,
227
+ ) => string | null;
228
+ };
280
229
  /** Override the GatePrompter passed to GateRunner. Defaults to an allow-all stub. */
281
230
  prompter?: GatePrompter;
282
231
  toolRegistry?: Partial<ToolRegistry>;
283
232
  /** Sugar: builds the `getAll` mock from a list of tool names. */
284
233
  tools?: string[];
285
234
  }) {
286
- const session = makeSession(overrides?.session);
235
+ const { session, permissionManager, sessionRules, forwarding, logger } =
236
+ makeRealSession();
237
+ const { resolver } = makeRealResolver(permissionManager, sessionRules);
238
+
239
+ // Apply session override bag to the real collaborators.
240
+ const so = overrides?.session;
241
+ if (so?.checkPermission) {
242
+ vi.mocked(permissionManager.checkPermission).mockImplementation(
243
+ so.checkPermission,
244
+ );
245
+ }
246
+ if (so?.getActiveSkillEntries) {
247
+ vi.spyOn(session, "getActiveSkillEntries").mockImplementation(
248
+ so.getActiveSkillEntries,
249
+ );
250
+ }
251
+ if (so?.getInfrastructureReadDirs) {
252
+ vi.spyOn(session, "getInfrastructureReadDirs").mockImplementation(
253
+ so.getInfrastructureReadDirs,
254
+ );
255
+ }
256
+ if (so?.getToolPreviewLimits) {
257
+ vi.spyOn(session, "getToolPreviewLimits").mockImplementation(
258
+ so.getToolPreviewLimits,
259
+ );
260
+ }
261
+ if (so?.resolveAgentName) {
262
+ vi.spyOn(session, "resolveAgentName").mockImplementation(
263
+ so.resolveAgentName,
264
+ );
265
+ }
266
+
287
267
  const events = makeEvents();
288
268
  const toolRegistry =
289
269
  overrides?.tools !== undefined
@@ -293,16 +273,18 @@ export function makeHandler(overrides?: {
293
273
  .mockReturnValue(overrides.tools.map((name) => ({ name }))),
294
274
  })
295
275
  : makeToolRegistry(overrides?.toolRegistry);
296
- const pipeline = new ToolCallGatePipeline(session);
297
- const skillInputPipeline = new SkillInputGatePipeline(session);
298
- const reporter = new GateDecisionReporter(session.logger, events);
276
+
277
+ const recorder = new SessionRules();
278
+ const pipeline = new ToolCallGatePipeline(resolver, session);
279
+ const skillInputPipeline = new SkillInputGatePipeline(resolver);
280
+ const reporter = new GateDecisionReporter(logger, events);
299
281
  const prompter: GatePrompter = overrides?.prompter ?? {
300
282
  canConfirm: vi.fn().mockReturnValue(true),
301
283
  prompt: vi
302
284
  .fn<GatePrompter["prompt"]>()
303
285
  .mockResolvedValue({ approved: true, state: "approved" }),
304
286
  };
305
- const runner = new GateRunner(session, session, prompter, reporter);
287
+ const runner = new GateRunner(resolver, recorder, prompter, reporter);
306
288
  const handler = new PermissionGateHandler(
307
289
  session,
308
290
  toolRegistry,
@@ -310,9 +292,20 @@ export function makeHandler(overrides?: {
310
292
  skillInputPipeline,
311
293
  runner,
312
294
  );
313
- return { handler, events, session, toolRegistry, prompter };
295
+ return {
296
+ handler,
297
+ events,
298
+ session,
299
+ toolRegistry,
300
+ prompter,
301
+ recorder,
302
+ permissionManager,
303
+ forwarding,
304
+ };
314
305
  }
315
306
 
307
+ // ── Decision-event helper ─────────────────────────────────────────────────
308
+
316
309
  /** Extract all permissions:decision payloads from the events.emit mock. */
317
310
  export function getDecisionEvents(
318
311
  events: ReturnType<typeof makeEvents>,
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Shared real-instance test fixtures for PermissionSession and
3
+ * PermissionResolver.
4
+ *
5
+ * Use these instead of hand-rolling per-file mock intersection types.
6
+ * Build a real PermissionSession from small per-collaborator fakes so tests
7
+ * assert against actual behavior rather than mock contracts.
8
+ *
9
+ * Note: tests that exercise `resolveAgentName` must mock `active-agent` in
10
+ * their own file (the vi.hoisted / vi.mock pattern from permission-session.test.ts)
11
+ * since that mock is module-scoped.
12
+ */
13
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
14
+ import { vi } from "vitest";
15
+
16
+ import type { SessionConfigStore } from "#src/config-store";
17
+ import { DEFAULT_EXTENSION_CONFIG } from "#src/extension-config";
18
+ import type { ExtensionPaths } from "#src/extension-paths";
19
+ import type { ForwardingController } from "#src/forwarding-manager";
20
+ import type { ScopedPermissionManager } from "#src/permission-manager";
21
+ import { PermissionResolver } from "#src/permission-resolver";
22
+ import { PermissionSession } from "#src/permission-session";
23
+ import type { PromptingGatewayLifecycle } from "#src/prompting-gateway";
24
+ import type { Ruleset } from "#src/rule";
25
+ import type { SessionLogger } from "#src/session-logger";
26
+ import { SessionRules } from "#src/session-rules";
27
+ import type { PermissionCheckResult, PermissionState } from "#src/types";
28
+
29
+ // ── Per-collaborator fake factories ────────────────────────────────────────
30
+
31
+ export function makePaths(
32
+ overrides: Partial<ExtensionPaths> = {},
33
+ ): ExtensionPaths {
34
+ return {
35
+ agentDir: "/test/agent",
36
+ sessionsDir: "/test/agent/sessions",
37
+ subagentSessionsDir: "/test/agent/subagent-sessions",
38
+ forwardingDir: "/test/agent/sessions/permission-forwarding",
39
+ globalLogsDir: "/test/agent/logs",
40
+ piInfrastructureDirs: ["/test/agent", "/test/agent/git"],
41
+ ...overrides,
42
+ };
43
+ }
44
+
45
+ export function makeLogger(): SessionLogger {
46
+ return {
47
+ debug: vi.fn(),
48
+ review: vi.fn(),
49
+ warn: vi.fn(),
50
+ };
51
+ }
52
+
53
+ export function makeConfigStore(
54
+ overrides: Partial<SessionConfigStore> = {},
55
+ ): SessionConfigStore {
56
+ return {
57
+ current:
58
+ overrides.current ??
59
+ vi
60
+ .fn<() => typeof DEFAULT_EXTENSION_CONFIG>()
61
+ .mockReturnValue({ ...DEFAULT_EXTENSION_CONFIG }),
62
+ refresh: overrides.refresh ?? vi.fn<(ctx?: ExtensionContext) => void>(),
63
+ logResolvedPaths: overrides.logResolvedPaths ?? vi.fn<() => void>(),
64
+ };
65
+ }
66
+
67
+ export function makeGateway(): PromptingGatewayLifecycle {
68
+ return {
69
+ activate: vi.fn<PromptingGatewayLifecycle["activate"]>(),
70
+ deactivate: vi.fn<PromptingGatewayLifecycle["deactivate"]>(),
71
+ };
72
+ }
73
+
74
+ export function makeForwarding(): ForwardingController {
75
+ return {
76
+ start: vi.fn(),
77
+ stop: vi.fn(),
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Fake `ScopedPermissionManager` with vi.fn() stubs.
83
+ *
84
+ * Return type is intentionally unannotated so callers retain full `vi.fn()`
85
+ * mock access (`mock.calls`, `toHaveBeenCalledWith`, `mockReturnValue`, etc.).
86
+ */
87
+ export function makeFakePermissionManager() {
88
+ return {
89
+ configureForCwd: vi.fn<(cwd: string | undefined | null) => void>(),
90
+ checkPermission: vi
91
+ .fn<
92
+ (
93
+ toolName: string,
94
+ input: unknown,
95
+ agentName?: string,
96
+ sessionRules?: Ruleset,
97
+ ) => PermissionCheckResult
98
+ >()
99
+ .mockReturnValue({
100
+ state: "allow",
101
+ toolName: "read",
102
+ source: "tool",
103
+ origin: "builtin",
104
+ }),
105
+ getToolPermission: vi
106
+ .fn<(toolName: string, agentName?: string) => PermissionState>()
107
+ .mockReturnValue("allow"),
108
+ getConfigIssues: vi.fn((): string[] => []),
109
+ getPolicyCacheStamp: vi.fn((): string => "stamp-1"),
110
+ };
111
+ }
112
+
113
+ // ── Real-instance factories ────────────────────────────────────────────────
114
+
115
+ /**
116
+ * Build a real PermissionSession from per-collaborator fakes.
117
+ *
118
+ * Returns the session and every collaborator so callers can destructure only
119
+ * what they need and assert against collaborator spies directly.
120
+ * The `permissionManager` is a `makeFakePermissionManager()` result unless
121
+ * the caller passes an explicit `ScopedPermissionManager`.
122
+ */
123
+ export function makeRealSession(overrides?: {
124
+ paths?: Partial<ExtensionPaths>;
125
+ logger?: SessionLogger;
126
+ forwarding?: ForwardingController;
127
+ permissionManager?: ScopedPermissionManager;
128
+ sessionRules?: SessionRules;
129
+ configStore?: SessionConfigStore;
130
+ gateway?: PromptingGatewayLifecycle;
131
+ }): {
132
+ session: PermissionSession;
133
+ paths: ExtensionPaths;
134
+ logger: SessionLogger;
135
+ forwarding: ForwardingController;
136
+ permissionManager: ReturnType<typeof makeFakePermissionManager>;
137
+ sessionRules: SessionRules;
138
+ configStore: SessionConfigStore;
139
+ gateway: PromptingGatewayLifecycle;
140
+ } {
141
+ const paths = makePaths(overrides?.paths);
142
+ const logger = overrides?.logger ?? makeLogger();
143
+ const forwarding = overrides?.forwarding ?? makeForwarding();
144
+ const permissionManager =
145
+ (overrides?.permissionManager as
146
+ | ReturnType<typeof makeFakePermissionManager>
147
+ | undefined) ?? makeFakePermissionManager();
148
+ const sessionRules = overrides?.sessionRules ?? new SessionRules();
149
+ const configStore = overrides?.configStore ?? makeConfigStore();
150
+ const gateway = overrides?.gateway ?? makeGateway();
151
+ const session = new PermissionSession(
152
+ paths,
153
+ logger,
154
+ forwarding,
155
+ permissionManager,
156
+ sessionRules,
157
+ configStore,
158
+ gateway,
159
+ );
160
+ return {
161
+ session,
162
+ paths,
163
+ logger,
164
+ forwarding,
165
+ permissionManager,
166
+ sessionRules,
167
+ configStore,
168
+ gateway,
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Build a real PermissionResolver from a fake manager and a SessionRules
174
+ * instance.
175
+ *
176
+ * When called with no arguments, creates a fresh fake manager and fresh
177
+ * SessionRules. Pass shared instances to connect the resolver to the same
178
+ * manager/rules used by a real session.
179
+ */
180
+ export function makeRealResolver(
181
+ manager?: ReturnType<typeof makeFakePermissionManager>,
182
+ sessionRules?: SessionRules,
183
+ ): {
184
+ resolver: PermissionResolver;
185
+ manager: ReturnType<typeof makeFakePermissionManager>;
186
+ sessionRules: SessionRules;
187
+ } {
188
+ const resolvedManager = manager ?? makeFakePermissionManager();
189
+ const resolvedRules = sessionRules ?? new SessionRules();
190
+ const resolver = new PermissionResolver(resolvedManager, resolvedRules);
191
+ return { resolver, manager: resolvedManager, sessionRules: resolvedRules };
192
+ }