dsh-isolation-gate 0.4.0 → 1.0.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.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0 — 2026-10-23
4
+
5
+ **1.0 = 功能与格式冻结,不是「完美版」。** 承诺范围见 README 的「1.0 的稳定性承诺」:状态文件 v3、CLI 子命令与退出码、HTTP 路径、四条判定语义 —— 只增不破。
6
+
7
+ 这一版**没有功能变更、没有格式变更**,只做发版前的对齐:
8
+
9
+ - **文档纠错**:状态文件章节标到 v3(原文写 v2,实际 `STATE_VERSION = 3`)。
10
+ - **测试数字纠错**:改为实跑结果 **6 个套件 · 396 条断言**(原文「4 个套件 · 325 断言」是旧数;英文 README 的 309 同样过期)。
11
+ - **定位改写**:从「别人做规则、我们做管理面」改为「别人按工具/参数立规则,我们按目录立对象」—— 前者已被同类追上,后者才是实际差异。
12
+ - **SECURITY.md**:支持范围改 `1.x`;新增「已知边界」五条(同权限域可自改、档位模式无 realpath、黑名单只判抽到的目标、审计可改、管不到 DSH 之外)。
13
+ - **新增**:README(中/英)各加一节「1.0 的稳定性承诺」。
14
+
3
15
  ## 0.4.0 — 2026-10-23
4
16
 
5
17
  - **改(重要)**:组类型(严格 / 宽松)以前只在按钮上写一句小字,实际是**两套相反语义** —— 严格组是白名单(没列进组的全拒),宽松组是黑名单(没列进组的照常)。实测踩坑:把目录加进严格组当「只禁这个」,结果全盘封死。现在模板卡片和编辑区都挂一条醒目的**模式横幅**(白名单模式 / 黑名单模式 + 「没列进组的怎么算」),编辑区还给一键「换成宽松组 / 严格组」(不动清单,只换清单外怎么算)。
package/README.en.md CHANGED
@@ -91,22 +91,24 @@ dsh plugin --profile desktop add dsh-isolation-gate
91
91
 
92
92
  ---
93
93
 
94
- ## State file (v2)
94
+ ## State file (v3)
95
95
 
96
96
  ```jsonc
97
97
  {
98
- "version": 2,
98
+ "version": 3,
99
99
  "defaultLevel": "deny",
100
100
  "groups": { "harness isolation": { "note": "", "updatedAt": "…" } },
101
101
  "objects": {
102
102
  "Zcode": { "level": "deny", "note": "", "group": "harness isolation", "updatedAt": "…" },
103
103
  "E:\\data\\shared\\project": { "level": "read", "note": "", "group": "", "updatedAt": "…" }
104
- }
104
+ },
105
+ "profiles": { "strict-delivery": { "mode": "allowlist", "allow": [{ "path": "E:\\data\\shared", "level": "read" }], "network": "deny", "unknownTool": "deny" } },
106
+ "sessionOverrides": { "<sessionId>": "strict-delivery" }
105
107
  }
106
108
  ```
107
109
 
108
- - **v1 is still readable**: legacy `harnesses: { key: { level } }` is migrated on read, **levels are preserved**;
109
- the next write persists v2.
110
+ - **Legacy formats stay readable**: v1 `harnesses: { key: { level } }` and v2 `objects` are normalised to v3 on read
111
+ (**levels are preserved**; `profiles` / `sessionOverrides` default to empty); the next write persists v3.
110
112
  - Missing file = **deny everything**; corrupt JSON = **deny everything and never overwrite it**.
111
113
  - No BOM; writes go through temp-file + rename (atomic).
112
114
  - `state.harnesses` remains a read-only in-memory alias; it is no longer written to disk.
@@ -185,6 +187,19 @@ External `Origin` → 403; wrong method → 405; bad JSON / invalid level → 40
185
187
 
186
188
  ---
187
189
 
190
+ ## The 1.0 stability promise
191
+
192
+ From 1.0 onward, the surfaces below **only grow, never break**. A breaking change would ship as 2.0 with a migration note.
193
+
194
+ | Surface | Promise |
195
+ |---|---|
196
+ | **State file** | On-disk format `v3`; v1 / v2 are read-compatible and upgraded on write, levels preserved. New fields are appended only; existing field meanings do not change. |
197
+ | **CLI** | `bin/gate.mjs` subcommands and exit codes (`0` allowed / `3` denied / `2` usage or environment error) are frozen; new flags are additive. |
198
+ | **HTTP** | Existing `/__dsh-isolation-gate/*` paths and methods are frozen; new routes are additive. |
199
+ | **Decision semantics** | The three levels (deny / read / full), longest-prefix matching, default deny and fail-closed are frozen — changing them would be a different product. |
200
+
201
+ **Not promised**: panel visuals and copy, and audit-log fields, may evolve; bug fixes are not breaking changes.
202
+
188
203
  ## Known boundaries (read this)
189
204
 
190
205
  1. **Raw filesystem access and separate processes are not blocked.** Any program or script that bypasses DSH tool calls can read/write the disk directly.
@@ -198,7 +213,7 @@ External `Origin` → 403; wrong method → 405; bad JSON / invalid level → 40
198
213
  ## Tests
199
214
 
200
215
  ```bash
201
- node test/run-all.mjs # 4 suites · 309 assertions · fully offline
216
+ node test/run-all.mjs # 6 suites · 396 assertions · fully offline
202
217
  node --check lib/*.js
203
218
  ```
204
219
 
package/README.md CHANGED
@@ -28,8 +28,10 @@ dsh plugin --profile desktop add dsh-isolation-gate
28
28
 
29
29
  它不是又一个 allow/deny 规则引擎,也不是沙箱本身。
30
30
 
31
- - **别人做的是「怎么让 agent 多访问几个目录」**(multi-root / allowlist / write-protect)或「怎么用规则拦住工具」(permission-rules / safety-net);
32
- - **我们做的是「这台机器上哪些目录属于禁区、现在给什么级别、谁改的、agent 自己怎么查」**。
31
+ - **别人按「工具 / 命令 / 参数」立规则**(`dsh-permission-rules`、`dsh-permissions` 这类:allow / deny / ask + glob / 正则);
32
+ - **我们按「目录」立对象**:这台机器上哪些目录属于禁区、现在给什么级别、谁改的、agent 自己怎么查。
33
+
34
+ 规则引擎回答的是「**这次调用准不准**」,门禁回答的是「**这个目录开不开**」。两者可以叠着用,不冲突。
33
35
 
34
36
  所以它的核心是**管理面**:
35
37
 
@@ -105,23 +107,23 @@ dsh plugin --profile desktop add dsh-isolation-gate
105
107
 
106
108
  ---
107
109
 
108
- ## 状态文件(v2)
110
+ ## 状态文件(v3)
109
111
 
110
112
  ```jsonc
111
113
  {
112
- "version": 2,
114
+ "version": 3,
113
115
  "defaultLevel": "deny",
114
- "groups": {
115
- "harness 隔离": { "note": "", "updatedAt": "…" }
116
- },
116
+ "groups": { "harness 隔离": { "note": "", "updatedAt": "…" } },
117
117
  "objects": {
118
118
  "Zcode": { "level": "deny", "note": "", "group": "harness 隔离", "updatedAt": "…" },
119
119
  "E:\\资料\\合作档案\\某项目": { "level": "read", "note": "", "group": "", "updatedAt": "…" }
120
- }
120
+ },
121
+ "profiles": { "严格交付": { "mode": "allowlist", "allow": [{ "path": "E:\\资料\\库", "level": "read" }], "network": "deny", "unknownTool": "deny" } },
122
+ "sessionOverrides": { "<sessionId>": "严格交付" }
121
123
  }
122
124
  ```
123
125
 
124
- - **v1 仍可读**:旧的 `harnesses: { key: { level } }` 读入时自动迁移成 `objects`,**级别不丢**;下一次写盘才落成 v2。
126
+ - **旧格式仍可读**:v1 的 `harnesses: { key: { level } }` 与 v2 的 `objects` 读入时自动收敛成 v3(**级别不丢**,`profiles` / `sessionOverrides` 缺省为空);下一次写盘才落成 v3。
125
127
  - 文件缺失 = **全禁**;坏 JSON = **全禁且不覆盖原文件**。
126
128
  - 无 BOM;写盘走临时文件 + rename(原子替换)。
127
129
  - `state.harnesses` 在内存里保留为只读别名,磁盘上不再写它。
@@ -202,6 +204,19 @@ node bin/gate.mjs log --limit 20
202
204
 
203
205
  ---
204
206
 
207
+ ## 1.0 的稳定性承诺
208
+
209
+ 从 1.0 起,下面这些**只增不破**;要破坏会走 2.0 并附迁移说明:
210
+
211
+ | 面 | 承诺 |
212
+ |---|---|
213
+ | **状态文件** | 磁盘格式 `v3`;v1 / v2 一律**读时兼容、写时升级**,级别不丢。新增字段只追加,不改已有字段含义。 |
214
+ | **CLI** | `bin/gate.mjs` 的子命令与退出码(`0` 放行 / `3` 拒绝 / `2` 用错或环境错误)不改;新参数只增加。 |
215
+ | **HTTP** | `/__dsh-isolation-gate/*` 现有路径与方法不改;新路由只增加。 |
216
+ | **判定语义** | 三级(deny / read / full)、最长前缀命中、默认禁、fail-closed —— 这四项冻结;改它们等于换产品。 |
217
+
218
+ **不承诺**:面板的视觉与文案、审计日志的字段可以随版本演进;修 bug 不算破坏性变更。
219
+
205
220
  ## 已知边界(必须明说)
206
221
 
207
222
  1. **raw fs 与独立进程拦不住。** 任何程序、脚本、别的 agent 不经过 DSH 工具调用就直接读写磁盘,本插件看不到。
@@ -217,16 +232,18 @@ node bin/gate.mjs log --limit 20
217
232
  ## 自测
218
233
 
219
234
  ```bash
220
- node test/run-all.mjs # 4 个套件 · 325 断言 · 全离线(不需要 GUI/dsh)
235
+ node test/run-all.mjs # 6 个套件 · 396 断言 · 全离线(不需要 GUI/dsh)
221
236
  node --check lib/*.js
222
237
  ```
223
238
 
224
239
  | 套件 | 覆盖 |
225
240
  |---|---|
226
- | `run-data-layer.mjs` | 状态 v1→v2 迁移 / 无 BOM / 坏 JSON 不覆盖 / 路径键 / 名单备份 / 分组 / 孤儿清理 |
227
- | `run-guard.mjs` | 三级×四操作矩阵 / 最长前缀 / 同前缀不误伤 / fail-closed / 真实 I/O 闭环 |
228
- | `run-routes.mjs` | 11 条路由 / 组级切 / 工具门挂载与干跑 / 选择器缺省 / 级别落盘 / 403/405/400 |
229
- | `run-client.mjs` | 两座位注册 / 摘要条 / 分组卡片 / 分段控件 / `⋯` 菜单 / 空态 / 交互接线 |
241
+ | `run-data-layer.mjs`(85) | 状态 v1/v2→v3 迁移 / 无 BOM / 坏 JSON 不覆盖 / 路径键 / 名单备份 / 分组 / 孤儿清理 |
242
+ | `run-guard.mjs`(74) | 三级×四操作矩阵 / 最长前缀 / 同前缀不误伤 / fail-closed / 真实 I/O 闭环 |
243
+ | `run-profiles.mjs`(45) | 隔离强度三档 / 白名单与黑名单语义 / 会话绑定只能加严 / 联网软禁 |
244
+ | `run-profiles-runtime.mjs`(11) | 档位文件读取 / 目录绑定 / 坏配置 fail-closed |
245
+ | `run-routes.mjs`(84) | 11 条路由 / 组级切 / 工具门挂载与干跑 / 选择器缺省 / 级别落盘 / 403/405/400 |
246
+ | `run-client.mjs`(97) | 两座位注册 / 摘要条 / 分组卡片 / 分段控件 / `⋯` 菜单 / 空态 / 交互接线 |
230
247
 
231
248
  ---
232
249
 
@@ -249,6 +266,7 @@ MIT · 见 [LICENSE](./LICENSE)。
249
266
 
250
267
  - [x] 截图四张:总览 / 组卡 / 审计与诊断 / 特别组草稿(见 [docs/screenshots](./docs/screenshots))
251
268
  - [ ] 30 秒演示 GIF(欢迎贡献:录你自己机器上的演示;我们不录,整屏会带出无关窗口)
269
+ - [ ] **认知帷幕**:受管路径的读取不直接回原文,只回字段摘要或打码内容(群友提的方向;比目录权限更接近「少看一点」)
252
270
  - [ ] `gate export --csv`:把审计日志导出成表格
253
271
  - [ ] 临时授权:给某对象一个到期时间,到点自动回到 `deny`
254
272
  - [ ] 状态文件并发锁(多窗口同时改不互相覆盖)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-isolation-gate",
3
- "version": "0.4.0",
3
+ "version": "1.0.0",
4
4
  "description": "门禁 · 目录访问管制(隔离区授权台):一屏管理「哪些目录受管、各自什么级别」,三级=禁/只读/可读写删;判定同时挂在受管辖通道(bin/gate.mjs)与宿主工具执行门(ctx.tools.guard)上,默认禁、名单缺失一律拒绝(fail-closed)、审计可查、agent 可自查;支持分组批量切、目录选择器与状态文件自动迁移。",
5
5
  "keywords": [
6
6
  "dsh",