dsh-isolation-gate 0.2.3 → 0.3.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
@@ -40,3 +40,25 @@
40
40
 
41
41
  ### 自测
42
42
  - `npm test` → 4 个套件 · **325 断言**全绿(数据层 85 / 通道 74 / 路由 84 / 客户端 82)。
43
+
44
+ ## 0.3.0 — 策略档(会话级隔离)
45
+
46
+ - 新增三种档:`blocklist`(原行为)/ `allowlist`(只允许列出目录,其余全拒)/ `sealed`(再加禁网与未知工具全拒)
47
+ - 档的绑定:**会话覆盖**(`state.sessionOverrides[sessionId]`,用 `exec.agent.id`)> **目录配置** `.dsh-gate.json` > 全局默认档
48
+ - `.dsh-gate.json` **只能加严、且只能管自己所在的子树**:写 `C:\` 不会生效(防"仓库自带配置解锁")
49
+ - 坏配置 / 坏状态文件 ⇒ 按 `sealed` 处理(fail-closed)
50
+ - 联网软禁:`web_search` / `web_fetch` 等工具 + `curl` / `npm install` / `git clone` 等命令;`npm test`、`git status` 不误判
51
+ - `sealed` 下认不出路径的 shell 命令一律拒
52
+ - 自测:新增 44 + 12 条断言,套件 6/6 通过
53
+
54
+ ### 面板拆成三页(同日)
55
+
56
+ - 侧栏三项:`门禁`(对象授权)/ `门禁 · 策略`(档位与目录绑定,只读)/ `门禁 · 审计`(磁盘差异 + 审计账本)
57
+ - 新增宿主路由 `GET /__dsh-isolation-gate/profiles`
58
+ - 原单页保留为第 1 页,内容未删
59
+
60
+ - 修正:不做三个侧栏项,改回**一个「门禁」+ 页内标签**(对象与分组 / 策略档 / 审计与诊断),与「技能」面板同款交互
61
+
62
+ - 审计页新增「清空审计」:清空前整份备份到 `D:\回收站\isolation-gate-audit\access-log-<时间>.jsonl`,再截断原文件;新增 `POST /__dsh-isolation-gate/audit/clear`
63
+
64
+ - 修:`POST /audit/clear` 缺 `clearAudit` 导入(运行时 ReferenceError → 400);前端改用 `post()` 正确序列化 body
package/lib/audit.js CHANGED
@@ -8,7 +8,7 @@
8
8
  * 有上限(默认 500 行):超了从头截掉,避免日志无限长。
9
9
  */
10
10
 
11
- import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
11
+ import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
12
12
  import { homedir } from 'node:os';
13
13
  import { dirname, join } from 'node:path';
14
14
 
@@ -90,3 +90,39 @@ export function appendAudit(logPath, entry, options = {}) {
90
90
  }
91
91
  return { ok: true, record };
92
92
  }
93
+
94
+ /** 清空前的备份落点(房规:备份一律进 D:\\回收站)。 */
95
+ export const DEFAULT_BACKUP_DIR = 'D:\\回收站\\isolation-gate-audit';
96
+
97
+ /**
98
+ * 一键清空审计:先整份复制到备份目录,再截断原文件。
99
+ * @param {string} logPath
100
+ * @param {{backupDir?:string, now?:Date}} options
101
+ */
102
+ export function clearAudit(logPath = DEFAULT_LOG_PATH, options = {}) {
103
+ if (!existsSync(logPath)) return { ok: true, removed: 0, backup: null };
104
+ let removed = 0;
105
+ try {
106
+ const text = readFileSync(logPath, 'utf8');
107
+ removed = text.split(/\r?\n/).filter((line) => line.trim() !== '').length;
108
+ } catch {
109
+ removed = 0;
110
+ }
111
+ const now = options.now instanceof Date ? options.now : new Date();
112
+ const backupDir = options.backupDir || DEFAULT_BACKUP_DIR;
113
+ const stampName = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
114
+ let backup = null;
115
+ try {
116
+ mkdirSync(backupDir, { recursive: true });
117
+ backup = join(backupDir, `access-log-${stampName}.jsonl`);
118
+ copyFileSync(logPath, backup);
119
+ } catch (error) {
120
+ return { ok: false, removed: 0, backup: null, error: `备份失败,未清空:${error?.message ?? String(error)}` };
121
+ }
122
+ try {
123
+ writeFileSync(logPath, '', 'utf8');
124
+ } catch (error) {
125
+ return { ok: false, removed: 0, backup, error: `清空失败:${error?.message ?? String(error)}` };
126
+ }
127
+ return { ok: true, removed, backup };
128
+ }