docs: reserve seam for complete capabilities
This commit is contained in:
@@ -70,7 +70,7 @@ function defaultProbeSeatbelt(seatbeltExec: string, timeoutMs: number): boolean
|
||||
return probe.status === 0
|
||||
}
|
||||
|
||||
/** Test seam: inject probe verdicts / a fake launcher / a platform without real runners. */
|
||||
/** Test hook: inject probe verdicts / a fake launcher / a platform without real runners. */
|
||||
export interface SandboxInternals {
|
||||
/** Replaces `process.platform` for chain selection (exercise any platform's chain from any host). */
|
||||
platform?: string
|
||||
@@ -179,7 +179,7 @@ export class LocalSandboxProvider extends SandboxProvider {
|
||||
probeTimeoutMs: z.natural().default(5_000),
|
||||
})
|
||||
|
||||
/** Test seam (mirrors the bash executors' `internals`). */
|
||||
/** Test hook (mirrors the bash executors' `internals`). */
|
||||
internals: SandboxInternals = {}
|
||||
|
||||
private readonly runnerCommand: string[] | undefined
|
||||
@@ -300,12 +300,12 @@ export class LocalSandboxProvider extends SandboxProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/** The Landlock launcher to probe and exec (test seam over the resolved one). */
|
||||
/** The Landlock launcher to probe and exec (test hook over the resolved one). */
|
||||
private landlockLauncher(): string {
|
||||
return this.internals.landlockLauncher ?? landlockLauncherPath()
|
||||
}
|
||||
|
||||
/** The `sandbox-exec` executable to probe and exec (test seam over the system one). */
|
||||
/** The `sandbox-exec` executable to probe and exec (test hook over the system one). */
|
||||
private seatbeltExec(): string {
|
||||
return this.internals.seatbeltExec ?? 'sandbox-exec'
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ describe('the platform chains', () => {
|
||||
|
||||
it('a multi-rung chain probes a seatbelt rung like any other (the walk, not the platform table, decides)', async () => {
|
||||
// The product chains reach seatbelt only as darwin's sole (unprobed)
|
||||
// candidate; the chain seam exercises the probing path it would take in
|
||||
// candidate; the probe chain exercises the path it would take in
|
||||
// a grown chain, keeping the default seatbelt probe honest.
|
||||
const exec = fakeSeatbeltExec(0)
|
||||
const probeBwrap = vi.fn(() => false)
|
||||
@@ -349,8 +349,8 @@ describe('probeTimeoutMs config', () => {
|
||||
|
||||
describe('the default seatbelt probe (sandbox-exec contract)', () => {
|
||||
// The product chains reach seatbelt only unprobed (darwin's sole
|
||||
// candidate), so the default probe's contract is pinned through the chain
|
||||
// seam: a grown chain must probe it like any other rung.
|
||||
// candidate), so the default probe's contract is pinned through the provider
|
||||
// chain: a grown chain must probe it like any other rung.
|
||||
it('selects the rung when the executable applies the read-only profile and exits 0', async () => {
|
||||
const exec = fakeSeatbeltExec(0)
|
||||
const { sandbox } = await setup({}, { chain: ['bwrap', 'seatbelt'], probeBwrap: () => false, seatbeltExec: exec })
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/sandbox/sandbox/README.md
|
||||
README.md: 8c1c747f6c7178f9c8c1a9827675ffa98f29aa6d
|
||||
README.zh.md: abc5d387384e3a69e35496d6ce4bc9830185c55d
|
||||
README.md: 50b7eff1a287ee0bc2432a7bf409586ff879920e
|
||||
README.zh.md: ff68a49f5487b5da9700698c5376199727f1cd5f
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
Abstract process-sandbox seam. Owns the `ctx.sandbox` service contract ([`SandboxProvider`](src/index.ts)) and the confinement vocabulary the harness shares: `SandboxMode` (`read-only` / `workspace-write` / `danger-full-access`, file effects only), `SandboxEnforcement` (`full` / `partial`, per kernel ABI), `SandboxExecutionPolicy` (the complete per-call mode + workspace root), `SandboxPolicy` (its confined subset), and the fail-closed `SANDBOX_UNAVAILABLE` error. Interface package of the [capability-seam split](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md): depends only on cordis (+ the harness error base), never on a backend.
|
||||
Process-sandbox Service Definition. Owns the `ctx.sandbox` service contract ([`SandboxProvider`](src/index.ts)) and the confinement vocabulary the harness shares: `SandboxMode` (`read-only` / `workspace-write` / `danger-full-access`, file effects only), `SandboxEnforcement` (`full` / `partial`, per kernel ABI), `SandboxExecutionPolicy` (the complete per-call mode + workspace root), `SandboxPolicy` (its confined subset), and the fail-closed `SANDBOX_UNAVAILABLE` error. As the Service Definition role of the [capability-seam split](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md), it depends only on cordis (+ the harness error base), never on a backend.
|
||||
|
||||
The contract in one line: `ctx.sandbox.confine(argv, policy)` returns the argv to spawn INSTEAD of your own — wrapped so the process (and everything it spawns) runs confined — plus the selected backend's enforcement completeness, denial dialect (`denialSignatures`), and structured runner-failure evidence (`runnerFailureRules`); when no backend is usable it throws rather than passing the argv through unconfined. The [core type catalog](../../../docs/subsystems/sandbox.md#wrapped-argv-and-classification-dialects) owns the exact classifier shape.
|
||||
|
||||
Policy rides the call, not the provider: two consumers may confine under different policies at the same instant (bash under `read-only` while a confined child agent keeps its state directory writable), and an approved escalated retry is just a new call with a wider policy.
|
||||
|
||||
**Same-world confinement only.** A backend shares the host's filesystem and kernel (`bwrap`, Landlock, Seatbelt); `workspaceRoot` names the filesystem-canonical real host directory. Workspace identity is resolved before lexical normalization, so a valid cwd containing `symlink/..` grants the directory where `chdir` actually lands rather than an unrelated lexical parent. Containers, microVMs, and remote executors are NOT backends of this seam — they replace whole capability implementations (`ctx.bash`, `ctx.fs`) as environment-coherent groups. The boundary and its rationale: [the sandbox Agent Note](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md).
|
||||
**Same-world confinement only.** A backend shares the host's filesystem and kernel (`bwrap`, Landlock, Seatbelt); `workspaceRoot` names the filesystem-canonical real host directory. Workspace identity is resolved before lexical normalization, so a valid cwd containing `symlink/..` grants the directory where `chdir` actually lands rather than an unrelated lexical parent. Containers, microVMs, and remote executors are NOT backends of this seam — they replace the Service providers for whole capability seams (`ctx.bash`, `ctx.fs`) as environment-coherent groups. The boundary and its rationale: [the sandbox Agent Note](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md).
|
||||
|
||||
Implementations: [`@deepseek-ai/dsh-sandbox-local`](../sandbox-local/) (Linux: `bwrap`, else the per-platform Landlock launcher; macOS: `sandbox-exec`/Seatbelt). Consumers: [`@deepseek-ai/dsh-bash-sandbox`](../../bash/bash-sandbox/) (wraps `['bash', '-c', command]`).
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
抽象进程沙箱 seam。负责定义 `ctx.sandbox` 服务约定([`SandboxProvider`](src/index.ts))与 harness 共享的限制词汇:`SandboxMode`(`read-only`/`workspace-write`/`danger-full-access`,仅限文件操作)、`SandboxEnforcement`(`full`/`partial`,针对每种内核 ABI)、`SandboxExecutionPolicy`(每次调用的完整模式及工作区根目录)、`SandboxPolicy`(其中受限制的子集),以及故障时拒绝放行的 `SANDBOX_UNAVAILABLE` 错误。它是[能力 seam 拆分](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)的接口包:只依赖 cordis(及 harness 错误基类),绝不依赖后端。
|
||||
进程沙箱 Service Definition。负责定义 `ctx.sandbox` 服务约定([`SandboxProvider`](src/index.ts))与 harness 共享的限制词汇:`SandboxMode`(`read-only`/`workspace-write`/`danger-full-access`,仅限文件操作)、`SandboxEnforcement`(`full`/`partial`,针对每种内核 ABI)、`SandboxExecutionPolicy`(每次调用的完整模式及工作区根目录)、`SandboxPolicy`(其中受限制的子集),以及故障时拒绝放行的 `SANDBOX_UNAVAILABLE` 错误。作为[能力 seam 拆分](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)中的 Service Definition 角色,它只依赖 cordis(及 harness 错误基类),绝不依赖后端。
|
||||
|
||||
用一句话概括约定:`ctx.sandbox.confine(argv, policy)` 返回用于 spawn、应当取代调用方原始 argv 的 argv。返回值经过包装,使进程及其派生的所有进程都在限制下运行;还会附带所选后端达到的强制执行完整度、拒绝方言(`denialSignatures`)和结构化 runner 失败证据(`runnerFailureRules`)。没有可用后端时,它会抛出异常,绝不会原样传递 argv 使其不受限制地运行。[核心类型目录](../../../docs/subsystems/sandbox.md#wrapped-argv-and-classification-dialects)负责定义分类器的精确结构。
|
||||
|
||||
策略随调用传递,而不属于提供方:两个消费方可以同时按不同策略施加限制(bash 使用 `read-only`,而受限制的子 agent(智能体)保持其状态目录可写);获批的升权重试只是使用更宽策略发起的新调用。
|
||||
|
||||
**只支持与宿主共享文件系统和内核的限制。** 后端与宿主共享文件系统和内核(`bwrap`、Landlock、Seatbelt);`workspaceRoot` 指向文件系统规范化后的真实主机目录。系统先解析工作区所指的目录,再做词法规范化,因此包含 `symlink/..` 的有效 cwd 会授权 `chdir` 实际到达的目录,而非无关的词法父目录。容器、microVM 与远程执行器都不是该 seam 的后端:它们会以环境一致的分组替换整个能力实现(`ctx.bash`、`ctx.fs`)。边界及其设计理由见[沙箱 Agent Note](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md)。
|
||||
**只支持与宿主共享文件系统和内核的限制。** 后端与宿主共享文件系统和内核(`bwrap`、Landlock、Seatbelt);`workspaceRoot` 指向文件系统规范化后的真实主机目录。系统先解析工作区所指的目录,再做词法规范化,因此包含 `symlink/..` 的有效 cwd 会授权 `chdir` 实际到达的目录,而非无关的词法父目录。容器、microVM 与远程执行器都不是该 seam 的后端:它们会以环境一致的分组替换整个能力 seam 的 Service provider(`ctx.bash`、`ctx.fs`)。边界及其设计理由见[沙箱 Agent Note](../../../.agents/notes/implemented/feature/2026-07-06-sandbox.md)。
|
||||
|
||||
实现:[`@deepseek-ai/dsh-sandbox-local`](../sandbox-local/)(Linux:`bwrap`,否则使用相应平台的 Landlock launcher;macOS:`sandbox-exec`/Seatbelt)。消费方:[`@deepseek-ai/dsh-bash-sandbox`](../../bash/bash-sandbox/)(包装 `['bash', '-c', command]`)。
|
||||
|
||||
@@ -39,5 +39,5 @@ sandbox mode "<mode>" is requested but no sandbox backend is usable on this host
|
||||
- **文件操作是完整的策略词汇**:该 seam 不表达网络、进程、系统调用、设备或凭据限制。
|
||||
- **只支持与宿主共享文件系统和内核的限制**:容器、microVM 与远程执行需要替换能力实现,而不是在此处增加提供方。
|
||||
- **拒绝报告是一种 stderr 方言**:该 seam 返回后端签名,而非类型化运行时拒绝通道,因此需要分类的消费方必须从子进程输出推断。
|
||||
- **Runner 诊断使用带内通道**:退出状态与 stderr 证据无法证明匹配行由哪个进程写入,因此受限子进程若故意模仿 runner,就可能造成可用性或诊断误归因。这无法绕过限制;带外 runner 状态通道暂缓实现。
|
||||
- **Runner 诊断使用带内通道**:退出状态与 stderr 证据无法证明匹配行由哪个进程写入,因此受限子进程若故意模仿 runner,就可能造成可用性或诊断误归因。这无法绕过约束;带外 runner 状态通道暂缓实现。
|
||||
- **每个上下文只有一个提供方**:同时组合不同沙箱机制需要提供方级阶梯或独立 Cordis 上下文;调用方逐调用选择策略,而非后端标识。
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Same-world process-confinement seam: wrap exact subprocess argv under a
|
||||
* Service Definition for the same-world process-confinement capability seam: wrap exact subprocess argv under a
|
||||
* host-path file policy. Containers, microVMs, and remote execution replace the
|
||||
* surrounding capability seam instead; this service shares the host kernel and filesystem.
|
||||
* @module @deepseek-ai/dsh-sandbox
|
||||
|
||||
Reference in New Issue
Block a user