@klarkxy/dsh-safe-auto 0.1.0-rc.4 → 0.1.0-rc.6

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/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # Safe Auto (release candidate)
2
2
 
3
- [中文](README.zh-CN.md) · [Preflight](docs/ADR-0001.md) · [One-shot escalation](docs/ADR-0002.md) · [Reviewer routing](docs/ADR-0003.md)
3
+ Budgeted preflight plus opt-in automatic approval of one native sandbox escalation at a time. **The reviewer follows the current conversation model by default, and can be configured independently.** The plugin reuses DSH's model adapters, tool loop and approval service. It never switches the standing session to Full Access, and never lets a model enlarge the envelope you configured.
4
4
 
5
- Budgeted preflight and opt-in automatic approval of one native sandbox escalation at a time. **The reviewer follows the current conversation model by default, and can be configured independently.** The plugin reuses DSH's model adapters, tool loop and approval service. It never switches the standing session to Full Access and never lets a model enlarge the operator's configured envelope.
6
-
7
- This is a local POSIX/native-tool candidate, not an independently audited security boundary. Start with `shadow`; retain native sandbox providers, human approval, isolation and backups. DSH `workspace-write` governs file effects, not network egress or all secret reads. An approved `danger-full-access` call genuinely bypasses the DSH file sandbox; exact rules are not a finer OS sandbox.
5
+ [简体中文](README.zh-CN.md) · [Preflight](docs/ADR-0001.md) · [One-shot escalation](docs/ADR-0002.md) · [Reviewer routing](docs/ADR-0003.md)
8
6
 
9
7
  ## Install and configure
10
8
 
@@ -30,15 +28,33 @@ config:
30
28
  # No endpoint or model override: follow this conversation's DSH provider/model.
31
29
  ```
32
30
 
33
- Select native Workspace Write separately. The enrolled canonical root must exactly match session cwd and the resolved sandbox root. Config is strictly validated and immutable per plugin instance; reload after edits. This release exposes profile configuration, not a graphical model picker or generated settings form.
31
+ The enrolled canonical root must exactly match session cwd and the resolved sandbox root. Operator envelopes, candidates and budgets remain strictly validated profile configuration; reload after editing them.
32
+
33
+ ## Plugin-page activation and independent approval review
34
+
35
+ **What you do.** Select a live root session on the plugin page and click **Enable**. **Disable** only revokes automatic review; it does not change native permissions. Enable keeps **Workspace Write + ask**, never the official Full Access Auto preset. Opening, refreshing or saving the page never activates a session. Children, restarts and UI Host disposal do not inherit activation.
36
+
37
+ **What the plugin does.** Set `approvalReview: true` (default `false`), or save **Independent approval reviewer** in the plugin-page mode selector. Inspired by `dsh-approval-review@0.5.1`, this mode reviews real native single-call sandbox escalation requests for `pwsh/bash/write/edit`, including Windows, without POSIX candidate commands. It binds to the current tool execution, not free-text claims, a reused callId or old logs. Unknown tools, remote execution, nested calls, children, incomplete inputs and requests that cannot be bound to a live execution are rejected while independent approval is active. The tool-free reviewer receives the complete bounded action, direct human intent and additional restrictions only.
38
+
39
+ Structured verdicts separate risk, authorization, scope and rationale. Automatic allowance requires low/medium risk, medium/high direct authorization and bounded scope. High/critical risk, uncertainty, unknown scripts lacking decisive evidence, malformed verdicts, errors, timeouts, insufficient budgets and invalidated grants are rejected. Explicit denials never fall back to another answerer. The default 64-token fast output budget may be too small for structured output; adjust profile budgets as needed. Truncated output never grants approval.
40
+
41
+ This is an explicit delegation of native approval, not authority for arbitrary operations. Native `approval: never` rejects before the chain. The plugin page displays a fixed **Reject (default)** policy for inability to judge. The human approval option is disabled and not persisted, because no human-only DSH channel has been verified; calling waterfall `next()` could reach another automatic answerer and is not a human fallback. Independent approval does not delegate non-allowing decisions downstream. Legacy exact-rule behavior is unchanged. Source changes do not uninstall installed plugins or publish a release.
42
+
43
+ ## Reviewer settings
44
+
45
+ The updated bundle loads a separate UI Host row. Settings and session controls live on the plugin page; the native composer permission control is not replaced. Enable uses the native preset write path, without the official Full Access `registerAuto()` hook. Native `approval: never` remains authoritative.
46
+
47
+ The Safe Auto plugin page selects fast/deep reviewer models, their advertised reasoning efforts, and an additional review prompt (up to 4096 characters). Empty fast route follows the current conversation; empty deep route disables deep review. Selecting a new model clears its previous effort; saved unlisted values are retained rather than silently replaced. Unsupported explicit efforts fail closed. The additional prompt can only add restrictions, never replace the fixed safety instructions or enlarge an envelope. Saving settings performs no inference, changes no session permission, keeps the budget ledger and invalidates pending old grants. Reasoning-heavy models may need larger `fastOutputTokens/deepOutputTokens` in the profile. HTTP mode is read-only in this panel and rejects native effort overrides.
48
+
49
+ The `dsh-safe-auto-ui` Host row persists reviewer preferences through `storageDomain`, overriding corresponding profile model fields, but never persists session authorization. Activation belongs to the exact live session object: native selection, an external permission change, restart or UI Host disposal disables it, and forks and children do not inherit it. While UI control is attached, legacy smart/unattended profiles do not automatically activate untouched sessions; loading only the original core Host row retains legacy operation. Removing the Client restores the original permission control.
34
50
 
35
51
  ## Choose the approval model
36
52
 
37
53
  ### Default: follow the conversation
38
54
 
39
- Leave `endpoint`, `fastProvider` and `fastModel` unset or empty. Each eligible review resolves the provider/model from the requesting session's accepted `requestHeader().config`. If no accepted header exists, it uses that same agent's `options`. A malformed header never falls back to another route. A new conversation request using a different model changes subsequent reviews; concurrent sessions do not share a global model selection.
55
+ Leave `endpoint`, `fastProvider` and `fastModel` unset or empty. Each eligible review resolves the provider/model from the requesting session's accepted `requestHeader().config`; if no accepted header exists, it uses that same agent's `options`. A malformed header never falls back to another route. A new conversation request using a different model changes subsequent reviews; concurrent sessions do not share a global model selection.
40
56
 
41
- This reuses DSH's configured provider and credentials. No additional API key or endpoint is required. **Only the model route is inherited**, not the conversation history, main-agent prompt, tools, replay state, reasoning setting or output budget. The reviewer is a separate tool-free one-shot with its own prompt and caps. A model requiring more reasoning tokens may need a larger reviewer cap; unsupported options fail closed rather than dropping limits.
57
+ This reuses DSH's configured provider and credentials, so no additional API key or endpoint is required. **Only the model route is inherited**, not the conversation history, main-agent prompt, tools, replay state, reasoning setting or output budget. The reviewer is a separate tool-free one-shot with its own prompt and caps. A model requiring more reasoning tokens may need a larger reviewer cap; unsupported options fail closed rather than dropping limits.
42
58
 
43
59
  ### Independent DSH model
44
60
 
@@ -58,7 +74,7 @@ deepProvider: your-deep-review-provider
58
74
  deepModel: your-deep-review-model
59
75
  ```
60
76
 
61
- Only a fast `review` decision invokes it. Both deep fields empty means no deep model; uncertainty then asks a human or denies in unattended mode. There is no second implicit call to the conversation model. Native provider/model fields must be configured in pairs.
77
+ Only a fast `review` decision invokes it. Both deep fields empty means no deep model; uncertainty is rejected in independent approval mode. Legacy exact-rule mode retains human handling in smart mode and rejection in unattended mode. There is no second implicit call to the conversation model. Native provider/model fields must be configured in pairs.
62
78
 
63
79
  ### Independent HTTP endpoint (RC2-compatible)
64
80
 
@@ -71,10 +87,12 @@ apiKeyEnv: DSH_SAFE_AUTO_API_KEY
71
87
 
72
88
  `endpoint` is the complete OpenAI-compatible Chat Completions URL. This explicit endpoint uses the existing HTTP transport, including compatible lapp gateways; omit `fastProvider` and `deepProvider`. Combining native providers with an HTTP endpoint is rejected rather than guessed. Only this mode reads the named API key environment variable. HTTPS is required except loopback HTTP; redirects, URL credentials, query and fragment are rejected. To restore following, clear the endpoint and its fast model, not just the endpoint.
73
89
 
74
- Both ordinary preflight and one-shot escalation use the selected reviewer. Routes are snapshotted for each review. A change during an outstanding native review invalidates automatic allowance; final guards recheck the route. Removing the model service leaves the policy guards installed. Switching models does not reset budgets. Explicit denials remain denials even if the route changes.
90
+ Both ordinary preflight and one-shot escalation use the selected reviewer. Routes are snapshotted for each review, and a change during an outstanding native review invalidates automatic allowance; the final guards recheck the route. Removing the model service leaves the policy guards installed, and switching models does not reset budgets. Explicit denials remain denials even if the route or user authority changes. Ordinary reviewed grants are bound before review to the action, workspace, sandbox policy and direct-user authority; the final guard rejects a stale grant after downstream policy completes.
75
91
 
76
92
  ## Policy and one-shot escalation
77
93
 
94
+ The following exact-rule smart-mode behavior is retained for compatibility (`approvalReview: false`); it is not the independent approval fallback policy.
95
+
78
96
  | Action | Smart behavior |
79
97
  | --- | --- |
80
98
  | Ordinary `read/read_image/write/edit` in an enrolled workspace | Deterministic pass to existing policy; no reviewer call |
@@ -113,11 +131,13 @@ The native tool consumes the grant; the plugin does not execute the command itse
113
131
 
114
132
  ## Modes and composition
115
133
 
134
+ The following legacy mode behavior is retained with `approvalReview: false`. Active independent approval rejects unknown/unbound requests and every non-allowing verdict, error, timeout, budget exhaustion or invalidation, without human or downstream fallback.
135
+
116
136
  `off` installs nothing. `shadow` observes ordinary candidates without protecting execution; **enrolled ordinary commands can now use the conversation model even without an explicit endpoint**, and consume reviewer tokens. Shadow escalation remains native/manual without automatic review. Empty candidate lists make no model requests on installation. `smart` enforces policy and sends uncertainty to native human approval. `unattended` can grant eligible reviewed one-shot escalations but rejects uncertainty and other approval requests.
117
137
 
118
- Native `approval: never` rejects before any answerer. For automatic escalation, keep native approval at `ask` even with plugin `unattended`; `ask` dispatches to an answerer, not necessarily a human. Missing native approval services fail closed. Ordinary passes call `next()`, preserving other policy denials and prompts. Never stack this with official experimental Auto, Autogate or another auto-answerer, because human fallback assumes the downstream native human channel.
138
+ Native `approval: never` rejects before any answerer. For automatic escalation, keep native approval at `ask` even with plugin `unattended`; `ask` dispatches to an answerer, not necessarily a human. Missing native approval services fail closed. Ordinary passes call `next()`, preserving other policy denials and prompts. Never stack this with official experimental Auto, Autogate or another auto-answerer. Legacy rule-mode human fallback assumes the downstream native human channel; active independent approval never uses that fallback.
119
139
 
120
- ## Budgets, privacy and limitations
140
+ ## Budgets and privacy
121
141
 
122
142
  | Setting | Default | Meaning |
123
143
  | --- | --- | --- |
@@ -134,13 +154,21 @@ Only the action and latest direct human text are supplied. No main transcript, a
134
154
 
135
155
  Preflight and escalation share a session ledger, reserved before I/O with no error refunds. Usage counts include DSH's disjoint cache counters when reported. Reservations are not exact billable tokens, currency limits or a cap on the main agent. Providers must honor limits. New direct user messages reset task counters but not session totals; model changes reset neither; plugin reload/restart resets in-memory counters. The fuse stops more reviews, not the whole agent loop.
136
156
 
137
- Tests, builds, installation and Git hooks can run repository-controlled code and are not inherently safe. Enrollment does not pin executable contents. `grep/glob`, PTC, MCP, PowerShell, remote execution, complex shell and subagent model grants remain outside the automatic envelope. Trusted same-process plugins and execution providers remain trusted; unloading a policy removes its guards. Path rechecks cannot eliminate OS TOCTOU. Use external isolation with restricted credentials and egress.
138
-
139
157
  ## Verification
140
158
 
141
- Run `npm test`, `npm run build` (JavaScript syntax checks, not TypeScript checking), and `npm pack --dry-run` in this package, plus repository `pnpm check`. Tests cover routing, concurrent sessions, native streams, caps, stale decisions, model service removal, preflight/escalation binding, real loopback HTTP, and real Cordis/ToolRuntime/ApprovalService/LlmRuntime contracts. CI requires installed DSH dependencies; offline source-only tests may explicitly skip native contracts.
159
+ Run `npm test`, `npm run build` (JavaScript syntax checks plus the browser bundle, not TypeScript checking), and `npm pack --dry-run` in this package, plus repository `pnpm check`. Tests cover routing, concurrent sessions, native streams, caps, stale decisions, model service removal, preflight/escalation binding, real loopback HTTP, and real Cordis/ToolRuntime/ApprovalService/LlmRuntime contracts. CI requires installed DSH dependencies; offline source-only tests may explicitly skip native contracts. POSIX-only file and escalation grant cases are explicitly skipped on Windows, while Windows tests assert fail-closed behavior; native model routing still runs. If the Windows sandbox blocks the test runner's subprocess pipes, run each test file separately with `node --test --test-isolation=none test/<file>.test.js`.
160
+
161
+ The native test uses a controlled adapter and fixture session/tool/policy. It proves runtime integration, not live model accuracy, OS isolation or authenticated Web/Headless acceptance. These remain in [ADR-0002's checklist](docs/ADR-0002.md). Logs separate assessment, escalation outcome and final result without raw commands/prompts/keys; host retention is operator-managed.
162
+
163
+ ## Boundaries and limits
142
164
 
143
- The native test uses a controlled adapter and fixture session/tool/policy. It proves runtime integration, not live model accuracy, OS isolation or authenticated Web/Headless acceptance. These remain in [ADR-0002's checklist](docs/ADR-0002.md). Logs separate assessment, escalation outcome and final result without raw commands/prompts/keys; host retention is operator-managed. No durable budget/audit database, cross-call grant cache, PI probe or graphical model picker is bundled. No absolute safety or savings percentage is claimed.
165
+ - **Not an audited boundary.** The exact-rule path (local POSIX/native-tool candidates) and independent approval mode (Windows native escalation included) are candidates, not an independently audited security boundary. Start with `shadow`, and keep the native sandbox providers, isolation and backups you already rely on.
166
+ - **Human approval is not a fallback for independent review.** It remains available only in legacy rule mode or when independent approval is inactive.
167
+ - **Exact rules are not a finer OS sandbox.** DSH `workspace-write` governs file effects, not network egress or all secret reads, and an approved `danger-full-access` call genuinely bypasses the DSH file sandbox.
168
+ - **Exact rule mode does not enlarge the operator envelope.** With `approvalReview: false`, empty candidate lists authorize no model grants; Windows file auto-passes and exact-rule PowerShell escalation remain unsupported. Independent approval mode requires an explicit saved choice and session activation, as described above.
169
+ - **Coverage stops at native single-call escalation.** `grep/glob`, PTC, MCP, remote execution and subagent model grants stay outside the automatic envelope, as does widening from read-only to workspace-write. Exact-rule mode also excludes PowerShell and complex shell; independent native approval mode can review them, but missing decisive script evidence is rejected.
170
+ - **Enrolled content is not pinned and other plugins stay trusted.** Tests, builds, installation and Git hooks can run repository-controlled code and are not inherently safe; enrollment does not pin executable contents. Trusted same-process plugins and execution providers remain trusted, and unloading a policy removes its guards. Path rechecks cannot eliminate OS TOCTOU, so use external isolation with restricted credentials and egress.
171
+ - **No guarantee is claimed.** There is no fail-open option, no read-only investigation tool and no claim of full Codex parity. No durable budget/audit database, cross-call grant cache or PI probe is bundled, and no absolute safety or savings percentage is claimed.
144
172
 
145
173
  ## License
146
174
 
package/README.zh-CN.md CHANGED
@@ -1,10 +1,8 @@
1
- # Safe Auto(候选版)
1
+ # 安全自动(候选版)
2
2
 
3
- [English / 完整配置表](README.md) · [单次提权](docs/ADR-0002.md) · [审批模型路由](docs/ADR-0003.md)
3
+ 在明确登记的范围内自动审核并批准单次原生沙箱提权,**审批模型默认跟随当前对话,也能单独指定 provider/model,或继续使用独立 HTTP 端点**。复用 DSH 原生工具循环、模型适配器和审批服务;不会把整个会话切成 Full Access,模型只能缩小规则给定的权限范围。
4
4
 
5
- 复用 DSH 原生工具循环、模型适配器和审批服务。**审批模型默认跟随当前对话,也能单独指定 provider/model,或继续使用独立 HTTP 端点。** 在明确登记的范围内,可以自动审核并批准单次沙箱提权,但不会把整个会话切成 Full Access。模型只能缩小规则给定的权限范围。
6
-
7
- 仍为本地 POSIX/native 工具候选版,未经独立安全审计。保留原生沙箱、人工审批、备份和外层隔离,不宣称兼容所有工具或平台。
5
+ [English](README.md) · [预检](docs/ADR-0001.md) · [单次提权](docs/ADR-0002.md) · [审批模型路由](docs/ADR-0003.md)
8
6
 
9
7
  ## 安装与默认配置
10
8
 
@@ -16,7 +14,7 @@ pnpm --filter @klarkxy/dsh-safe-auto test
16
14
  dsh plugin --profile web add ./plugins/dsh-safe-auto
17
15
  ```
18
16
 
19
- PR 不等于 npm 已发布。在 bundle 插入的 `dsh-safe-auto` 条目中配置 `config`:
17
+ PR 不等于 npm 已发布。bundle 会插入 `dsh-safe-auto` 条目,通过 profile 补丁机制配置它的 `config`:
20
18
 
21
19
  ```yaml
22
20
  mode: shadow
@@ -27,7 +25,25 @@ shellCandidates:
27
25
  # 模型字段不填,默认跟随本对话。
28
26
  ```
29
27
 
30
- 另行选择原生 Workspace Write;工作区必须是规范绝对路径,与会话 cwd 和沙箱 root 完全相同。配置严格校验,修改后重载插件。**目前通过 profile 配置,未提供图形化模型选择器或自动设置表单。**
28
+ 工作区必须是规范绝对路径,与会话 cwd 和沙箱 root 完全相同。授权范围、候选命令、提权名单和预算仍通过 profile 配置,严格校验且修改后重载插件。
29
+
30
+ ## 插件页启停与独立代审批
31
+
32
+ **你做什么。** 在插件页 **替我审批** 区块选择活跃主会话并点击 **启用**。停用只关闭代审批,不修改会话原生权限。启用保留 **Workspace Write + ask**,不注册官方 Full Access Auto。打开页面、刷新、保存模型配置都不会自动启用会话。子会话、重启及 UI Host 卸载不继承启用状态。
33
+
34
+ **插件做什么。** 新增 `approvalReview: true`(默认为 `false`),或在插件页审核模式选择 **独立模型替我审批** 并保存。这一模式参考 `dsh-approval-review@0.5.1` 的独立应答者原理,不要求 POSIX 精确候选命令;可以审核 Windows 原生 `pwsh` 以及 `bash/write/edit` 发出的真实单次沙箱提权请求。仅绑定当前工具执行的真实请求,不依据自由文本、同名 callId 或旧日志批准;启用独立审批时,未知工具、远程、嵌套、子代理、不完整参数及无法绑定当前执行的请求均拒绝。模型无工具,仅收到完整有界动作、当前直接用户意图和附加约束。
35
+
36
+ 模型必须提供结构化风险、用户授权、有界范围和理由;只有低/中风险、至少中等直接授权且范围有界才可能自动批准。高/严重风险、不确定、证据不足的未知脚本、非法结果、模型错误、超时、预算不足及授权失效均直接拒绝;明确拒绝绝不回退给其他应答者。默认快速 64 token 可能不足以生成结构化结果,可通过 profile 调整预算;截断时不会放行。
37
+
38
+ 此模式是对原生审批链的显式委托,不是任意操作授权;`approval: never` 仍在链前拒绝。插件页固定显示「无法自动判断时 → 直接拒绝」,该策略不可修改也不保存,因为尚未核验 DSH 的仅人工审批通道。调用 waterfall `next()` 可能到达其他自动应答者,不等于人工回退。独立审批的非允许结果不委托下游。旧版精确规则兼容行为不变。本次源码修改不会自动卸载已安装插件或发布新版本。
39
+
40
+ ## 审核模型设置
41
+
42
+ 新版 bundle 包含核心与 UI Host 两个条目;设置和会话操作统一位于插件页,不替换输入框原生权限菜单。启用操作使用宿主预设,不走官方 Full Access 的 `registerAuto()`;原生 `approval: never` 仍不可绕过。
43
+
44
+ 在插件页 **安全自动设置** 中选择快速/深度审核模型、各自思考强度及最多 4096 字符的额外审核提示词。模型目录和档位来自宿主;快速模型为空表示跟随本会话,深审为空表示关闭。选新模型清空旧档位,未列出的已保存配置不会被静默替换。原生模型不支持指定档位时失败关闭。提示词只能增加审核条件,不能替换固定安全规则或扩大授权。保存不调用模型、不改变会话权限、不重置预算;会使未完成的旧授权失效。思考模型若需要更高输出预算,请在 profile 调整 `fastOutputTokens/deepOutputTokens`。HTTP 模式面板只读,仍保留 profile 配置,不支持原生思考档位。
45
+
46
+ UI Host 条目 `dsh-safe-auto-ui` 使用 `storageDomain` 持久保存审核偏好,覆盖同名 profile 模型字段;不保存会话授权。启用状态仅属于当前活跃会话对象:切回原生选项、外部权限变更、重启或 UI Host 卸载都会关闭自动审核,分叉及子会话不继承。UI 接管后,旧版 profile 的 smart/unattended 不会自动启用未选择的会话;单独加载核心 Host 条目时保留旧配置模式。卸载 Client 后原生权限控件恢复。
31
47
 
32
48
  ## 审批模型可以单独设置
33
49
 
@@ -39,14 +55,14 @@ shellCandidates:
39
55
 
40
56
  ### 独立指定 DSH 模型
41
57
 
42
- 在同一插件配置中成对设置:
58
+ 在同一插件配置中成对设置,填写 DSH 已配置的实际 provider/model ID:
43
59
 
44
60
  ```yaml
45
61
  fastProvider: your-review-provider
46
62
  fastModel: your-small-review-model
47
63
  ```
48
64
 
49
- 填写 DSH 已配置的实际 provider/model ID。可以和对话完全不同;对话切换模型不会影响这个固定审批模型。清空两项恢复跟随。provider 不存在、模型不可用、凭据错误等会回人工或拒绝,**不静默改用对话模型或其他服务**。
65
+ 可以和对话完全不同;对话切换模型不会影响这个固定审批模型。清空两项恢复跟随。provider 不存在、模型不可用、凭据错误等在独立审批模式中直接拒绝;旧版精确规则模式保留原有人工或拒绝行为,**不静默改用对话模型或其他服务**。
50
66
 
51
67
  可选深审也可单独指定,包括主审批模型继续跟随对话的情况:
52
68
 
@@ -55,7 +71,7 @@ deepProvider: your-deep-review-provider
55
71
  deepModel: your-deep-review-model
56
72
  ```
57
73
 
58
- 只有快速审核返回 `review` 才调用深审。两项均为空表示不开启深审,不会默认再调用一次对话模型。不确定时 Smart 回人工,无人值守拒绝。原生路由的 provider/model 必须成对填写。
74
+ 只有快速审核返回 `review` 才调用深审。两项均为空表示不开启深审,不会默认再调用一次对话模型。独立审批模式中不确定直接拒绝;旧版精确规则模式仍是 Smart 回人工、无人值守拒绝。原生路由的 provider/model 必须成对填写。
59
75
 
60
76
  ### 保留独立 HTTP 端点
61
77
 
@@ -70,15 +86,17 @@ apiKeyEnv: DSH_SAFE_AUTO_API_KEY
70
86
 
71
87
  这是完整 OpenAI-compatible Chat Completions URL,可接兼容 lapp 网关。此模式不要填写 `fastProvider/deepProvider`;与原生路由混填会报错。只有 HTTP 模式读取上述 API Key 环境变量。仅允许 HTTPS 或 loopback HTTP,拒绝重定向、URL 凭据、查询参数和 fragment。恢复跟随时要同时清空 endpoint 和 HTTP fastModel,不能只删 endpoint。
72
88
 
73
- 普通预检和单次提权都使用这套选择。一次审核固定两阶段路由;审核期间模型变化会作废自动放行结果,最终 guard 再次核对。模型服务失效不会导致安全 guard 一并卸载。切换模型不重置预算;已经明确拒绝的操作也不会因为换模型被改成可再次争取放行。
89
+ 普通预检和单次提权都使用这套选择。每次审核固定两阶段路由;审核期间模型变化会作废自动放行结果,最终 guard 再次核对。模型服务失效不会导致安全 guard 一并卸载。切换模型不重置预算;已经明确拒绝的操作也不会因为换模型或用户意图变化被改成可再次争取放行。普通模型预检也会在审查前绑定动作、工作区、沙箱策略和直接用户意图,并在下游策略结束后的最终 guard 中拒绝过期授权。
74
90
 
75
91
  ## 默认行为与单次提权
76
92
 
93
+ 以下为 `approvalReview: false` 的旧版精确规则兼容行为,不是独立审批的回退策略。启用独立审批时,未知或未绑定请求、不允许的结果、错误、超时、预算耗尽及授权失效均拒绝,不回人工或下游审批链。
94
+
77
95
  `off` 不安装策略。`shadow` 只观察,不保护执行;**登记了普通候选命令后,即使没有独立 endpoint,也可能使用对话模型产生审核费用**。提权在 Shadow 中仍交原生审批,不自动审查或批准。安装时候选列表默认全空,不自动产生审核请求。
78
96
 
79
97
  `smart` 对普通工作区 `read/read_image/write/edit` 做零模型检查,保留其他原生策略;受保护凭据、安全配置和部分危险命令硬拒绝。未知情况交人工。`unattended` 可以批准符合条件的单次提权,但不确定和其他审批需求均拒绝。
80
98
 
81
- `escalationCandidates` 与 `shellCandidates` 独立,普通命令候选不授予沙箱外权限。例如:
99
+ `escalationCandidates` 与 `shellCandidates` 独立,普通命令候选不授予沙箱外权限,默认 `[]`。例如:
82
100
 
83
101
  ```yaml
84
102
  escalationCandidates:
@@ -104,25 +122,40 @@ escalationMaxTimeoutMs: 30000
104
122
 
105
123
  只在匹配的原生 approval/request 内返回 allowed-once,由原生工具消费,不自行执行或修改会话权限。批准绑定 opaque token、异步上下文、Agent、callId、signal、完整参数、cwd、权限模式、直接用户意图和文件状态。并发相同 callId 不能互借;每次执行只消费一次,无跨调用批准缓存。审批 TTL 是决定新鲜度,不是进程 TTL、撤销或回滚;操作副作用不会自动撤销。详见 [ADR-0002](docs/ADR-0002.md)。
106
124
 
107
- **原生 approval: never 优先拒绝所有审批。** 启用自动提权时,原生服务仍需设为 ask,即使插件模式是 unattended。ask 表示分发给审批者,不代表一定有人在线。缺少原生审批服务时不提权。不要叠加官方 Auto、Autogate 或其他自动 answerer,人工 fallback 假定下游是原生人工通道。
125
+ **原生 approval: never 优先拒绝所有审批。** 启用自动提权时,原生服务仍需设为 ask,即使插件模式是 unattended。ask 表示分发给审批者,不代表一定有人在线。缺少原生审批服务时不提权;普通放行调用 `next()`,保留下游的拒绝与提示。不要叠加官方 Auto、Autogate 或其他自动 answerer;旧版规则模式的人工 fallback 假定下游是原生人工通道,启用独立审批时不使用该回退。
108
126
 
109
- ## 成本、隐私与安全边界
127
+ ## 成本与隐私
110
128
 
111
- 默认快速/深审输出上限 64/256 tokens,分别写入原生 maxTokens 或 HTTP 参数;每个直接用户任务最多 20/3 次;每阶段超时 8000ms,输入上限 8192 字节;连续 3 次或每会话累计 20 次非允许审核触发熔断。快速返回 allow/review/deny,深审返回 allow/ask/deny。错误 JSON、额外字段、工具调用、缺失 finish 和截断不能批准;原生 reasoning 内容也受响应大小限制。
129
+ | 设置 | 默认值 | 含义 |
130
+ | --- | --- | --- |
131
+ | `timeoutMs`、`maxInputBytes` | `8000`、`8192` | 每阶段超时与提示/输入合计 UTF-8 上限 |
132
+ | `fastOutputTokens`、`deepOutputTokens` | `64`、`256` | 原生 `maxTokens` 或 HTTP 输出上限 |
133
+ | `tokenField` | `max_tokens` | 仅 HTTP 模式,可选 `max_completion_tokens` |
134
+ | `fastCallsPerTask`、`deepCallsPerTask` | `20`、`3` | 每个直接用户任务的逻辑审核预留次数 |
135
+ | `sessionBudgetUnits` | `100000` | 提示字节数 + 输出上限 + 每阶段 1024 预留 |
136
+ | `consecutiveDenials`、`totalDenials` | `3`、`20` | 单任务/单会话的非允许审核熔断 |
112
137
 
113
- 普通预检和提权共享网络前原子预算,失败不退额。sessionBudgetUnits 默认 100000,按提示 UTF-8 字节数 + 输出上限 + 1024 预留,不是精确账单或主 Agent 总成本。原生缓存计数按 DSH 的互斥计量合并。插件不主动进行传输/语义重试;宿主适配器或中间件可能有自身传输策略,预留计数是逻辑审核请求,不是所有底层 HTTP 尝试。新用户消息只重置任务计数,换模型不重置;重载/重启仍会重置内存计数。
138
+ 快速返回 allow/review/deny,深审返回 allow/ask/deny。错误 JSON、额外字段、工具调用、缺失 finish 和截断不能批准;原生 reasoning 内容也受响应大小限制。插件不主动做传输/语义重试;宿主适配器或中间件可能有自身传输策略,预留计数是逻辑审核请求,不是所有底层 HTTP 尝试。
114
139
 
115
140
  仅发送动作和最近直接人类文本,不发送完整历史、主 Agent 推理或工具结果。justification 不是授权。敏感检测是启发式;选定或跟随远端 provider 会发送这些有界输入,文件提权包含内容。固定配置失效时不偷偷更换数据目的地。
116
141
 
117
- DSH workspace-write 只约束文件效果,不是网络隔离或全面敏感读取防护。单次 Full Access 确实移除该次 DSH 文件沙箱;精确规则不等于 OS 仅放开一个文件。路径重查不能消除 TOCTOU。测试、构建、安装和 Git hooks 可运行任意代码,命令登记不固定其未来内容。无人值守需额外隔离凭据与网络。可信同进程插件、工具和执行提供方仍属于信任基础。
142
+ 普通预检和提权共享网络前原子预算,失败不退额。sessionBudgetUnits 默认 100000,按提示 UTF-8 字节数 + 输出上限 + 1024 预留,不是精确账单或主 Agent 总成本。原生缓存计数按 DSH 的互斥计量合并。新用户消息只重置任务计数,换模型不重置;重载/重启仍会重置内存计数。熔断停止的是审核,不是整个 Agent 循环。
118
143
 
119
144
  ## 验证与剩余范围
120
145
 
121
- 运行 npm test、npm run build(JavaScript 语法检查,不是 TypeScript typecheck)、npm pack --dry-run 和全仓 pnpm check。测试包括路由/并发/失效/取消,以及真实 DSH LlmRuntime、ToolRuntime、ApprovalService 和受控适配器集成。CI 必须运行真实 DSH tests;缺依赖的离线本地环境可以明确跳过。
146
+ 运行 npm test、npm run build(JavaScript 语法检查与浏览器 bundle 构建,不是 TypeScript typecheck)、npm pack --dry-run 和全仓 pnpm check。测试包括路由/并发/失效/取消,以及真实 DSH LlmRuntime、ToolRuntime、ApprovalService 和受控适配器集成。CI 必须运行真实 DSH tests;缺依赖的离线本地环境可以明确跳过。Windows 上显式跳过 POSIX 专用文件授权与提权用例,并验证失败关闭行为,原生模型路由测试仍运行。若 Windows 沙箱阻止测试运行器创建子进程管道,可逐文件执行 `node --test --test-isolation=none test/<file>.test.js`。
147
+
148
+ 受控模型和 fixture 的 session/tool/policy 不是在线模型准确率、OS 沙箱或 authenticated Web/Headless 验收。剩余清单在 [ADR-0002](docs/ADR-0002.md)。日志区分 assessment、escalation 和实际 result,不记录原始命令/提示/Key,留存由宿主管理。
122
149
 
123
- 受控模型和 fixture 的 session/tool/policy 不是在线模型准确率、OS 沙箱或 authenticated Web/Headless 验收。剩余清单在 ADR-0002。日志区分 assessment、escalation 和实际 result,不记录原始命令/提示/Key,留存由宿主管理。
150
+ ## 边界与限制
124
151
 
125
- PowerShell、PTC/MCP、远程、复杂 Shell、子代理模型提权和 read-only 到 workspace-write 仍未纳入自动放行。没有持久化预算/审计库、跨调用批准缓存、PI probe 或图形化模型选择器。不承诺绝对安全或固定节省比例。
152
+ - **不是经过审计的安全边界。** 精确规则路径(本地 POSIX/native 工具候选)和独立审批模式(含 Windows 原生提权)都只是候选实现,未经独立安全审计。先用 `shadow`,并保留你原本依赖的原生沙箱、隔离与备份。
153
+ - **人工审批不是独立审核的回退。** 它只存在于旧版规则模式或未启用独立审批时。
154
+ - **精确规则不等于更细的 OS 沙箱。** DSH workspace-write 只约束文件效果,不是网络隔离或全面敏感读取防护;单次 Full Access 确实移除该次 DSH 文件沙箱。
155
+ - **精确规则模式不扩大授权名单。** `approvalReview: false` 时,候选列表为空不产生模型自动批准,Windows 文件自动放行和 PowerShell 精确规则提权仍不支持。独立审批模式需明确保存选择并启用会话,适用范围见上节。
156
+ - **覆盖范围止于原生单次提权。** PTC/MCP、远程、子代理模型提权和 `grep/glob` 仍在自动放行范围之外,read-only 到 workspace-write 的放宽同样未纳入。精确规则模式仍排除 PowerShell 和复杂 Shell;独立审批模式可以审查原生 Shell 提权,但缺少决定性脚本证据直接拒绝。
157
+ - **登记内容不被固定,同进程插件仍受信任。** 测试、构建、安装和 Git hooks 可运行任意代码,命令登记不固定其未来内容;卸载策略会一并移除其 guard。可信同进程插件、工具和执行提供方仍属于信任基础。路径重查不能消除 TOCTOU;无人值守需额外隔离凭据与网络。
158
+ - **不承诺任何保证。** 没有失败放行选项,不提供独立只读探针或 Codex 全功能等价保证;没有持久化预算/审计库、跨调用批准缓存或 PI probe,也不承诺绝对安全或固定节省比例。
126
159
 
127
160
  ## 许可证
128
161
 
package/cordis.patch.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  - insert:
2
2
  - id: dsh-safe-auto
3
3
  name: '@klarkxy/dsh-safe-auto'
4
+ - id: dsh-safe-auto-ui
5
+ name: '@klarkxy/dsh-safe-auto/ui-host'
package/docs/ADR-0001.md CHANGED
@@ -14,7 +14,7 @@ DSH contracts were inspected at `477b4f420553e8a52c2fbccc464d7561b239c443` (`0.1
14
14
  - [Public synchronous policy resolver](https://github.com/deepseek-ai/deepseek-harness/blob/477b4f420553e8a52c2fbccc464d7561b239c443/packages/sandbox/sandbox-policy/src/index.ts).
15
15
  - [Cordis plugin registry](https://github.com/deepseek-ai/deepseek-harness/blob/477b4f420553e8a52c2fbccc464d7561b239c443/docs/cordis-api/registry.md) accepts a real Standard Schema v1 validator. The package supplies one rather than an unvalidated Config object. No volatile settings form is promised.
16
16
 
17
- Design references: [Autogate](https://github.com/wangxing-git/dsh-autogate) (public hooks, path checks, independent reviewer) and [Approve for me](https://github.com/timeance/dsh-approve-for-me) (rules bound maximum grant, tool-free review, fail-closed). These are not independent security endorsements. Approve for me's README itself marks full authenticated profile smoke outstanding. No community source was vendored, so there is no MIT-derived code to silently relicense.
17
+ Design references: [Autogate](https://github.com/wangxing-git/dsh-autogate) (public hooks, path checks, independent reviewer) and [Approve for me](https://github.com/timeance/dsh-approve-for-me) (rules bound maximum grant, tool-free review, fail-closed). These are not independent security endorsements. Approve for me's own README still marks the full authenticated profile smoke test as outstanding. No community source was vendored, so there is no MIT-derived code to silently relicense.
18
18
 
19
19
  ## Decision
20
20
 
@@ -34,9 +34,9 @@ tool dispatch -> final result audit
34
34
 
35
35
  The plugin NEVER answers `allowed-once`. It rejects approval requests in unattended mode and otherwise delegates them. An LLM's `allow` is only permission to continue through preflight under existing constraints; it cannot approve an unrelated tool ask or escalation.
36
36
 
37
- All current shared `workspaceRoots` and `shellCandidates` are explicit host-operator grants. Candidate commands match exactly, including all arguments. File names/contents and tool descriptions are not user authority. Only the latest direct `user/message` supplies reviewer authority. Missing history, attachments, unresolved short replies, delegated instructions or oversized input cannot enlarge capabilities. Short human replies can lack sufficient context and cause manual fallback by design.
37
+ The current shared `workspaceRoots` and `shellCandidates` are explicit host-operator grants. Candidate commands match exactly, including all arguments. File names/contents and tool descriptions are not user authority. Only the latest direct `user/message` supplies reviewer authority. Missing history, attachments, unresolved short replies, delegated instructions or oversized input cannot enlarge capabilities. Short human replies can lack sufficient context and cause manual fallback by design.
38
38
 
39
- The session authority reader uses existing `snapshotEvents()` in one isolated adapter function. DSH deprecates synchronous historical reads; do not spread this dependency. Replace it with a host projection/read contract when that can preserve direct-user provenance without trusting model summaries.
39
+ The session authority reader uses existing `snapshotEvents()` in one isolated adapter function. DSH deprecates synchronous historical reads; do not propagate this dependency. Replace it with a host projection/read contract when that can preserve direct-user provenance without trusting model summaries.
40
40
 
41
41
  ## What the prototype does not guarantee
42
42
 
@@ -54,12 +54,12 @@ Automated tests: deterministic policies and protected paths; symlink/hardlink/ra
54
54
 
55
55
  The real Cordis/ToolRuntime contract test loads the same installed DSH dependencies as the existing workspace, verifies the Standard Schema plugin mount, real guard ordering, same-ID cleanup, downstream denials, preflight bypass rejection and disposal. It uses fixture tool bodies and a fixture sandbox-policy service, NOT a real operating-system sandbox. In CI missing host packages fail, rather than silently skip.
56
56
 
57
- Before promoting beyond candidate:
57
+ Before promoting beyond candidate status:
58
58
 
59
59
  1. `pnpm install --frozen-lockfile && pnpm check` must pass including the real-host contract test. Inspect npm pack contents and the prerelease `next` tag behavior; do not publish by merging without review.
60
60
  2. Install the local package into a disposable authenticated Web profile with native tools and real filesystem/process sandbox providers. Start shadow, inspect logs, then enable smart. Confirm ordinary file work, protected targets, unknown tools, user rejection and unavailable reviewer behavior.
61
61
  3. Repeat in Headless/unattended: approvals must not be auto-granted; verify cancellation, provider failure and limits. Test partial/missing sandbox backends and Full Access rejection explicitly.
62
62
  4. Use a fake HTTP server for deterministic fast/deep outcomes and a separately consented real endpoint to validate its `tokenField`, usage, caps and structured output. Do not spend user API credit implicitly from tests.
63
- 5. Run a task corpus and malicious-input corpus before making accuracy, prompt-injection resistance or token-saving claims. Test supported OS/provider versions individually.
63
+ 5. Run task and malicious-input corpora before making accuracy, prompt-injection resistance or token-saving claims. Test supported OS/provider versions individually.
64
64
 
65
65
  CI should remain frozen-lockfile and must not be loosened merely to make this package pass. A dependency-free new workspace importer may need to be recorded by pnpm; any resulting lockfile-only metadata change should contain no dependency version updates.
package/docs/ADR-0002.md CHANGED
@@ -38,7 +38,7 @@ native tool consumes mode for this invocation only
38
38
  -> tools/result clears execution decision; next call remains confined
39
39
  ```
40
40
 
41
- An `AsyncLocalStorage` scope is necessary because ApprovalRequest has neither full arguments nor a registry token. A process-wide map keyed by model-visible callId can confuse agents or parallel calls. Match agent object, tool name, callId, current signal and complete helper reason against the active dispatch; the opaque token binds its preflight. Mark the single slot claimed before any await. Detached child async work retains an inactive store and cannot reuse a finished dispatch. Other same-process plugins are trusted, not adversaries this mechanism can isolate.
41
+ An `AsyncLocalStorage` scope is necessary because ApprovalRequest has neither full arguments nor a registry token. A process-wide map keyed by model-visible callId can confuse agents or parallel calls. Match agent object, tool name, callId, current signal and complete helper reason against the active dispatch; the opaque token binds its preflight. Mark the single slot as claimed before any await. Detached child async work retains an inactive store and cannot reuse a finished dispatch. Other same-process plugins are trusted, not adversaries this mechanism can isolate.
42
42
 
43
43
  The SHA-256 binding includes complete arguments, effective policy/root, latest direct user message identity and text, execution-world/lifetime flags and file state where applicable. Both automatic and fallback outcomes are rechecked before return. It is a stale-decision detector, not an OS capability or promise of zero races. Model justifications are data and never authority.
44
44
 
@@ -62,7 +62,7 @@ Native `approval: ask` is required for the answerer to run, including plugin una
62
62
 
63
63
  The PR adds 50 escalation unit/race/fault tests, a real loopback HTTP transport test, and a real Cordis/ToolRuntime/ApprovalService/approveEscalation contract test. Combined with RC1's tests, CI ran **119 tests, all passing, none skipped**, for implementation commit `37c4c987c84656f0490f09232f2a0612bc576630` ([CI #34](https://github.com/klarkxy/dsh-plugins/actions/runs/36293861872)). Frozen-lockfile installation and the entire existing `pnpm check` also passed without loosening CI.
64
64
 
65
- The native contract verifies an outside-workspace disposable fixture write, the real asked/decided pair, native `never` precedence, downstream denial and absence of escalation inheritance on the next call. A loopback server exercises real HTTP, not a paid model. Session storage, filesystem policy and tool bodies are test fixtures. This verifies interface composition, not authenticated client routing, an actual OS sandbox or classifier accuracy. Local dependency-free testing ran the 50 new unit tests plus HTTP test; the new native contract ran in CI with the workspace's pinned DSH dependencies.
65
+ The native contract verifies an outside-workspace disposable fixture write, the real asked/decided pair, native `never` precedence, downstream denial and absence of escalation inheritance on the next call. A loopback server exercises real HTTP, not a paid model. Session storage, filesystem policy and tool bodies are test fixtures. This verifies interface composition, not authenticated client routing, an actual OS sandbox or classifier accuracy. Local dependency-free testing ran the 50 new unit tests plus the HTTP test; the new native contract ran in CI with the workspace's pinned DSH dependencies.
66
66
 
67
67
  ## Remaining deployment acceptance
68
68
 
package/docs/ADR-0003.md CHANGED
@@ -20,7 +20,7 @@ With endpoint/fastProvider/fastModel empty, resolve the requesting conversation'
20
20
 
21
21
  Explicit HTTP endpoint + fastModel retains RC2 behavior. Native provider fields with an HTTP endpoint are invalid. Partial native pairs fail load validation. Missing routes/adapters or failed calls ask/deny; they never switch to another provider, another session or an implicit HTTP route.
22
22
 
23
- Only route identifiers are inherited. Reviewer calls use a new prompt and one identity-free input, no tools, main transcript, request replay state, parent sessionId, reasoning setting or output budget. Native adapters own credentials. The reviewer retains its own caps; adapter defaults can still affect reasoning. Incompatibility fails closed, and users can independently choose a suitable review model/cap.
23
+ Only route identifiers are inherited. Reviewer calls use a new prompt and one identity-free input, and carry no tools, main transcript, request replay state, parent sessionId, reasoning setting or output budget. Native adapters own credentials. The reviewer retains its own caps; adapter defaults can still affect reasoning. Incompatibility fails closed, and users can independently choose a suitable review model/cap.
24
24
 
25
25
  Snapshot fast/deep routes once per action. Compare again after review and in the final preflight guard/approval completion. A changed model or removed native service cannot grant from stale review; explicit model denials remain final. The optional llm dependency is a child injection so its disappearance does not unload root safety guards. Model changes never reset task/session budgets.
26
26
 
package/dsh.plugin.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "id": "@klarkxy/dsh-safe-auto",
3
- "version": "0.1.0-rc.4",
3
+ "version": "0.1.0-rc.6",
4
4
  "main": "src/index.js",
5
5
  "description": "Safe Auto: budgeted preflight and one-shot escalation with conversation-following or independent reviewers.",
6
- "engines": { "dsh": ">=0.1.7-rc.2 <0.2.0" },
6
+ "engines": { "dsh": ">=0.1.7-rc.2" },
7
7
  "contributes": { "tools": [], "skills": [] }
8
8
  }