@xynogen/pix-gate 0.1.11 → 0.1.13
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/README.md +13 -7
- package/package.json +3 -2
- package/src/gate.test.ts +3 -2
- package/src/index.ts +7 -1
- package/src/lib.ts +17 -11
- package/src/prompt.ts +9 -1
package/README.md
CHANGED
|
@@ -35,18 +35,24 @@ rules as the bash tool (auto-deny on match, no prompt).
|
|
|
35
35
|
|
|
36
36
|
## Configuration
|
|
37
37
|
|
|
38
|
-
`~/.pi/agent/pix-gate.json
|
|
38
|
+
Gate rules are read from the **`gate` section of `~/.pi/agent/pix.json`** (the unified config file). The legacy `~/.pi/agent/pix-gate.json` file is no longer used.
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
`~/.pi/agent/pix.json` — `gate` section:
|
|
41
|
+
|
|
42
|
+
```jsonc
|
|
41
43
|
{
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
"gate": {
|
|
45
|
+
"disableDefaults": false,
|
|
46
|
+
"extraRules": [
|
|
47
|
+
{ "pattern": "rm -rf /my-dir", "severity": "critical", "reason": "Deletes project root" }
|
|
48
|
+
],
|
|
49
|
+
"autoApprove": ["^echo "]
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
```
|
|
49
53
|
|
|
54
|
+
The schema is identical to the old `pix-gate.json` — move your existing config into `pix.json` under the `gate` key.
|
|
55
|
+
|
|
50
56
|
## Full distro
|
|
51
57
|
|
|
52
58
|
Source: [github.com/xynogen/pix-mono](https://github.com/xynogen/pix-mono)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-gate",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Pi extension — permission gate for dangerous bash commands (confirm/block with TUI dialog)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@xynogen/pix-pretty": "^1.7.9"
|
|
45
|
+
"@xynogen/pix-pretty": "^1.7.9",
|
|
46
|
+
"@xynogen/pix-data": "workspace:*"
|
|
46
47
|
},
|
|
47
48
|
"peerDependencies": {
|
|
48
49
|
"@earendil-works/pi-coding-agent": "*",
|
package/src/gate.test.ts
CHANGED
|
@@ -131,8 +131,9 @@ describe("buildRules", () => {
|
|
|
131
131
|
|
|
132
132
|
test("autoApprove strings compile to regexes", () => {
|
|
133
133
|
const { autoApprove } = buildRules({ autoApprove: ["^npm publish"] });
|
|
134
|
-
|
|
135
|
-
expect(
|
|
134
|
+
const rule0 = autoApprove[0] as RegExp;
|
|
135
|
+
expect(rule0.test("npm publish --access public")).toBe(true);
|
|
136
|
+
expect(rule0.test("yarn publish")).toBe(false);
|
|
136
137
|
});
|
|
137
138
|
|
|
138
139
|
test("defaults included when disableDefaults absent", () => {
|
package/src/index.ts
CHANGED
|
@@ -88,7 +88,13 @@ export default function (pi: ExtensionAPI): void {
|
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
// ── Unified bash gate (path + command concerns in ONE dialog) ───────────
|
|
91
|
-
const SEVERITY_TIER:
|
|
91
|
+
const SEVERITY_TIER: {
|
|
92
|
+
critical: number;
|
|
93
|
+
block: number;
|
|
94
|
+
dangerous: number;
|
|
95
|
+
warn: number;
|
|
96
|
+
risky: number;
|
|
97
|
+
} = {
|
|
92
98
|
critical: 5,
|
|
93
99
|
block: 4,
|
|
94
100
|
dangerous: 3,
|
package/src/lib.ts
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
* Pure helpers for pix-gate — no Pi API deps, fully unit-testable.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
|
-
import { join } from "node:path";
|
|
5
|
+
import { type GateRuleConfig, pixConfig } from "@xynogen/pix-data/pix-config";
|
|
8
6
|
|
|
9
7
|
export type Severity = "critical" | "dangerous" | "risky";
|
|
10
8
|
|
|
@@ -132,13 +130,21 @@ export const DEFAULT_RULES: Rule[] = [
|
|
|
132
130
|
];
|
|
133
131
|
|
|
134
132
|
export function loadUserConfig(): UserConfig {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
133
|
+
// Read from ~/.pi/agent/pix.json gate section
|
|
134
|
+
const pix = pixConfig().gate;
|
|
135
|
+
return {
|
|
136
|
+
disableDefaults: pix.disableDefaults || undefined,
|
|
137
|
+
autoApprove: pix.autoApprove.length > 0 ? pix.autoApprove : undefined,
|
|
138
|
+
extraRules:
|
|
139
|
+
pix.extraRules.length > 0
|
|
140
|
+
? pix.extraRules.map((r: GateRuleConfig) => ({
|
|
141
|
+
pattern: r.pattern,
|
|
142
|
+
flags: r.flags,
|
|
143
|
+
severity: r.severity as Severity | undefined,
|
|
144
|
+
reason: r.reason,
|
|
145
|
+
}))
|
|
146
|
+
: undefined,
|
|
147
|
+
};
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
export function buildRules(cfg: UserConfig): {
|
|
@@ -276,7 +282,7 @@ export function extractPathsFromBash(cmd: string): string[] {
|
|
|
276
282
|
const out: string[] = [];
|
|
277
283
|
const re =
|
|
278
284
|
/(?:^|[\s=><|;&"'`(])((?:\.\.\/|\/|~\/|\.)[^\s"'`<>|;&)]+|\.env(?:\.[A-Za-z0-9_-]+)?|[A-Za-z0-9_./-]+\.(?:pem|key|p12|pfx|crt|cer|env|envrc|netrc))/g;
|
|
279
|
-
for (const m of cmd.matchAll(re)) out.push(m[1]
|
|
285
|
+
for (const m of cmd.matchAll(re)) out.push(m[1] ?? "");
|
|
280
286
|
return out;
|
|
281
287
|
}
|
|
282
288
|
|
package/src/prompt.ts
CHANGED
|
@@ -126,7 +126,13 @@ export async function promptPathDecision(
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/** Tier for dialog behavior — higher = more restrictive (deny-first, shorter timeout). */
|
|
129
|
-
const SEVERITY_TIER:
|
|
129
|
+
const SEVERITY_TIER: {
|
|
130
|
+
critical: number;
|
|
131
|
+
block: number;
|
|
132
|
+
dangerous: number;
|
|
133
|
+
warn: number;
|
|
134
|
+
risky: number;
|
|
135
|
+
} = {
|
|
130
136
|
critical: 5,
|
|
131
137
|
block: 4,
|
|
132
138
|
dangerous: 3,
|
|
@@ -146,6 +152,8 @@ export async function promptMergedGateDecision(
|
|
|
146
152
|
// Sort by tier desc so the highest-severity concern drives dialog behavior.
|
|
147
153
|
const sorted = [...concerns].sort((a, b) => b.tier - a.tier);
|
|
148
154
|
const highest = sorted[0];
|
|
155
|
+
if (!highest)
|
|
156
|
+
throw new Error("promptMergedGateDecision requires at least one concern");
|
|
149
157
|
const isRestrictive = highest.tier >= SEVERITY_TIER.block; // block or critical
|
|
150
158
|
|
|
151
159
|
// Title: unique severity types, joined with " + "
|