@gotgenes/pi-permission-system 1.2.1 → 3.0.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 +44 -0
- package/LICENSE +1 -1
- package/README.md +93 -36
- package/config/config.example.json +6 -0
- package/package.json +1 -1
- package/schemas/permissions.schema.json +18 -4
- package/src/config-loader.ts +398 -0
- package/src/config-paths.ts +34 -0
- package/src/config-reporter.ts +16 -8
- package/src/index.ts +98 -112
- package/src/permission-manager.ts +25 -111
- package/tests/config-loader.test.ts +364 -0
- package/tests/config-paths.test.ts +78 -0
- package/tests/config-reporter.test.ts +42 -33
- package/tests/extension-config.test.ts +51 -0
- package/tests/permission-system.test.ts +9 -26
- package/tests/session-start.test.ts +8 -33
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,50 @@ 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
|
+
## [3.0.0](https://github.com/gotgenes/pi-permission-system/compare/v2.0.0...v3.0.0) (2026-05-03)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### ⚠ BREAKING CHANGES
|
|
12
|
+
|
|
13
|
+
* Config is now loaded from ~/.pi/agent/extensions/pi-permission-system/config.json (global) and <cwd>/.pi/extensions/pi-permission-system/config.json (project). Legacy paths are detected and merged with migration warnings.
|
|
14
|
+
* Config and log file paths move from the extension install directory and ~/.pi/agent/ to the extensions/<id>/ convention.
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* add config-paths module with new layout paths ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([532d2a1](https://github.com/gotgenes/pi-permission-system/commit/532d2a1f1d816c1cfba5419f7d0041382c848b31))
|
|
19
|
+
* add unified config loader ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([20143e0](https://github.com/gotgenes/pi-permission-system/commit/20143e0f7b608965d889433a6b9bbd6f9ab8b4cc))
|
|
20
|
+
* detect and merge legacy config paths ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([95046de](https://github.com/gotgenes/pi-permission-system/commit/95046de6a57d604c5f0d9fa8c13a64478ba15c89))
|
|
21
|
+
* implement config merge in unified loader ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([30b9afe](https://github.com/gotgenes/pi-permission-system/commit/30b9afe3d83940aa3ad708c9d6783bb2d4337743))
|
|
22
|
+
* update config-reporter for consolidated layout ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([96c9ef4](https://github.com/gotgenes/pi-permission-system/commit/96c9ef4964f9551b0fa89bbbc506f7660c055d74))
|
|
23
|
+
* wire index.ts to consolidated config layout ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([e7f8e5f](https://github.com/gotgenes/pi-permission-system/commit/e7f8e5f2fb094f0d291561258190d1892a1e6856))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Documentation
|
|
27
|
+
|
|
28
|
+
* plan config layout consolidation ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([eb2924d](https://github.com/gotgenes/pi-permission-system/commit/eb2924d57655d06f67891574839aebfa0586a43d))
|
|
29
|
+
* **retro:** add retro notes for issue [#20](https://github.com/gotgenes/pi-permission-system/issues/20) ([4735f0c](https://github.com/gotgenes/pi-permission-system/commit/4735f0c646a0ede11c9a76083822969eb6ca4a8f))
|
|
30
|
+
* update schema, example, and docs for consolidated config ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([39b5c01](https://github.com/gotgenes/pi-permission-system/commit/39b5c01de1c8c721e998b244e9c825a6eb05f858))
|
|
31
|
+
|
|
32
|
+
## [2.0.0](https://github.com/gotgenes/pi-permission-system/compare/v1.2.1...v2.0.0) (2026-05-03)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### ⚠ BREAKING CHANGES
|
|
36
|
+
|
|
37
|
+
* the pi-permission-system:permission-request event channel is no longer emitted. No known consumers exist; the type was never exported. Re-adding with a proper public contract is tracked
|
|
38
|
+
|
|
39
|
+
### Features
|
|
40
|
+
|
|
41
|
+
* add /build-plan prompt template for non-TDD plans ([e98f13c](https://github.com/gotgenes/pi-permission-system/commit/e98f13c2ef32f51edda58ea065635bef31365baa))
|
|
42
|
+
* delete permission-request event channel ([#20](https://github.com/gotgenes/pi-permission-system/issues/20)) ([6a41cfa](https://github.com/gotgenes/pi-permission-system/commit/6a41cfadc56e709d255538f63ff63d587e1b64f3))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
### Documentation
|
|
46
|
+
|
|
47
|
+
* plan delete permission-request event channel ([#20](https://github.com/gotgenes/pi-permission-system/issues/20)) ([e202350](https://github.com/gotgenes/pi-permission-system/commit/e2023509f9ab849f5a1d8bc28a5705b2898b912b))
|
|
48
|
+
* remove event channel from preserved-identity list ([#20](https://github.com/gotgenes/pi-permission-system/issues/20)) ([52299a2](https://github.com/gotgenes/pi-permission-system/commit/52299a27aeaed6e35849878fa224d8a78dcf0f6d))
|
|
49
|
+
* **retro:** add retro notes for issue [#22](https://github.com/gotgenes/pi-permission-system/issues/22) ([55629fe](https://github.com/gotgenes/pi-permission-system/commit/55629fed16b6d73b6d7b02698227e2adab7acd3e))
|
|
50
|
+
* update copyright in license ([b27994e](https://github.com/gotgenes/pi-permission-system/commit/b27994e7d67863ce8b28aa6bd680b60bc700d66d))
|
|
51
|
+
|
|
8
52
|
## [1.2.1](https://github.com/gotgenes/pi-permission-system/compare/v1.2.0...v1.2.1) (2026-05-03)
|
|
9
53
|
|
|
10
54
|
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Permission enforcement extension for the Pi coding agent that provides centraliz
|
|
|
6
6
|
|
|
7
7
|
> **Fork notice:** This package is a friendly fork of [MasuRii/pi-permission-system](https://github.com/MasuRii/pi-permission-system), published to npm as `@gotgenes/pi-permission-system`.
|
|
8
8
|
> This fork diverges from upstream in config layout (#10).
|
|
9
|
-
> The `/permission-system` slash command
|
|
9
|
+
> The `/permission-system` slash command name is preserved; the config and log paths are not.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -48,7 +48,7 @@ Pi auto-discovers extensions in these paths.
|
|
|
48
48
|
|
|
49
49
|
### Quick Start
|
|
50
50
|
|
|
51
|
-
1. Create the global
|
|
51
|
+
1. Create the global config file (default: `~/.pi/agent/extensions/pi-permission-system/config.json`, respects `PI_CODING_AGENT_DIR`):
|
|
52
52
|
|
|
53
53
|
```jsonc
|
|
54
54
|
{
|
|
@@ -57,12 +57,12 @@ Pi auto-discovers extensions in these paths.
|
|
|
57
57
|
"bash": "ask",
|
|
58
58
|
"mcp": "ask",
|
|
59
59
|
"skills": "ask",
|
|
60
|
-
"special": "ask"
|
|
60
|
+
"special": "ask"
|
|
61
61
|
},
|
|
62
62
|
"tools": {
|
|
63
63
|
"read": "allow",
|
|
64
|
-
"write": "deny"
|
|
65
|
-
}
|
|
64
|
+
"write": "deny"
|
|
65
|
+
}
|
|
66
66
|
}
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -100,36 +100,60 @@ The extension integrates via Pi's lifecycle hooks:
|
|
|
100
100
|
|
|
101
101
|
## Configuration
|
|
102
102
|
|
|
103
|
-
###
|
|
103
|
+
### Config File
|
|
104
|
+
|
|
105
|
+
**Location:** one unified config file per scope, following the `pi-autoformat` convention:
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
| Scope | Path |
|
|
108
|
+
| ------- | ------------------------------------------------------------------------------------------------- |
|
|
109
|
+
| Global | `~/.pi/agent/extensions/pi-permission-system/config.json` (respects `PI_CODING_AGENT_DIR`) |
|
|
110
|
+
| Project | `<cwd>/.pi/extensions/pi-permission-system/config.json` |
|
|
106
111
|
|
|
107
|
-
|
|
112
|
+
Project config overrides global config; per-agent frontmatter overrides both.
|
|
113
|
+
Object-shaped fields (`defaultPolicy`, `tools`, `bash`, `mcp`, `skills`, `special`) use shallow-merge (later source wins per-key).
|
|
114
|
+
Scalar fields (`debugLog`, `permissionReviewLog`, `yoloMode`) use simple replacement.
|
|
108
115
|
|
|
109
|
-
|
|
116
|
+
The config file combines runtime knobs and permission policy in one object:
|
|
117
|
+
|
|
118
|
+
```jsonc
|
|
110
119
|
{
|
|
120
|
+
"$schema": "https://raw.githubusercontent.com/gotgenes/pi-permission-system/main/schemas/permissions.schema.json",
|
|
121
|
+
|
|
122
|
+
// Runtime knobs
|
|
111
123
|
"debugLog": false,
|
|
112
124
|
"permissionReviewLog": true,
|
|
113
|
-
"yoloMode": false
|
|
125
|
+
"yoloMode": false,
|
|
126
|
+
|
|
127
|
+
// Policy
|
|
128
|
+
"defaultPolicy": {
|
|
129
|
+
"tools": "ask",
|
|
130
|
+
"bash": "ask",
|
|
131
|
+
"mcp": "ask",
|
|
132
|
+
"skills": "ask",
|
|
133
|
+
"special": "ask"
|
|
134
|
+
},
|
|
135
|
+
"tools": { "read": "allow", "write": "deny" },
|
|
136
|
+
"bash": { "git status": "allow", "git *": "ask" },
|
|
137
|
+
"mcp": { "mcp_status": "allow" },
|
|
138
|
+
"skills": { "*": "ask" },
|
|
139
|
+
"special": { "doom_loop": "deny", "external_directory": "ask" }
|
|
114
140
|
}
|
|
115
141
|
```
|
|
116
142
|
|
|
143
|
+
#### Runtime knobs
|
|
144
|
+
|
|
117
145
|
| Key | Default | Description |
|
|
118
146
|
| --------------------- | ------- | ------------------------------------------------------------------------------------------------------- |
|
|
119
147
|
| `debugLog` | `false` | Enables verbose diagnostic logging to `logs/pi-permission-system-debug.jsonl` |
|
|
120
148
|
| `permissionReviewLog` | `true` | Enables the permission request/denial review log at `logs/pi-permission-system-permission-review.jsonl` |
|
|
121
149
|
| `yoloMode` | `false` | Auto-approves `ask` results instead of prompting when yolo mode is enabled |
|
|
122
150
|
|
|
123
|
-
Both logs write to
|
|
151
|
+
Both logs write to `~/.pi/agent/extensions/pi-permission-system/logs/`.
|
|
152
|
+
No debug output is printed to the terminal.
|
|
124
153
|
|
|
125
|
-
|
|
126
|
-
> The extension warns at startup when it detects misplaced keys.
|
|
154
|
+
#### Policy sections
|
|
127
155
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
**Location:** global Pi policy file (default: `~/.pi/agent/pi-permissions.jsonc`, respects `PI_CODING_AGENT_DIR`)
|
|
131
|
-
|
|
132
|
-
The policy file is a JSON object with these sections:
|
|
156
|
+
The config file is a JSON object with these policy sections:
|
|
133
157
|
|
|
134
158
|
| Section | Description |
|
|
135
159
|
| --------------- | ---------------------------------------------------------------------------- |
|
|
@@ -169,21 +193,22 @@ permission:
|
|
|
169
193
|
|
|
170
194
|
**Limitations:** The frontmatter parser is intentionally minimal. Use only `key: value` scalars and nested maps. Avoid arrays, multi-line scalars, and YAML anchors.
|
|
171
195
|
|
|
172
|
-
### Project-Level
|
|
196
|
+
### Project-Level Config and Overrides
|
|
173
197
|
|
|
174
|
-
|
|
198
|
+
Project-local config uses the same format as the global config file.
|
|
199
|
+
Per-agent overrides use YAML frontmatter in the project agents directory:
|
|
175
200
|
|
|
176
|
-
| Scope | Path
|
|
177
|
-
| ---------------------- |
|
|
178
|
-
| Project
|
|
179
|
-
| Project agent override | `<cwd>/.pi/agent/agents/<agent>.md`
|
|
201
|
+
| Scope | Path |
|
|
202
|
+
| ---------------------- | ------------------------------------------------------------- |
|
|
203
|
+
| Project config | `<cwd>/.pi/extensions/pi-permission-system/config.json` |
|
|
204
|
+
| Project agent override | `<cwd>/.pi/agent/agents/<agent>.md` |
|
|
180
205
|
|
|
181
|
-
|
|
206
|
+
These project files are resolved from Pi's current session `cwd`, so they are workspace-specific and do **not** move under `PI_CODING_AGENT_DIR`.
|
|
182
207
|
|
|
183
208
|
**Precedence order:**
|
|
184
209
|
|
|
185
|
-
1. Global
|
|
186
|
-
2. Project
|
|
210
|
+
1. Global config file
|
|
211
|
+
2. Project config file
|
|
187
212
|
3. Global agent frontmatter
|
|
188
213
|
4. Project agent frontmatter
|
|
189
214
|
|
|
@@ -454,7 +479,7 @@ When the extension prompts, denies, or forwards permission requests, it can appe
|
|
|
454
479
|
|
|
455
480
|
```text
|
|
456
481
|
Default global logs directory: ~/.pi/agent/extensions/pi-permission-system/logs/
|
|
457
|
-
Actual global logs directory: $PI_CODING_AGENT_DIR/extensions/pi-permission-system/logs when PI_CODING_AGENT_DIR is set
|
|
482
|
+
Actual global logs directory: $PI_CODING_AGENT_DIR/extensions/pi-permission-system/logs/ when PI_CODING_AGENT_DIR is set
|
|
458
483
|
```
|
|
459
484
|
|
|
460
485
|
- `pi-permission-system-permission-review.jsonl` — enabled by default for permission review/audit history, including bounded `toolInputPreview` values for non-bash/non-MCP tool calls
|
|
@@ -466,16 +491,17 @@ This makes it easy to verify which files the extension actually loaded:
|
|
|
466
491
|
```jsonc
|
|
467
492
|
{
|
|
468
493
|
"event": "config.resolved",
|
|
469
|
-
"
|
|
470
|
-
"
|
|
471
|
-
"
|
|
472
|
-
"
|
|
473
|
-
"projectConfigPath": "/…/my-project/.pi/agent/pi-permissions.jsonc",
|
|
474
|
-
"projectConfigExists": true,
|
|
494
|
+
"globalConfigPath": "/…/.pi/agent/extensions/pi-permission-system/config.json",
|
|
495
|
+
"globalConfigExists": true,
|
|
496
|
+
"projectConfigPath": "/…/my-project/.pi/extensions/pi-permission-system/config.json",
|
|
497
|
+
"projectConfigExists": false,
|
|
475
498
|
"agentsDir": "/…/.pi/agent/agents",
|
|
476
499
|
"agentsDirExists": true,
|
|
477
500
|
"projectAgentsDir": "/…/my-project/.pi/agent/agents",
|
|
478
501
|
"projectAgentsDirExists": false,
|
|
502
|
+
"legacyGlobalPolicyDetected": false,
|
|
503
|
+
"legacyProjectPolicyDetected": false,
|
|
504
|
+
"legacyExtensionConfigDetected": false
|
|
479
505
|
}
|
|
480
506
|
```
|
|
481
507
|
|
|
@@ -485,8 +511,10 @@ This makes it easy to verify which files the extension actually loaded:
|
|
|
485
511
|
index.ts → Root Pi entrypoint shim
|
|
486
512
|
src/
|
|
487
513
|
├── index.ts → Extension bootstrap, permission checks, readable prompts, review logging, reload handling, and subagent forwarding
|
|
514
|
+
├── config-loader.ts → Unified config loader, merger, and legacy-path detection
|
|
515
|
+
├── config-paths.ts → Path derivation for global, project, and legacy config locations
|
|
488
516
|
├── config-reporter.ts → Resolved config path reporting for diagnostic logs
|
|
489
|
-
├── extension-config.ts →
|
|
517
|
+
├── extension-config.ts → Runtime config normalization and defaults
|
|
490
518
|
├── logging.ts → File-only debug/review logging helpers
|
|
491
519
|
├── permission-manager.ts → Global/project policy loading, merging, and resolution with caching
|
|
492
520
|
├── skill-prompt-sanitizer.ts → Skill prompt parsing, multi-block sanitization, and skill-read path matching
|
|
@@ -553,11 +581,40 @@ npx --yes ajv-cli@5 validate \
|
|
|
553
581
|
|
|
554
582
|
---
|
|
555
583
|
|
|
584
|
+
## Migration from pre-v2 layout
|
|
585
|
+
|
|
586
|
+
Before v2, config was split across two files:
|
|
587
|
+
|
|
588
|
+
- Policy: `~/.pi/agent/pi-permissions.jsonc`
|
|
589
|
+
- Runtime knobs: `<extension-install-dir>/config.json`
|
|
590
|
+
|
|
591
|
+
These are now consolidated into one file.
|
|
592
|
+
The extension detects legacy files and merges them with a warning for one release.
|
|
593
|
+
To migrate manually:
|
|
594
|
+
|
|
595
|
+
```bash
|
|
596
|
+
# Move the global policy file
|
|
597
|
+
mkdir -p ~/.pi/agent/extensions/pi-permission-system
|
|
598
|
+
mv ~/.pi/agent/pi-permissions.jsonc ~/.pi/agent/extensions/pi-permission-system/config.json
|
|
599
|
+
|
|
600
|
+
# If you had project-level policy:
|
|
601
|
+
mkdir -p .pi/extensions/pi-permission-system
|
|
602
|
+
mv .pi/agent/pi-permissions.jsonc .pi/extensions/pi-permission-system/config.json
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
Then add any runtime knobs (`debugLog`, `permissionReviewLog`, `yoloMode`) to the same file.
|
|
606
|
+
The old extension-root `config.json` is no longer read from the install directory.
|
|
607
|
+
|
|
608
|
+
> **Note:** Logs also moved from `<extension-install-dir>/logs/` to `~/.pi/agent/extensions/pi-permission-system/logs/`.
|
|
609
|
+
> Old log files are not deleted or migrated — they remain readable but no new entries are appended.
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
556
613
|
## Troubleshooting
|
|
557
614
|
|
|
558
615
|
| Problem | Cause | Solution |
|
|
559
616
|
| ------------------------------------ | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
560
|
-
| Config not applied (everything asks) | File not found or parse error | Verify the global
|
|
617
|
+
| Config not applied (everything asks) | File not found or parse error | Verify the global config at `~/.pi/agent/extensions/pi-permission-system/config.json` (respects `PI_CODING_AGENT_DIR`); check for trailing commas |
|
|
561
618
|
| Per-agent override not applied | Frontmatter parsing issue | Ensure `---` delimiters at file top; keep YAML simple; restart session |
|
|
562
619
|
| Tool blocked as unregistered | Unknown tool name | Use a registered `mcp` tool for server tools: `{ "tool": "server:tool" }` |
|
|
563
620
|
| `/skill:<name>` blocked | Deny policy or confirmation unavailable | Check merged `skills` policy (global/project/agent layers). Active agent context is optional in the main session; `ask` still requires UI or forwarded confirmation. |
|
package/package.json
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://pi-
|
|
4
|
-
"title": "PI Permission Configuration",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/gotgenes/pi-permission-system/main/schemas/permissions.schema.json",
|
|
4
|
+
"title": "PI Permission System Configuration",
|
|
5
|
+
"description": "Unified config file combining runtime knobs and permission policy for pi-permission-system.",
|
|
5
6
|
"type": "object",
|
|
6
7
|
"additionalProperties": false,
|
|
7
8
|
"properties": {
|
|
8
9
|
"$schema": {
|
|
9
10
|
"type": "string"
|
|
10
11
|
},
|
|
12
|
+
"debugLog": {
|
|
13
|
+
"description": "Write verbose permission-system diagnostics to the extension logs directory.",
|
|
14
|
+
"type": "boolean",
|
|
15
|
+
"default": false
|
|
16
|
+
},
|
|
17
|
+
"permissionReviewLog": {
|
|
18
|
+
"description": "Write permission request and decision audit events to the extension logs directory.",
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"default": true
|
|
21
|
+
},
|
|
22
|
+
"yoloMode": {
|
|
23
|
+
"description": "Auto-approve ask-state permission checks, including subagent approval forwarding.",
|
|
24
|
+
"type": "boolean",
|
|
25
|
+
"default": false
|
|
26
|
+
},
|
|
11
27
|
"defaultPolicy": {
|
|
12
28
|
"type": "object",
|
|
13
29
|
"additionalProperties": false,
|
|
14
|
-
"required": ["tools", "bash", "mcp", "skills"],
|
|
15
30
|
"properties": {
|
|
16
31
|
"tools": {
|
|
17
32
|
"$ref": "#/$defs/permissionState"
|
|
@@ -57,7 +72,6 @@
|
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
},
|
|
60
|
-
"required": ["defaultPolicy"],
|
|
61
75
|
"$defs": {
|
|
62
76
|
"permissionState": {
|
|
63
77
|
"type": "string",
|