pi-permission-system 0.2.0 → 0.2.2
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 +29 -0
- package/README.md +66 -30
- package/config.json +4 -0
- package/package.json +60 -59
- package/schemas/permissions.schema.json +2 -0
- package/src/extension-config.ts +106 -0
- package/src/index.ts +341 -36
- package/src/logging.ts +94 -0
- package/src/permission-manager.ts +13 -34
- package/src/test.ts +173 -23
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,35 @@ 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
|
+
## [0.2.2] - 2026-03-13
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Removed delegation task restriction logic — the `task` tool is no longer restricted to orchestrator agent only
|
|
12
|
+
- Simplified tool permission lookup to use explicit `tools` entries for arbitrary registered tools instead of MCP fallback
|
|
13
|
+
- Renamed `TOOL_PERMISSION_NAMES` to `BUILT_IN_TOOL_PERMISSION_NAMES` to clarify it covers only canonical Pi tools
|
|
14
|
+
- Updated schema descriptions for `tools` and `mcp` fields to guide configuration usage
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
- Removed delegation-specific permission checks (`isDelegationAllowedAgent`, `getDelegationBlockReason`) from permission evaluation
|
|
18
|
+
|
|
19
|
+
### Tests
|
|
20
|
+
- Added comprehensive test coverage for tool permission lookup behavior
|
|
21
|
+
|
|
22
|
+
## [0.2.1] - 2026-03-13
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Extension configuration system (`config.json`) with `debugLog` and `permissionReviewLog` options
|
|
26
|
+
- JSONL debug logging to `logs/pi-permission-system-debug.jsonl` when `debugLog` is enabled
|
|
27
|
+
- JSONL permission review logging to `logs/pi-permission-system-permission-review.jsonl` for auditing
|
|
28
|
+
- Permission request event emission on `pi-permission-system:permission-request` channel for external consumers
|
|
29
|
+
- New `extension-config.ts` module for config file management and path resolution
|
|
30
|
+
- New `logging.ts` module with `createPermissionSystemLogger` for structured log output
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- Replaced `console.warn`/`console.error` calls with structured logging to file
|
|
34
|
+
- Permission forwarding now logs request creation, response received, timeout, and user prompts
|
|
35
|
+
- Updated README documentation to cover extension config, logging, and event emission
|
|
36
|
+
|
|
8
37
|
## [0.2.0] - 2026-03-12
|
|
9
38
|
|
|
10
39
|
### Added
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🔐 pi-permission-system
|
|
2
2
|
|
|
3
|
-
[](package.json)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
6
|
Permission enforcement extension for the Pi coding agent that provides centralized, deterministic permission gates for tool, bash, MCP, skill, and special operations.
|
|
@@ -17,6 +17,8 @@ Permission enforcement extension for the Pi coding agent that provides centraliz
|
|
|
17
17
|
- **Skill Protection** — Controls which skills can be loaded or read from disk
|
|
18
18
|
- **Per-Agent Overrides** — Agent-specific permission policies via YAML frontmatter
|
|
19
19
|
- **Subagent Permission Forwarding** — Forwards `ask` confirmations from non-UI subagents back to the main interactive session
|
|
20
|
+
- **File-Based Review Logging** — Writes permission request/denial review entries to a file by default for later auditing
|
|
21
|
+
- **Optional Debug Logging** — Keeps verbose extension diagnostics in a separate file when enabled in `config.json`
|
|
20
22
|
- **JSON Schema Validation** — Full schema for editor autocomplete and config validation
|
|
21
23
|
|
|
22
24
|
## Installation
|
|
@@ -77,26 +79,46 @@ The extension integrates via Pi's lifecycle hooks:
|
|
|
77
79
|
**Additional behaviors:**
|
|
78
80
|
- Unknown/unregistered tools are blocked before permission checks (prevents bypass attempts)
|
|
79
81
|
- The `Available tools:` system prompt section is rewritten to match the filtered active tool set
|
|
80
|
-
-
|
|
82
|
+
- Extension-provided tools like `task`, `mcp`, and third-party tools are handled by exact registered name instead of private built-in hardcodes
|
|
81
83
|
- When a subagent hits an `ask` permission without direct UI access, the request can be forwarded to the main interactive session for confirmation
|
|
82
84
|
- When a subagent triggers an `ask` permission without UI access, the request can be forwarded to the main session and answered there
|
|
83
85
|
|
|
84
86
|
## Configuration
|
|
85
87
|
|
|
88
|
+
### Extension Config File
|
|
89
|
+
|
|
90
|
+
**Location:** `~/.pi/agent/extensions/pi-permission-system/config.json`
|
|
91
|
+
|
|
92
|
+
The extension creates this file automatically when it is missing. It controls only extension-local logging behavior:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"debugLog": false,
|
|
97
|
+
"permissionReviewLog": true
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| Key | Default | Description |
|
|
102
|
+
|-----|---------|-------------|
|
|
103
|
+
| `debugLog` | `false` | Enables verbose diagnostic logging to `logs/pi-permission-system-debug.jsonl` |
|
|
104
|
+
| `permissionReviewLog` | `true` | Enables the permission request/denial review log at `logs/pi-permission-system-permission-review.jsonl` |
|
|
105
|
+
|
|
106
|
+
Both logs write to files only under the extension directory. No debug output is printed to the terminal.
|
|
107
|
+
|
|
86
108
|
### Global Policy File
|
|
87
109
|
|
|
88
110
|
**Location:** `~/.pi/agent/pi-permissions.jsonc`
|
|
89
111
|
|
|
90
112
|
The policy file is a JSON object with these sections:
|
|
91
113
|
|
|
92
|
-
| Section | Description
|
|
93
|
-
|
|
94
|
-
| `defaultPolicy` | Fallback permissions per category
|
|
95
|
-
| `tools` |
|
|
96
|
-
| `bash` | Command pattern permissions
|
|
97
|
-
| `mcp` | MCP server/tool permissions
|
|
98
|
-
| `skills` | Skill name pattern permissions
|
|
99
|
-
| `special` | Reserved permission checks
|
|
114
|
+
| Section | Description |
|
|
115
|
+
|-----------------|-----------------------------------------------------|
|
|
116
|
+
| `defaultPolicy` | Fallback permissions per category |
|
|
117
|
+
| `tools` | Exact-name tool permissions for registered tools |
|
|
118
|
+
| `bash` | Command pattern permissions |
|
|
119
|
+
| `mcp` | MCP server/tool permissions for calls routed through a registered `mcp` tool |
|
|
120
|
+
| `skills` | Skill name pattern permissions |
|
|
121
|
+
| `special` | Reserved permission checks |
|
|
100
122
|
|
|
101
123
|
> **Note:** Trailing commas are **not** supported. If parsing fails, the extension falls back to `ask` for all categories.
|
|
102
124
|
|
|
@@ -125,7 +147,7 @@ permission:
|
|
|
125
147
|
|
|
126
148
|
**Precedence:** Agent frontmatter overrides global config (shallow-merged per section).
|
|
127
149
|
|
|
128
|
-
**MCP behavior:** `permission.tools.mcp` is the coarse entry/fallback permission for
|
|
150
|
+
**MCP behavior:** `permission.tools.mcp` is the coarse entry/fallback permission for a registered `mcp` tool when one is available. More specific `permission.mcp` target rules override that fallback when they match.
|
|
129
151
|
|
|
130
152
|
**Limitations:** The frontmatter parser is intentionally minimal. Use only `key: value` scalars and nested maps. Avoid arrays, multi-line scalars, and YAML anchors.
|
|
131
153
|
|
|
@@ -151,33 +173,34 @@ Sets fallback permissions when no specific rule matches:
|
|
|
151
173
|
|
|
152
174
|
### `tools`
|
|
153
175
|
|
|
154
|
-
Controls
|
|
176
|
+
Controls tools by exact registered name (no wildcards). This is the recommended standalone format for **all** tool entries, including Pi built-ins and arbitrary third-party extension tools.
|
|
155
177
|
|
|
156
|
-
| Tool
|
|
157
|
-
|
|
158
|
-
| `bash`
|
|
159
|
-
| `read`
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `find` | File discovery |
|
|
164
|
-
| `ls` | Directory listing |
|
|
165
|
-
| `mcp` | MCP proxy tool entry/fallback |
|
|
178
|
+
| Tool name example | Description |
|
|
179
|
+
|-----------------------|-------------|
|
|
180
|
+
| `bash` | Shell command execution (tool-level fallback before `bash` pattern rules) |
|
|
181
|
+
| `read` / `write` | Canonical Pi built-in file tools |
|
|
182
|
+
| `mcp` | Registered MCP proxy tool entry/fallback when available |
|
|
183
|
+
| `task` | Delegation tool handled like any other registered extension tool |
|
|
184
|
+
| `third_party_tool` | Arbitrary registered extension tool |
|
|
166
185
|
|
|
167
186
|
```jsonc
|
|
168
187
|
{
|
|
169
188
|
"tools": {
|
|
170
189
|
"read": "allow",
|
|
171
190
|
"write": "deny",
|
|
172
|
-
"
|
|
173
|
-
"
|
|
191
|
+
"mcp": "allow",
|
|
192
|
+
"third_party_tool": "ask"
|
|
174
193
|
}
|
|
175
194
|
}
|
|
176
195
|
```
|
|
177
196
|
|
|
197
|
+
Unknown or absent tools are not required in the config. If another extension is not installed, its tool simply will not be registered at runtime, and this extension will block attempts to call that missing tool before permission checks run.
|
|
198
|
+
|
|
178
199
|
> **Note:** Setting `tools.bash` affects the *default* for bash commands, but `bash` patterns can provide command-level overrides.
|
|
179
200
|
>
|
|
180
|
-
> **Note:** Setting `tools.mcp` controls coarse access to
|
|
201
|
+
> **Note:** Setting `tools.mcp` controls coarse access to a registered `mcp` tool when one is available. Specific `mcp` rules still override it when a target pattern matches.
|
|
202
|
+
>
|
|
203
|
+
> **Note:** Top-level shorthand is only supported for the canonical Pi built-ins (`bash`, `read`, `write`, `edit`, `grep`, `find`, `ls`) in agent frontmatter. Use `permission.tools.<name>` for `mcp`, `task`, and any third-party tool.
|
|
181
204
|
|
|
182
205
|
### `bash`
|
|
183
206
|
|
|
@@ -219,7 +242,7 @@ MCP permissions match against derived targets from tool input. These rules are m
|
|
|
219
242
|
|
|
220
243
|
#### MCP Tool Fallback via `tools.mcp`
|
|
221
244
|
|
|
222
|
-
|
|
245
|
+
A registered `mcp` tool can use `tools.mcp` as an entry permission point. This provides a fallback when no specific MCP pattern matches:
|
|
223
246
|
|
|
224
247
|
```jsonc
|
|
225
248
|
{
|
|
@@ -352,12 +375,25 @@ When a delegated or routed subagent runs without direct UI access, `ask` permiss
|
|
|
352
375
|
|
|
353
376
|
This keeps `ask` policies usable even when the original permission check happens inside a non-UI execution context.
|
|
354
377
|
|
|
378
|
+
### Logging
|
|
379
|
+
|
|
380
|
+
When the extension prompts, denies, or forwards permission requests, it can append structured JSONL entries under:
|
|
381
|
+
|
|
382
|
+
```text
|
|
383
|
+
~/.pi/agent/extensions/pi-permission-system/logs/
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
- `pi-permission-system-permission-review.jsonl` — enabled by default for permission review/audit history
|
|
387
|
+
- `pi-permission-system-debug.jsonl` — disabled by default and intended for troubleshooting
|
|
388
|
+
|
|
355
389
|
### Architecture
|
|
356
390
|
|
|
357
391
|
```
|
|
358
392
|
index.ts → Root Pi entrypoint shim
|
|
359
393
|
src/
|
|
360
|
-
├── index.ts → Extension bootstrap, permission checks, and subagent forwarding
|
|
394
|
+
├── index.ts → Extension bootstrap, permission checks, review logging, and subagent forwarding
|
|
395
|
+
├── extension-config.ts → Extension-local config loading and default creation
|
|
396
|
+
├── logging.ts → File-only debug/review logging helpers
|
|
361
397
|
├── permission-manager.ts → Policy loading, merging, and resolution with caching
|
|
362
398
|
├── bash-filter.ts → Bash command wildcard pattern matching
|
|
363
399
|
├── wildcard-matcher.ts → Shared wildcard pattern compilation and matching
|
|
@@ -366,9 +402,9 @@ src/
|
|
|
366
402
|
├── types.ts → TypeScript type definitions
|
|
367
403
|
└── test.ts → Test runner
|
|
368
404
|
schemas/
|
|
369
|
-
└── permissions.schema.json → JSON Schema for
|
|
405
|
+
└── permissions.schema.json → JSON Schema for policy validation
|
|
370
406
|
config/
|
|
371
|
-
└── config.example.json → Starter
|
|
407
|
+
└── config.example.json → Starter global policy template
|
|
372
408
|
```
|
|
373
409
|
|
|
374
410
|
#### Module Organization
|
|
@@ -421,7 +457,7 @@ npx --yes ajv-cli@5 validate \
|
|
|
421
457
|
|---------|-------|----------|
|
|
422
458
|
| Config not applied (everything asks) | File not found or parse error | Verify file at `~/.pi/agent/pi-permissions.jsonc`; check for trailing commas |
|
|
423
459
|
| Per-agent override not applied | Frontmatter parsing issue | Ensure `---` delimiters at file top; keep YAML simple; restart session |
|
|
424
|
-
| Tool blocked as unregistered | Unknown tool name | Use
|
|
460
|
+
| Tool blocked as unregistered | Unknown tool name | Use a registered `mcp` tool for server tools: `{ "tool": "server:tool" }` |
|
|
425
461
|
| `/skill:<name>` blocked | Missing context or deny policy | Requires active agent context; `ask` behaves as block in headless mode |
|
|
426
462
|
|
|
427
463
|
---
|
package/config.json
ADDED
package/package.json
CHANGED
|
@@ -1,59 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-permission-system",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Permission enforcement extension for the Pi coding agent.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./index.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": "./index.ts"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"index.ts",
|
|
12
|
-
"src",
|
|
13
|
-
"config
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"pi",
|
|
29
|
-
"pi
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"@
|
|
58
|
-
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-permission-system",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Permission enforcement extension for the Pi coding agent.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.ts",
|
|
12
|
+
"src",
|
|
13
|
+
"config.json",
|
|
14
|
+
"config/config.example.json",
|
|
15
|
+
"schemas/permissions.schema.json",
|
|
16
|
+
"asset",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "npx --yes -p typescript@5.7.3 tsc -p tsconfig.json --noCheck",
|
|
23
|
+
"lint": "npm run build",
|
|
24
|
+
"test": "bun ./src/test.ts",
|
|
25
|
+
"check": "npm run lint && npm run test"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"pi-package",
|
|
29
|
+
"pi",
|
|
30
|
+
"pi-extension",
|
|
31
|
+
"permissions",
|
|
32
|
+
"policy",
|
|
33
|
+
"coding-agent"
|
|
34
|
+
],
|
|
35
|
+
"author": "MasuRii",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/MasuRii/pi-permission-system.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/MasuRii/pi-permission-system#readme",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/MasuRii/pi-permission-system/issues"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"pi": {
|
|
52
|
+
"extensions": [
|
|
53
|
+
"./index.ts"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@mariozechner/pi-coding-agent": "*",
|
|
58
|
+
"@sinclair/typebox": "*"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -31,12 +31,14 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"tools": {
|
|
34
|
+
"description": "Exact-name permissions for registered tools. Use this map for the canonical Pi built-ins and any extension-provided or third-party tools.",
|
|
34
35
|
"$ref": "#/$defs/permissionMap"
|
|
35
36
|
},
|
|
36
37
|
"bash": {
|
|
37
38
|
"$ref": "#/$defs/permissionMap"
|
|
38
39
|
},
|
|
39
40
|
"mcp": {
|
|
41
|
+
"description": "Pattern-based permissions for targets invoked through a registered `mcp` tool when available.",
|
|
40
42
|
"$ref": "#/$defs/permissionMap"
|
|
41
43
|
},
|
|
42
44
|
"skills": {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
import { toRecord } from "./common.js";
|
|
6
|
+
|
|
7
|
+
export const EXTENSION_ID = "pi-permission-system";
|
|
8
|
+
|
|
9
|
+
export interface PermissionSystemExtensionConfig {
|
|
10
|
+
debugLog: boolean;
|
|
11
|
+
permissionReviewLog: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PermissionSystemConfigLoadResult {
|
|
15
|
+
config: PermissionSystemExtensionConfig;
|
|
16
|
+
created: boolean;
|
|
17
|
+
warning?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const DEFAULT_EXTENSION_CONFIG: PermissionSystemExtensionConfig = {
|
|
21
|
+
debugLog: false,
|
|
22
|
+
permissionReviewLog: true,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function resolveExtensionRoot(moduleUrl = import.meta.url): string {
|
|
26
|
+
return join(dirname(fileURLToPath(moduleUrl)), "..");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const EXTENSION_ROOT = resolveExtensionRoot();
|
|
30
|
+
export const CONFIG_PATH = join(EXTENSION_ROOT, "config.json");
|
|
31
|
+
export const LOGS_DIR = join(EXTENSION_ROOT, "logs");
|
|
32
|
+
export const DEBUG_LOG_PATH = join(LOGS_DIR, `${EXTENSION_ID}-debug.jsonl`);
|
|
33
|
+
export const PERMISSION_REVIEW_LOG_PATH = join(LOGS_DIR, `${EXTENSION_ID}-permission-review.jsonl`);
|
|
34
|
+
|
|
35
|
+
function cloneDefaultConfig(): PermissionSystemExtensionConfig {
|
|
36
|
+
return {
|
|
37
|
+
debugLog: DEFAULT_EXTENSION_CONFIG.debugLog,
|
|
38
|
+
permissionReviewLog: DEFAULT_EXTENSION_CONFIG.permissionReviewLog,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function createDefaultConfigContent(): string {
|
|
43
|
+
return `${JSON.stringify(DEFAULT_EXTENSION_CONFIG, null, 2)}\n`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function normalizeConfig(raw: unknown): PermissionSystemExtensionConfig {
|
|
47
|
+
const record = toRecord(raw);
|
|
48
|
+
return {
|
|
49
|
+
debugLog: record.debugLog === true,
|
|
50
|
+
permissionReviewLog: record.permissionReviewLog !== false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ensureConfigDirectory(configPath: string): void {
|
|
55
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function ensurePermissionSystemConfig(configPath = CONFIG_PATH): { created: boolean; warning?: string } {
|
|
59
|
+
if (existsSync(configPath)) {
|
|
60
|
+
return { created: false };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
ensureConfigDirectory(configPath);
|
|
65
|
+
writeFileSync(configPath, createDefaultConfigContent(), "utf-8");
|
|
66
|
+
return { created: true };
|
|
67
|
+
} catch (error) {
|
|
68
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
69
|
+
return {
|
|
70
|
+
created: false,
|
|
71
|
+
warning: `Failed to initialize permission-system config at '${configPath}': ${message}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function loadPermissionSystemConfig(configPath = CONFIG_PATH): PermissionSystemConfigLoadResult {
|
|
77
|
+
const ensureResult = ensurePermissionSystemConfig(configPath);
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
81
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
82
|
+
const config = normalizeConfig(parsed);
|
|
83
|
+
return {
|
|
84
|
+
config,
|
|
85
|
+
created: ensureResult.created,
|
|
86
|
+
warning: ensureResult.warning,
|
|
87
|
+
};
|
|
88
|
+
} catch (error) {
|
|
89
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
90
|
+
return {
|
|
91
|
+
config: cloneDefaultConfig(),
|
|
92
|
+
created: ensureResult.created,
|
|
93
|
+
warning: ensureResult.warning ?? `Failed to read permission-system config at '${configPath}': ${message}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function ensurePermissionSystemLogsDirectory(logsDir = LOGS_DIR): string | undefined {
|
|
99
|
+
try {
|
|
100
|
+
mkdirSync(logsDir, { recursive: true });
|
|
101
|
+
return undefined;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
104
|
+
return `Failed to create permission-system log directory '${logsDir}': ${message}`;
|
|
105
|
+
}
|
|
106
|
+
}
|