dsh-perm-gate 0.2.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.ja.md +62 -0
- package/CHANGELOG.ko.md +60 -0
- package/CHANGELOG.md +62 -0
- package/INSTALL.ja.md +152 -0
- package/INSTALL.ko.md +151 -0
- package/INSTALL.md +154 -0
- package/INSTALL.zh.md +147 -0
- package/LICENSE +21 -0
- package/README.ja.md +197 -0
- package/README.ko.md +195 -0
- package/README.md +209 -0
- package/README.zh.md +144 -0
- package/assets/.gitkeep +0 -0
- package/assets/README.md +5 -0
- package/cordis.patch.yml +35 -0
- package/examples/permissions.example.yaml +20 -0
- package/lib/allowlist.d.ts +19 -0
- package/lib/allowlist.js +97 -0
- package/lib/audit.d.ts +45 -0
- package/lib/audit.js +34 -0
- package/lib/classifier.d.ts +74 -0
- package/lib/classifier.js +129 -0
- package/lib/cli.d.ts +2 -0
- package/lib/cli.js +67 -0
- package/lib/client.js +859 -0
- package/lib/client.js.map +1 -0
- package/lib/compiler.d.ts +30 -0
- package/lib/compiler.js +126 -0
- package/lib/config.d.ts +69 -0
- package/lib/config.js +64 -0
- package/lib/engine.d.ts +17 -0
- package/lib/engine.js +85 -0
- package/lib/evaluate.d.ts +20 -0
- package/lib/evaluate.js +94 -0
- package/lib/events.d.ts +56 -0
- package/lib/events.js +129 -0
- package/lib/grant.d.ts +60 -0
- package/lib/grant.js +121 -0
- package/lib/index.d.ts +17 -0
- package/lib/index.js +140 -0
- package/lib/learning.d.ts +58 -0
- package/lib/learning.js +181 -0
- package/lib/path.d.ts +47 -0
- package/lib/path.js +94 -0
- package/lib/risk.d.ts +58 -0
- package/lib/risk.js +100 -0
- package/lib/rule.d.ts +64 -0
- package/lib/rule.js +220 -0
- package/lib/runtime.d.ts +146 -0
- package/lib/runtime.js +350 -0
- package/lib/shell.d.ts +38 -0
- package/lib/shell.js +176 -0
- package/package.json +120 -0
package/INSTALL.zh.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# 安装指南
|
|
2
|
+
|
|
3
|
+
- [English README](./README.md)
|
|
4
|
+
- [中文 README](./README.zh.md)
|
|
5
|
+
- [日本語 README](./README.ja.md)
|
|
6
|
+
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Installation guide](./INSTALL.md)
|
|
8
|
+
- [中文安装指南](./INSTALL.zh.md)
|
|
9
|
+
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
|
+
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
11
|
+
- [Changelog](./CHANGELOG.md)
|
|
12
|
+
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
|
+
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
14
|
+
|
|
15
|
+
`dsh-perm-gate` 版本 **0.1.0**。裁决链、规则文件格式与 Permissive 档位请见
|
|
16
|
+
[中文 README](./README.zh.md)。
|
|
17
|
+
|
|
18
|
+
## 前置条件
|
|
19
|
+
|
|
20
|
+
- 已安装 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)。
|
|
21
|
+
- Node.js **>= 20**(见 `package.json` 的 `engines`)。
|
|
22
|
+
- `dsh` CLI 已在 `PATH` 中。
|
|
23
|
+
- 需要一个目标 profile —— 浏览器端只为 `web` profile 构建(`package.json`
|
|
24
|
+
里 `dsh.client.platform = "web"`)。
|
|
25
|
+
|
|
26
|
+
## 用官方 CLI 安装
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
dsh plugin --profile web add dsh-perm-gate
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
该命令会拉取已发布的包、应用 `cordis.patch.yml`(Permissive 会话档位 + 插件条目),
|
|
33
|
+
并装配 host / client 两半。
|
|
34
|
+
|
|
35
|
+
## 从源码安装
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
git clone https://github.com/drscrewdriver/dsh-perm-gate.git
|
|
39
|
+
cd dsh-perm-gate
|
|
40
|
+
npm install
|
|
41
|
+
npm run build # tsc -> lib/*.js + lib/*.d.ts,tsdown -> lib/client.js
|
|
42
|
+
dsh plugin --profile web add .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`npm run build` 同时是 `prepublishOnly` 步骤,所以发布时不会带出过期的 `lib/`。
|
|
46
|
+
|
|
47
|
+
## 启用与配置
|
|
48
|
+
|
|
49
|
+
在 profile 的 `cordis.yml` 中加入插件:
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
- id: dsh-perm-gate
|
|
53
|
+
name: dsh-perm-gate
|
|
54
|
+
config:
|
|
55
|
+
rulesFile: ./permissions.yaml # 可选;留空则按 defaultAction 兜底
|
|
56
|
+
dshHome: $DSH_HOME # 受保护目标检查的钉死根目录
|
|
57
|
+
defaultAction: ask # allow | ask | deny
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
可从 [examples/permissions.example.yaml](./examples/permissions.example.yaml) 起步,
|
|
61
|
+
然后重载 profile。
|
|
62
|
+
|
|
63
|
+
## 升级
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
dsh plugin --profile web update dsh-perm-gate
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
随后重新应用 profile 以重读补丁文件:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
dsh profile reload --profile web
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 从分裂的插件迁移
|
|
76
|
+
|
|
77
|
+
`dsh-perm-gate` 把原先散落在 `dsh-permission-rules`、`dsh-auto-mode`、
|
|
78
|
+
`dsh-auto-review`、`dsh-movein-permissions` 中的门禁、审批接缝与(可选)分类器
|
|
79
|
+
合并为一个包。
|
|
80
|
+
|
|
81
|
+
1. 导出既有规则列表(deny / allow / ask),合并到同一个 `permissions.yaml`。
|
|
82
|
+
2. 从 `cordis.yml` 删除上述四个插件,只加入唯一的 `dsh-perm-gate` 条目。
|
|
83
|
+
3. 删除这些插件贡献的 preset 覆盖 —— `cordis.patch.yml` 是**整体替换**
|
|
84
|
+
`permission.config.presets`,其他插件遗留的逐 key 补丁可能静默抹掉
|
|
85
|
+
Permissive 或 Auto 档。
|
|
86
|
+
4. 重载 profile,并用下面的 `--list` 验证。
|
|
87
|
+
|
|
88
|
+
## 验证
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
# 汇总已加载的规则集(无需 harness)
|
|
92
|
+
dsh-perm-gate --rules permissions.yaml --list
|
|
93
|
+
|
|
94
|
+
# 对单次调用 dry-run
|
|
95
|
+
dsh-perm-gate --rules permissions.yaml --tool bash --args '{"command":"pnpm install"}'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`--list` 的输出形如:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"rulesFile": "/abs/path/permissions.yaml",
|
|
103
|
+
"defaultAction": "ask",
|
|
104
|
+
"ruleCount": 8,
|
|
105
|
+
"permissive": false,
|
|
106
|
+
"permissiveStrategies": { "trustAutoAllow": true, "alwaysConfirm": false, "llmAssist": false }
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
UI 里 **设置 → 插件 → Permissive 审批档** 应渲染出一个开关加三个后台策略开关。
|
|
111
|
+
|
|
112
|
+
## 卸载
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
dsh plugin --profile web remove dsh-perm-gate
|
|
116
|
+
dsh profile reload --profile web
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
移除插件也会移除它的补丁贡献,Permissive 档位会重新从会话权限下拉框消失。
|
|
120
|
+
|
|
121
|
+
## 排查
|
|
122
|
+
|
|
123
|
+
**权限下拉框里没有 Permissive 档。**
|
|
124
|
+
DSH 的 bundle patch 是整体替换 `permission.config.presets`,而非逐 key 合并。
|
|
125
|
+
请重载 profile 让 `cordis.patch.yml` 重新生效,并确认没有更晚加载的插件覆盖了
|
|
126
|
+
`presets`。
|
|
127
|
+
|
|
128
|
+
**规则文件存在但 `--list` 显示 `ruleCount: 0`。**
|
|
129
|
+
`rulesFile` 按 harness 进程的 CWD 解析,而不是插件目录。建议使用绝对路径,
|
|
130
|
+
或确认 shell 的 CWD。格式错误的文档在加载时 loud fail,绝不会静默失效。
|
|
131
|
+
|
|
132
|
+
**`llmAssist` 从不触发。**
|
|
133
|
+
需要配置 `classifierEndpoint`、`classifierModel`、`classifierApiKey`
|
|
134
|
+
(在 **设置 → 插件 → Permissive 审批档** 或 `cordis.yml` 中填写)。
|
|
135
|
+
任一缺失或网络错误都会回退到人工接缝 —— 门禁按设计 fail-closed。
|
|
136
|
+
|
|
137
|
+
**设置卡片显示「设置命名空间不可用」。**
|
|
138
|
+
该插件未装配进当前 profile。执行 `dsh plugin --profile web add dsh-perm-gate`
|
|
139
|
+
并重载。
|
|
140
|
+
|
|
141
|
+
**选择 `ja` / `ko` 报 `locale "<id>" is not registered`。**
|
|
142
|
+
官方 DSH 的 `LocaleRuntime` 只暴露 `zh` / `en`,详见
|
|
143
|
+
[中文 README](./README.zh.md) 的兼容性说明。
|
|
144
|
+
|
|
145
|
+
## 许可证
|
|
146
|
+
|
|
147
|
+
[MIT](./LICENSE)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 drscrewdriver
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ja.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# dsh-perm-gate
|
|
2
|
+
|
|
3
|
+
- [English README](./README.md)
|
|
4
|
+
- [中文 README](./README.zh.md)
|
|
5
|
+
- [日本語 README](./README.ja.md)
|
|
6
|
+
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Installation guide](./INSTALL.md)
|
|
8
|
+
- [中文安装指南](./INSTALL.zh.md)
|
|
9
|
+
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
|
+
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
11
|
+
- [Changelog](./CHANGELOG.md)
|
|
12
|
+
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
|
+
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
14
|
+
|
|
15
|
+
> **互換性に関する注記:** v0.1.0 は `ja` / `ko` 辞書を同梱しますが、公式 DSH の
|
|
16
|
+
> `LocaleRuntime` が公開するのは `zh` / `en` のみです(`LOCALE_IDS = ["zh", "en"]`)。
|
|
17
|
+
> 素の DSH で `ja` / `ko` を選択すると `locale "<id>" is not registered` になります。
|
|
18
|
+
> `LOCALE_IDS`(locale-settings.ts)と `LOCALES` ラベル(client/index.ts)を更新した
|
|
19
|
+
> DSH fork を使って再ビルドしてください。
|
|
20
|
+
|
|
21
|
+
バージョン **0.1.0** — 変更履歴は [日本語 changelog](./CHANGELOG.ja.md) を参照。
|
|
22
|
+
|
|
23
|
+
DeepSeek Harness 向けの、単一・自己完結・決定論優先・fail-closed な権限ゲートです。
|
|
24
|
+
|
|
25
|
+
ツール呼び出しごとに固定の優先チェーンで判定します:
|
|
26
|
+
|
|
27
|
+
| 段階 | 判定 | 内容 |
|
|
28
|
+
| ---- | ---- | ---- |
|
|
29
|
+
| **P0** | `deny` | 決定論的ハード拒否:資格情報の material / 保護パスの変更 / 危険な shell |
|
|
30
|
+
| **P1** | `allow` | 精密で有界な**セッション許可** grant |
|
|
31
|
+
| **P2** | `deny/allow/ask` | 静的ルール連鎖:ブラックリスト → allow → ask の順 |
|
|
32
|
+
| **P3** | `allow/deny/ask` | 任意の LLM 意味分類器(既定**オフ**) |
|
|
33
|
+
| **P4** | `ask` | 公式の approval seam |
|
|
34
|
+
|
|
35
|
+
fail-closed を徹底します:P0 の判定は、grant・ルール・分類器・人間のいずれにも
|
|
36
|
+
上書きされません。
|
|
37
|
+
|
|
38
|
+
## 背景
|
|
39
|
+
|
|
40
|
+
DSH の安全まわりのエコシステムでは、この役割が `dsh-permission-rules` /
|
|
41
|
+
`dsh-auto-mode` / `dsh-auto-review` / `dsh-movein-permissions` の複数プラグインに
|
|
42
|
+
分散しています。`dsh-perm-gate` はゲート・承認・(任意の)分類器を 1 パッケージに
|
|
43
|
+
統合し、監査ログを 1 本にまとめ、プラグイン間のバージョン結合をなくします。
|
|
44
|
+
|
|
45
|
+
## 主な機能
|
|
46
|
+
|
|
47
|
+
- **コマンド ホワイト/ブラックリスト** — 生文字列ではなく **argv 分解**で照合
|
|
48
|
+
(`sh -c`/`bash -c` の再帰降下、パイプライン検出、リダイレクト先の検査、
|
|
49
|
+
再帰/強制(`rm -rf`)の認識)。
|
|
50
|
+
- **拒否優先** — 拒否ルールはどの allow ルールにも勝ります。
|
|
51
|
+
- **セッション許可** — `(ツール, 正準フィンガープリント)` 単位の精密な許可
|
|
52
|
+
(TTL+maxUses。対象が変われば権限は再利用されません。サブエージェントは継承
|
|
53
|
+
できますが自ら発行はできません)。
|
|
54
|
+
- **純関数ルール エンジン** — glob/regex コンパイル+ReDoS 上限、不正ルールは
|
|
55
|
+
loud fail、ソースの内容ハッシュによるコンパイル キャッシュ。
|
|
56
|
+
- **監査** — すべての判定を `callId` 付きの `{ignorable:true}` イベントとして記録。
|
|
57
|
+
モデルに見える理由と記録される結果は常に一致します。
|
|
58
|
+
- **Permissive ティア** — read-only / full-access / whitelist とは別の**独立した承認
|
|
59
|
+
モード**。「自動承認」でもなく、包括的な権限付与でもありません。フロントが露出する
|
|
60
|
+
のは**単一スイッチ**(`permissive`)だけで、バックエンドの 3 つの戦略は**組み合わせ
|
|
61
|
+
可能**でプラグイン設定から制御されます。P0 に対しては依然 fail-closed です。
|
|
62
|
+
|
|
63
|
+
## インストール
|
|
64
|
+
|
|
65
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) が導入済みである
|
|
66
|
+
必要があります。
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
dsh plugin --profile web add dsh-perm-gate
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
インストール・アップグレード・移行・トラブルシューティングの詳細は
|
|
73
|
+
[日本語インストールガイド](./INSTALL.ja.md)([English](./INSTALL.md) /
|
|
74
|
+
[中文](./INSTALL.zh.md) / [한국어](./INSTALL.ko.md))にあります。
|
|
75
|
+
|
|
76
|
+
## 設定
|
|
77
|
+
|
|
78
|
+
`cordis.yml` に追加します:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
- id: dsh-perm-gate
|
|
82
|
+
name: dsh-perm-gate
|
|
83
|
+
config:
|
|
84
|
+
rulesFile: ./permissions.yaml # 任意。空なら defaultAction に従う
|
|
85
|
+
dshHome: $DSH_HOME # 保護対象チェックのルート固定
|
|
86
|
+
defaultAction: ask # allow | ask | deny
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### ルール ファイル
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
permissions:
|
|
93
|
+
defaultAction: ask
|
|
94
|
+
deny:
|
|
95
|
+
- command: [rm#recursive]
|
|
96
|
+
reason: no recursive rm
|
|
97
|
+
- paths: [.dsh/**]
|
|
98
|
+
reason: protect harness metadata
|
|
99
|
+
allow:
|
|
100
|
+
- command: [pnpm, node]
|
|
101
|
+
reason: dev tools
|
|
102
|
+
- command: [curl, wget]
|
|
103
|
+
args: ["https://*.example.com/*"]
|
|
104
|
+
reason: allowed endpoint
|
|
105
|
+
ask:
|
|
106
|
+
- command: [bash, sh]
|
|
107
|
+
reason: ask shells
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
コマンド項目の `word#flag` は、コマンド語 `word` に修飾子 `recursive` または
|
|
111
|
+
`force` を付けて照合します。つまり `rm#recursive` は `rm -rf`、`env rm -rf`、
|
|
112
|
+
`sh -c "rm -rf /"` に一致します。
|
|
113
|
+
|
|
114
|
+
完全な例: [examples/permissions.example.yaml](./examples/permissions.example.yaml)
|
|
115
|
+
|
|
116
|
+
## Permissive ティア
|
|
117
|
+
|
|
118
|
+
Permissive は権限ピッカーの中で Read Only / Workspace Write / Full access /
|
|
119
|
+
Whitelist と並ぶ**独立した承認ティア**です。「自動承認」ではなく、包括的な権限を
|
|
120
|
+
発行することもありません。人間/LLM のシーム**の前**で判定を狭めたり広めたりする
|
|
121
|
+
だけで、P0 ハード拒否は単調かつ交渉不能のままです。
|
|
122
|
+
|
|
123
|
+
`cordis.yml` では:
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
- id: dsh-perm-gate
|
|
127
|
+
name: dsh-perm-gate
|
|
128
|
+
config:
|
|
129
|
+
rulesFile: ./permissions.yaml
|
|
130
|
+
defaultAction: ask
|
|
131
|
+
permissive: true # フロント唯一のスイッチ(独立ティア ON)
|
|
132
|
+
permissiveStrategies: # バックエンド戦略、組み合わせ可
|
|
133
|
+
trustAutoAllow: true # スコープ内安全操作は自動許可、危険/不明は ask
|
|
134
|
+
alwaysConfirm: false # すべて ask。許可コントロールに拡張ボタン 2 つ
|
|
135
|
+
llmAssist: false # まず LLM が分類、ask/失敗時は人手へ
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`trustAutoAllow` は中間ティアのベースラインです(rule-allow は自動通過)。
|
|
139
|
+
`alwaysConfirm` はすべての境界で承認パネルを表示し、その「許可コントロール」に
|
|
140
|
+
2 つの拡張ボタンを追加します — **このセッションで当該種別を繰り返し許可**
|
|
141
|
+
(`approveRepeat`、有界なセッション許可)と**すべての発生を許可**
|
|
142
|
+
(`approveAllowEverywhere`、コマンド語を `permissions.yaml` の allow ホワイトリストへ
|
|
143
|
+
永続化して再読込)。`llmAssist` は設定済みの実際の LLM
|
|
144
|
+
(`classifierEndpoint` / `classifierModel`。OpenAI 互換 API なら何でも可)に
|
|
145
|
+
`ask` の自動判定を委ね、`ask`/エラー時は人手のシームへフォールバックします —
|
|
146
|
+
常に fail-closed です。`permissive` がオフなら、ゲートの挙動は以前と完全に同じです。
|
|
147
|
+
|
|
148
|
+
### 選択可能なセッション ティア
|
|
149
|
+
|
|
150
|
+
`cordis.patch.yml` は DSH の `permission.config.presets` を拡張し、Workspace Write と
|
|
151
|
+
Full access の間に `permissive` preset(`sandbox: workspace-write`、`approval: ask`、
|
|
152
|
+
名称 **Permissive**)を追加します。Auto モードと同じ仕組みです。したがって
|
|
153
|
+
セッションの権限ピッカーには「auto-approval」ではなく、**独立して選択できる承認
|
|
154
|
+
ティア**として Permissive が並びます。
|
|
155
|
+
|
|
156
|
+
### UI から設定可能
|
|
157
|
+
|
|
158
|
+
このティアは実行時にも **設定 → プラグイン → Permissive 承認ティア** から調整できます
|
|
159
|
+
(プラグインのブラウザ側が描画する `settings.plugins.tab` ページ)。1 つのスイッチが
|
|
160
|
+
`permissive` を切り替え、3 つのトグルがバックエンドの `permissiveStrategies` を編集
|
|
161
|
+
します。host は名前空間を live に読むため、変更は再起動なしで次のツール呼び出しから
|
|
162
|
+
適用されます。これは独立した承認クラスであり、DSH の「auto-approval」モードでは
|
|
163
|
+
**ありません**。
|
|
164
|
+
|
|
165
|
+
### リスク判定 llmAssist、裁決学習、イベントフィード
|
|
166
|
+
|
|
167
|
+
`llmAssist` 有効時、設定された LLM(OpenAI 互換エンドポイントなら任意——`classifierEndpoint` / `classifierModel` / `classifierApiKey` を自分の API に向けてください)が構造化プロトコルで `ask` を 1 件ずつ判定します:
|
|
168
|
+
|
|
169
|
+
- `safe` → 自動許可(監査ソースは `classifier`)。
|
|
170
|
+
- `risky` + **ハードリスクカテゴリ**(`deletion`、`credential`、`remote`、`system`、`bulk`)→ 常に人手へ。ハードリスクは自動許可も学習もされません。
|
|
171
|
+
- `risky:neutral` → `riskLearning` 有効時(設定カード内、既定オフ)、人手で承認され実際に実行された neutral リスクは `tool|カテゴリ` ごとにカウントされ、`riskThreshold`(既定 3)到達かつ新呼び出しの操作指紋(コマンド語+対象の基底名)が確認済みサンプルに一致した場合、**同一操作のみ**自動許可されます。
|
|
172
|
+
- タイムアウト(`riskTimeoutMs`、既定 20 秒、1 回リトライ)、通信失敗、プロトコル外出力は元の `ask` を維持します。
|
|
173
|
+
|
|
174
|
+
学習状態はプラグイン所有の JSON(`$DSH_HOME/perm-gate/learning.json` または `learningFile`)に永続化され、YAML ルールには書き込みません。各決定は `$DSH_HOME/perm-gate/events.jsonl`(または `eventsFile`)に追記され、`GET /api/dsh-perm-gate/events?sessionId=&since=` で提供されます。ブラウザ側はこれをポーリングし、入力欄の上に最新の決定を通知バーで表示します。Permissive ティアは権限ピッカーに盾アイコンを保持します(メニュー項目と折りたたみトリガーの両方)。
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
## CLI(スタンドアロン dry-run)
|
|
178
|
+
|
|
179
|
+
Harness なしで 1 件の呼び出しをルール ファイルに対して評価できます:
|
|
180
|
+
|
|
181
|
+
```sh
|
|
182
|
+
dsh-perm-gate --rules permissions.yaml --tool bash --args '{"command":"pnpm install"}'
|
|
183
|
+
dsh-perm-gate --rules permissions.yaml --list
|
|
184
|
+
dsh-perm-gate --permissive --tool bash --args '{"command":"pnpm install"}'
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 開発
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
npm run typecheck
|
|
191
|
+
npm test
|
|
192
|
+
npm run build
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## ライセンス
|
|
196
|
+
|
|
197
|
+
[MIT](./LICENSE)
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# dsh-perm-gate
|
|
2
|
+
|
|
3
|
+
- [English README](./README.md)
|
|
4
|
+
- [中文 README](./README.zh.md)
|
|
5
|
+
- [日本語 README](./README.ja.md)
|
|
6
|
+
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Installation guide](./INSTALL.md)
|
|
8
|
+
- [中文安装指南](./INSTALL.zh.md)
|
|
9
|
+
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
|
+
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
11
|
+
- [Changelog](./CHANGELOG.md)
|
|
12
|
+
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
|
+
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
14
|
+
|
|
15
|
+
> **호환성 안내:** v0.1.0은 `ja` / `ko` 사전을 포함하지만, 공식 DSH의 `LocaleRuntime`은
|
|
16
|
+
> `zh` / `en`만 노출합니다(`LOCALE_IDS = ["zh", "en"]`). 기본 DSH에서 `ja` / `ko`를
|
|
17
|
+
> 선택하면 `locale "<id>" is not registered` 오류가 발생합니다. `LOCALE_IDS`
|
|
18
|
+
> (locale-settings.ts)와 `LOCALES` 라벨(client/index.ts)을 갱신한 DSH fork를 사용해
|
|
19
|
+
> 다시 빌드하세요.
|
|
20
|
+
|
|
21
|
+
버전 **0.1.0** — 변경 내역은 [한국어 changelog](./CHANGELOG.ko.md)를 참고하세요.
|
|
22
|
+
|
|
23
|
+
DeepSeek Harness용 단일·자족적·결정론 우선·fail-closed 권한 게이트입니다.
|
|
24
|
+
|
|
25
|
+
도구 호출마다 고정된 우선순위 체인으로 판정합니다:
|
|
26
|
+
|
|
27
|
+
| 단계 | 판정 | 내용 |
|
|
28
|
+
| ---- | ---- | ---- |
|
|
29
|
+
| **P0** | `deny` | 결정론적 하드 거부: 자격 증명 material / 보호 경로 변경 / 위험한 shell |
|
|
30
|
+
| **P1** | `allow` | 정밀하고 유계인 **세션 허용** grant |
|
|
31
|
+
| **P2** | `deny/allow/ask` | 정적 규칙 체인: 블랙리스트 → allow → ask 순서 |
|
|
32
|
+
| **P3** | `allow/deny/ask` | 선택적 LLM 의미 분류기(기본 **꺼짐**) |
|
|
33
|
+
| **P4** | `ask` | 공식 approval seam |
|
|
34
|
+
|
|
35
|
+
엄격하게 fail-closed입니다: P0 판정은 grant·규칙·분류기·사람 누구에게도
|
|
36
|
+
덮어써지지 않습니다.
|
|
37
|
+
|
|
38
|
+
## 배경
|
|
39
|
+
|
|
40
|
+
DSH 안전 생태계에서는 이 역할이 `dsh-permission-rules` / `dsh-auto-mode` /
|
|
41
|
+
`dsh-auto-review` / `dsh-movein-permissions` 등 여러 플러그인에 흩어져 있습니다.
|
|
42
|
+
`dsh-perm-gate`는 게이트·승인·선택적 분류기를 하나의 패키지로 합쳐 감사 로그를
|
|
43
|
+
단일화하고 플러그인 간 버전 결합을 없앱니다.
|
|
44
|
+
|
|
45
|
+
## 주요 기능
|
|
46
|
+
|
|
47
|
+
- **명령 화이트/블랙리스트** — 원시 문자열이 아니라 **argv 분해**로 매칭
|
|
48
|
+
(`sh -c`/`bash -c` 재귀 하강, 파이프라인 감지, 리다이렉트 대상 검사,
|
|
49
|
+
재귀/강제(`rm -rf`) 인식).
|
|
50
|
+
- **거부 우선** — 거부 규칙은 어떤 allow 규칙보다 우선합니다.
|
|
51
|
+
- **세션 허용** — `(도구, 정규화 지문)` 단위의 정밀 허용(TTL + maxUses. 대상이
|
|
52
|
+
달라지면 권한을 재사용하지 않습니다. 서브 에이전트는 상속할 수 있지만 스스로
|
|
53
|
+
발행할 수 없습니다).
|
|
54
|
+
- **순수 함수 규칙 엔진** — glob/regex 컴파일 + ReDoS 상한, 잘못된 규칙은 loud fail,
|
|
55
|
+
소스 콘텐츠 해시 기반 컴파일 캐시.
|
|
56
|
+
- **감사** — 모든 판정을 `callId`와 함께 `{ignorable:true}` 이벤트로 기록합니다.
|
|
57
|
+
모델에 보이는 이유와 기록된 결과는 항상 일치합니다.
|
|
58
|
+
- **Permissive 티어** — read-only / full-access / whitelist와 구별되는 **독립 승인
|
|
59
|
+
모드**. "자동 승인"도 아니고 포괄적 권한 부여도 아닙니다. 프론트는 **단일 스위치**
|
|
60
|
+
(`permissive`)만 노출하고, 백엔드의 세 가지 전략은 **조합 가능**하며 플러그인
|
|
61
|
+
설정으로 제어됩니다. P0에 대해서는 여전히 fail-closed입니다.
|
|
62
|
+
|
|
63
|
+
## 설치
|
|
64
|
+
|
|
65
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)가 설치되어 있어야
|
|
66
|
+
합니다.
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
dsh plugin --profile web add dsh-perm-gate
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
설치·업그레이드·이전·문제 해결의 전체 절차는
|
|
73
|
+
[한국어 설치 안내](./INSTALL.ko.md)([English](./INSTALL.md) /
|
|
74
|
+
[中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md))에 있습니다.
|
|
75
|
+
|
|
76
|
+
## 설정
|
|
77
|
+
|
|
78
|
+
`cordis.yml`에 추가합니다:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
- id: dsh-perm-gate
|
|
82
|
+
name: dsh-perm-gate
|
|
83
|
+
config:
|
|
84
|
+
rulesFile: ./permissions.yaml # 선택. 비우면 defaultAction을 따름
|
|
85
|
+
dshHome: $DSH_HOME # 보호 대상 검사의 고정 루트
|
|
86
|
+
defaultAction: ask # allow | ask | deny
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 규칙 파일
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
permissions:
|
|
93
|
+
defaultAction: ask
|
|
94
|
+
deny:
|
|
95
|
+
- command: [rm#recursive]
|
|
96
|
+
reason: no recursive rm
|
|
97
|
+
- paths: [.dsh/**]
|
|
98
|
+
reason: protect harness metadata
|
|
99
|
+
allow:
|
|
100
|
+
- command: [pnpm, node]
|
|
101
|
+
reason: dev tools
|
|
102
|
+
- command: [curl, wget]
|
|
103
|
+
args: ["https://*.example.com/*"]
|
|
104
|
+
reason: allowed endpoint
|
|
105
|
+
ask:
|
|
106
|
+
- command: [bash, sh]
|
|
107
|
+
reason: ask shells
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
명령 항목의 `word#flag`는 명령어 `word`에 수식어 `recursive` 또는 `force`를 붙여
|
|
111
|
+
매칭합니다. 즉 `rm#recursive`는 `rm -rf`, `env rm -rf`, `sh -c "rm -rf /"`에
|
|
112
|
+
일치합니다.
|
|
113
|
+
|
|
114
|
+
전체 예시: [examples/permissions.example.yaml](./examples/permissions.example.yaml)
|
|
115
|
+
|
|
116
|
+
## Permissive 티어
|
|
117
|
+
|
|
118
|
+
Permissive는 권한 선택기에서 Read Only / Workspace Write / Full access / Whitelist와
|
|
119
|
+
나란한 **독립 승인 티어**입니다. "자동 승인"이 아니며 포괄적 권한을 발행하지도 않습니다.
|
|
120
|
+
사람/LLM 심 **이전에** 판정을 좁히거나 넓힐 뿐이고, P0 하드 거부는 단조롭고 협상
|
|
121
|
+
불가능하게 유지됩니다.
|
|
122
|
+
|
|
123
|
+
`cordis.yml`에서:
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
- id: dsh-perm-gate
|
|
127
|
+
name: dsh-perm-gate
|
|
128
|
+
config:
|
|
129
|
+
rulesFile: ./permissions.yaml
|
|
130
|
+
defaultAction: ask
|
|
131
|
+
permissive: true # 프론트의 유일한 스위치(독립 티어 켜기)
|
|
132
|
+
permissiveStrategies: # 백엔드 전략, 조합 가능
|
|
133
|
+
trustAutoAllow: true # 범위 내 안전 작업 자동 허용, 위험/미확인은 ask
|
|
134
|
+
alwaysConfirm: false # 매번 ask. 허용 컨트롤에 확장 버튼 2개
|
|
135
|
+
llmAssist: false # 먼저 LLM이 분류, ask/실패 시 사람에게
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`trustAutoAllow`는 중간 티어의 기준선입니다(rule-allow는 자동 통과). `alwaysConfirm`은
|
|
139
|
+
모든 경계에서 승인 패널을 띄우며, 그「허용 컨트롤」에 두 개의 확장 버튼을 추가합니다 —
|
|
140
|
+
**이 세션에서 해당 유형 반복 허용**(`approveRepeat`, 유계 세션 허용)과 **모든 발생
|
|
141
|
+
허용**(`approveAllowEverywhere`, 명령어를 `permissions.yaml`의 allow 허용 목록에
|
|
142
|
+
영속 기록 후 재로드). `llmAssist`는 설정된 실제 LLM(`classifierEndpoint` /
|
|
143
|
+
`classifierModel`, OpenAI 호환 API면 무엇이든 가능)에 `ask` 자동 판정을 맡기고,
|
|
144
|
+
`ask`/오류 시 사람의 승인 심으로 폴백합니다 — 항상 fail-closed입니다.
|
|
145
|
+
`permissive`가 꺼져 있으면 게이트는 이전과 완전히 동일하게 동작합니다.
|
|
146
|
+
|
|
147
|
+
### 선택 가능한 세션 티어
|
|
148
|
+
|
|
149
|
+
`cordis.patch.yml`은 DSH의 `permission.config.presets`를 확장해 Workspace Write와
|
|
150
|
+
Full access 사이에 `permissive` preset(`sandbox: workspace-write`, `approval: ask`,
|
|
151
|
+
이름 **Permissive**)을 추가합니다. Auto 모드와 같은 메커니즘입니다. 따라서 세션 권한
|
|
152
|
+
선택기에는 "auto-approval"이 아니라 **독립적으로 선택 가능한 승인 티어**인 Permissive가
|
|
153
|
+
놓입니다.
|
|
154
|
+
|
|
155
|
+
### UI에서 설정 가능
|
|
156
|
+
|
|
157
|
+
이 티어는 실행 중에도 **설정 → 플러그인 → Permissive 승인 티어**에서 조정할 수 있습니다
|
|
158
|
+
(플러그인 브라우저 절반이 렌더링하는 `settings.plugins.tab` 페이지). 스위치 하나가
|
|
159
|
+
`permissive`를 토글하고, 토글 세 개가 백엔드 `permissiveStrategies`를 편집합니다.
|
|
160
|
+
host는 네임스페이스를 live로 읽으므로 변경은 재시작 없이 다음 도구 호출부터 적용됩니다.
|
|
161
|
+
이것은 독립적인 승인 클래스이며 DSH의 "auto-approval" 모드가 **아닙니다**.
|
|
162
|
+
|
|
163
|
+
### 위험 등급 llmAssist, 판정 학습, 이벤트 피드
|
|
164
|
+
|
|
165
|
+
`llmAssist`가 켜져 있으면 설정된 LLM(OpenAI 호환 엔드포인트라면 무엇이든 — `classifierEndpoint` / `classifierModel` / `classifierApiKey`을 자신의 API로 지정)이 구조화된 프로토콜로 `ask`를 하나씩 판정합니다:
|
|
166
|
+
|
|
167
|
+
- `safe` → 자동 허용(감사 소스 `classifier`).
|
|
168
|
+
- `risky` + **하드 위험 카테고리**(`deletion`, `credential`, `remote`, `system`, `bulk`) → 항상 사람에게 전달. 하드 위험은 자동 허용도 학습도 되지 않습니다.
|
|
169
|
+
- `risky:neutral` → `riskLearning` 활성 시(설정 카드, 기본 꺼짐), 사람이 승인하고 실제 실행된 neutral 위험은 `tool|카테고리` 키로 카운트되며, `riskThreshold`(기본 3) 도달 및 새 호출의 작업 지문(명령어 단어 + 대상 기본 이름)이 확인된 샘플과 일치하면 **동일 작업만** 자동 허용됩니다.
|
|
170
|
+
- 시간 초과(`riskTimeoutMs`, 기본 20초, 1회 재시도), 전송 실패, 프로토콜 외 출력은 원래 `ask`를 유지합니다.
|
|
171
|
+
|
|
172
|
+
학습 상태는 플러그인 소유 JSON(`$DSH_HOME/perm-gate/learning.json` 또는 `learningFile`)에 영속화되며 YAML 규칙 파일에는 기록되지 않습니다. 모든 결정은 `$DSH_HOME/perm-gate/events.jsonl`(또는 `eventsFile`)에 추가되고 `GET /api/dsh-perm-gate/events?sessionId=&since=`로 제공됩니다. 브라우저 절반이 이를 폴링하여 입력창 위에 최신 결정을 알림 바로 표시합니다. Permissive 티어는 권한 선택기에서 방패 아이콘을 유지합니다(메뉴 항목과 축소 트리거 모두).
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
## CLI(독립 실행 dry-run)
|
|
176
|
+
|
|
177
|
+
Harness 없이 규칙 파일에 대해 호출 하나를 평가할 수 있습니다:
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
dsh-perm-gate --rules permissions.yaml --tool bash --args '{"command":"pnpm install"}'
|
|
181
|
+
dsh-perm-gate --rules permissions.yaml --list
|
|
182
|
+
dsh-perm-gate --permissive --tool bash --args '{"command":"pnpm install"}'
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 개발
|
|
186
|
+
|
|
187
|
+
```sh
|
|
188
|
+
npm run typecheck
|
|
189
|
+
npm test
|
|
190
|
+
npm run build
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## 라이선스
|
|
194
|
+
|
|
195
|
+
[MIT](./LICENSE)
|