dsh-perm-gate 5.0.2 → 5.0.3
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 +2 -0
- package/CHANGELOG.ko.md +2 -0
- package/CHANGELOG.md +2 -0
- package/INSTALL.ja.md +15 -0
- package/INSTALL.ko.md +15 -0
- package/INSTALL.md +15 -0
- package/INSTALL.zh.md +15 -0
- package/README.de.md +487 -0
- package/README.es.md +489 -0
- package/README.fr.md +498 -0
- package/README.it.md +490 -0
- package/README.ja.md +18 -1
- package/README.ko.md +18 -1
- package/README.md +18 -1
- package/README.ru.md +478 -0
- package/README.zh.md +18 -1
- package/lib/client.js +788 -5
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.ja.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# 変更履歴
|
|
2
2
|
|
|
3
|
+
言語: [English](./CHANGELOG.md) · [日本語](./CHANGELOG.ja.md) · [한국어](./CHANGELOG.ko.md) · [Français](./CHANGELOG.fr.md) · [Deutsch](./CHANGELOG.de.md) · [Italiano](./CHANGELOG.it.md) · [Русский](./CHANGELOG.ru.md) · [Español](./CHANGELOG.es.md)
|
|
4
|
+
|
|
3
5
|
このプロジェクトの重要な変更はすべてこのファイルに記録されます。
|
|
4
6
|
|
|
5
7
|
形式は [Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) に従い、
|
package/CHANGELOG.ko.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# 변경 로그
|
|
2
2
|
|
|
3
|
+
언어: [English](./CHANGELOG.md) · [日本語](./CHANGELOG.ja.md) · [한국어](./CHANGELOG.ko.md) · [Français](./CHANGELOG.fr.md) · [Deutsch](./CHANGELOG.de.md) · [Italiano](./CHANGELOG.it.md) · [Русский](./CHANGELOG.ru.md) · [Español](./CHANGELOG.es.md)
|
|
4
|
+
|
|
3
5
|
이 프로젝트의 중요한 변경 사항은 모두 이 파일에 기록됩니다.
|
|
4
6
|
|
|
5
7
|
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)을 따르며,
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
Languages: [English](./CHANGELOG.md) · [日本語](./CHANGELOG.ja.md) · [한국어](./CHANGELOG.ko.md) · [Français](./CHANGELOG.fr.md) · [Deutsch](./CHANGELOG.de.md) · [Italiano](./CHANGELOG.it.md) · [Русский](./CHANGELOG.ru.md) · [Español](./CHANGELOG.es.md)
|
|
4
|
+
|
|
3
5
|
All notable changes to this project will be documented in this file.
|
|
4
6
|
|
|
5
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
package/INSTALL.ja.md
CHANGED
|
@@ -4,13 +4,28 @@
|
|
|
4
4
|
- [中文 README](./README.zh.md)
|
|
5
5
|
- [日本語 README](./README.ja.md)
|
|
6
6
|
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Français README](./README.fr.md)
|
|
8
|
+
- [Deutsch README](./README.de.md)
|
|
9
|
+
- [Italiano README](./README.it.md)
|
|
10
|
+
- [Русский README](./README.ru.md)
|
|
11
|
+
- [Español README](./README.es.md)
|
|
7
12
|
- [Installation guide](./INSTALL.md)
|
|
8
13
|
- [中文安装指南](./INSTALL.zh.md)
|
|
9
14
|
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
15
|
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
16
|
+
- [Guide d'installation](./INSTALL.fr.md)
|
|
17
|
+
- [Installationsanleitung](./INSTALL.de.md)
|
|
18
|
+
- [Guida all'installazione](./INSTALL.it.md)
|
|
19
|
+
- [Руководство по установке](./INSTALL.ru.md)
|
|
20
|
+
- [Guía de instalación](./INSTALL.es.md)
|
|
11
21
|
- [Changelog](./CHANGELOG.md)
|
|
12
22
|
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
23
|
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
24
|
+
- [Français changelog](./CHANGELOG.fr.md)
|
|
25
|
+
- [Deutsch changelog](./CHANGELOG.de.md)
|
|
26
|
+
- [Italiano changelog](./CHANGELOG.it.md)
|
|
27
|
+
- [Русский changelog](./CHANGELOG.ru.md)
|
|
28
|
+
- [Español changelog](./CHANGELOG.es.md)
|
|
14
29
|
|
|
15
30
|
`dsh-perm-gate` バージョン **2.4.1**。判定チェーン、ルールファイル形式、自动审查
|
|
16
31
|
ティアについては [日本語 README](./README.ja.md) を参照してください。
|
package/INSTALL.ko.md
CHANGED
|
@@ -4,13 +4,28 @@
|
|
|
4
4
|
- [中文 README](./README.zh.md)
|
|
5
5
|
- [日本語 README](./README.ja.md)
|
|
6
6
|
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Français README](./README.fr.md)
|
|
8
|
+
- [Deutsch README](./README.de.md)
|
|
9
|
+
- [Italiano README](./README.it.md)
|
|
10
|
+
- [Русский README](./README.ru.md)
|
|
11
|
+
- [Español README](./README.es.md)
|
|
7
12
|
- [Installation guide](./INSTALL.md)
|
|
8
13
|
- [中文安装指南](./INSTALL.zh.md)
|
|
9
14
|
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
15
|
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
16
|
+
- [Guide d'installation](./INSTALL.fr.md)
|
|
17
|
+
- [Installationsanleitung](./INSTALL.de.md)
|
|
18
|
+
- [Guida all'installazione](./INSTALL.it.md)
|
|
19
|
+
- [Руководство по установке](./INSTALL.ru.md)
|
|
20
|
+
- [Guía de instalación](./INSTALL.es.md)
|
|
11
21
|
- [Changelog](./CHANGELOG.md)
|
|
12
22
|
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
23
|
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
24
|
+
- [Français changelog](./CHANGELOG.fr.md)
|
|
25
|
+
- [Deutsch changelog](./CHANGELOG.de.md)
|
|
26
|
+
- [Italiano changelog](./CHANGELOG.it.md)
|
|
27
|
+
- [Русский changelog](./CHANGELOG.ru.md)
|
|
28
|
+
- [Español changelog](./CHANGELOG.es.md)
|
|
14
29
|
|
|
15
30
|
`dsh-perm-gate` 버전 **2.4.1**. 결정 체인, 규칙 파일 형식, 自动审查 티어는
|
|
16
31
|
[한국어 README](./README.ko.md)를 참고하세요.
|
package/INSTALL.md
CHANGED
|
@@ -4,13 +4,28 @@
|
|
|
4
4
|
- [中文 README](./README.zh.md)
|
|
5
5
|
- [日本語 README](./README.ja.md)
|
|
6
6
|
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Français README](./README.fr.md)
|
|
8
|
+
- [Deutsch README](./README.de.md)
|
|
9
|
+
- [Italiano README](./README.it.md)
|
|
10
|
+
- [Русский README](./README.ru.md)
|
|
11
|
+
- [Español README](./README.es.md)
|
|
7
12
|
- [Installation guide](./INSTALL.md)
|
|
8
13
|
- [中文安装指南](./INSTALL.zh.md)
|
|
9
14
|
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
15
|
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
16
|
+
- [Guide d'installation](./INSTALL.fr.md)
|
|
17
|
+
- [Installationsanleitung](./INSTALL.de.md)
|
|
18
|
+
- [Guida all'installazione](./INSTALL.it.md)
|
|
19
|
+
- [Руководство по установке](./INSTALL.ru.md)
|
|
20
|
+
- [Guía de instalación](./INSTALL.es.md)
|
|
11
21
|
- [Changelog](./CHANGELOG.md)
|
|
12
22
|
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
23
|
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
24
|
+
- [Français changelog](./CHANGELOG.fr.md)
|
|
25
|
+
- [Deutsch changelog](./CHANGELOG.de.md)
|
|
26
|
+
- [Italiano changelog](./CHANGELOG.it.md)
|
|
27
|
+
- [Русский changelog](./CHANGELOG.ru.md)
|
|
28
|
+
- [Español changelog](./CHANGELOG.es.md)
|
|
14
29
|
|
|
15
30
|
`dsh-perm-gate` version **2.4.1**. Continue with the [README](./README.md) for the
|
|
16
31
|
decision chain, the rules file format and the 自动审查 tier.
|
package/INSTALL.zh.md
CHANGED
|
@@ -4,13 +4,28 @@
|
|
|
4
4
|
- [中文 README](./README.zh.md)
|
|
5
5
|
- [日本語 README](./README.ja.md)
|
|
6
6
|
- [한국어 README](./README.ko.md)
|
|
7
|
+
- [Français README](./README.fr.md)
|
|
8
|
+
- [Deutsch README](./README.de.md)
|
|
9
|
+
- [Italiano README](./README.it.md)
|
|
10
|
+
- [Русский README](./README.ru.md)
|
|
11
|
+
- [Español README](./README.es.md)
|
|
7
12
|
- [Installation guide](./INSTALL.md)
|
|
8
13
|
- [中文安装指南](./INSTALL.zh.md)
|
|
9
14
|
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
10
15
|
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
16
|
+
- [Guide d'installation](./INSTALL.fr.md)
|
|
17
|
+
- [Installationsanleitung](./INSTALL.de.md)
|
|
18
|
+
- [Guida all'installazione](./INSTALL.it.md)
|
|
19
|
+
- [Руководство по установке](./INSTALL.ru.md)
|
|
20
|
+
- [Guía de instalación](./INSTALL.es.md)
|
|
11
21
|
- [Changelog](./CHANGELOG.md)
|
|
12
22
|
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
13
23
|
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
24
|
+
- [Français changelog](./CHANGELOG.fr.md)
|
|
25
|
+
- [Deutsch changelog](./CHANGELOG.de.md)
|
|
26
|
+
- [Italiano changelog](./CHANGELOG.it.md)
|
|
27
|
+
- [Русский changelog](./CHANGELOG.ru.md)
|
|
28
|
+
- [Español changelog](./CHANGELOG.es.md)
|
|
14
29
|
|
|
15
30
|
`dsh-perm-gate` 版本 **2.4.1**。裁决链、规则文件格式与自动审查档位请见
|
|
16
31
|
[中文 README](./README.zh.md)。
|
package/README.de.md
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
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
|
+
- [Français README](./README.fr.md)
|
|
8
|
+
- [Deutsch README](./README.de.md)
|
|
9
|
+
- [Italiano README](./README.it.md)
|
|
10
|
+
- [Русский README](./README.ru.md)
|
|
11
|
+
- [Español README](./README.es.md)
|
|
12
|
+
- [Installation guide](./INSTALL.md)
|
|
13
|
+
- [中文安装指南](./INSTALL.zh.md)
|
|
14
|
+
- [日本語インストールガイド](./INSTALL.ja.md)
|
|
15
|
+
- [한국어 설치 안내](./INSTALL.ko.md)
|
|
16
|
+
- [Guide d'installation](./INSTALL.fr.md)
|
|
17
|
+
- [Installationsanleitung](./INSTALL.de.md)
|
|
18
|
+
- [Guida all'installazione](./INSTALL.it.md)
|
|
19
|
+
- [Руководство по установке](./INSTALL.ru.md)
|
|
20
|
+
- [Guía de instalación](./INSTALL.es.md)
|
|
21
|
+
- [Changelog](./CHANGELOG.md)
|
|
22
|
+
- [日本語 changelog](./CHANGELOG.ja.md)
|
|
23
|
+
- [한국어 changelog](./CHANGELOG.ko.md)
|
|
24
|
+
- [Français changelog](./CHANGELOG.fr.md)
|
|
25
|
+
- [Deutsch changelog](./CHANGELOG.de.md)
|
|
26
|
+
- [Italiano changelog](./CHANGELOG.it.md)
|
|
27
|
+
- [Русский changelog](./CHANGELOG.ru.md)
|
|
28
|
+
- [Español changelog](./CHANGELOG.es.md)
|
|
29
|
+
|
|
30
|
+
> **Kompatibilitätshinweis:** v2.0.0 liefert `ja`-/`ko`-Wörterbücher mit, aber das offizielle DSH
|
|
31
|
+
> stellt über `LocaleRuntime` nur `zh` / `en` bereit (`LOCALE_IDS = ["zh", "en"]`). Auf einem
|
|
32
|
+
> unveränderten DSH schlägt die Auswahl von `ja` / `ko` mit `locale "<id>" is not registered` fehl.
|
|
33
|
+
> Verwenden Sie einen DSH-Fork, der `LOCALE_IDS` (locale-settings.ts) und die `LOCALES`-Beschriftungen
|
|
34
|
+
> (client/index.ts) aktualisiert, und bauen Sie ihn neu.
|
|
35
|
+
|
|
36
|
+
> **▼ DSH-Versionskompatibilität**
|
|
37
|
+
>
|
|
38
|
+
> Zwei DSH-Linien werden von zwei langlebigen Branches bedient, jeder mit seiner eigenen
|
|
39
|
+
> Versionsserie, seinem `engines.dsh` und seinem npm-Dist-Tag
|
|
40
|
+
> ([Release-Aufteilung](./RELEASING.md)):
|
|
41
|
+
>
|
|
42
|
+
> | DSH-Version | Branch | Version | npm-Tag |
|
|
43
|
+
> | --- | --- | --- | --- |
|
|
44
|
+
> | 0.1.0-rc.7 ~ 0.1.1-rc.x | `legacy` | `1.x` | `@legacy` |
|
|
45
|
+
> | 0.1.2-alpha.1+ (inkl. 0.1.5-rc.2) | `main` | `2.x` | `@latest` / `@dsh-0.1.2` (`@2.x` ist eine Range) |
|
|
46
|
+
> | 0.2.0-rc.1 (0.2.0-Linie) | `compat/0.2.0` | `5.x` | `@dsh-0.2.0` |
|
|
47
|
+
>
|
|
48
|
+
> Die Seriennummer folgt der **DSH-Linie** (`1.x` = DSH ≤ 0.1.1, `2.x` = DSH 0.1.2+), und die
|
|
49
|
+
> Majors zäunen einander ein: Eine `^1.x`-Installation löst nie eine `2.x`-Version auf und
|
|
50
|
+
> umgekehrt. `engines.dsh` sagt dieselbe Trennung aus, aber DSH liest es nie — die Ranges und
|
|
51
|
+
> Dist-Tags sind es, die ein altes DSH auf `1.x` halten.
|
|
52
|
+
>
|
|
53
|
+
> `@deepseek-ai/dsh-client-runtime` wurde mit `0.1.2-alpha.1` **entfernt** — es ist nicht bloß
|
|
54
|
+
> umgezogen. Die `legacy`-Linie erreicht `ctx.slots` weiterhin über es; `main` bekommt dieselbe
|
|
55
|
+
> Deklaration aus `@deepseek-ai/dsh-client-ui-renderer/client`. Zwei versionsempfindliche Nähte
|
|
56
|
+
> werden über Capability-Probes statt Versionsprüfungen gehandhabt: (1) Die
|
|
57
|
+
> Einstellungsregistrierung verwendet `register`, das es auf beiden Linien gibt (`installSection`
|
|
58
|
+
> ist eine Ergänzung, kein Ersatz); (2) `effectivePolicy` ist auf beiden eine **private** Methode
|
|
59
|
+
> des Nutzerfreigabe-Dienstes, daher wird sie hinter einer `typeof`-Probe gelesen und degradiert
|
|
60
|
+
> zu „Policy unbekannt“, wenn sie fehlt oder wirft.
|
|
61
|
+
|
|
62
|
+
Version **2.6.0** — siehe das [Changelog](./CHANGELOG.de.md).
|
|
63
|
+
|
|
64
|
+
Ein einzelnes, in sich geschlossenes, determinismus-zuerst- und fail-closed-Permission-Gate für
|
|
65
|
+
DeepSeek Harness.
|
|
66
|
+
|
|
67
|
+
`dsh-perm-gate` entscheidet jeden Toolaufruf über eine feste Prioritätskette:
|
|
68
|
+
|
|
69
|
+
| Stufe | Entscheidung | Was es ist |
|
|
70
|
+
| ---- | ---- | ---- |
|
|
71
|
+
| **P0** | `deny` | deterministisches Hard-Deny: Zugangsdaten-Material, Mutation geschützter Pfade, gefährliche Shell |
|
|
72
|
+
| **P1** | `allow` | ein präzises, begrenztes **Session-Grant** |
|
|
73
|
+
| **P2** | `deny/allow/ask` | statische Regelkette: zuerst Blacklist, dann Allow, dann Ask |
|
|
74
|
+
| **P3** | `allow/deny/ask` | optionaler LLM-Semantikklassifikator (Standardmäßig **aus**) |
|
|
75
|
+
| **P4** | `ask` | offizieller Approval-Seam |
|
|
76
|
+
|
|
77
|
+
Streng fail-closed: Eine P0-Entscheidung wird nie von einem Grant, einer Regel, dem Klassifikator
|
|
78
|
+
oder einem Menschen überstimmt.
|
|
79
|
+
|
|
80
|
+
## Warum
|
|
81
|
+
|
|
82
|
+
Das DSH-Sicherheitsökosystem verteilt dies auf mehrere Plugins (`dsh-permission-rules`,
|
|
83
|
+
`dsh-auto-mode`, `dsh-auto-review`, `dsh-movein-permissions`). `dsh-perm-gate` führt Gate +
|
|
84
|
+
Freigabe + (optionalen) Klassifikator in einem Paket zusammen — mit einem einzigen Audit-Trail und
|
|
85
|
+
ohne versionsübergreifende Plugin-Kopplung.
|
|
86
|
+
|
|
87
|
+
## Funktionen
|
|
88
|
+
|
|
89
|
+
- **Befehls-Whitelist / Blacklist** — Abgleich über eine **argv-Zerlegung** (kein Rohstring), mit
|
|
90
|
+
rekursivem Abstieg in `sh -c`/`bash -c`, Pipeline-Erkennung, Prüfung von
|
|
91
|
+
Redirect-Zielen und Erkennung von recursive/force (`rm -rf`).
|
|
92
|
+
- **Deny-Priorität** — eine passende Deny-Regel schlägt jede Allow-Regel.
|
|
93
|
+
- **Session-Grants** — präzise `(Tool, kanonischer Fingerabdruck)`-Grants mit `TTL` + `maxUses`;
|
|
94
|
+
ein erneutes Ausführen mit anderem Ziel nutzt die Autorität nie wieder. Sub-Agents erben, können
|
|
95
|
+
aber nicht selbst münzen.
|
|
96
|
+
- **Pure-Function-Regel-Engine** — glob/regex-Kompilierung mit ReDoS-Schranke, lautes Versagen bei
|
|
97
|
+
fehlerhaften Regeln und Compile-Cache über Source-Hash.
|
|
98
|
+
- **Audit** — jede Entscheidung wird als `{ignorable:true}`-Ereignis mit ihrer `callId`
|
|
99
|
+
protokolliert; der modellsichtbare Grund entspricht dem aufgezeichneten Ausgang.
|
|
100
|
+
- **自动审查-Stufe** (`permissive`, dazu `permissive-full`) — ein **unabhängiger
|
|
101
|
+
Freigabemodus** (getrennt von den Stufen Read-only, Full-access und Whitelist), der weder
|
|
102
|
+
„Auto-Genehmigung“ noch pauschales Vertrauen ist. Das Frontend stellt einen **einzigen
|
|
103
|
+
Schalter** bereit (`permissive`); die vier Backend-Strategien sind **kombinierbar** und werden
|
|
104
|
+
über die Plugin-Einstellungen gesteuert — weiterhin fail-closed gegenüber P0. Der
|
|
105
|
+
Berechtigungs-Picker und die Einstellungszeile zeigen sie beide unter dem Produktlabel
|
|
106
|
+
自动审查, ohne Icon. Die Variante `permissive-full` behält dasselbe Freigabeverhalten, fällt
|
|
107
|
+
aber die eingebaute Datei-Sandbox weg, die sonst die benannten Pipes verweigert, die
|
|
108
|
+
`git clone` / Cygwin / ConPTY brauchen.
|
|
109
|
+
- **Auto-Antwort auf Sandbox-Eskalation** (`trustEscalation`) — eine Sandbox-Eskalation wird aus
|
|
110
|
+
*dem Inneren* des shell-/pwsh-/edit-Toolkörpers heraus gestellt, nach `tools/pre-execute`; das
|
|
111
|
+
Gate sah sie nie, und ein automatisch erlaubter Aufruf forderte Sie trotzdem auf, die
|
|
112
|
+
Ausweitung zu genehmigen. Ist diese Strategie an, wird genau der vom Gate freigegebene Aufruf
|
|
113
|
+
(an `callId` erkannt) hier beantwortet.
|
|
114
|
+
- **Risikogestufter `llmAssist`** — ein eigenes OpenAI-kompatibles LLM stuft jedes `ask` als
|
|
115
|
+
`safe` / `risky:<Kategorie>` ein; harte Kategorien (Löschen, Zugangsdaten, Remote, System,
|
|
116
|
+
Massen) **fragen immer**, Neutrales fließt in das Verdict-Lernen ein, und jeder Fehler bleibt
|
|
117
|
+
fail-closed.
|
|
118
|
+
- **Verdict-Lernen** — neutrale `ask`s, die ein Mensch freigibt und die tatsächlich ausgeführt
|
|
119
|
+
werden, zählen hoch; nach dem Schwellenwert wird *exakt derselbe Vorgang* (fingerabdruckgleich)
|
|
120
|
+
automatisch erlaubt.
|
|
121
|
+
- **Entscheidungs-Ereignis-Feed** — jede Entscheidung wird an einen JSONL-Feed angehängt und von
|
|
122
|
+
der Browser-Hälfte als Hinweisband über der Konversationseingabe plus ein
|
|
123
|
+
Freigabe-Protokoll-Tab (neueste zuerst) in der Konversationsansicht angezeigt.
|
|
124
|
+
|
|
125
|
+
Eine vordefinierte **Deny-Keyword-Blacklist** (geerbt von dsh-approval-gates
|
|
126
|
+
`DEFAULT_DENY_KEYWORDS`: `rm -rf`, `push --force`, `drop table`, `mkfs`, `git reset --hard`,
|
|
127
|
+
`docker system prune`, …) setzt ein Veto gegen jeden Aufruf, dessen Text ein Keyword enthält —
|
|
128
|
+
case-insensitiver Teilstring, angewandt vor Whitelist, Grants und LLM. Sie ist in der
|
|
129
|
+
Einstellungskarte als Liste editierbar (Vorlageneinträge sind markiert, ein Klick stellt die
|
|
130
|
+
Vorlage wieder her); nicht gesetzt oder leer bedeutet die Vorlage — die Blacklist schaltet sich
|
|
131
|
+
nie still ab.
|
|
132
|
+
|
|
133
|
+
## Installation
|
|
134
|
+
|
|
135
|
+
Benötigt eine bestehende
|
|
136
|
+
[DeepSeek-Harness](https://github.com/deepseek-ai/deepseek-harness)-Installation.
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
dsh plugin --profile web add dsh-perm-gate
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Vollständige Schritte zu Installation, Upgrade, Migration und Fehlerbehebung stehen in der
|
|
143
|
+
[Installationsanleitung](./INSTALL.de.md) — auch verfügbar auf
|
|
144
|
+
[English](./INSTALL.md) / [中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md) /
|
|
145
|
+
[한국어](./INSTALL.ko.md) / [Français](./INSTALL.fr.md) / [Italiano](./INSTALL.it.md) /
|
|
146
|
+
[Русский](./INSTALL.ru.md) / [Español](./INSTALL.es.md).
|
|
147
|
+
|
|
148
|
+
## Konfiguration
|
|
149
|
+
|
|
150
|
+
Fügen Sie das Plugin in die `cordis.yml` ein:
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
- id: dsh-perm-gate
|
|
154
|
+
name: dsh-perm-gate
|
|
155
|
+
config:
|
|
156
|
+
rulesFile: ./permissions.yaml # optional; defaults to $DSH_HOME/perm-gate/rules.yml
|
|
157
|
+
dshHome: $DSH_HOME # root pinned for protected-target checks
|
|
158
|
+
defaultAction: ask # allow | ask | deny
|
|
159
|
+
gatePresets: [permissive, permissive-full] # tiers where the gate is active (default)
|
|
160
|
+
sessionSweep: true # hourly cleanup of archived/dead sessions' gate data
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Session-Sweep
|
|
164
|
+
|
|
165
|
+
Beim Start und stündlich liest das Gate den Workspace-Speicher von DSH
|
|
166
|
+
(`$DSH_HOME/storages/workspace.json`, nur lesend) und klassifiziert jede Sitzung, für die es
|
|
167
|
+
Autorisationskettendaten hält. Sitzungen, die DSH archiviert hat (`global.archivedSessionIds`)
|
|
168
|
+
oder gar nicht mehr führt, verlieren ihre Entscheidungsereignisse aus
|
|
169
|
+
`$DSH_HOME/perm-gate/events.jsonl`, und ihre Snapshot-Dateien vor der Änderung werden aus
|
|
170
|
+
`$DSH_HOME/perm-gate/snapshots/` gelöscht — Historie, die die Review-Seite nicht mehr erreichen
|
|
171
|
+
kann, für Daten, die der Harness selbst als weg betrachtet. Lebende Sitzungen bleiben unberührt,
|
|
172
|
+
nicht zuordenbare Zeilen (leere Sitzungs-ID) werden nie gelöscht, und jeder Fehler ist fail-open:
|
|
173
|
+
Der Durchlauf wird übersprungen und eine Stunde später wiederholt. Setzen Sie
|
|
174
|
+
`sessionSweep: false` zum Deaktivieren; `workspaceStoreFile` überschreibt den Speicherpfad. Die
|
|
175
|
+
Wiederherstellung einer archivierten Sitzung stellt deren weggesäuberte Historie nicht wieder her.
|
|
176
|
+
|
|
177
|
+
### Regeldatei
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
permissions:
|
|
181
|
+
defaultAction: ask
|
|
182
|
+
deny:
|
|
183
|
+
- command: [rm#recursive]
|
|
184
|
+
reason: no recursive rm
|
|
185
|
+
- command: [ssh]
|
|
186
|
+
reason: no direct ssh
|
|
187
|
+
- paths: [.dsh/**]
|
|
188
|
+
reason: protect harness metadata
|
|
189
|
+
allow:
|
|
190
|
+
- command: [pnpm, node]
|
|
191
|
+
reason: dev tools
|
|
192
|
+
- command: [curl, wget]
|
|
193
|
+
args: ["https://*.example.com/*"]
|
|
194
|
+
reason: allowed endpoint
|
|
195
|
+
ask:
|
|
196
|
+
- command: [bash, sh]
|
|
197
|
+
reason: ask shells
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Ein Befehlseintrag `word#flag` matcht das Befehlswort (`word`) mit dem Modifikator `recursive`
|
|
201
|
+
oder `force` — `rm#recursive` matcht also `rm -rf`, `env rm -rf` und `sh -c "rm -rf /"`.
|
|
202
|
+
|
|
203
|
+
### Netzwerk-Policy (Opt-in)
|
|
204
|
+
|
|
205
|
+
Ein lokaler HTTP/CONNECT-Proxy, der den ausgehenden Verkehr von **Shell-Subprozessen** anhand
|
|
206
|
+
derselben Regeldatei entscheidet, plus ein Freigabepfad für Ziele, die keine Regel abdeckt.
|
|
207
|
+
**Standardmäßig aus** — die Aktivierung bindet einen Loopback-Port und schreibt die
|
|
208
|
+
Proxy-Umgebung der Kindprozesse um; sie wird daher nie implizit eingeschaltet.
|
|
209
|
+
|
|
210
|
+
```yaml
|
|
211
|
+
- id: dsh-perm-gate
|
|
212
|
+
config:
|
|
213
|
+
networkEnabled: false # master switch (default false)
|
|
214
|
+
networkMode: whitelist # deny-all | whitelist | allow-all
|
|
215
|
+
networkUnlisted: ask # ask | deny — unlisted target handling
|
|
216
|
+
networkUnattributed: allow # allow | deny — traffic with no shell attribution
|
|
217
|
+
networkInjectEnv: true # rewrite HTTP(S)_PROXY/ALL_PROXY for children
|
|
218
|
+
networkAskTimeoutMs: 120000 # approval wait before failing closed
|
|
219
|
+
networkGrantTtlMs: 1800000 # how long one approval covers its target
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Gestuftes Verhalten.** Nichts erreicht das Netzwerk ohne Allow-Regel. Ein nicht gelistetes
|
|
223
|
+
Ziel wird an die interaktive Freigabenaht eskaliert, im Namen des Shell-Befehls erhoben, der die
|
|
224
|
+
Verbindung öffnete; eine Freigabe weitet die Reichweite für dieses Ziel für die Sitzung. Eine
|
|
225
|
+
`deny`-Regel wird **nie** eskaliert — eine Freigabe kann erweitern, was ein nicht gelistetes Ziel
|
|
226
|
+
erreichen darf, aber sie kann nie eine Regel überstimmen, die Nein sagt.
|
|
227
|
+
|
|
228
|
+
**Die Grenze — lesen Sie das, bevor Sie sich darauf verlassen.** Der Proxy ist eine
|
|
229
|
+
*kooperative* Policy-Schicht, keine Durchsetzungsgrenze. Er sieht nur Verkehr von Clients, die die
|
|
230
|
+
Proxy-Umgebung lesen:
|
|
231
|
+
|
|
232
|
+
| Client | Abgedeckt? |
|
|
233
|
+
|--------|----------|
|
|
234
|
+
| `curl`, `wget`, `git`, Go `net/http`, Python `requests` | ja |
|
|
235
|
+
| **Node.js `http`/`https`/`fetch`** | **nein — verbindet direkt** |
|
|
236
|
+
| Java (ohne `-D`-Proxy-Flags), .NET `HttpClient` | nein |
|
|
237
|
+
| Raw Sockets, eigenes TCP | nein |
|
|
238
|
+
| DNS, QUIC/HTTP3, Nicht-HTTP-Protokolle | nein |
|
|
239
|
+
| Verbindungen zu einer literalen IP | nein |
|
|
240
|
+
|
|
241
|
+
Ein Shell-Befehl wie `node -e "require('http').get('http://host/')"` wird also nicht
|
|
242
|
+
abgefangen. Betrachten Sie dies als Leitplanke gegen Unfälle und als Ort, um Absicht zu
|
|
243
|
+
dokumentieren — nicht als hermetische Sandbox.
|
|
244
|
+
|
|
245
|
+
DSHs **eigener** Netzwerkverkehr — die eingebauten Netzwerk-Tools und der LLM-Transport — wird
|
|
246
|
+
bewusst in Ruhe gelassen. Diese Verbindungen tragen keine Shell-Zuordnung, und
|
|
247
|
+
`networkUnattributed: allow` (der Default) lässt sie ungeprüft durch: Sie zu prüfen würde dem
|
|
248
|
+
Host erlauben, *sich selbst* zu blockieren — ein schlimmerer Fehler als ein verpasster Block.
|
|
249
|
+
Setzen Sie `networkUnattributed: deny` nur, wenn Sie wissen, dass die Clients Ihres Hosts die
|
|
250
|
+
Proxy-Umgebung ignorieren.
|
|
251
|
+
|
|
252
|
+
Den Live-Zustand abfragen über `GET /api/dsh-perm-gate/network` (Modus, Bind, Port,
|
|
253
|
+
Proxy-Lebendigkeit, Env-Injection-Status, Block-Zähler, letzte Blocks).
|
|
254
|
+
|
|
255
|
+
## Die 自动审查-Stufe (Maschinenwert `permissive`)
|
|
256
|
+
|
|
257
|
+
自动审查 ist eine **unabhängige Freigabestufe** im DSH-Berechtigungs-Picker, parallel zu
|
|
258
|
+
Read Only / Workspace Write / Full Access / Whitelist. Sie ist **keine** generische
|
|
259
|
+
„Auto-Genehmigung“ und prägt nie pauschale Autorität: Sie verengt oder weitet nur die Naht *vor*
|
|
260
|
+
dem Mensch/LLM-Schritt, während das P0-Hard-Deny **innerhalb des eigenen Geltungsbereichs des
|
|
261
|
+
Gates** monoton und nicht verhandelbar bleibt.
|
|
262
|
+
|
|
263
|
+
> **P0 ist begrenzt, nicht global.** Das Gate wirkt nur, solange der Berechtigungs-Preset der
|
|
264
|
+
> Sitzung einer der `gatePresets` ist (Default `permissive` / `permissive-full`). Unter jedem
|
|
265
|
+
> anderen Preset — Read Only, Workspace Write oder Full Access — tritt das **gesamte** Gate
|
|
266
|
+
> zurück, das P0-Hard-Deny eingeschlossen, weil die eigene Policy der gewählten Stufe diese
|
|
267
|
+
> Sitzung regiert. Das ist beabsichtigt (siehe `gatePresets` in der Konfigurationstabelle), heißt
|
|
268
|
+
> aber: „P0 ist nicht verhandelbar“ gilt *innerhalb* der Gate-Stufen, nicht über jede Stufe
|
|
269
|
+
> hinweg. Ein Rückzug ist nicht lautlos: Das Gate zeichnet ein `stand-down`-Ereignis pro
|
|
270
|
+
> Sitzungs-/Preset-Wechsel auf, und der Browser zeigt ein klebendes **GATE OFF**-Band über der
|
|
271
|
+
> Eingabe. Setzen Sie `gatePresets: ['*']`, um P0 wieder global zu machen.
|
|
272
|
+
|
|
273
|
+
**Es werden zwei Varianten ausgeliefert**, denn `sandbox` und `approval` eines Presets sind
|
|
274
|
+
unabhängige Stellschrauben, und ihre Kopplung erzwang einen schlechten Kompromiss:
|
|
275
|
+
|
|
276
|
+
| Picker-Label | Maschinenwert | sandbox | approval |
|
|
277
|
+
|--------------|---------------|---------|----------|
|
|
278
|
+
| 自动审查 | `permissive` | `workspace-write` | `ask` |
|
|
279
|
+
| 自动审查(高权限) | `permissive-full` | `danger-full-access` | `ask` |
|
|
280
|
+
|
|
281
|
+
Die schlichte Stufe behält die eingebaute Datei-Sandbox. Diese Sandbox verweigert auch die
|
|
282
|
+
benannten Pipes, die ein Kindprozess zum Starten braucht; deshalb scheitern daran `git clone`,
|
|
283
|
+
MSYS2/Cygwin-`sh.exe` und ConPTY mit `Win32 error 5` / `couldn't create signal pipe`. Da das Gate
|
|
284
|
+
**nur** in den in `gatePresets` gelisteten Stufen aktiv ist, hieß Gate wollen, diese Einschränkung
|
|
285
|
+
akzeptieren. 自动审查(高权限) löst die Kopplung: identisches Freigabeverhalten, keine
|
|
286
|
+
Datei-Sandbox-Einschränkung. Die Beschreibung der Stufe sagt den Kompromiss offen — der
|
|
287
|
+
Workflow ist reibungsloser, Freigaben gelten weiterhin pro Aufruf, aber es bleibt **keine
|
|
288
|
+
System-Sandbox als Rückfallebene**. Beide stehen im Default der `gatePresets`, also gibt Ihnen
|
|
289
|
+
jede die volle P0–P4-Kette — das Gate liest nur den **Namen** des Presets, nie den Sandbox-Modus.
|
|
290
|
+
|
|
291
|
+
Das Picker-Label ist ein **vom Host gelieferter Produkt-String**, kein pro-Locale-Wörterbucheintrag:
|
|
292
|
+
DSH rendert den `name:` einer Plugin-Stufe wortwörtlich auf beiden Berechtigungsflächen (die
|
|
293
|
+
Default-Zeile in den allgemeinen Einstellungen und der Composer-Picker) und liefert eigene
|
|
294
|
+
lokalisierte Labels nur für die drei eingebauten Werte; `cordis.patch.yml` liefert daher das
|
|
295
|
+
chinesische Label für jede Sitzung.
|
|
296
|
+
|
|
297
|
+
Beim **Icon** ist es eine andere Geschichte. Die Glyph-Map des Composers ist geschlossen, und ihr
|
|
298
|
+
eigener Kommentar nennt die Regel: *host-configured names outside the design set get none.*
|
|
299
|
+
`permissive` ist ein eingebauter Wert, daher hat 自动审查 bereits ein Schild+Auge-Glyph;
|
|
300
|
+
`permissive-full` bekommt dasselbe Glyph nur, weil `npx dsh-perm-gate-patch-glyph` es in diese Map
|
|
301
|
+
einträgt. Dieser Patch editiert ein **Host**-Paket und geht deshalb bei jedem DSH-Upgrade
|
|
302
|
+
verloren — siehe [Nach einem DSH-Upgrade](./INSTALL.de.md).
|
|
303
|
+
|
|
304
|
+
In der `cordis.yml`:
|
|
305
|
+
|
|
306
|
+
```yaml
|
|
307
|
+
- id: dsh-perm-gate
|
|
308
|
+
name: dsh-perm-gate
|
|
309
|
+
config:
|
|
310
|
+
rulesFile: ./permissions.yaml
|
|
311
|
+
defaultAction: ask
|
|
312
|
+
permissive: true # single front-facing switch (independent tier on)
|
|
313
|
+
permissiveStrategies: # backend, combinable
|
|
314
|
+
trustAutoAllow: true # in-scope safe ops auto-allow; dangerous/unknown ask
|
|
315
|
+
alwaysConfirm: false # every crossing asks; allow-controls add repeat-allow / wl-migrate buttons
|
|
316
|
+
llmAssist: false # LLM classify first, human fallback on ask/failure
|
|
317
|
+
trustEscalation: true # a cleared call's own sandbox escalation needs no prompt
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
`trustAutoAllow` ist die Basismittelstufe (eine Regel-Allow läuft automatisch durch).
|
|
321
|
+
`alwaysConfirm` zeigt bei jedem Übertritt das Freigabepanel; seine „Allow-Controls“ fügen zwei
|
|
322
|
+
erweiterte Buttons hinzu — **diesen Typ für diese Sitzung wiederholt erlauben** (ein begrenztes
|
|
323
|
+
Session-Grant) und **jedes Vorkommen erlauben** (das das Befehlswort per `approveAllowEverywhere`
|
|
324
|
+
in die `allow`-Whitelist der `permissions.yaml` überträgt). `llmAssist` zieht ein echtes,
|
|
325
|
+
konfigurierbares LLM hinzu (`classifierEndpoint` / `classifierModel`, jede OpenAI-kompatible
|
|
326
|
+
API), um ein `ask` automatisch zu entscheiden, und fällt bei `ask`/Fehler auf die menschliche
|
|
327
|
+
Naht zurück — immer fail-closed. `trustEscalation` (standardmäßig an, solange die Stufe an ist)
|
|
328
|
+
beantwortet eine `sandbox_permissions`-Eskalation, die aus dem Inneren eines bereits vom Gate
|
|
329
|
+
erlaubten Aufrufs gestellt wurde; siehe unten. Bei ausgeschaltetem `permissive` verhält sich das
|
|
330
|
+
Gate genau wie zuvor.
|
|
331
|
+
|
|
332
|
+
### Sandbox-Eskalation: warum ein `safe`-Verdict trotzdem nachfragte
|
|
333
|
+
|
|
334
|
+
Ein Toolaufruf kann **zwei unabhängige Freigaben** auslösen. Das Gate besitzt die erste — sein
|
|
335
|
+
eigenes `ask` im `tools/pre-execute`-Wasserfall. Die zweite kommt von `approveEscalation`
|
|
336
|
+
**im Toolkörper**, zur Zeit von `tools/execute`, wann immer das Modell `sandbox_permissions` +
|
|
337
|
+
`justification` übergeben hat; bis dahin ist `tools/pre-execute` bereits entschieden, sodass das
|
|
338
|
+
Allow des Gates sie nie erreicht. Ein vom LLM als `safe` eingestufter und vom Gate automatisch
|
|
339
|
+
erlaubter Aufruf zeigte also trotzdem eine Aufforderung, die Sandbox-Ausweitung zu genehmigen.
|
|
340
|
+
|
|
341
|
+
`trustEscalation` schließt diese Lücke. Das Gate merkt sich jeden positiv erlaubten Aufruf
|
|
342
|
+
(schlüsselt auf der `callId` des Hosts, die die Eskalationsanfrage wiederholt), und beantwortet
|
|
343
|
+
die Eskalation selbst mit `allowed-once`. Sie greift nur, wenn **alles** zutrifft:
|
|
344
|
+
|
|
345
|
+
- die 自动审查-Stufe ist an und `trustEscalation` ist an;
|
|
346
|
+
- die Anfrage trägt eine vom Gate freigegebene `callId` mit passendem Toolnamen;
|
|
347
|
+
- der Grund ist eine erkannte Eskalation, die `workspace-write` oder `danger-full-access` nennt.
|
|
348
|
+
|
|
349
|
+
Alles andere — ein unbekannter Grund, ein anderer Aufruf, ein vom Gate nachgefragter oder
|
|
350
|
+
verweigerter Aufruf, der `approval: never`-Durchgriff — delegiert unverändert an den Menschen,
|
|
351
|
+
sodass eine künftige Formulierungsänderung in DSH geschlossen statt offen scheitert. Die
|
|
352
|
+
Auto-Antwort wird im Ereignis-Feed aufgezeichnet (`verdict: "escalation-auto"`, `mode: <Ziel>`).
|
|
353
|
+
Schalten Sie den Schalter aus, um Sandbox-Ausweitungen menschlich gateen zu lassen, während
|
|
354
|
+
andere Allows automatisch bleiben.
|
|
355
|
+
|
|
356
|
+
### Risikogestufter llmAssist, Verdict-Lernen und der Ereignis-Feed
|
|
357
|
+
|
|
358
|
+
Ist `llmAssist` an, stuft das konfigurierte LLM jeweils ein `ask` nach einem strukturierten
|
|
359
|
+
Protokoll ein. Die Bewertung geschieht **im `tools/pre-execute`-Wasserfall des Gates, bevor die
|
|
360
|
+
Entscheidung an den Host zurückgeht**: ein `safe`-Verdict delegiert den Aufruf direkt durch, das
|
|
361
|
+
Freigabepanel erscheint also nie; nur ein wirklich unsicheres Verdict erreicht Sie. Zwei
|
|
362
|
+
Empfängerquellen sind in der Einstellungskarte wählbar: eine **eigene API** (jeder
|
|
363
|
+
OpenAI-kompatible Endpoint — `classifierEndpoint` / `classifierModel` / `classifierApiKey`, mit
|
|
364
|
+
Presets u. a. Xiaomi MiMo `https://api.xiaomimimo.com/v1`) oder die **DSH-Host-Modellgruppe** (der
|
|
365
|
+
konfigurierte `llm`-Dienst der Sitzung, über `agentDefaultModel.currentSelection`, optional
|
|
366
|
+
überschrieben mit `classifierProvider` / `classifierModel`). Ein **Gesundheitstest**-Button
|
|
367
|
+
(`POST /api/dsh-perm-gate/health`) führt eine minimale Completion aus und meldet die Latenz.
|
|
368
|
+
|
|
369
|
+
- `safe` → der Aufruf wird automatisch erlaubt (auditert mit der Quelle `classifier`); kein Panel.
|
|
370
|
+
- `risky` + eine **harte Kategorie** (`deletion`, `credential`, `remote`, `system`, `bulk`) → der
|
|
371
|
+
Aufruf **behält die menschliche Nachfrage**. Der Klassifikator **verweigert nie**: Der
|
|
372
|
+
Deny-Pfad gehört allein den deterministischen Schichten (P0-Hard-Deny, die
|
|
373
|
+
Deny-Keyword-Blacklist, explizite `deny:`-Regeln), sodass eine falsch eingestufte Kategorie
|
|
374
|
+
immer verhandelbar bleibt statt einer nicht anfechtbaren Blockade. Harte Kategorien bleiben in
|
|
375
|
+
einem wichtigen Punkt von `neutral` verschieden: Sie werden **nie gelernt**, sodass wiederholte
|
|
376
|
+
menschliche Freigaben sie nie zu einem Auto-Allow sedimentieren können.
|
|
377
|
+
(Das Verweigern nach dem Wort des Modells wurde live gemessen: ein harmloses `git commit -F …`,
|
|
378
|
+
eingestuft als `remote`, erzeugte ein Auto-Deny ohne Panel und ohne Grant zum Wiederholen.)
|
|
379
|
+
- `risky:neutral` → mit aktiviertem `riskLearning` (Einstellungskarte, standardmäßig aus) zählt
|
|
380
|
+
jede menschliche Freigabe, die tatsächlich ausgeführt wird (über das `tools/result`-Ereignis des
|
|
381
|
+
Hosts abgerechnet), auf einen `tool|category`-Schlüssel; sobald der Zähler `riskThreshold`
|
|
382
|
+
(Default 3) erreicht **und** der Vorgangs-Fingerabdruck des neuen Aufrufs (Befehlswort +
|
|
383
|
+
Basisname des Ziels) zu einer bestätigten Probe passt, wird exakt derselbe Vorgang automatisch
|
|
384
|
+
erlaubt. Ein anderes Ziel nutzt diese Autorität nie wieder. Mit Sedimentation (`riskSediment`,
|
|
385
|
+
standardmäßig an) werden die bestätigten Proben eines Schwellenwert erreichten Schlüssels zu
|
|
386
|
+
**deterministischen Allow-Regeln**: ein exakter Treffer erlaubt ohne weiteren LLM-Aufruf —
|
|
387
|
+
sogar bei ausgeschaltetem `llmAssist` — und die sedimentierten Regeln sind in der
|
|
388
|
+
Einstellungskarte sichtbar und verwalten (beenden / entfernen).
|
|
389
|
+
- Timeouts (`riskTimeoutMs`, Default 20 s, ein Wiederholungsversuch), Transportfehler und
|
|
390
|
+
protokollfremde Modellausgaben lassen das `ask` unangetastet — das Gate rät nie.
|
|
391
|
+
|
|
392
|
+
Der Lernzustand persistiert in einer plugin-eigenen JSON-Datei
|
|
393
|
+
(`$DSH_HOME/perm-gate/learning.json` oder `learningFile`), nie in Ihre YAML-Regeldatei. Jede
|
|
394
|
+
Entscheidung wird an `$DSH_HOME/perm-gate/events.jsonl` (oder `eventsFile`) angehängt und unter
|
|
395
|
+
`GET /api/dsh-perm-gate/events?sessionId=&since=` ausgeliefert; die Browser-Hälfte fragt sie ab
|
|
396
|
+
und zeigt die letzte Entscheidung als Hinweisband über der Konversationseingabe (Asks bleiben
|
|
397
|
+
sichtbar, bis das nächste Ereignis kommt) und listet alle Entscheidungen der Sitzung, neueste
|
|
398
|
+
zuerst, im **Approvals**-Tab der Konversationsansicht.
|
|
399
|
+
|
|
400
|
+
Die betroffenen Dateien jeder Entscheidung werden gesnapshottet, bevor die Änderung landet
|
|
401
|
+
(≤ 5 Dateien, je ≤ 256 KB) unter `$DSH_HOME/perm-gate/snapshots/`; im **Approvals**-Tab öffnet
|
|
402
|
+
jeder Datei-Chip ein Zeilen-Diff (`GET /api/dsh-perm-gate/diff`) mit einer **Revert**-Aktion, die
|
|
403
|
+
eine Wiederherstellungsanweisung in die Konversation liefert (`POST /api/dsh-perm-gate/revert`).
|
|
404
|
+
Eine Snapshot-Bestandsleiste löscht sie pro Sitzung oder insgesamt
|
|
405
|
+
(`GET /api/dsh-perm-gate/snapshots-stats` / `POST /api/dsh-perm-gate/snapshots-clear`).
|
|
406
|
+
|
|
407
|
+
Ein an einen Menschen gerichtetes `ask` wird verfolgt, bis der Mensch antwortet: ein passiver
|
|
408
|
+
`approval/request`-Beobachter zeichnet den geschlossenen Ausgang auf (`allowed-once` →
|
|
409
|
+
**genehmigt**, `rejected` → **abgelehnt**, `cancelled` → **abgebrochen**, `unavailable` → eine
|
|
410
|
+
Ablehnung, da kein Freigabekanal existierte), mit `tools/result`, dasselbe Ask als Fallback
|
|
411
|
+
abzuschließen, wenn der Beobachter es nicht zuordnen kann. Freigaben berichten den
|
|
412
|
+
Lernfortschritt nach der Freigabe (`n`/Schwellenwert), und das Hinweisband beschriftet alle drei
|
|
413
|
+
Endzustände.
|
|
414
|
+
|
|
415
|
+
自动审查 und 自动审查(高权限) zeichnen beide das Schild+Auge-Glyph im Picker — die erste aus
|
|
416
|
+
DSHs eingebauter Map, die zweite aus dem Host-Patch, das die Installationsanleitung beschreibt.
|
|
417
|
+
Ohne diesen Patch ist die zweite Stufe überall nur Text; Label und Gate-Verhalten bleiben
|
|
418
|
+
unberührt.
|
|
419
|
+
|
|
420
|
+
### Eine wählbare Sitzungsstufe
|
|
421
|
+
|
|
422
|
+
`cordis.patch.yml` fügt ein `permissive`-Preset hinzu (`sandbox: workspace-write`,
|
|
423
|
+
`approval: ask`, Name **自动审查**) zwischen Workspace Write und Full Access. Der
|
|
424
|
+
DSH-Bundle-Patch ersetzt die gesamte `permission.config.presets`-Map, statt per Schlüssel zu
|
|
425
|
+
mergen, daher restatuiert die Datei auch die drei eingebauten (`read-only` / `workspace-write` /
|
|
426
|
+
`danger-full-access`, aus `@deepseek-ai/dsh-base/cordis.patch.yml`); `test/patch-presets.spec.ts`
|
|
427
|
+
pinnt diesen Schlüsselsatz. So bietet der Berechtigungs-Picker der Sitzung 自动审查 als
|
|
428
|
+
unabhängige, wählbare Freigabestufe an — nicht als generischen „Auto-Genehmigungs“-Modus.
|
|
429
|
+
|
|
430
|
+
Das Gate ist **nur in den in `gatePresets` gelisteten Stufen aktiv** (Default
|
|
431
|
+
`['permissive', 'permissive-full']`, die beiden Stufen, die dieses Plugin hinzufügt). In jeder
|
|
432
|
+
anderen Stufe — Read Only, Workspace Write, Full Access, `custom` — läuft der Entscheidungsfluss
|
|
433
|
+
des Gates gar nicht: kein Allow, kein Ask, kein Deny, kein P0-Hard-Deny, kein
|
|
434
|
+
Deny-Keyword-Veto, kein Audit-Ereignis. Die eigene Policy der gewählten Stufe regiert den Aufruf,
|
|
435
|
+
und das ist der Punkt: Das eingebaute `danger-full-access` ist als „Vollzugriff ohne
|
|
436
|
+
Freigabeaufforderungen“ definiert, es also mit einem Ask zu überstimmen (dort unbeantwortbar —
|
|
437
|
+
die Freigabenaht lehnt ab, bevor irgendein Antworter läuft, was
|
|
438
|
+
`the user rejected tool "..."` ohne Panel ergibt) oder mit einem Hard-Deny würde die vom Nutzer
|
|
439
|
+
gewählte Stufe still widerrufen. `gatePresets: ['*']` macht das Gate wieder global (Hard-Deny
|
|
440
|
+
eingeschlossen); innerhalb einer aktiven Stufe wird ein `ask` weiterhin zum Durchgriff degradiert,
|
|
441
|
+
wenn die effektive Freigabe-Policy der Sitzung `never` ist — deshalb deklarieren beide
|
|
442
|
+
自动审查-Stufen `approval: ask`.
|
|
443
|
+
|
|
444
|
+
### In der Oberfläche konfigurierbar
|
|
445
|
+
|
|
446
|
+
Die Stufe lässt sich auch zur Laufzeit anpassen unter **Einstellungen → Plugins → 自动审查**
|
|
447
|
+
(eine `settings.plugins.tab`-Seite, gerendert vom Browser-Client des Plugins): Ein Schalter
|
|
448
|
+
legt `permissive` um, vier weitere editieren die Backend-`permissiveStrategies`. Der Host liest
|
|
449
|
+
den Namespace live, eine Änderung greift also beim nächsten Toolaufruf ohne Neustart. Dies ist
|
|
450
|
+
eine unabhängige Freigabeklasse, KEIN generischer „Auto-Genehmigungs“-Modus.
|
|
451
|
+
|
|
452
|
+
### Regeltest (Dry-Run)
|
|
453
|
+
|
|
454
|
+
Dieselbe Seite trägt ein **Regeltest**-Panel: Toolnamen und Befehl eingeben, Test drücken, und
|
|
455
|
+
das Gate beurteilt diesen Aufruf gegen den aktuell geladenen Regelsatz — ohne etwas auszuführen
|
|
456
|
+
und ohne eine Regel zu schreiben. Sie erhalten das Verdict, die passende Regel (Index und
|
|
457
|
+
Aktion), die Dimensionen, die sie einschränkt, und den Grund.
|
|
458
|
+
|
|
459
|
+
Es berichtet sowohl das effektive Verdict (die ganze Kette P0 → P1 → P2 → P3 → P4) *als auch* die
|
|
460
|
+
eigene Antwort der Regelebene — nicht dasselbe: Ein P0-Hard-Deny oder ein Preset-Deny-Keyword
|
|
461
|
+
zündet vor der Regelkette und hinterlässt keinen Regelindex, daher sagt das Panel „keine Regel
|
|
462
|
+
gematcht“, statt eine unrelated Regel zu benennen. Ein Hinweis „0 Regeln geladen“ bedeutet, dass
|
|
463
|
+
der `rulesFile`-Pfad nichts aufgelöst hat.
|
|
464
|
+
|
|
465
|
+
Das Panel spricht mit `POST /api/dsh-perm-gate/dry-run`, das **konstruktionsbedingt nur lesend**
|
|
466
|
+
ist — es hat überhaupt keine Schreibform, ein Regeltest kann eine Regel also nie ändern.
|
|
467
|
+
|
|
468
|
+
## CLI
|
|
469
|
+
|
|
470
|
+
Dry-Run eines Aufrufs gegen eine Regeldatei (ohne Harness):
|
|
471
|
+
|
|
472
|
+
```sh
|
|
473
|
+
dsh-perm-gate --rules permissions.yaml --tool bash --args '{"command":"pnpm install"}'
|
|
474
|
+
dsh-perm-gate --rules permissions.yaml --list
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Entwicklung
|
|
478
|
+
|
|
479
|
+
```sh
|
|
480
|
+
npm run typecheck
|
|
481
|
+
npm test
|
|
482
|
+
npm run build
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Lizenz
|
|
486
|
+
|
|
487
|
+
[MIT](./LICENSE)
|