@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.
Files changed (64) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/src/agent-prep-session.ts +28 -0
  5. package/src/decision-reporter.ts +41 -0
  6. package/src/denial-messages.ts +11 -0
  7. package/src/forwarded-permissions/permission-forwarder.ts +549 -0
  8. package/src/forwarding-manager.ts +3 -7
  9. package/src/gate-handler-session.ts +13 -0
  10. package/src/gate-prompter.ts +14 -0
  11. package/src/handlers/before-agent-start.ts +2 -3
  12. package/src/handlers/gates/bash-command.ts +4 -18
  13. package/src/handlers/gates/bash-external-directory.ts +3 -15
  14. package/src/handlers/gates/bash-path.ts +3 -16
  15. package/src/handlers/gates/descriptor.ts +0 -28
  16. package/src/handlers/gates/path.ts +3 -15
  17. package/src/handlers/gates/runner.ts +142 -105
  18. package/src/handlers/gates/skill-input-gate-pipeline.ts +104 -0
  19. package/src/handlers/gates/skill-input.ts +44 -0
  20. package/src/handlers/gates/tool-call-gate-pipeline.ts +120 -0
  21. package/src/handlers/lifecycle.ts +9 -9
  22. package/src/handlers/permission-gate-handler.ts +34 -238
  23. package/src/index.ts +49 -69
  24. package/src/mcp-targets.ts +56 -46
  25. package/src/permission-prompter.ts +7 -58
  26. package/src/permission-resolver.ts +17 -0
  27. package/src/permission-session.ts +77 -9
  28. package/src/permissions-service.ts +53 -0
  29. package/src/service-lifecycle.ts +49 -0
  30. package/src/session-approval-recorder.ts +6 -0
  31. package/src/session-lifecycle-session.ts +24 -0
  32. package/src/tool-input-preview.ts +0 -62
  33. package/src/tool-input-prompt-formatters.ts +63 -0
  34. package/src/tool-preview-formatter.ts +6 -4
  35. package/test/decision-reporter.test.ts +112 -0
  36. package/test/denial-messages.test.ts +62 -0
  37. package/test/forwarding-manager.test.ts +26 -44
  38. package/test/handlers/before-agent-start.test.ts +45 -21
  39. package/test/handlers/external-directory-integration.test.ts +86 -22
  40. package/test/handlers/external-directory-session-dedup.test.ts +102 -55
  41. package/test/handlers/gates/bash-command.test.ts +49 -90
  42. package/test/handlers/gates/bash-external-directory.test.ts +54 -95
  43. package/test/handlers/gates/bash-path.test.ts +63 -148
  44. package/test/handlers/gates/path.test.ts +38 -105
  45. package/test/handlers/gates/runner.test.ts +150 -93
  46. package/test/handlers/gates/skill-input-gate-pipeline.test.ts +176 -0
  47. package/test/handlers/gates/skill-input.test.ts +128 -0
  48. package/test/handlers/gates/tool-call-gate-pipeline.test.ts +180 -0
  49. package/test/handlers/input.test.ts +1 -2
  50. package/test/handlers/lifecycle.test.ts +49 -33
  51. package/test/handlers/tool-call-events.test.ts +1 -1
  52. package/test/helpers/gate-fixtures.ts +147 -16
  53. package/test/helpers/handler-fixtures.ts +143 -27
  54. package/test/mcp-targets.test.ts +55 -0
  55. package/test/permission-forwarder.test.ts +295 -0
  56. package/test/permission-forwarding.test.ts +0 -282
  57. package/test/permission-prompter.test.ts +33 -44
  58. package/test/permission-session.test.ts +160 -27
  59. package/test/permissions-service.test.ts +151 -0
  60. package/test/runtime.test.ts +0 -4
  61. package/test/service-lifecycle.test.ts +162 -0
  62. package/test/tool-input-preview.test.ts +0 -111
  63. package/test/tool-input-prompt-formatters.test.ts +115 -0
  64. package/src/forwarded-permissions/polling.ts +0 -411
package/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [10.1.0](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v10.0.0...pi-permission-system-v10.1.0) (2026-06-03)
9
+
10
+
11
+ ### Features
12
+
13
+ * add DecisionReporter and GateDecisionReporter ([530211d](https://github.com/gotgenes/pi-packages/commit/530211da9158a012e86f37311e326f4e2b571c55))
14
+ * add GatePrompter and SessionApprovalRecorder session roles ([2f761e4](https://github.com/gotgenes/pi-packages/commit/2f761e44fd07c98fe98147275f75fc170163b06d))
15
+ * add GateRunner class consolidating gate dispatch ([a390558](https://github.com/gotgenes/pi-packages/commit/a390558f19723fa911924b2d1878d4d874d6966d))
16
+ * add getToolPreviewLimits and getInfrastructureReadDirs to PermissionSession ([#327](https://github.com/gotgenes/pi-packages/issues/327)) ([a0bf166](https://github.com/gotgenes/pi-packages/commit/a0bf1662119eeeb4b390c668c6993c7ff87194bf))
17
+ * add PermissionResolver.resolve to PermissionSession ([c922bbd](https://github.com/gotgenes/pi-packages/commit/c922bbddcfb47a2ec88d349f3a797b633bd58f45))
18
+ * add skill_input denial context ([#326](https://github.com/gotgenes/pi-packages/issues/326)) ([71e9d28](https://github.com/gotgenes/pi-packages/commit/71e9d28c5f6c8a09d2bfa9fe21cca6c55948898b))
19
+ * introduce SkillInputGatePipeline collaborator ([#329](https://github.com/gotgenes/pi-packages/issues/329)) ([4ddd5af](https://github.com/gotgenes/pi-packages/commit/4ddd5af1c476ab3c3eb29ce456a33b273c386ca0))
20
+ * introduce ToolCallGatePipeline collaborator ([#327](https://github.com/gotgenes/pi-packages/issues/327)) ([3a87727](https://github.com/gotgenes/pi-packages/commit/3a877274091bfc2db3998ca915f76ecbdd2ac1e7))
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * drop vestigial events field; document makeReporter in package skill ([9e0a8a7](https://github.com/gotgenes/pi-packages/commit/9e0a8a7d89b4c081d21465e02b7aa77c18ddd1b0))
26
+
27
+
28
+ ### Documentation
29
+
30
+ * document SkillInputGatePipeline in architecture and package skill ([#329](https://github.com/gotgenes/pi-packages/issues/329)) ([9193c86](https://github.com/gotgenes/pi-packages/commit/9193c86ecc2fa6b18da6a7c7e4a9f9efbbc807ed))
31
+ * record the composition-root collaborator extraction ([#320](https://github.com/gotgenes/pi-packages/issues/320)) ([dab8890](https://github.com/gotgenes/pi-packages/commit/dab8890df05e003bb9136924ab2d344c7fe69319))
32
+ * standardize and correct package READMEs ([4c270ad](https://github.com/gotgenes/pi-packages/commit/4c270adac97ca816fa1889a879d1d4fe19cdd464))
33
+
8
34
  ## [10.0.0](https://github.com/gotgenes/pi-packages/compare/pi-permission-system-v9.2.0...pi-permission-system-v10.0.0) (2026-06-02)
9
35
 
10
36
 
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # @gotgenes/pi-permission-system
6
6
 
7
- [![npm version](https://img.shields.io/npm/v/@gotgenes/pi-permission-system?style=flat&logo=npm&logoColor=white)](https://www.npmjs.com/package/@gotgenes/pi-permission-system) [![CI](https://img.shields.io/github/actions/workflow/status/gotgenes/pi-permission-system/ci.yml?style=flat&logo=github&label=CI)](https://github.com/gotgenes/pi-permission-system/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/TypeScript-6.x-3178C6?style=flat&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![Pi Package](https://img.shields.io/badge/Pi-Package-6366F1?style=flat)](https://pi.mariozechner.at/)
7
+ [![npm version](https://img.shields.io/npm/v/@gotgenes/pi-permission-system?style=flat&logo=npm&logoColor=white)](https://www.npmjs.com/package/@gotgenes/pi-permission-system) [![CI](https://img.shields.io/github/actions/workflow/status/gotgenes/pi-packages/ci.yml?style=flat&logo=github&label=CI)](https://github.com/gotgenes/pi-packages/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/TypeScript-6.x-3178C6?style=flat&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![pnpm](https://img.shields.io/badge/pnpm-%3E%3D11-F69220?style=flat&logo=pnpm&logoColor=white)](https://pnpm.io/) [![Pi Package](https://img.shields.io/badge/Pi-Package-6366F1?style=flat)](https://pi.mariozechner.at/)
8
8
 
9
9
  Permission enforcement extension for the [Pi](https://pi.mariozechner.at/) coding agent that provides centralized, deterministic permission gates over tool, bash, MCP, skill, and special operations.
10
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-permission-system",
3
- "version": "10.0.0",
3
+ "version": "10.1.0",
4
4
  "description": "Permission enforcement extension for the Pi coding agent.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -0,0 +1,28 @@
1
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+
3
+ import type { GateHandlerSession } from "./gate-handler-session";
4
+ import type {
5
+ SkillPermissionChecker,
6
+ SkillPromptEntry,
7
+ } from "./skill-prompt-sanitizer";
8
+ import type { PermissionState } from "./types";
9
+
10
+ /**
11
+ * The session surface `AgentPrepHandler` invokes during `before_agent_start`:
12
+ * bind context + identify the agent (via {@link GateHandlerSession}), check
13
+ * skill permissions for prompt sanitization (via {@link SkillPermissionChecker}),
14
+ * refresh config, decide tool exposure, manage the active-tools / prompt-state
15
+ * cache keys, and store the resolved skill entries.
16
+ */
17
+ export interface AgentPrepSession
18
+ extends GateHandlerSession,
19
+ SkillPermissionChecker {
20
+ refreshConfig(ctx?: ExtensionContext): void;
21
+ getToolPermission(toolName: string, agentName?: string): PermissionState;
22
+ shouldUpdateActiveTools(cacheKey: string): boolean;
23
+ commitActiveToolsCacheKey(cacheKey: string): void;
24
+ getPolicyCacheStamp(agentName?: string): string;
25
+ shouldUpdatePromptState(cacheKey: string): boolean;
26
+ commitPromptStateCacheKey(cacheKey: string): void;
27
+ setActiveSkillEntries(entries: SkillPromptEntry[]): void;
28
+ }
@@ -0,0 +1,41 @@
1
+ import {
2
+ emitDecisionEvent,
3
+ type PermissionDecisionEvent,
4
+ type PermissionEventBus,
5
+ } from "./permission-events";
6
+ import type { SessionLogger } from "./session-logger";
7
+
8
+ /**
9
+ * Reports a permission gate's outcome to the review log and the decision
10
+ * channel. Groups the two side effects that always travel together:
11
+ * writing a structured review-log entry and broadcasting a decision event.
12
+ */
13
+ export interface DecisionReporter {
14
+ writeReviewLog(event: string, details: Record<string, unknown>): void;
15
+ emitDecision(event: PermissionDecisionEvent): void;
16
+ }
17
+
18
+ /**
19
+ * Owns the `SessionLogger` and the event bus so neither the handler nor
20
+ * the runner has to reach through the session to its logger or close over
21
+ * the event bus directly.
22
+ *
23
+ * Built once in `PermissionGateHandler`'s constructor; shared between
24
+ * `handleToolCall` (gate runner + bypass branch) and `handleInput`.
25
+ *
26
+ * Answers "who owns the event bus" — the reporter does, not the session.
27
+ */
28
+ export class GateDecisionReporter implements DecisionReporter {
29
+ constructor(
30
+ private readonly logger: SessionLogger,
31
+ private readonly events: PermissionEventBus,
32
+ ) {}
33
+
34
+ writeReviewLog(event: string, details: Record<string, unknown>): void {
35
+ this.logger.review(event, details);
36
+ }
37
+
38
+ emitDecision(event: PermissionDecisionEvent): void {
39
+ emitDecisionEvent(this.events, event);
40
+ }
41
+ }
@@ -45,6 +45,11 @@ export type DenialContext =
45
45
  skillName: string;
46
46
  readPath: string;
47
47
  agentName?: string;
48
+ }
49
+ | {
50
+ kind: "skill_input";
51
+ skillName: string;
52
+ agentName?: string;
48
53
  };
49
54
 
50
55
  // ── Public formatter API ───────────────────────────────────────────────────
@@ -91,6 +96,8 @@ function buildDenyBody(ctx: DenialContext): string {
91
96
  return `${subject(ctx.agentName)} is not permitted to access path '${ctx.pathValue}' via tool 'bash'.`;
92
97
  case "skill_read":
93
98
  return `${subject(ctx.agentName)} is not permitted to access skill '${ctx.skillName}' via '${ctx.readPath}'.`;
99
+ case "skill_input":
100
+ return `${subject(ctx.agentName)} is not permitted to access skill '${ctx.skillName}'.`;
94
101
  }
95
102
  }
96
103
 
@@ -184,6 +191,8 @@ function buildUnavailableBody(ctx: DenialContext): string {
184
191
  return `Bash command '${ctx.command}' accesses path '${ctx.pathValue}' which requires approval, but no interactive UI is available.`;
185
192
  case "skill_read":
186
193
  return `Accessing skill '${ctx.skillName}' requires approval, but no interactive UI is available.`;
194
+ case "skill_input":
195
+ return `Accessing skill '${ctx.skillName}' requires approval, but no interactive UI is available.`;
187
196
  }
188
197
  }
189
198
 
@@ -212,6 +221,8 @@ function buildUserDeniedBody(
212
221
  return `User denied path access for bash command '${ctx.command}' (path '${ctx.pathValue}').${reasonSuffix(denialReason)}`;
213
222
  case "skill_read":
214
223
  return `User denied access to skill '${ctx.skillName}'.${reasonSuffix(denialReason)}`;
224
+ case "skill_input":
225
+ return `User denied access to skill '${ctx.skillName}'.${reasonSuffix(denialReason)}`;
215
226
  }
216
227
  }
217
228