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/README.it.md
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
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
|
+
> **Nota di compatibilità:** la v2.0.0 include i dizionari `ja` / `ko`, ma il DSH ufficiale espone
|
|
31
|
+
> solo `zh` / `en` tramite `LocaleRuntime` (`LOCALE_IDS = ["zh", "en"]`). Su un DSH originale, la
|
|
32
|
+
> selezione di `ja` / `ko` fallisce con `locale "<id>" is not registered`. Usare un fork di DSH
|
|
33
|
+
> che aggiorni `LOCALE_IDS` (locale-settings.ts) e le etichette `LOCALES` (client/index.ts), poi
|
|
34
|
+
> ricompilare.
|
|
35
|
+
|
|
36
|
+
> **▼ Compatibilità delle versioni DSH**
|
|
37
|
+
>
|
|
38
|
+
> Due linee DSH sono servite da due branch di lunga durata, ciascuno con la propria serie di
|
|
39
|
+
> versioni, il proprio `engines.dsh` e il proprio dist-tag npm
|
|
40
|
+
> ([disposizione delle release](./RELEASING.md)):
|
|
41
|
+
>
|
|
42
|
+
> | Versione DSH | Branch | Versione | Tag npm |
|
|
43
|
+
> | --- | --- | --- | --- |
|
|
44
|
+
> | 0.1.0-rc.7 ~ 0.1.1-rc.x | `legacy` | `1.x` | `@legacy` |
|
|
45
|
+
> | 0.1.2-alpha.1+ (incl. 0.1.5-rc.2) | `main` | `2.x` | `@latest` / `@dsh-0.1.2` (`@2.x` è un intervallo) |
|
|
46
|
+
> | 0.2.0-rc.1 (linea 0.2.0) | `compat/0.2.0` | `5.x` | `@dsh-0.2.0` |
|
|
47
|
+
>
|
|
48
|
+
> Il numero di serie segue la **linea DSH** (`1.x` = DSH ≤ 0.1.1, `2.x` = DSH 0.1.2+), e i major
|
|
49
|
+
> si recintano a vicenda: un'installazione `^1.x` non risolve mai una versione `2.x` e viceversa.
|
|
50
|
+
> `engines.dsh` dichiara la stessa separazione, ma DSH non lo legge mai — sono gli intervalli e i
|
|
51
|
+
> dist-tag a tenere un vecchio DSH su `1.x`.
|
|
52
|
+
>
|
|
53
|
+
> `@deepseek-ai/dsh-client-runtime` è stato **rimosso** a partire da `0.1.2-alpha.1` — non si è
|
|
54
|
+
> semplicemente spostato. La linea `legacy` raggiunge ancora `ctx.slots` attraverso di esso;
|
|
55
|
+
> `main` ottiene la stessa dichiarazione da `@deepseek-ai/dsh-client-ui-renderer/client`. Due
|
|
56
|
+
> giunzioni sensibili alla versione sono gestite con sonde di capacità anziché con controlli di
|
|
57
|
+
> versione: (1) la registrazione delle impostazioni usa `register`, presente su entrambe le linee
|
|
58
|
+
> (`installSection` è un'aggiunta, non una sostituzione); (2) `effectivePolicy` è un metodo
|
|
59
|
+
> **privato** del servizio di approvazione utente su entrambe, quindi viene letto dietro una
|
|
60
|
+
> sonda `typeof` e degrada a "policy sconosciuta" quando è assente o lancia un errore.
|
|
61
|
+
|
|
62
|
+
Versione **2.6.0** — vedere il [changelog](./CHANGELOG.it.md).
|
|
63
|
+
|
|
64
|
+
Un unico gate di permessi autosufficiente, deterministico in primis e fail-closed per DeepSeek
|
|
65
|
+
Harness.
|
|
66
|
+
|
|
67
|
+
`dsh-perm-gate` decide ogni chiamata a un tool attraverso una catena di priorità fissa:
|
|
68
|
+
|
|
69
|
+
| Stadio | Decisione | Che cosa è |
|
|
70
|
+
| ---- | ---- | ---- |
|
|
71
|
+
| **P0** | `deny` | hard-deny deterministico: materiale credenziali, mutazione di percorsi protetti, shell pericolosa |
|
|
72
|
+
| **P1** | `allow` | un **grant di sessione** preciso e delimitato |
|
|
73
|
+
| **P2** | `deny/allow/ask` | catena di regole statica: prima la blacklist, poi l'allow, poi l'ask |
|
|
74
|
+
| **P3** | `allow/deny/ask` | classificatore semantico LLM opzionale (**off** per impostazione predefinita) |
|
|
75
|
+
| **P4** | `ask` | seam di approvazione ufficiale |
|
|
76
|
+
|
|
77
|
+
Strettamente fail-closed: una decisione P0 non viene mai scavalcata da un grant, una regola, il
|
|
78
|
+
classificatore o un essere umano.
|
|
79
|
+
|
|
80
|
+
## Perché
|
|
81
|
+
|
|
82
|
+
L'ecosistema di sicurezza di DSH distribuisce questo su più plugin (`dsh-permission-rules`,
|
|
83
|
+
`dsh-auto-mode`, `dsh-auto-review`, `dsh-movein-permissions`). `dsh-perm-gate` fonde gate +
|
|
84
|
+
approvazione + classificatore (opzionale) in un solo pacchetto, con un'unica traccia di audit e
|
|
85
|
+
nessun accoppiamento di versione tra plugin.
|
|
86
|
+
|
|
87
|
+
## Funzionalità
|
|
88
|
+
|
|
89
|
+
- **Whitelist / blacklist dei comandi** — confronto su una **scomposizione argv** (non una stringa
|
|
90
|
+
grezza), con discesa ricorsiva in `sh -c`/`bash -c`, rilevamento delle pipeline, controllo delle
|
|
91
|
+
destinazioni delle redirezioni e riconoscimento di ricorsivo/forzato (`rm -rf`).
|
|
92
|
+
- **Priorità al deny** — una regola deny corrispondente batte qualsiasi regola allow.
|
|
93
|
+
- **Grant di sessione** — grant precisi `(tool, fingerprint canonico)` con `TTL` + `maxUses`;
|
|
94
|
+
rieseguire con un target diverso non riutilizza mai l'autorità. I sub-agent ereditano ma non
|
|
95
|
+
possono coniarne.
|
|
96
|
+
- **Motore di regole a funzioni pure** — compilazione glob/regex con un limite ReDoS, fallimento
|
|
97
|
+
rumoroso su regole malformate e cache di compilazione basata sull'hash della sorgente.
|
|
98
|
+
- **Audit** — ogni decisione viene registrata come evento `{ignorable:true}` con il suo `callId`;
|
|
99
|
+
il motivo visibile al modello corrisponde all'esito registrato.
|
|
100
|
+
- **Livello 自动审查** (`permissive`, più `permissive-full`) — una **modalità di approvazione
|
|
101
|
+
indipendente** (separata dai livelli sola lettura, accesso completo e whitelist) che non è né
|
|
102
|
+
"approvazione automatica" né fiducia indiscriminata. Il front-end espone un **unico
|
|
103
|
+
interruttore** (`permissive`); le quattro strategie di back-end sono **combinabili** e guidate
|
|
104
|
+
dalle impostazioni del plugin — sempre fail-closed contro P0. Il selettore dei permessi e la
|
|
105
|
+
riga delle impostazioni la mostrano entrambi con l'etichetta di prodotto 自动审查, senza icona.
|
|
106
|
+
La variante `permissive-full` mantiene lo stesso comportamento di approvazione ma elimina la
|
|
107
|
+
sandbox dei file integrata, che altrimenti nega le named pipe di cui `git clone` / Cygwin /
|
|
108
|
+
ConPTY hanno bisogno.
|
|
109
|
+
- **Risposta automatica alle escalation della sandbox** (`trustEscalation`) — un'escalation della
|
|
110
|
+
sandbox viene richiesta dall'*interno* del corpo del tool shell / pwsh / edit, dopo
|
|
111
|
+
`tools/pre-execute`, così il gate non l'ha mai vista e una chiamata che aveva auto-consentito
|
|
112
|
+
richiedeva comunque l'approvazione dell'ampliamento. Con questa strategia attiva, è qui che
|
|
113
|
+
viene risposta l'esatta richiesta che il gate aveva autorizzato (riconosciuta per `callId`).
|
|
114
|
+
- **`llmAssist` con rischio graduato** — un LLM personalizzato compatibile OpenAI valuta ogni
|
|
115
|
+
`ask` come `safe` / `risky:<categoria>`; le categorie hard (eliminazione, credenziali, remoto,
|
|
116
|
+
sistema, massa) **chiedono sempre**, il neutro alimenta l'apprendimento dei verdetti e ogni
|
|
117
|
+
guasto resta fail-closed.
|
|
118
|
+
- **Apprendimento dei verdetti** — gli `ask` a rischio neutro approvati da una persona ed
|
|
119
|
+
effettivamente eseguiti si accumulano; superata la soglia, *la stessa identica operazione*
|
|
120
|
+
(riconosciuta per fingerprint) si auto-consente.
|
|
121
|
+
- **Feed di eventi di decisione** — ogni decisione viene aggiunta a un feed JSONL e mostrata dalla
|
|
122
|
+
parte browser come una striscia di avviso sopra l'input della conversazione, più una scheda dei
|
|
123
|
+
registri di approvazione (dal più recente) nella vista conversazione.
|
|
124
|
+
|
|
125
|
+
Una **blacklist di parole chiave deny preimpostata** (ereditata dai `DEFAULT_DENY_KEYWORDS` di
|
|
126
|
+
dsh-approval-gate: `rm -rf`, `push --force`, `drop table`, `mkfs`, `git reset --hard`,
|
|
127
|
+
`docker system prune`, …) mette il veto a qualsiasi chiamata il cui testo contenga una parola
|
|
128
|
+
chiave — sottostringa case-insensitive, applicata prima della whitelist, dei grant e dell'LLM. È
|
|
129
|
+
modificabile come elenco nella scheda impostazioni (le voci preimpostate sono etichettate e un
|
|
130
|
+
ripristino con un clic rimette il preset); non impostata o vuota si applica il preset — la
|
|
131
|
+
blacklist non si spegne mai silenziosamente.
|
|
132
|
+
|
|
133
|
+
## Installazione
|
|
134
|
+
|
|
135
|
+
Richiede un'installazione esistente di
|
|
136
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
dsh plugin --profile web add dsh-perm-gate
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
I passaggi completi di installazione, aggiornamento, migrazione e risoluzione dei problemi si
|
|
143
|
+
trovano nella [Guida all'installazione](./INSTALL.it.md) — disponibile anche in
|
|
144
|
+
[English](./INSTALL.md) / [中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md) /
|
|
145
|
+
[한국어](./INSTALL.ko.md) / [Français](./INSTALL.fr.md) / [Deutsch](./INSTALL.de.md) /
|
|
146
|
+
[Русский](./INSTALL.ru.md) / [Español](./INSTALL.es.md).
|
|
147
|
+
|
|
148
|
+
## Configurazione
|
|
149
|
+
|
|
150
|
+
Aggiungere il plugin al `cordis.yml`:
|
|
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
|
+
### Pulizia delle sessioni
|
|
164
|
+
|
|
165
|
+
All'avvio e ogni ora il gate legge l'archivio dei workspace di DSH
|
|
166
|
+
(`$DSH_HOME/storages/workspace.json`, in sola lettura) e classifica ogni sessione per cui
|
|
167
|
+
conserva dati della catena di autorizzazione. Le sessioni che DSH ha archiviato
|
|
168
|
+
(`global.archivedSessionIds`) o non traccia più affatto vedono i propri eventi di decisione
|
|
169
|
+
rimossi da `$DSH_HOME/perm-gate/events.jsonl` e i propri file di snapshot pre-modifica cancellati
|
|
170
|
+
da `$DSH_HOME/perm-gate/snapshots/` — storia che la pagina di revisione non può più raggiungere,
|
|
171
|
+
per dati che l'harness stesso considera andati. Le sessioni vive non vengono toccate, le righe non
|
|
172
|
+
attribuibili (session id vuoto) non vengono mai cancellate, e ogni guasto è fail-open: il giro
|
|
173
|
+
viene saltato e ritentato un'ora dopo. Impostare `sessionSweep: false` per disattivare;
|
|
174
|
+
`workspaceStoreFile` sostituisce il percorso dell'archivio. Ripristinare una sessione archiviata
|
|
175
|
+
non ripristina la sua storia ripulita.
|
|
176
|
+
|
|
177
|
+
### File delle regole
|
|
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
|
+
Una voce di comando `word#flag` corrisponde alla parola comando (`word`) con il modificatore
|
|
201
|
+
`recursive` o `force` — così `rm#recursive` corrisponde a `rm -rf`, `env rm -rf` e
|
|
202
|
+
`sh -c "rm -rf /"`.
|
|
203
|
+
|
|
204
|
+
### Politica di rete (opt-in)
|
|
205
|
+
|
|
206
|
+
Un proxy HTTP/CONNECT locale che giudica il traffico in uscita dei **sottoprocessi shell** in
|
|
207
|
+
base allo stesso file di regole, più un percorso di approvazione per i target che nessuna regola
|
|
208
|
+
copre. **Disattivato per impostazione predefinita** — attivarlo lega una porta di loopback e
|
|
209
|
+
riscrive l'ambiente proxy per i processi figli, quindi non viene mai attivato implicitamente.
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
- id: dsh-perm-gate
|
|
213
|
+
config:
|
|
214
|
+
networkEnabled: false # master switch (default false)
|
|
215
|
+
networkMode: whitelist # deny-all | whitelist | allow-all
|
|
216
|
+
networkUnlisted: ask # ask | deny — unlisted target handling
|
|
217
|
+
networkUnattributed: allow # allow | deny — traffic with no shell attribution
|
|
218
|
+
networkInjectEnv: true # rewrite HTTP(S)_PROXY/ALL_PROXY for children
|
|
219
|
+
networkAskTimeoutMs: 120000 # approval wait before failing closed
|
|
220
|
+
networkGrantTtlMs: 1800000 # how long one approval covers its target
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Comportamento a livelli.** Nulla raggiunge la rete senza una regola allow. Un target non
|
|
224
|
+
elencato viene escalato al seam di approvazione interattivo, sollevato per conto del comando
|
|
225
|
+
shell che ha aperto la connessione; approvare amplia la copertura per quel target per la
|
|
226
|
+
sessione. Una regola `deny` non viene **mai** escalata — l'approvazione può ampliare ciò che un
|
|
227
|
+
target non elencato può raggiungere, ma non può mai scavalcare una regola che dice no.
|
|
228
|
+
|
|
229
|
+
**Il confine — da leggere prima di contarci.** Il proxy è uno strato di policy *cooperativo*,
|
|
230
|
+
non un confine di applicazione. Vede solo il traffico dei client che leggono l'ambiente proxy:
|
|
231
|
+
|
|
232
|
+
| Client | Coperto? |
|
|
233
|
+
|--------|----------|
|
|
234
|
+
| `curl`, `wget`, `git`, Go `net/http`, Python `requests` | sì |
|
|
235
|
+
| **Node.js `http`/`https`/`fetch`** | **no — si collega direttamente** |
|
|
236
|
+
| Java (senza flag proxy `-D`), .NET `HttpClient` | no |
|
|
237
|
+
| Socket raw, TCP personalizzato | no |
|
|
238
|
+
| DNS, QUIC/HTTP3, protocolli non HTTP | no |
|
|
239
|
+
| Connessioni a un IP letterale | no |
|
|
240
|
+
|
|
241
|
+
Quindi un comando shell come `node -e "require('http').get('http://host/')"` non viene
|
|
242
|
+
intercettato. Trattatelo come un guard-rail contro gli incidenti e un luogo dove dichiarare
|
|
243
|
+
un'intenzione, non come una sandbox ermetica.
|
|
244
|
+
|
|
245
|
+
Il traffico di rete **proprio** di DSH — i tool di rete integrati e il trasporto LLM — è
|
|
246
|
+
deliberatamente lasciato in pace. Quelle connessioni non portano alcuna attribuzione shell, e
|
|
247
|
+
`networkUnattributed: allow` (il valore predefinito) le lascia passare senza revisione:
|
|
248
|
+
revisionarle permetterebbe all'host di bloccare *se stesso*, che è un fallimento peggiore di un
|
|
249
|
+
blocco mancato. Impostare `networkUnattributed: deny` solo se si sa che i client del proprio host
|
|
250
|
+
ignorano l'ambiente proxy.
|
|
251
|
+
|
|
252
|
+
Lo stato live si interroga su `GET /api/dsh-perm-gate/network` (modalità, bind, porta, vivacità
|
|
253
|
+
del proxy, stato dell'iniezione d'ambiente, contatori dei blocchi, blocchi recenti).
|
|
254
|
+
|
|
255
|
+
## Il livello 自动审查 (valore macchina `permissive`)
|
|
256
|
+
|
|
257
|
+
自动审查 è un **livello di approvazione indipendente** nel selettore dei permessi di DSH, in
|
|
258
|
+
parallelo a Sola lettura / Scrittura workspace / Accesso completo / Whitelist. Non è
|
|
259
|
+
un'"approvazione automatica" generica e non conia mai autorità indiscriminata: restringe o
|
|
260
|
+
amplia soltanto il seam *prima* del passaggio umano/LLM, mentre l'hard-deny P0 resta monotono e
|
|
261
|
+
non negoziabile **dentro l'ambito proprio del gate**.
|
|
262
|
+
|
|
263
|
+
> **P0 è delimitato, non globale.** Il gate agisce solo quando il preset dei permessi della
|
|
264
|
+
> sessione è uno dei `gatePresets` (predefinito `permissive` / `permissive-full`). Con qualsiasi
|
|
265
|
+
> altro preset — Sola lettura, Scrittura workspace o Accesso completo — **l'intero** gate si
|
|
266
|
+
> ritira, hard-deny P0 compreso, perché la politica propria del livello scelto governa quella
|
|
267
|
+
> sessione. È voluto (si veda `gatePresets` nella tabella di configurazione), ma significa che "P0
|
|
268
|
+
> non è negoziabile" vale *dentro* i livelli del gate e non attraverso ogni livello. Un ritiro
|
|
269
|
+
> non è silenzioso: il gate registra un evento `stand-down` per ogni transizione sessione/preset
|
|
270
|
+
> e il browser mostra una striscia persistente **GATE OFF** sopra l'input. Impostare
|
|
271
|
+
> `gatePresets: ['*']` per rendere di nuovo globale P0.
|
|
272
|
+
|
|
273
|
+
**Ne vengono shipiate due varianti**, perché `sandbox` e `approval` di un preset sono manopole
|
|
274
|
+
indipendenti e accoppiarle imponeva un cattivo compromesso:
|
|
275
|
+
|
|
276
|
+
| Etichetta nel selettore | Valore macchina | sandbox | approval |
|
|
277
|
+
|--------------|---------------|---------|----------|
|
|
278
|
+
| 自动审查 | `permissive` | `workspace-write` | `ask` |
|
|
279
|
+
| 自动审查(高权限) | `permissive-full` | `danger-full-access` | `ask` |
|
|
280
|
+
|
|
281
|
+
Il livello semplice conserva la sandbox dei file integrata. Quella sandbox nega anche le named
|
|
282
|
+
pipe di cui un processo figlio ha bisogno per avviarsi, così `git clone`, `sh.exe` di MSYS2/Cygwin
|
|
283
|
+
e ConPTY falliscono con `Win32 error 5` / `couldn't create signal pipe`. Poiché il gate è attivo
|
|
284
|
+
**solo** nei livelli elencati in `gatePresets`, volere il gate significava accettare quella
|
|
285
|
+
restrizione. 自动审查(高权限) rimuove l'accoppiamento: identico comportamento di approvazione,
|
|
286
|
+
nessuna restrizione di sandbox dei file. La descrizione del livello enuncia il compromesso senza
|
|
287
|
+
giri di parole — il flusso di lavoro è più fluido, le approvazioni valgono comunque per chiamata,
|
|
288
|
+
ma non resta **nessuna sandbox di sistema come rete di sicurezza**. Entrambi sono nei
|
|
289
|
+
`gatePresets` predefiniti, quindi l'uno o l'altro danno l'intera catena P0–P4 — il gate legge solo
|
|
290
|
+
il **nome** del preset, mai la modalità di sandbox.
|
|
291
|
+
|
|
292
|
+
L'etichetta nel selettore è una **stringa di prodotto fornita dall'host**, non una voce di
|
|
293
|
+
dizionario per locale: DSH rende verbatim il `name:` del livello di un plugin su entrambe le
|
|
294
|
+
superfici dei permessi (la riga predefinita nelle impostazioni generali e il selettore del
|
|
295
|
+
composer) e fornisce le proprie etichette localizzate solo per i tre valori integrati, così
|
|
296
|
+
`cordis.patch.yml` spedisce l'etichetta cinese per ogni sessione.
|
|
297
|
+
|
|
298
|
+
**L'icona** è un'altra storia. La mappa dei glifi del composer è chiusa e il suo stesso commento
|
|
299
|
+
enuncia la regola: *host-configured names outside the design set get none.* `permissive` è un
|
|
300
|
+
valore integrato, quindi 自动审查 ha già un glifo scudo+occhio; `permissive-full` riceve lo stesso
|
|
301
|
+
glifo solo perché `npx dsh-perm-gate-patch-glyph` lo aggiunge a quella mappa. Quella patch modifica
|
|
302
|
+
un pacchetto **host**, quindi si perde a ogni aggiornamento di DSH — si veda
|
|
303
|
+
[Dopo un aggiornamento di DSH](./INSTALL.it.md).
|
|
304
|
+
|
|
305
|
+
Nel `cordis.yml`:
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
- id: dsh-perm-gate
|
|
309
|
+
name: dsh-perm-gate
|
|
310
|
+
config:
|
|
311
|
+
rulesFile: ./permissions.yaml
|
|
312
|
+
defaultAction: ask
|
|
313
|
+
permissive: true # single front-facing switch (independent tier on)
|
|
314
|
+
permissiveStrategies: # backend, combinable
|
|
315
|
+
trustAutoAllow: true # in-scope safe ops auto-allow; dangerous/unknown ask
|
|
316
|
+
alwaysConfirm: false # every crossing asks; allow-controls add repeat-allow / wl-migrate buttons
|
|
317
|
+
llmAssist: false # LLM classify first, human fallback on ask/failure
|
|
318
|
+
trustEscalation: true # a cleared call's own sandbox escalation needs no prompt
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
`trustAutoAllow` è il livello intermedio di base (un allow da regola passa da sé).
|
|
322
|
+
`alwaysConfirm` mostra il pannello di approvazione a ogni attraversamento; i suoi "controlli
|
|
323
|
+
allow" aggiungono due pulsanti estesi — **ri-consentire questo tipo per questa sessione** (un
|
|
324
|
+
grant di sessione delimitato) e **consentire ogni occorrenza** (che persiste la parola comando
|
|
325
|
+
nella whitelist `allow` del `permissions.yaml` tramite `approveAllowEverywhere`). `llmAssist`
|
|
326
|
+
consulta un vero LLM configurabile (`classifierEndpoint` / `classifierModel`, qualsiasi API
|
|
327
|
+
compatibile OpenAI) per decidere automaticamente un `ask`, e ricade sul seam umano su
|
|
328
|
+
`ask`/errore — sempre fail-closed. `trustEscalation` (attivo per impostazione predefinita quando
|
|
329
|
+
il livello è attivo) risponde a un'escalation `sandbox_permissions` sollevata dall'interno di una
|
|
330
|
+
chiamata che il gate aveva già consentito; si veda sotto. Con `permissive` disattivo, il gate si
|
|
331
|
+
comporta esattamente come prima.
|
|
332
|
+
|
|
333
|
+
### Escalation della sandbox: perché un verdetto `safe` mostrava comunque la richiesta
|
|
334
|
+
|
|
335
|
+
Una chiamata a un tool può sollevare **due approvazioni indipendenti**. Il gate possiede la prima
|
|
336
|
+
— il suo `ask`, sulla cascata `tools/pre-execute`. La seconda arriva da `approveEscalation`
|
|
337
|
+
**dentro il corpo del tool**, al momento di `tools/execute`, ogni volta che il modello ha passato
|
|
338
|
+
`sandbox_permissions` + `justification`; a quel punto `tools/pre-execute` è già deciso, così
|
|
339
|
+
l'allow del gate non la raggiunge mai. Una chiamata valutata `safe` dall'LLM e auto-consentita dal
|
|
340
|
+
gate mostrava quindi comunque una richiesta di approvare l'ampliamento della sandbox.
|
|
341
|
+
|
|
342
|
+
`trustEscalation` chiude questo varco. Il gate ricorda ogni chiamata che ha effettivamente
|
|
343
|
+
consentito (indicizzata per la `callId` dell'host, che la richiesta di escalation ripete) e
|
|
344
|
+
risponde da sé all'escalation con `allowed-once`. Si applica solo quando valgono **tutti** i
|
|
345
|
+
punti:
|
|
346
|
+
|
|
347
|
+
- il livello 自动审查 è attivo e `trustEscalation` è attivo;
|
|
348
|
+
- la richiesta porta una `callId` che il gate ha autorizzato, con nome del tool corrispondente;
|
|
349
|
+
- il motivo è un'escalation riconosciuta che nomina `workspace-write` o `danger-full-access`.
|
|
350
|
+
|
|
351
|
+
Tutto il resto — un motivo non riconosciuto, una chiamata diversa, una chiamata che il gate aveva
|
|
352
|
+
richiesto o negato, il passaggio diretto `approval: never` — delega immutato all'umano, così un
|
|
353
|
+
futuro cambio di formulazione di DSH fallisce chiuso anziché aperto. La risposta automatica viene
|
|
354
|
+
registrata nel feed di eventi (`verdict: "escalation-auto"`, `mode: <target>`). Spegnere
|
|
355
|
+
l'interruttore per tenere l'ampliamento della sandbox sotto controllo umano mentre gli altri
|
|
356
|
+
allow restano automatici.
|
|
357
|
+
|
|
358
|
+
### llmAssist con rischio graduato, apprendimento dei verdetti e feed di eventi
|
|
359
|
+
|
|
360
|
+
Con `llmAssist` attivo, l'LLM configurato valuta un `ask` alla volta con un protocollo strutturato.
|
|
361
|
+
La valutazione avviene **dentro la cascata `tools/pre-execute` del gate, prima che la decisione
|
|
362
|
+
torni all'host**: un verdetto `safe` delega la chiamata direttamente, così il pannello di
|
|
363
|
+
approvazione non appare mai; solo un verdetto davvero incerto raggiunge l'utente. Due sorgenti di
|
|
364
|
+
ricevitore sono selezionabili nella scheda impostazioni: un'**API personalizzata** (qualsiasi
|
|
365
|
+
endpoint compatibile OpenAI — `classifierEndpoint` / `classifierModel` / `classifierApiKey`, con
|
|
366
|
+
preset tra cui Xiaomi MiMo `https://api.xiaomimimo.com/v1`), oppure il **gruppo di modelli host
|
|
367
|
+
DSH** (il servizio `llm` configurato della sessione, via `agentDefaultModel.currentSelection`,
|
|
368
|
+
facoltativamente sostituito con `classifierProvider` / `classifierModel`). Un pulsante di **test
|
|
369
|
+
di salute** (`POST /api/dsh-perm-gate/health`) esegue una completion minima e riporta la latenza.
|
|
370
|
+
|
|
371
|
+
- `safe` → la chiamata è auto-consentita (audited come sorgente `classifier`); nessun pannello.
|
|
372
|
+
- `risky` + una **categoria hard** (`deletion`, `credential`, `remote`, `system`, `bulk`) → la
|
|
373
|
+
chiamata **mantiene l'ask umano**. Il classificatore **non nega mai**: il percorso di deny
|
|
374
|
+
appartiene ai soli strati deterministici (hard-deny P0, la blacklist di parole chiave deny, le
|
|
375
|
+
regole `deny:` esplicite), così una categoria mal valutata resta sempre negoziabile invece di
|
|
376
|
+
essere un blocco impugnabile.
|
|
377
|
+
(Negare sulla parola del modello è stato misurato dal vivo: un benigno `git commit -F …`
|
|
378
|
+
valutato `remote` ha prodotto un auto-deny senza pannello e senza grant per riprovare.)
|
|
379
|
+
- `risky:neutral` → con `riskLearning` attivo (scheda Impostazioni, spento per impostazione
|
|
380
|
+
predefinita), ogni approvazione umana effettivamente eseguita (saldato tramite l'evento
|
|
381
|
+
`tools/result` dell'host) conta su una chiave `tool|category`; quando il conteggio raggiunge
|
|
382
|
+
`riskThreshold` (predefinito 3) **e** il fingerprint dell'operazione della nuova chiamata
|
|
383
|
+
(parola comando + basename del target) corrisponde a un campione confermato, la stessa identica
|
|
384
|
+
operazione si auto-consente. Un target diverso non riutilizza mai quell'autorità. Con la
|
|
385
|
+
sedimentazione (`riskSediment`, attiva per impostazione predefinita) i campioni confermati di
|
|
386
|
+
una chiave arrivata a soglia diventano **regole allow deterministiche**: una corrispondenza
|
|
387
|
+
esatta consente outright senza un'altra chiamata LLM — anche con `llmAssist` spento — e le
|
|
388
|
+
regole sedimentate sono visibili e gestibili (terminare / rimuovere) nella scheda impostazioni.
|
|
389
|
+
- Timeout (`riskTimeoutMs`, predefinito 20 s, un tentativo), guasti di trasporto e uscite fuori
|
|
390
|
+
protocollo lasciano l'ask intatto — il gate non indovina mai.
|
|
391
|
+
|
|
392
|
+
Lo stato di apprendimento persiste in un JSON di proprietà del plugin
|
|
393
|
+
(`$DSH_HOME/perm-gate/learning.json`, o `learningFile`), mai nel file di regole YAML
|
|
394
|
+
dell'utente. Ogni decisione viene aggiunta a `$DSH_HOME/perm-gate/events.jsonl` (o `eventsFile`) e
|
|
395
|
+
servita su `GET /api/dsh-perm-gate/events?sessionId=&since=`; la parte browser la interroga e
|
|
396
|
+
mostra l'ultima decisione come striscia di avviso sopra l'input della conversazione (gli ask
|
|
397
|
+
restano visibili fino all'evento successivo) ed elenca tutte le decisioni della sessione dalla più
|
|
398
|
+
recente nella scheda **Approvals** della vista conversazione.
|
|
399
|
+
|
|
400
|
+
I file toccati da ogni decisione vengono istantaneizzati prima che la modifica atterri (≤ 5 file,
|
|
401
|
+
≤ 256 KB ciascuno) sotto `$DSH_HOME/perm-gate/snapshots/`; nella scheda **Approvals** ogni chip di
|
|
402
|
+
file apre un diff di righe (`GET /api/dsh-perm-gate/diff`) con un'azione di **revert** che invia
|
|
403
|
+
un'istruzione di ripristino nella conversazione (`POST /api/dsh-perm-gate/revert`). Una barra di
|
|
404
|
+
inventario degli snapshot li cancella per sessione o del tutto
|
|
405
|
+
(`GET /api/dsh-perm-gate/snapshots-stats` / `POST /api/dsh-perm-gate/snapshots-clear`).
|
|
406
|
+
|
|
407
|
+
Un `ask` instradato dal gate a una persona viene tracciato finché la persona risponde: un
|
|
408
|
+
osservatore passivo `approval/request` registra l'esito chiuso (`allowed-once` → **approvato**,
|
|
409
|
+
`rejected` → **rifiutato**, `cancelled` → **annullato**, `unavailable` → un diniego, poiché non
|
|
410
|
+
esisteva alcun canale di approvazione), con `tools/result` che salda lo stesso ask come fallback
|
|
411
|
+
quando l'osservatore non riesce a correlarlo. Le approvazioni riportano il progresso
|
|
412
|
+
dell'apprendimento post-approvazione (`n`/soglia), e la striscia di avviso etichetta tutti e tre
|
|
413
|
+
gli stati terminali.
|
|
414
|
+
|
|
415
|
+
自动审查 e 自动审查(高权限) disegnano entrambi il glifo scudo+occhio nel selettore — la prima
|
|
416
|
+
dalla mappa integrata di DSH, la seconda dalla patch host descritta nella guida
|
|
417
|
+
all'installazione. Senza quella patch il secondo livello è solo testo su ogni superficie;
|
|
418
|
+
l'etichetta e il gating restano invariati.
|
|
419
|
+
|
|
420
|
+
### Un livello di sessione selezionabile
|
|
421
|
+
|
|
422
|
+
`cordis.patch.yml` aggiunge un preset `permissive` (`sandbox: workspace-write`, `approval: ask`,
|
|
423
|
+
nome **自动审查**) tra Scrittura workspace e Accesso completo. La patch del bundle DSH sostituisce
|
|
424
|
+
l'intera mappa `permission.config.presets` invece di fare merge per chiave, quindi il file
|
|
425
|
+
ridichiara anche i tre integrati (`read-only` / `workspace-write` / `danger-full-access`, da
|
|
426
|
+
`@deepseek-ai/dsh-base/cordis.patch.yml`); `test/patch-presets.spec.ts` fissa quel set di chiavi.
|
|
427
|
+
Così il selettore dei permessi di sessione offre 自动审查 come livello di approvazione indipendente
|
|
428
|
+
selezionabile, non una generica modalità di "approvazione automatica".
|
|
429
|
+
|
|
430
|
+
Il gate è attivo **solo nei livelli elencati in `gatePresets`** (predefinito
|
|
431
|
+
`['permissive', 'permissive-full']`, i due livelli che questo plugin aggiunge). In ogni altro
|
|
432
|
+
livello — Sola lettura, Scrittura workspace, Accesso completo, `custom` — il flusso di decisione
|
|
433
|
+
del gate non gira affatto: nessun allow, nessun ask, nessun deny, nessun hard-deny P0, nessun veto
|
|
434
|
+
di parola chiave deny, nessun evento di audit. La politica propria del livello scelto governa la
|
|
435
|
+
chiamata, ed è questo il punto: il `danger-full-access` integrato è definito come "accesso
|
|
436
|
+
completo senza richieste di approvazione", quindi scavalcato con un ask (lì irrivendicabile — il
|
|
437
|
+
seam di approvazione rifiuta prima che qualsiasi risponditore parta, producendo
|
|
438
|
+
`the user rejected tool "..."` senza pannello) o con un hard-deny contraddirebbe silenziosamente
|
|
439
|
+
il livello scelto dall'utente. `gatePresets: ['*']` rende di nuovo globale il gate (hard-deny
|
|
440
|
+
compreso); dentro un livello attivo un `ask` viene comunque degradato a passthrough quando la
|
|
441
|
+
politica di approvazione effettiva della sessione è `never` — ecco perché entrambi i livelli
|
|
442
|
+
自动审查 dichiarano `approval: ask`.
|
|
443
|
+
|
|
444
|
+
### Configurabile nell'interfaccia
|
|
445
|
+
|
|
446
|
+
Il livello è regolabile anche a runtime da **Impostazioni → Plugin → 自动审查** (una pagina
|
|
447
|
+
`settings.plugins.tab` resa dal client browser del plugin): un interruttore commuta `permissive`,
|
|
448
|
+
e quattro interruttori modificano le `permissiveStrategies` di back-end. L'host legge il namespace
|
|
449
|
+
al volo, quindi una modifica si applica alla successiva chiamata a tool senza riavvio. Questa è
|
|
450
|
+
una classe di approvazione indipendente, NON una generica modalità di "approvazione automatica".
|
|
451
|
+
|
|
452
|
+
### Test delle regole (dry-run)
|
|
453
|
+
|
|
454
|
+
La stessa pagina ospita un pannello di **test delle regole**: digitare un nome di tool e un
|
|
455
|
+
comando, premere Test, e il gate giudica quella chiamata contro l'insieme di regole che ha
|
|
456
|
+
attualmente caricato — senza eseguire nulla e senza scrivere alcuna regola. Si ottengono il
|
|
457
|
+
verdetto, la regola corrispondente (indice e azione), le dimensioni che quella regola vincola e il
|
|
458
|
+
motivo.
|
|
459
|
+
|
|
460
|
+
Riporta sia il verdetto effettivo (l'intera catena P0 → P1 → P2 → P3 → P4) *sia* la risposta
|
|
461
|
+
propria dello strato di regole, che non sono la stessa cosa: un hard-deny P0 o una parola chiave
|
|
462
|
+
deny da preset scattano prima della catena di regole e non lasciano dietro alcun indice di
|
|
463
|
+
regola, così il pannello dice "nessuna regola corrispondente" anziché nominare una regola non
|
|
464
|
+
pertinente. Una nota "0 regole caricate" significa che il percorso `rulesFile` non ha risolto
|
|
465
|
+
nulla.
|
|
466
|
+
|
|
467
|
+
Il pannello parla con `POST /api/dsh-perm-gate/dry-run`, che è **in sola lettura per
|
|
468
|
+
costruzione** — non ha alcuna forma di scrittura, quindi testare una regola non potrà mai
|
|
469
|
+
modificarla.
|
|
470
|
+
|
|
471
|
+
## CLI
|
|
472
|
+
|
|
473
|
+
Dry-run di una chiamata contro un file di regole (senza harness):
|
|
474
|
+
|
|
475
|
+
```sh
|
|
476
|
+
dsh-perm-gate --rules permissions.yaml --tool bash --args '{"command":"pnpm install"}'
|
|
477
|
+
dsh-perm-gate --rules permissions.yaml --list
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Sviluppo
|
|
481
|
+
|
|
482
|
+
```sh
|
|
483
|
+
npm run typecheck
|
|
484
|
+
npm test
|
|
485
|
+
npm run build
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Licenza
|
|
489
|
+
|
|
490
|
+
[MIT](./LICENSE)
|
package/README.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
|
> **互換性に関する注記:** v2.0.0 は `ja` / `ko` 辞書を同梱しますが、公式 DSH の
|
|
16
31
|
> `LocaleRuntime` が公開するのは `zh` / `en` のみです(`LOCALE_IDS = ["zh", "en"]`)。
|
|
@@ -104,7 +119,9 @@ dsh plugin --profile web add dsh-perm-gate
|
|
|
104
119
|
|
|
105
120
|
インストール・アップグレード・移行・トラブルシューティングの詳細は
|
|
106
121
|
[日本語インストールガイド](./INSTALL.ja.md)([English](./INSTALL.md) /
|
|
107
|
-
[中文](./INSTALL.zh.md) / [한국어](./INSTALL.ko.md)
|
|
122
|
+
[中文](./INSTALL.zh.md) / [한국어](./INSTALL.ko.md) / [Français](./INSTALL.fr.md) /
|
|
123
|
+
[Deutsch](./INSTALL.de.md) / [Italiano](./INSTALL.it.md) / [Русский](./INSTALL.ru.md) /
|
|
124
|
+
[Español](./INSTALL.es.md))にあります。
|
|
108
125
|
|
|
109
126
|
## 設定
|
|
110
127
|
|
package/README.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
|
> **호환성 안내:** v2.0.0은 `ja` / `ko` 사전을 포함하지만, 공식 DSH의 `LocaleRuntime`은
|
|
16
31
|
> `zh` / `en`만 노출합니다(`LOCALE_IDS = ["zh", "en"]`). 기본 DSH에서 `ja` / `ko`를
|
|
@@ -101,7 +116,9 @@ dsh plugin --profile web add dsh-perm-gate
|
|
|
101
116
|
|
|
102
117
|
설치·업그레이드·이전·문제 해결의 전체 절차는
|
|
103
118
|
[한국어 설치 안내](./INSTALL.ko.md)([English](./INSTALL.md) /
|
|
104
|
-
[中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md))
|
|
119
|
+
[中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md) / [Français](./INSTALL.fr.md) /
|
|
120
|
+
[Deutsch](./INSTALL.de.md) / [Italiano](./INSTALL.it.md) / [Русский](./INSTALL.ru.md) /
|
|
121
|
+
[Español](./INSTALL.es.md))에 있습니다.
|
|
105
122
|
|
|
106
123
|
## 설정
|
|
107
124
|
|
package/README.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
|
> **Compatibility note:** v2.0.0 ships `ja` / `ko` dictionaries, but official DSH exposes
|
|
16
31
|
> only `zh` / `en` through `LocaleRuntime` (`LOCALE_IDS = ["zh", "en"]`). On stock DSH,
|
|
@@ -115,7 +130,9 @@ dsh plugin --profile web add dsh-perm-gate
|
|
|
115
130
|
|
|
116
131
|
Full install, upgrade, migration and troubleshooting steps live in the
|
|
117
132
|
[Installation guide](./INSTALL.md) — also available in
|
|
118
|
-
[中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md) / [한국어](./INSTALL.ko.md)
|
|
133
|
+
[中文](./INSTALL.zh.md) / [日本語](./INSTALL.ja.md) / [한국어](./INSTALL.ko.md) /
|
|
134
|
+
[Français](./INSTALL.fr.md) / [Deutsch](./INSTALL.de.md) / [Italiano](./INSTALL.it.md) /
|
|
135
|
+
[Русский](./INSTALL.ru.md) / [Español](./INSTALL.es.md).
|
|
119
136
|
|
|
120
137
|
## Configuration
|
|
121
138
|
|