@klarkxy/dsh-safe-auto 0.1.0-rc.6 → 0.2.0-rc.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/README.md +68 -135
- package/README.zh-CN.md +70 -124
- package/docs/ADR-0001.md +1 -1
- package/docs/ADR-0002.md +1 -1
- package/docs/ADR-0003.md +1 -1
- package/docs/ADR-0004.md +33 -0
- package/docs/ADR-0005.md +31 -0
- package/docs/ADR-0006.md +50 -0
- package/dsh.plugin.json +9 -4
- package/lib/client.js +1340 -467
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +14 -10
- package/src/approval-review.js +19 -1
- package/src/config.js +12 -35
- package/src/control.js +29 -17
- package/src/execution-evidence.js +114 -0
- package/src/gate.js +37 -31
- package/src/human-approval.js +64 -0
- package/src/index.js +161 -199
- package/src/model-route.js +10 -29
- package/src/policy.js +20 -75
- package/src/review-context.js +31 -0
- package/src/reviewer.js +61 -120
- package/src/shell-command.js +500 -0
- package/src/ui-host.js +42 -43
- package/src/escalation.js +0 -118
package/README.md
CHANGED
|
@@ -1,174 +1,107 @@
|
|
|
1
1
|
# Safe Auto (release candidate)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Automatic review of native sandbox escalation requests. When a real `write`/`edit`/`bash`/`pwsh` call asks to widen its sandbox beyond Workspace Write, an independent reviewer model vets that one call — except a `bash` call the built-in static proof can show is read-only, which is granted without a model. A pass continues automatically; other review results offer an exact-call confirmation in the current session, with 60 seconds to approve once or reject. No response means rejection. The plugin never switches the standing session to Full Access.
|
|
4
4
|
|
|
5
|
-
[简体中文](README.zh-CN.md) · [
|
|
5
|
+
[简体中文](README.zh-CN.md) · [One-shot escalation](docs/ADR-0002.md) · [Reviewer routing](docs/ADR-0003.md) · [Authorization and evidence](docs/ADR-0004.md) · [Timed human confirmation](docs/ADR-0005.md) · [Static shell proof](docs/ADR-0006.md)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> **0.2.0 is a breaking simplification.** The 0.1.x exact-rule preflight, workspace/shell/escalation candidate lists, `shadow`/`smart`/`unattended` modes, the deep review stage and the HTTP endpoint were removed. See [Migrating from 0.1.x](#migrating-from-01x).
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Install and enable
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
|
|
13
|
-
pnpm --filter @klarkxy/dsh-safe-auto test
|
|
14
|
-
dsh plugin --profile web add ./plugins/dsh-safe-auto
|
|
12
|
+
dsh plugin --profile <profile> add @klarkxy/dsh-safe-auto
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```yaml
|
|
20
|
-
id: dsh-safe-auto
|
|
21
|
-
name: '@klarkxy/dsh-safe-auto'
|
|
22
|
-
config:
|
|
23
|
-
mode: shadow
|
|
24
|
-
workspaceRoots:
|
|
25
|
-
- /absolute/canonical/project
|
|
26
|
-
shellCandidates:
|
|
27
|
-
- git status --short
|
|
28
|
-
# No endpoint or model override: follow this conversation's DSH provider/model.
|
|
29
|
-
```
|
|
30
|
-
|
|
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.
|
|
50
|
-
|
|
51
|
-
## Choose the approval model
|
|
52
|
-
|
|
53
|
-
### Default: follow the conversation
|
|
54
|
-
|
|
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.
|
|
56
|
-
|
|
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.
|
|
58
|
-
|
|
59
|
-
### Independent DSH model
|
|
15
|
+
From a checked source checkout instead:
|
|
60
16
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
fastModel: your-small-review-model
|
|
17
|
+
```sh
|
|
18
|
+
pnpm install --frozen-lockfile
|
|
19
|
+
pnpm --filter @klarkxy/dsh-safe-auto test
|
|
20
|
+
dsh plugin --profile <profile> add ./plugins/dsh-safe-auto
|
|
66
21
|
```
|
|
67
22
|
|
|
68
|
-
The
|
|
23
|
+
The bundle inserts the `dsh-safe-auto` and `dsh-safe-auto-ui` profile rows. Safe Auto then appears as a fourth option in the composer's permission menu, next to the native presets — pick **Safe Auto** there to enable it for the current session, and pick any native preset to disable it again. Nothing is automatic until you do: no session inherits activation, and restart, a permission change or uninstall revokes it. The plugin page only holds reviewer configuration, safety notes and the read-only budget limits, grouped into tabs.
|
|
69
24
|
|
|
70
|
-
The
|
|
25
|
+
> The composer permission control is a replacement slot: while Safe Auto is installed, the plugin renders that control itself (native presets included) so the option can appear in the menu. If the host redesigns this control, the plugin's copy may lag behind until updated.
|
|
71
26
|
|
|
72
|
-
|
|
73
|
-
deepProvider: your-deep-review-provider
|
|
74
|
-
deepModel: your-deep-review-model
|
|
75
|
-
```
|
|
27
|
+
## How it works
|
|
76
28
|
|
|
77
|
-
|
|
29
|
+
1. A native tool call asks for `sandbox_permissions` widening (`workspace-write` or `danger-full-access`).
|
|
30
|
+
2. The plugin binds the live execution — agent, callId, signal, exact arguments, cwd, sandbox policy and the ordered direct-human instructions, including later restrictions and revocations.
|
|
31
|
+
3. A fully literal `bash` command is granted without evidence or a model only when every invocation matches an exact positive grammar: case-sensitive POSIX program names, supported flags and values, input-only operand counts, safe redirects and bounded environment prefixes. Unknown options, abbreviations, clusters, output operands and assignment-only statements continue to review. Ordinary reads such as `ls -la`, `cat input | jq .name`, `grep -rn pattern src`, `find . -name "*.md"` and `ps aux` retain this fast path; `pwsh` does not.
|
|
32
|
+
4. The exact request is reviewed once. For shell calls, bounded workspace package definitions and referenced local scripts provide untrusted evidence; their canonical paths and content are rechecked before granting.
|
|
33
|
+
5. A reviewed pass returns `allowed-once`. For an otherwise eligible action, model denial, uncertainty, failure or budget exhaustion opens a timed confirmation. The dialog shows the exact operation, requested permission, reviewer opinion and countdown. Explicit approval grants this call after another binding/evidence check; rejection or expiry returns `rejected`. Closing the dialog rejects. No downstream approval answerer is consulted.
|
|
78
34
|
|
|
79
|
-
|
|
35
|
+
Native prohibitions, structural refusals, changed evidence, cancellation and invalidated requests cannot be overridden. Timed confirmation requires the UI row and an authenticated browser client; without them, or with the timeout set to zero, the existing non-grant path remains. Headless sessions do not gain an automatic fallback.
|
|
80
36
|
|
|
81
|
-
|
|
82
|
-
endpoint: https://your-trusted-gateway.example/v1/chat/completions
|
|
83
|
-
fastModel: your-http-review-model
|
|
84
|
-
# deepModel: your-http-deep-model
|
|
85
|
-
apiKeyEnv: DSH_SAFE_AUTO_API_KEY
|
|
86
|
-
```
|
|
87
|
-
|
|
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.
|
|
37
|
+
The reviewer sees the bounded action, chronological direct-human instructions and local evidence, with no main-agent prompt, private reasoning or tools. Authorization is judged by substance: necessary local installation, build and test steps may implement a requested development task without the user naming every command. Earlier authority remains visible after a progress question or “continue”; later restrictions still apply. Automatic allowance requires low/medium risk, medium/high authorization and bounded side effects.
|
|
89
38
|
|
|
90
|
-
|
|
39
|
+
Human text is retained without lossy selection, up to 12 KiB. Sensitive text, nontext constraints or overflow prevent automatic review rather than silently dropping restrictions; an otherwise valid action can receive fresh explicit confirmation through the timed UI without sending that history to the model. Evidence is capped at eight files, 6 KiB per file and 12 KiB overall. Protected, escaped, sensitive or unreadable files are withheld with explicit omission markers. Evidence coverage is partial: dependencies, imported code and workspace-wide scripts are not exhaustively inspected. Material remaining uncertainty prevents automatic permission.
|
|
91
40
|
|
|
92
|
-
##
|
|
41
|
+
## Configuration
|
|
93
42
|
|
|
94
|
-
|
|
43
|
+
Everything is optional; with no configuration the reviewer follows the current conversation's model. Edit the profile row's `config` and reload:
|
|
95
44
|
|
|
96
|
-
|
|
|
97
|
-
| --- | --- |
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
|
|
106
|
-
`
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
escalationCandidates:
|
|
110
|
-
- tool: write
|
|
111
|
-
cwd: /absolute/canonical/project
|
|
112
|
-
mode: danger-full-access
|
|
113
|
-
filePath: /absolute/other-project/notes.txt
|
|
114
|
-
- tool: edit
|
|
115
|
-
cwd: /absolute/canonical/project
|
|
116
|
-
mode: danger-full-access
|
|
117
|
-
filePath: /absolute/other-project/notes.txt
|
|
118
|
-
- tool: bash
|
|
119
|
-
cwd: /absolute/canonical/project
|
|
120
|
-
mode: danger-full-access
|
|
121
|
-
command: git status --short
|
|
122
|
-
escalationApprovalTtlMs: 30000
|
|
123
|
-
escalationMaxTimeoutMs: 30000
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
Rules require exactly tool/cwd/mode and filePath or command. No prefixes, globs or directory grants. Native DSH requests use `sandbox_permissions: danger-full-access` with `justification`, not Codex's `require_escalated`. Only widening from Workspace Write is supported. File targets must be absolute and canonical, with existing parents; links, hard-linked writes, protected/system targets and unknown arguments do not get automatic approval. The reviewer receives complete bounded file-write/edit arguments, including content, or refuses oversized/sensitive inputs without truncating them.
|
|
45
|
+
| Key | Default | Meaning |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `enabled` | `true` | Master switch. `false` mounts nothing. |
|
|
48
|
+
| `provider` / `model` | *(follow conversation)* | Fixed reviewer route, configured as a pair using your DSH model IDs. |
|
|
49
|
+
| `reasoningEffort` | *(model default)* | Advertised reasoning effort of the fixed route. |
|
|
50
|
+
| `reviewerPrompt` | *(none)* | Extra review constraints (≤4096 chars); may only restrict, never widen. |
|
|
51
|
+
| `timeoutMs` | `30000` | Per-review deadline. |
|
|
52
|
+
| `humanApprovalTimeoutMs` | `60000` | Human confirmation window, separate from model review; `0` disables it. Maximum 300000 ms; profile-owned. |
|
|
53
|
+
| `maxInputBytes` | `32768` | Combined UTF-8 prompt/input cap; existing explicit values are retained. |
|
|
54
|
+
| `outputTokens` | `1024` | Reviewer output cap, including reasoning where the model counts it. Explicit profile values are retained; incomplete or invalid verdicts still require human confirmation. |
|
|
55
|
+
| `maxReviewsPerTask` | `20` | Review calls per direct user task. |
|
|
56
|
+
| `consecutiveDenials` | `3` | Consecutive explicit denials before the breaker opens. Uncertainty and failures reset the streak but still consume review reservations. |
|
|
57
|
+
| `staticReadonly` | `true` | Grant provably read-only `bash` escalations without a model call. `false` sends everything to the reviewer. |
|
|
127
58
|
|
|
128
|
-
|
|
59
|
+
Unknown keys fail validation rather than being ignored. Reviewer model, effort and prompt can also be set per deployment on the plugin page; those saved values override the profile route but never the budgets.
|
|
129
60
|
|
|
130
|
-
The
|
|
61
|
+
## The reviewer model
|
|
131
62
|
|
|
132
|
-
|
|
63
|
+
**Default: follow the conversation.** Leave `provider`/`model` empty. Each review resolves the provider/model from the requesting session's accepted request header, reusing DSH's configured credentials — no extra API key. Only the model route is inherited, not history, prompt, tools or budgets.
|
|
133
64
|
|
|
134
|
-
|
|
65
|
+
**Fixed model.** Set `provider` and `model` together to pin a reviewer that stays put when the conversation switches models. A missing or invalid route rejects instead of falling back silently.
|
|
135
66
|
|
|
136
|
-
|
|
67
|
+
## Policy
|
|
137
68
|
|
|
138
|
-
|
|
69
|
+
| Request | Outcome |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| Bound single escalation of `write`/`edit`/`bash`/`pwsh`, reviewer passes | `allowed-once`, this call only |
|
|
72
|
+
| Bound `bash` escalation proven read-only by the strict static parse | `allowed-once`, no model call, no budget consumed |
|
|
73
|
+
| Protected credentials/security files, secrets, dangerous programs (anywhere in a fully parsed command) | Hard denial before review |
|
|
74
|
+
| Model denial (including risk opinions), uncertainty or review failure for an eligible action | Timed human confirmation; no grant without explicit approval |
|
|
75
|
+
| Unknown tools, subagents, nested or unbound requests | No automatic grant |
|
|
76
|
+
| Human rejection or confirmation expiry | Rejected; fresh execution needs fresh review |
|
|
77
|
+
| Changed evidence, invalidated grants, audit failure or cancellation | No grant; terminal feedback |
|
|
139
78
|
|
|
140
|
-
|
|
79
|
+
Native `approval: never` still rejects before any answerer. Never stack this with another automatic approval answerer.
|
|
141
80
|
|
|
142
|
-
|
|
143
|
-
| --- | --- | --- |
|
|
144
|
-
| `timeoutMs`, `maxInputBytes` | `8000`, `8192` | Per-stage deadline and combined UTF-8 prompt/input cap |
|
|
145
|
-
| `fastOutputTokens`, `deepOutputTokens` | `64`, `256` | Explicit native `maxTokens` or HTTP output caps |
|
|
146
|
-
| `tokenField` | `max_tokens` | HTTP only; alternatively `max_completion_tokens` |
|
|
147
|
-
| `fastCallsPerTask`, `deepCallsPerTask` | `20`, `3` | Atomic logical-review reservations per direct user task |
|
|
148
|
-
| `sessionBudgetUnits` | `100000` | Prompt bytes + output cap + 1024 reserved per stage |
|
|
149
|
-
| `consecutiveDenials`, `totalDenials` | `3`, `20` | Non-allowing review/error fuse per task/session |
|
|
81
|
+
## Migrating from 0.1.x
|
|
150
82
|
|
|
151
|
-
|
|
83
|
+
- Profile keys `mode`, `workspaceRoots`, `shellCandidates`, `escalationCandidates`, `endpoint`, `apiKeyEnv`, `tokenField`, `fast*`/`deep*` and the budget fuses `sessionBudgetUnits`/`totalDenials` were removed; a profile still carrying them fails validation. The equivalent of 0.1.x `approvalReview: true` plus a UI-enabled session is now the only behavior.
|
|
84
|
+
- `fastProvider`/`fastModel`/`fastReasoningEffort` became `provider`/`model`/`reasoningEffort`; `fastOutputTokens` became `outputTokens`; `fastCallsPerTask` became `maxReviewsPerTask`.
|
|
85
|
+
- Settings saved by the 0.1.x panel keep loading (retired keys are stripped), but the reviewer route falls back to following the conversation — re-pick a model on the plugin page if you had a fixed one.
|
|
152
86
|
|
|
153
|
-
|
|
87
|
+
## Boundaries and limits
|
|
154
88
|
|
|
155
|
-
|
|
89
|
+
- **Not an audited boundary.** The reviewer is a language model and can be wrong, especially in adversarial contexts. Keep the native sandbox, isolation and backups you already rely on.
|
|
90
|
+
- **Static proof assumes operator-trusted PATH and runtimes.** It checks the original command text, not installed binary identity, shell functions or ambient runtime integrity. Explicit executable paths, `.exe`/`.cmd` suffixes, case variants, executable pager/config environment prefixes and persistent assignments do not qualify. Parser or grammar defects can produce incorrect proofs; this is not a runtime attestation or an absolute safety guarantee. An unproven command returns to reviewer/manual confirmation, not a new hard refusal.
|
|
91
|
+
- **Quoting does not bypass hard refusals.** Literal argv, environment and redirect values are decoded before the protected-path/secret checks, including adjacent quote fragments. These checks also apply outside the static path and cannot be overridden by reviewer or manual confirmation. Unquoted wildcard fragments still invalidate proof even next to quoted text. Bash `/dev/tcp` and `/dev/udp` file redirects return to review, including quoted and numbered-fd input redirects; ordinary file input, fd merges and `/dev/null` output retain their existing rules.
|
|
92
|
+
- **Git is not read-only by subcommand name.** Bare `git status`, worktree diffs, `git ls-files --modified` and other content-checking worktree operations remain under review because refresh/conversion can execute configured clean/process filters. Supported object/index reads require the original `--no-pager --no-optional-locks --no-lazy-fetch -c core.fsmonitor=false`; cached/staged diff also requires `--no-ext-diff --no-textconv --ignore-submodules=all`. History reads additionally need `--no-show-signature` and a supported fixed format such as `--oneline`. The plugin never prepends controls or rewrites argv. Exact `git version` and `git --no-pager config --get user.name` are narrow independent reads; transport helpers, editors, filters and mixed config mutations do not qualify. Ordinary `sort` can spill to temporary files, so only its check mode qualifies.
|
|
93
|
+
- **Dedicated confirmation channel.** Pinned DSH 0.2.0-rc.2 approval and question waterfalls accept automatic answerers. Manual confirmation instead uses the plugin's authenticated browser HTTP endpoints and unpredictable single-use request IDs. Fetch metadata and host origin/authentication checks protect the browser channel against cross-site requests; they do not prove physical human action. Authenticated clients, their transport and same-process plugins remain trusted. No model tool is registered for approval.
|
|
94
|
+
- **Server-owned expiry.** The window starts when a pending request is published. The server uses a monotonic deadline and atomically accepts the first valid answer; duplicate, late or cross-session answers fail. Disabling, changing settings, unloading or cancelling invalidates pending requests. Requests are in memory only, so restarts do not restore them. Both direct browser requests and the authenticated DSH desktop carrier are supported; incompatible request metadata is rejected.
|
|
95
|
+
- **Foreign native approvals remain native.** Blueprint order and Classmates model approvals continue to downstream answerers when no Safe Auto-owned execution context exists. Requests in an owned context, including mismatches, stale/claimed requests, and unbound impersonation of `bash`/`pwsh`/`write`/`edit`, remain fail-closed.
|
|
96
|
+
- **Coverage stops at native single-call escalation.** Only `write`/`edit`/`bash`/`pwsh` widening from `workspace-write` is reviewed. Other tools, MCP, remote execution, subagent calls and standing permission changes stay outside the automatic envelope.
|
|
97
|
+
- **Evidence is checked, execution is not atomic.** Evidence paths, versions and SHA-256 digests are revalidated before granting, but files can still change between approval and execution. Other same-process plugins remain trusted; unloading removes the guards. Keep external isolation with restricted credentials and egress.
|
|
98
|
+
- **No guarantee is claimed.** There is no fail-open option, no durable audit database and no claim of absolute safety or savings.
|
|
156
99
|
|
|
157
100
|
## Verification
|
|
158
101
|
|
|
159
|
-
Run `npm test`, `npm run build`
|
|
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
|
|
102
|
+
Run `npm test`, `npm run build` 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, execution binding, and real Cordis/ToolRuntime/ApprovalService/LlmRuntime contracts. CI requires installed DSH dependencies; offline source-only runs may skip the native contracts. 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`.
|
|
164
103
|
|
|
165
|
-
|
|
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.
|
|
104
|
+
The native contract tests use controlled adapters and fixture sessions/tools. They prove runtime integration, not live model accuracy, OS isolation or authenticated Web/Headless acceptance; those remain in [ADR-0002's checklist](docs/ADR-0002.md). Logs separate assessment, outcome and final result without raw commands, prompts or keys; host retention is operator-managed.
|
|
172
105
|
|
|
173
106
|
## License
|
|
174
107
|
|
package/README.zh-CN.md
CHANGED
|
@@ -1,162 +1,108 @@
|
|
|
1
1
|
# 安全自动(候选版)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
自动审核原生沙箱提权请求。当真实的 `write`/`edit`/`bash`/`pwsh` 调用要求把沙箱放宽到 Workspace Write 之外时,由独立审核模型把关这一次调用——内置静态证明能判定为只读的 `bash` 命令除外,它们不调模型直接放行。通过就自动继续;其他审核结果会在当前会话显示完整操作,给你 60 秒选择“仅批准这一次”或拒绝。无人响应则到期拒绝。插件不会把整个会话切成 Full Access。
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [
|
|
5
|
+
[English](README.md) · [单次提权](docs/ADR-0002.md) · [审核模型路由](docs/ADR-0003.md) · [授权与证据](docs/ADR-0004.md) · [限时人工确认](docs/ADR-0005.md) · [静态 Shell 证明](docs/ADR-0006.md)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> **0.2.0 是破坏性简化。** 0.1.x 的精确规则预检、workspace/shell/escalation 候选名单、`shadow`/`smart`/`unattended` 模式、深度审核阶段和 HTTP 端点均已删除。见[从 0.1.x 迁移](#从-01x-迁移)。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## 安装与启用
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
|
|
13
|
-
pnpm --filter @klarkxy/dsh-safe-auto test
|
|
14
|
-
dsh plugin --profile web add ./plugins/dsh-safe-auto
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
PR 不等于 npm 已发布。bundle 会插入 `dsh-safe-auto` 条目,通过 profile 补丁机制配置它的 `config`:
|
|
18
|
-
|
|
19
|
-
```yaml
|
|
20
|
-
mode: shadow
|
|
21
|
-
workspaceRoots:
|
|
22
|
-
- /absolute/canonical/project
|
|
23
|
-
shellCandidates:
|
|
24
|
-
- git status --short
|
|
25
|
-
# 模型字段不填,默认跟随本对话。
|
|
12
|
+
dsh plugin --profile <profile> add @klarkxy/dsh-safe-auto
|
|
26
13
|
```
|
|
27
14
|
|
|
28
|
-
|
|
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 后原生权限控件恢复。
|
|
47
|
-
|
|
48
|
-
## 审批模型可以单独设置
|
|
49
|
-
|
|
50
|
-
### 默认:跟随当前对话
|
|
51
|
-
|
|
52
|
-
`endpoint`、`fastProvider`、`fastModel` 均留空。每次需要模型审核时,读取请求会话已经接受的 `requestHeader().config` 的 provider/model;尚无请求 header 才使用同一 Agent 的 options。存在但不完整的 header 不会偷偷回退。对话下一轮接受了新模型,后续审核随之更新;不同会话不会共用一个全局模型选择。
|
|
53
|
-
|
|
54
|
-
直接复用 DSH 对应 provider 的适配器和凭据,**不用再填一遍 API Key**。只继承模型路由,不继承聊天历史、主 Agent 提示词、工具权限、回放状态、思考档位或输出预算。审批仍是独立、无工具的模型请求,使用自身的提示和成本上限。需要大量推理 token 的模型可能要提高审批输出上限;无法支持的参数应失败关闭,不能丢掉限制后执行。
|
|
15
|
+
使用源码检出安装:
|
|
55
16
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```yaml
|
|
61
|
-
fastProvider: your-review-provider
|
|
62
|
-
fastModel: your-small-review-model
|
|
17
|
+
```sh
|
|
18
|
+
pnpm install --frozen-lockfile
|
|
19
|
+
pnpm --filter @klarkxy/dsh-safe-auto test
|
|
20
|
+
dsh plugin --profile <profile> add ./plugins/dsh-safe-auto
|
|
63
21
|
```
|
|
64
22
|
|
|
65
|
-
|
|
23
|
+
bundle 会插入 `dsh-safe-auto` 与 `dsh-safe-auto-ui` 两个 profile 条目。之后输入框的权限菜单里会在原生档位旁出现第四个选项——选择 **安全自动** 即为本会话启用,选回任意原生档位即停用。在此之前没有任何自动行为:会话不继承启用状态,重启、切换权限或卸载都会撤销它。插件页只保留审核配置、安全说明和只读的预算边界,按页签分区。
|
|
66
24
|
|
|
67
|
-
|
|
25
|
+
> 输入框的权限控件是替换型插槽:安装 Safe Auto 期间由插件自己渲染这个控件(包含原生档位),选项才能出现在菜单里。如果宿主以后重新设计这个控件,插件的副本在新版本跟进前可能落后。
|
|
68
26
|
|
|
69
|
-
|
|
70
|
-
deepProvider: your-deep-review-provider
|
|
71
|
-
deepModel: your-deep-review-model
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
只有快速审核返回 `review` 才调用深审。两项均为空表示不开启深审,不会默认再调用一次对话模型。独立审批模式中不确定直接拒绝;旧版精确规则模式仍是 Smart 回人工、无人值守拒绝。原生路由的 provider/model 必须成对填写。
|
|
27
|
+
## 工作原理
|
|
75
28
|
|
|
76
|
-
|
|
29
|
+
1. 原生工具调用请求 `sandbox_permissions` 提权(`workspace-write` 或 `danger-full-access`)。
|
|
30
|
+
2. 插件绑定当前活跃执行——agent、callId、signal、完整参数、cwd、沙箱策略,以及按时间排序的真人指令,包含后续限制和撤销。
|
|
31
|
+
3. 完全按字面解析的 `bash` 命令,只有每次调用都符合精确正向语法才会不收集证据、不调模型直接放行:区分大小写的 POSIX 程序名、支持的选项和值、只含输入的操作数数量、安全重定向和受限环境前缀。未知选项、缩写、未列出的短选项组合、输出文件操作数及仅赋值的语句继续审核。`ls -la`、`cat input | jq .name`、`grep -rn pattern src`、`find . -name "*.md"`、`ps aux` 等普通读取保留快速通道;`pwsh` 不走此通道。
|
|
32
|
+
4. 审核模型审查一次完整请求。Shell 调用会补充有界的工作区包配置和所引用本地脚本作为非可信证据;放行前重新核对路径与内容。
|
|
33
|
+
5. 审核通过返回 `allowed-once`。请求本身符合范围时,模型拒绝、不确定、故障或预算耗尽会进入限时人工确认。窗口显示完整操作、请求权限、审核意见和倒计时;明确批准后再次核对绑定及证据,只放行这一调用。拒绝、关闭窗口或超时返回 `rejected`,不交给下游审批器。
|
|
77
34
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```yaml
|
|
81
|
-
endpoint: https://your-trusted-gateway.example/v1/chat/completions
|
|
82
|
-
fastModel: your-http-review-model
|
|
83
|
-
# deepModel: your-http-deep-model
|
|
84
|
-
apiKeyEnv: DSH_SAFE_AUTO_API_KEY
|
|
85
|
-
```
|
|
35
|
+
宿主禁止、结构性拒绝、证据变化、取消或请求失效不能被覆盖。人工确认需要 UI 条目和已认证的浏览器客户端;没有界面或把人工超时设为零时,保持原来的不放行处理。Headless 会话不会获得自动回退权限。
|
|
86
36
|
|
|
87
|
-
|
|
37
|
+
审核模型看到有界动作、按时间排序的真人指令和本地证据,不继承主代理提示词、隐藏推理或工具。授权按实际含义判断:完成开发任务所需的本地安装、构建和测试可以属于已授权工作,无须用户逐条点名命令。询问进度或说“继续”不会丢掉先前授权,后续限制仍然有效。只有低/中风险、至少中等授权且副作用有界才自动放行。
|
|
88
38
|
|
|
89
|
-
|
|
39
|
+
真人文本完整保留,合计最多 12 KiB。敏感文本、非文本约束或超限会阻止自动审查,不会静默丢掉限制;请求本身有效时,仍可在限时窗口中明确批准当前完整操作,不把这段历史发给模型。证据最多八个文件、每个 6 KiB、合计 12 KiB;受保护、越界、敏感或不可读内容会被标记并排除。证据并非完整安全证明:不会穷举依赖、导入代码或整个 workspace 的脚本,仍有实质不确定性时不得自动放行。
|
|
90
40
|
|
|
91
|
-
##
|
|
41
|
+
## 配置
|
|
92
42
|
|
|
93
|
-
|
|
43
|
+
全部可选;不配置时审核模型跟随当前对话。编辑 profile 条目的 `config` 并重载:
|
|
94
44
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
`
|
|
98
|
-
|
|
99
|
-
`
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
cwd: /absolute/canonical/project
|
|
109
|
-
mode: danger-full-access
|
|
110
|
-
filePath: /absolute/other-project/notes.txt
|
|
111
|
-
- tool: bash
|
|
112
|
-
cwd: /absolute/canonical/project
|
|
113
|
-
mode: danger-full-access
|
|
114
|
-
command: git status --short
|
|
115
|
-
escalationApprovalTtlMs: 30000
|
|
116
|
-
escalationMaxTimeoutMs: 30000
|
|
117
|
-
```
|
|
45
|
+
| 键 | 默认 | 含义 |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| `enabled` | `true` | 总开关。`false` 不挂载任何守卫。 |
|
|
48
|
+
| `provider` / `model` | *(跟随对话)* | 固定审核路由,用你的 DSH 模型 ID 成对配置。 |
|
|
49
|
+
| `reasoningEffort` | *(模型默认)* | 固定路由 advertised 的思考强度。 |
|
|
50
|
+
| `reviewerPrompt` | *(无)* | 额外审核约束(≤4096 字符);只能收紧,不能放宽。 |
|
|
51
|
+
| `timeoutMs` | `30000` | 单次审查超时。 |
|
|
52
|
+
| `humanApprovalTimeoutMs` | `60000` | 独立于模型审查的人工确认窗口;`0` 关闭,最多 300000 ms,只在 profile 配置。 |
|
|
53
|
+
| `maxInputBytes` | `32768` | 提示词与输入合计的 UTF-8 字节上限;已有显式配置保持原值。 |
|
|
54
|
+
| `outputTokens` | `1024` | 审核输出上限,含模型计入的思考预算。已有 profile 显式值保持不变;不完整或无效结论仍需人工确认。 |
|
|
55
|
+
| `maxReviewsPerTask` | `20` | 每个真人任务的审查次数上限。 |
|
|
56
|
+
| `consecutiveDenials` | `3` | 连续明确拒绝达到该值后熔断。不确定和故障重置拒绝计数,但仍消耗审查预算。 |
|
|
57
|
+
| `staticReadonly` | `true` | 可证明只读的 `bash` 提权不调模型直接放行;`false` 则一律送审核模型。 |
|
|
118
58
|
|
|
119
|
-
|
|
59
|
+
未知键会直接校验失败,而不是被忽略。审核模型、思考强度和提示词也可以在插件页配置;保存的值覆盖 profile 路由,但永远不覆盖预算。
|
|
120
60
|
|
|
121
|
-
|
|
61
|
+
## 审核模型
|
|
122
62
|
|
|
123
|
-
|
|
63
|
+
**默认:跟随对话。** `provider`/`model` 留空。每次审查从请求会话已接受的请求头解析 provider/model,复用 DSH 已配置的凭据——不需要额外 API key。继承的只有模型路由,不包括历史、提示词、工具或预算。
|
|
124
64
|
|
|
125
|
-
|
|
65
|
+
**固定模型。** 成对设置 `provider` 和 `model`,对话切换模型时审核路由保持不变。路由缺失或非法时直接拒绝,不做静默回退。
|
|
126
66
|
|
|
127
|
-
##
|
|
67
|
+
## 策略
|
|
128
68
|
|
|
129
|
-
|
|
|
130
|
-
| --- | --- |
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
|
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
|
|
|
69
|
+
| 请求 | 结果 |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| 绑定的 `write`/`edit`/`bash`/`pwsh` 单次提权,审查通过 | `allowed-once`,仅此一次 |
|
|
72
|
+
| 严格静态解析可证明只读的 `bash` 提权 | `allowed-once`,不调模型、不耗预算 |
|
|
73
|
+
| 受保护的凭据/安全文件、密钥、危险程序(完整解析的命令中任何位置) | 审查前硬拒绝 |
|
|
74
|
+
| 符合请求范围的模型拒绝(含风险意见)、不确定或审查故障 | 限时人工确认;未明确批准就不放行 |
|
|
75
|
+
| 未知工具、子代理、嵌套或未绑定请求 | 不自动放行 |
|
|
76
|
+
| 人工拒绝或确认超时 | 拒绝;再次执行须重新审查 |
|
|
77
|
+
| 证据变化、请求失效、审计故障或取消 | 不放行并给出终止原因 |
|
|
137
78
|
|
|
138
|
-
|
|
79
|
+
原生 `approval: never` 仍在任何应答者之前拒绝。不要与其他自动审批应答者叠加使用。
|
|
139
80
|
|
|
140
|
-
|
|
81
|
+
## 从 0.1.x 迁移
|
|
141
82
|
|
|
142
|
-
|
|
83
|
+
- profile 键 `mode`、`workspaceRoots`、`shellCandidates`、`escalationCandidates`、`endpoint`、`apiKeyEnv`、`tokenField`、`fast*`/`deep*` 以及熔断 `sessionBudgetUnits`/`totalDenials` 已删除;仍携带这些键的 profile 会校验失败。0.1.x 的 `approvalReview: true` 加插件页启用,现在就是唯一行为。
|
|
84
|
+
- `fastProvider`/`fastModel`/`fastReasoningEffort` 更名为 `provider`/`model`/`reasoningEffort`;`fastOutputTokens` 更名为 `outputTokens`;`fastCallsPerTask` 更名为 `maxReviewsPerTask`。
|
|
85
|
+
- 0.1.x 面板保存的设置仍可加载(废弃键会被剥离),但审核路由回退为跟随对话——如果你用过固定模型,请在插件页重新选择。
|
|
143
86
|
|
|
144
|
-
##
|
|
87
|
+
## 边界与限制
|
|
145
88
|
|
|
146
|
-
|
|
89
|
+
- **不是经过审计的安全边界。** 审核方是语言模型,可能出错,尤其在对抗性上下文中。保留你原本依赖的原生沙箱、隔离和备份。
|
|
90
|
+
- **静态证明以操作者信任 PATH 和运行时为前提。** 它检查原始命令文本,不核验已安装二进制、shell 函数或环境运行时的完整性。显式程序路径、`.exe`/`.cmd` 后缀、大小写变体、可执行 pager/配置环境前缀和会持久化的赋值都不符合条件。解析器或语法缺陷仍可能造成错误证明;这不是运行时认证,也不保证绝对安全。无法证明的命令回到审核/人工确认,不新增硬拒绝。
|
|
91
|
+
- **引号不能绕过硬拒绝。** 保护路径和秘密检查先读取解码后的字面参数、环境及重定向值,包括相邻引号片段拼接;退出静态通道时仍执行这些检查,模型或人工确认不能覆盖。引号旁的未引用通配符仍使静态证明失败。Bash 的 `/dev/tcp`、`/dev/udp` 文件重定向回到审核,包括引用过的路径及编号 fd 输入重定向;普通文件输入、fd 合并和 `/dev/null` 输出保留原有规则。
|
|
92
|
+
- **Git 的子命令名不能证明只读。** 裸 `git status`、工作区 diff、`git ls-files --modified` 及其他工作区内容检查继续审核,因为刷新和内容转换可能执行配置中的 clean/process filter。支持的对象/索引读取必须在原始参数中带 `--no-pager --no-optional-locks --no-lazy-fetch -c core.fsmonitor=false`;暂存区 diff 还需 `--no-ext-diff --no-textconv --ignore-submodules=all`。历史读取另需 `--no-show-signature` 和受支持的固定格式,例如 `--oneline`。插件不会补参数或重写命令。精确的 `git version`、`git --no-pager config --get user.name` 是独立的窄范围读取;传输 helper、编辑器、filter 和混合配置修改都不能走快速通道。普通 `sort` 可能写临时文件,因此只保留其检查模式。
|
|
93
|
+
- **独立确认通道。** 当前 DSH 0.2.0-rc.2 的审批和问答链允许自动应答器。人工确认改用插件已认证的浏览器 HTTP 入口和不可预测、单次使用的请求 ID。Fetch Metadata 与宿主的来源、认证检查用于防跨站请求,并不证明物理真人点击;已认证客户端、其传输层和同进程插件仍然可信。不向模型注册审批工具。
|
|
94
|
+
- **服务端掌握时限。** 请求发布后开始计时,用单调时钟判定到期,只接受第一个有效答案。重复、迟到和跨会话回答均失败。停用、修改设置、卸载或取消会使待审批失效;请求仅存内存,重启不会恢复。兼容直接浏览器请求与已认证的 DSH 桌面传输;不符合要求的请求类型仍会被拒绝。
|
|
95
|
+
- **其他插件的原生审批保持原生流程。** 没有 Safe Auto 自有执行上下文时,Blueprint 顺序审批、Classmates 模型审批会继续交给后续处理器。已有自有上下文中的不匹配、过期、已领取请求,以及无上下文却冒用 `bash`/`pwsh`/`write`/`edit` 的请求仍然关闭放行。
|
|
96
|
+
- **覆盖范围止于原生单次提权。** 只审核从 `workspace-write` 放宽的 `write`/`edit`/`bash`/`pwsh`。其他工具、MCP、远程执行、子代理调用和常驻权限变更都在自动范围之外。
|
|
97
|
+
- **证据会复核,执行并非原子操作。** 放行前复核证据路径、版本和 SHA-256 摘要,但审批与执行之间仍可能发生文件变化。同进程插件仍然可信,卸载会移除守卫;实际隔离仍依赖外部手段及受限的凭据与出站。
|
|
98
|
+
- **不作任何保证。** 没有 fail-open 选项,没有持久审计数据库,也不承诺绝对安全或节省比例。
|
|
147
99
|
|
|
148
|
-
|
|
100
|
+
## 验证
|
|
149
101
|
|
|
150
|
-
|
|
102
|
+
在本包运行 `npm test`、`npm run build` 和 `npm pack --dry-run`,以及仓库级 `pnpm check`。测试覆盖路由、并发会话、原生流、上限、过期决定、模型服务移除、执行绑定,以及真实 Cordis/ToolRuntime/ApprovalService/LlmRuntime 契约。CI 要求安装 DSH 依赖;离线纯源码运行可跳过原生契约。如果 Windows 沙箱拦截测试运行器的子进程管道,用 `node --test --test-isolation=none test/<file>.test.js` 逐文件运行。
|
|
151
103
|
|
|
152
|
-
|
|
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,也不承诺绝对安全或固定节省比例。
|
|
104
|
+
原生契约测试使用受控适配器和夹具会话/工具,证明的是运行时集成,不是真实模型准确率、OS 隔离或已认证的 Web/Headless 验收;这些仍在 [ADR-0002 的清单](docs/ADR-0002.md)中。日志分离评估、结果和最终状态,不含原始命令、提示词或密钥;宿主留存由运维管理。
|
|
159
105
|
|
|
160
106
|
## 许可证
|
|
161
107
|
|
|
162
|
-
|
|
108
|
+
原创实现基于 [SATA License 2.1](LICENSE)。社区设计启发了本工作;未打包其代码。
|
package/docs/ADR-0001.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ADR-0001: bounded preflight, not an escalation auto-answerer
|
|
2
2
|
|
|
3
|
-
Status: historical RC1 decision, partially superseded by [ADR-0002](ADR-0002.md) in `0.1.0-rc.2`.
|
|
3
|
+
Status: historical RC1 decision, partially superseded by [ADR-0002](ADR-0002.md) in `0.1.0-rc.2`. **The preflight mechanism itself (ordinary-command review, workspace/shell candidates, shadow/smart/unattended modes) was removed in `0.2.0-rc.0`**; only the execution-bound approval review of ADR-0002 remains.
|
|
4
4
|
|
|
5
5
|
**The no-auto-escalation statements below describe RC1, not the current candidate.** RC2 adds separately enrolled, execution-bound native `allowed-once` approvals, including unattended mode, without changing standing sandbox policy. Use ADR-0002 and the current READMEs for configuration and deployment acceptance. The original decision is retained here as history.
|
|
6
6
|
|
package/docs/ADR-0002.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ADR-0002: native, execution-bound one-shot escalation
|
|
2
2
|
|
|
3
|
-
Status: implemented in `0.1.0-rc.2`; automated contracts verified; live-profile acceptance pending.
|
|
3
|
+
Status: implemented in `0.1.0-rc.2`; automated contracts verified; live-profile acceptance pending. Since `0.2.0-rc.0` this execution-bound approval review is the plugin's only mechanism; the exact-rule candidate enrollment described below was removed along with preflight.
|
|
4
4
|
|
|
5
5
|
This partially supersedes [ADR-0001](ADR-0001.md): its prohibition on returning `allowed-once` and blanket unattended escalation rejection were an RC1 limitation, not the final design. Ordinary preflight, explicit envelopes, bounded review, no global permission writes and conservative failure handling remain in force.
|
|
6
6
|
|
package/docs/ADR-0003.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ADR-0003: conversation-following and independent reviewer routes
|
|
2
2
|
|
|
3
|
-
Status: implemented in RC3. This supersedes the HTTP-only routing statements in ADR-0001/0002, not their remaining execution restrictions or deployment acceptance gates.
|
|
3
|
+
Status: implemented in RC3. This supersedes the HTTP-only routing statements in ADR-0001/0002, not their remaining execution restrictions or deployment acceptance gates. **`0.2.0-rc.0` narrowed the routing surface to a single reviewer route** (`provider`/`model`/`reasoningEffort`, defaulting to the conversation): the deep stage, the HTTP transport and the fast/deep split described below were removed.
|
|
4
4
|
|
|
5
5
|
## Requirement
|
|
6
6
|
|