feat(sandbox): cross-family file sandbox — one policy home, sandboxed fs provider, fs escalation parity

Extend SandboxMode enforcement from bash to the filesystem tools, the sandbox
RFC's deferred cross-family phase.

- dsh-sandbox-policy (new, ctx.sandboxPolicy): the single home for the
  deployment default mode + workspaceRoot and the per-session override event,
  renamed bash/sandbox-mode -> sandbox/mode and moved here with its fold/setter.
  Decouples the bash seam from dsh-session.
- dsh-fs-sandbox (new): SandboxedFileSystem extends LocalFileSystem and fences
  write/edit by the per-call mode (read-only denies, workspace-write contains to
  the workspace + temp roots via the shared writableRoots, danger passes
  through); reads pass through. Structured FS_SANDBOX_DENIED; in-lock parent
  re-canonicalization. A policy fence in trusted code, not a kernel boundary.
- dsh-sandbox: the shared escalation kit (writableRoots, the strictly-wider
  ladder, denial/hint markers, approveEscalation) both tool families use;
  approveEscalation takes a structural approver so dsh-sandbox gains no
  approval/agent dependency, and both tools stay duplication-free.
- tool-fs: write/edit advertise sandbox_permissions/justification under a
  confining ctx.fs, map FS_SANDBOX_DENIED to the shared [sandbox: ...] marker,
  and resolve the same one-approved-wider retry.
- examples/acp-agent: composes sandbox-policy + fs-sandbox, drops the gating
  that disabled the fs stack under confined modes.

RFC docs/rfc/implemented/feature/2026-07-14-cross-family-fs-sandbox.md; the old
sandbox RFC's In-process/deferred/FAQ sections updated to shipped fact.
This commit is contained in:
kingwl
2026-07-14 20:05:57 +08:00
parent c3137b5474
commit 2dc62497ce
100 changed files with 2238 additions and 385 deletions

109
pnpm-lock.yaml generated
View File

@@ -89,9 +89,6 @@ importers:
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../sandbox/sandbox
'@deepseek-ai/dsh-session':
specifier: workspace:^
version: link:../../core/session
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
@@ -113,10 +110,6 @@ importers:
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/bash/bash-sandbox:
dependencies:
schemastery:
specifier: ^3.18.0
version: 3.18.0
devDependencies:
'@deepseek-ai/dsh-bash':
specifier: workspace:^
@@ -130,6 +123,9 @@ importers:
'@deepseek-ai/dsh-sandbox-local':
specifier: workspace:^
version: link:../../sandbox/sandbox-local
'@deepseek-ai/dsh-sandbox-policy':
specifier: workspace:^
version: link:../../sandbox/sandbox-policy
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
@@ -163,6 +159,9 @@ importers:
'@deepseek-ai/dsh-sandbox-local':
specifier: workspace:^
version: link:../../sandbox/sandbox-local
'@deepseek-ai/dsh-sandbox-policy':
specifier: workspace:^
version: link:../../sandbox/sandbox-policy
'@deepseek-ai/dsh-session':
specifier: workspace:^
version: link:../../core/session
@@ -457,6 +456,9 @@ importers:
'@deepseek-ai/dsh-llm':
specifier: workspace:^
version: link:../../llm/llm
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../sandbox/sandbox
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
@@ -489,6 +491,24 @@ importers:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/fs/fs-sandbox:
devDependencies:
'@deepseek-ai/dsh-fs':
specifier: workspace:^
version: link:../fs
'@deepseek-ai/dsh-fs-local':
specifier: workspace:^
version: link:../fs-local
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../sandbox/sandbox
'@deepseek-ai/dsh-sandbox-policy':
specifier: workspace:^
version: link:../../sandbox/sandbox-policy
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/fs/tool-fs:
dependencies:
diff:
@@ -519,6 +539,12 @@ importers:
'@deepseek-ai/dsh-llm-deepseek':
specifier: workspace:^
version: link:../../llm/llm-deepseek
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../sandbox/sandbox
'@deepseek-ai/dsh-sandbox-policy':
specifier: workspace:^
version: link:../../sandbox/sandbox-policy
'@deepseek-ai/dsh-session':
specifier: workspace:^
version: link:../../core/session
@@ -528,6 +554,9 @@ importers:
'@deepseek-ai/dsh-tools':
specifier: workspace:^
version: link:../../core/tools
'@deepseek-ai/dsh-user-approval':
specifier: workspace:^
version: link:../../ui/user-approval
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
@@ -718,6 +747,22 @@ importers:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/sandbox/sandbox-policy:
dependencies:
schemastery:
specifier: ^3.18.0
version: 3.18.0
devDependencies:
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../sandbox
'@deepseek-ai/dsh-session':
specifier: workspace:^
version: link:../../core/session
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/session-persistence/session-persistence:
devDependencies:
'@deepseek-ai/dsh-session':
@@ -1280,28 +1325,6 @@ importers:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@vendor+include)(@cordisjs/plugin-loader@vendor+loader)
packages/ui/permission:
dependencies:
schemastery:
specifier: ^3.18.0
version: 3.18.0
devDependencies:
'@deepseek-ai/dsh-bash':
specifier: workspace:^
version: link:../../bash/bash
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../sandbox/sandbox
'@deepseek-ai/dsh-session':
specifier: workspace:^
version: link:../../core/session
'@deepseek-ai/dsh-user-approval':
specifier: workspace:^
version: link:../user-approval
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/ui/jsonrpc:
dependencies:
schemastery:
@@ -1346,6 +1369,31 @@ importers:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/ui/permission:
dependencies:
schemastery:
specifier: ^3.18.0
version: 3.18.0
devDependencies:
'@deepseek-ai/dsh-bash':
specifier: workspace:^
version: link:../../bash/bash
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../sandbox/sandbox
'@deepseek-ai/dsh-sandbox-policy':
specifier: workspace:^
version: link:../../sandbox/sandbox-policy
'@deepseek-ai/dsh-session':
specifier: workspace:^
version: link:../../core/session
'@deepseek-ai/dsh-user-approval':
specifier: workspace:^
version: link:../user-approval
cordis:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.6(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.4)
packages/ui/stdio-agent:
devDependencies:
'@cordisjs/plugin-include':
@@ -1762,6 +1810,9 @@ importers:
'@deepseek-ai/dsh-sandbox':
specifier: workspace:^
version: link:../../packages/sandbox/sandbox
'@deepseek-ai/dsh-sandbox-policy':
specifier: workspace:^
version: link:../../packages/sandbox/sandbox-policy
'@deepseek-ai/dsh-scope':
specifier: workspace:^
version: link:../../packages/core/scope