botmux 3.5.0 → 3.5.2
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/dist/adapters/backend/sandbox.d.ts +99 -279
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +424 -826
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +4 -0
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/fs-policy.d.ts +244 -0
- package/dist/adapters/cli/fs-policy.d.ts.map +1 -0
- package/dist/adapters/cli/fs-policy.js +539 -0
- package/dist/adapters/cli/fs-policy.js.map +1 -0
- package/dist/adapters/cli/read-isolation.d.ts +14 -200
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +18 -477
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/bot-registry.d.ts +26 -23
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +16 -0
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +25 -18
- package/dist/cli.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +16 -58
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +26 -27
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +1 -1
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/plugins/mcp/gateway-installer.d.ts.map +1 -1
- package/dist/core/plugins/mcp/gateway-installer.js +14 -2
- package/dist/core/plugins/mcp/gateway-installer.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +90 -60
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/worker-pool.d.ts +24 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +50 -6
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +6 -0
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +5 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +7 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +16 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +225 -6
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +7 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +38 -22
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +1 -44
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-AUKV7P4L.js +10 -0
- package/dist/dashboard-web/chunks/{chunk-QCPPKCX3.js → chunk-KPQAUX7V.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-WXPMNEYV.js → chunk-NRL6CVAS.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-EJDYUINZ.js → chunk-R7IAKAYX.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-H7P5UV4W.js → chunk-X2L65IOM.js} +6 -6
- package/dist/dashboard-web/chunks/{connectors-page-IR54AOAI.js → connectors-page-HDQFEXZI.js} +1 -1
- package/dist/dashboard-web/chunks/{groups-page-3P4TLUMF.js → groups-page-6DKXBYOM.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-TDCZV56A.js → insights-page-NWARTJ6J.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-QWCWL3SX.js → monitor-room-AGX3XRJX.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-IOWFSNVC.js → monitoring-page-GGGIWN4C.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-5AUPEHZP.js → office-page-6SIVKSK3.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-QJMI6NLW.js → overview-page-FVR3NKAF.js} +1 -1
- package/dist/dashboard-web/chunks/{roles-page-WJVB52ET.js → roles-page-WE2YB7KN.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-RVRWHP4V.js → schedules-page-TB3I24XN.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-KOOOASIL.js +2 -0
- package/dist/dashboard-web/chunks/{settings-page-TNZEPC7V.js → settings-page-IEBR7TGN.js} +1 -1
- package/dist/dashboard-web/chunks/{skills-page-7YT5TIX5.js → skills-page-3QAT2IWD.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-NJZKTU7A.js → team-federation-page-K4VVAVAK.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-NQ73UA2Q.js → v3-page-V6IOJR2B.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-DSM3MDMN.js → whiteboards-page-V6CGKRNX.js} +1 -1
- package/dist/dashboard-web/style.css +20 -3
- package/dist/dashboard.js +86 -1
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +4 -1
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -19
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1 -19
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +0 -13
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +0 -34
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +1 -30
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +36 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +80 -0
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +28 -3
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/services/sandbox-migration.d.ts +14 -0
- package/dist/services/sandbox-migration.d.ts.map +1 -0
- package/dist/services/sandbox-migration.js +85 -0
- package/dist/services/sandbox-migration.js.map +1 -0
- package/dist/services/sandbox-store.d.ts +28 -0
- package/dist/services/sandbox-store.d.ts.map +1 -1
- package/dist/services/sandbox-store.js +82 -0
- package/dist/services/sandbox-store.js.map +1 -1
- package/dist/types.d.ts +13 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/child-env.d.ts +2 -2
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +14 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/worker.js +417 -498
- package/dist/worker.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +56 -0
- package/dist/workflows/events/payloads.d.ts.map +1 -1
- package/dist/workflows/events/payloads.js +9 -0
- package/dist/workflows/events/payloads.js.map +1 -1
- package/dist/workflows/events/schema.d.ts +86 -0
- package/dist/workflows/events/schema.d.ts.map +1 -1
- package/dist/workflows/shared/sandbox-policy.d.ts +10 -1
- package/dist/workflows/shared/sandbox-policy.d.ts.map +1 -1
- package/dist/workflows/shared/sandbox-policy.js +12 -0
- package/dist/workflows/shared/sandbox-policy.js.map +1 -1
- package/dist/workflows/v3/bot-resolve.d.ts.map +1 -1
- package/dist/workflows/v3/bot-resolve.js +36 -0
- package/dist/workflows/v3/bot-resolve.js.map +1 -1
- package/dist/workflows/v3/contract.d.ts +8 -0
- package/dist/workflows/v3/contract.d.ts.map +1 -1
- package/dist/workflows/v3/contract.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-O376WSER.js +0 -5
- package/dist/dashboard-web/chunks/sessions-page-KWLGBX6G.js +0 -3
- package/dist/services/sandbox-land.d.ts +0 -45
- package/dist/services/sandbox-land.d.ts.map +0 -1
- package/dist/services/sandbox-land.js +0 -394
- package/dist/services/sandbox-land.js.map +0 -1
|
@@ -1,105 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* the same fs as `upper`. Returns true iff `mount` exited 0.
|
|
5
|
-
*/
|
|
6
|
-
export declare function mountOverlay(opts: {
|
|
7
|
-
lower: string;
|
|
8
|
-
upper: string;
|
|
9
|
-
work: string;
|
|
10
|
-
merged: string;
|
|
11
|
-
}): boolean;
|
|
12
|
-
/** True iff `path` is currently a mountpoint (host-side overlay still mounted).
|
|
13
|
-
* Read mountinfo instead of stat'ing the path: a broken recursive FUSE mount can
|
|
14
|
-
* leave any path-based `mountpoint` probe blocked in uninterruptible I/O. */
|
|
15
|
-
export declare function isMounted(path: string): boolean;
|
|
16
|
-
/** Unmount an overlay merged dir. Best-effort: lazy detach if a normal unmount
|
|
17
|
-
* fails because a still-draining bwrap child holds the FUSE mount busy. */
|
|
18
|
-
export declare function unmountOverlay(merged: string): void;
|
|
19
|
-
export interface SandboxPlan {
|
|
20
|
-
/** In-sandbox path the project is bound at — equals the original workingDir the
|
|
21
|
-
* CLI was given, so the CLI's existing path args resolve. Also the child's chdir. */
|
|
22
|
-
projectMount: string;
|
|
23
|
-
/** Host path of the merged project overlay (reads=real lower, writes=upper). */
|
|
24
|
-
projectMerged: string;
|
|
25
|
-
/** In-sandbox path the home overlay is bound at — equals the real home path so
|
|
26
|
-
* every CLI's hardcoded `~/.<cli>` resolves there. */
|
|
27
|
-
home: string;
|
|
28
|
-
/** Host path of the merged home overlay. */
|
|
29
|
-
homeMerged: string;
|
|
30
|
-
/** Daemon-mediated `botmux send` outbox — bound LAST so it wins over any mask. */
|
|
31
|
-
outbox: string;
|
|
32
|
-
/** Trusted worker-side MCP socket directory. The sandbox sees only this
|
|
33
|
-
* session's socket at a fixed path under its private /run tmpfs. */
|
|
34
|
-
mcpGatewaySocket?: {
|
|
35
|
-
hostDir: string;
|
|
36
|
-
sandboxDir: string;
|
|
37
|
-
};
|
|
38
|
-
/** Per-bot privacy masks: directories blanked with an empty tmpfs. */
|
|
39
|
-
hideDirs: string[];
|
|
40
|
-
/** Per-bot privacy masks: files blanked with a read-only empty placeholder. */
|
|
41
|
-
hideFiles: {
|
|
42
|
-
path: string;
|
|
43
|
-
empty: string;
|
|
44
|
-
}[];
|
|
45
|
-
/** CLI auth/login paths kept REAL + writable (bound rw over the isolated home so
|
|
46
|
-
* the CLI's token refresh / login persists — unlike project edits which are
|
|
47
|
-
* isolated). Resolved + existence-filtered by prepareSandbox. */
|
|
48
|
-
authReal?: string[];
|
|
49
|
-
/** Runtime-generated roots that the CLI must see but must not mutate. Trusted
|
|
50
|
-
* (daemon-produced, e.g. skill plugin dirs) — bound AFTER the privacy masks so
|
|
51
|
-
* a broad hideDir can't break skill delivery. */
|
|
52
|
-
readonlyRoots?: string[];
|
|
53
|
-
/** Sensitive files inside readonlyRoots that must stay hidden. Applied after
|
|
54
|
-
* the readonly bind so that re-exposing a plugin runtime cannot reveal its
|
|
55
|
-
* install-time MCP descriptor. */
|
|
56
|
-
postReadonlyHideDirs?: string[];
|
|
57
|
-
postReadonlyHideFiles?: {
|
|
58
|
-
path: string;
|
|
59
|
-
empty: string;
|
|
60
|
-
}[];
|
|
61
|
-
/** Daemon-generated private roots re-bound writable AFTER credential masks.
|
|
62
|
-
* Used for the current bot's isolated CLI home only; never accepts user
|
|
63
|
-
* config. */
|
|
64
|
-
trustedWritableRoots?: string[];
|
|
65
|
-
/** Crown-jewel masks emitted after trusted writable carve-outs. */
|
|
66
|
-
finalHideDirs?: string[];
|
|
67
|
-
finalHideFiles?: {
|
|
68
|
-
path: string;
|
|
69
|
-
empty: string;
|
|
70
|
-
}[];
|
|
71
|
-
/** User-configured read-only inputs (per-bot sandboxReadonlyPaths). Bound BEFORE
|
|
72
|
-
* the privacy masks so hidePaths always win over them — an entry overlapping a
|
|
73
|
-
* masked path must never re-expose the real content. */
|
|
74
|
-
userReadonlyRoots?: string[];
|
|
75
|
-
/** Keep network egress. File-only scope ⇒ default true (npm/pip/git work). */
|
|
76
|
-
net?: boolean;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Build the bwrap argv prefix. Final spawn becomes:
|
|
80
|
-
* bwrap <these args> -- <cliBin> <cliArgs...>
|
|
81
|
-
*
|
|
82
|
-
* Mount order matters (later mounts win): the whole real fs read-only first, then
|
|
83
|
-
* the home + project merged overlays bind over it (so writes there are isolated),
|
|
84
|
-
* then user readonly inputs, then privacy masks blank specific paths (masks bind
|
|
85
|
-
* after user readonly roots so an overlapping readonly entry can never re-expose
|
|
86
|
-
* masked content), then trusted runtime roots, then the outbox binds LAST so it
|
|
87
|
-
* stays writable even if a mask covers a parent dir.
|
|
88
|
-
*/
|
|
89
|
-
export declare function buildSandboxArgs(plan: SandboxPlan): string[];
|
|
90
|
-
/**
|
|
91
|
-
* Build the lightweight bwrap wrapper used when full overlay sandboxing is off.
|
|
92
|
-
* The host filesystem, including BOTMUX_HOME itself, remains live/read-write.
|
|
93
|
-
* Device credentials and their arbitrary future sidecars live below a dedicated
|
|
94
|
-
* authority directory which is replaced wholesale with a private tmpfs. The
|
|
95
|
-
* few legacy/root authority files are masked individually with read-only
|
|
96
|
-
* /dev/null mounts. This preserves root-level atomic writes, newly created
|
|
97
|
-
* plugin/skill/run directories, symlinks, and live config replacement.
|
|
98
|
-
*/
|
|
1
|
+
import { type FsPolicy } from '../cli/fs-policy.js';
|
|
2
|
+
/** Lightweight bwrap used when only the one-way device credential boundary is
|
|
3
|
+
* required and the full file sandbox is off. */
|
|
99
4
|
export declare function buildCredentialOnlySandboxArgs(input: {
|
|
100
5
|
hideDirectories: string[];
|
|
101
6
|
hideFiles: string[];
|
|
102
|
-
/** Worker-owned marker/profile roots that must remain immutable to the CLI. */
|
|
103
7
|
readonlyPaths?: string[];
|
|
104
8
|
workingDir: string;
|
|
105
9
|
cliBin: string;
|
|
@@ -118,13 +22,7 @@ export type HostCredentialIsolationMechanismProbe = {
|
|
|
118
22
|
mechanism: null;
|
|
119
23
|
reason: string;
|
|
120
24
|
};
|
|
121
|
-
/** Host-side pre-enrollment probe. It accepts no child/session environment or
|
|
122
|
-
* adapter input, performs no writes/installation, and therefore can safely run
|
|
123
|
-
* before the fixed marker is created. Enrollment uses this to refuse enabling
|
|
124
|
-
* device credentials on a host where future workers could not confine them. */
|
|
125
25
|
export declare function probeHostCredentialIsolationMechanism(): HostCredentialIsolationMechanismProbe;
|
|
126
|
-
/** Probe/install the one lightweight Linux dependency. Kept separate so the
|
|
127
|
-
* worker can make the mandatory gate decision before any local CLI is spawned. */
|
|
128
26
|
export declare function credentialOnlySandboxAvailable(): boolean;
|
|
129
27
|
export declare function prepareCredentialOnlySandbox(input: {
|
|
130
28
|
hideDirectories: string[];
|
|
@@ -134,71 +32,73 @@ export declare function prepareCredentialOnlySandbox(input: {
|
|
|
134
32
|
cliBin: string;
|
|
135
33
|
cliArgs: string[];
|
|
136
34
|
}): CredentialOnlySandboxSpawn | null;
|
|
137
|
-
/**
|
|
138
|
-
* After `buildSandboxArgs` masks `/run` with a fresh tmpfs, any executable whose
|
|
139
|
-
* resolved path lives UNDER `/run` (the common case: fnm/nvm/volta expose the
|
|
140
|
-
* active toolchain's bin dir as a per-session symlink farm under
|
|
141
|
-
* `/run/user/<uid>/fnm_multishells/<hash>/bin`, and `which codex` / the daemon's
|
|
142
|
-
* own `process.execPath` for node land there) would VANISH inside the sandbox →
|
|
143
|
-
* bwrap `execvp` fails → the CLI exits instantly → Botmux's crash-loop guard
|
|
144
|
-
* trips after 4 retries. This re-exposes each such bin dir read-only at its real
|
|
145
|
-
* path so the binary (and the node interpreter its `#!/usr/bin/env node` shebang
|
|
146
|
-
* needs, which lives in the same fnm bin dir) survive the tmpfs.
|
|
147
|
-
*
|
|
148
|
-
* The caller feeds in EVERY path that will be exec'd inside the sandbox, not just
|
|
149
|
-
* the direct bwrap target: the cliBin, the daemon's own node (process.execPath),
|
|
150
|
-
* AND each adapter-declared SECOND-STAGE executable (CliAdapter.sandboxExtraExecPaths)
|
|
151
|
-
* — e.g. the codex-app adapter's resolved `codex` (its resolvedBin is the daemon
|
|
152
|
-
* node running the runner, which spawns the real codex later for the app-server,
|
|
153
|
-
* so without this the codex path would still be masked). We deliberately do NOT
|
|
154
|
-
* scan raw cliArgs: a path arg like `--cwd /run/user/<uid>/proj` would re-bind its
|
|
155
|
-
* PARENT `/run/user/<uid>`, shadowing the project overlay mounted there and
|
|
156
|
-
* exposing sibling files / IPC sockets — re-exposing must be limited to declared
|
|
157
|
-
* executables.
|
|
158
|
-
*
|
|
159
|
-
* Pure: returns the `--ro-bind-try <dir> <dir>` args (deduped, `/run/`-subpaths
|
|
160
|
-
* only — NEVER `/run` itself, which would clobber the tmpfs and the relay shim
|
|
161
|
-
* mounted at /run/sbxbin). `-try` so a stale/racing path can't fail the spawn.
|
|
162
|
-
* Returns [] for binaries already outside /run (system node, npm/pnpm globals) —
|
|
163
|
-
* non-fnm users are unaffected.
|
|
164
|
-
*/
|
|
35
|
+
/** Re-expose trusted executable directories hidden below the fresh /run tmpfs. */
|
|
165
36
|
export declare function reexposeRunBinArgs(binPaths: (string | undefined)[]): string[];
|
|
166
|
-
/**
|
|
167
|
-
*
|
|
168
|
-
|
|
169
|
-
* when the symlink's parent is masked inside the sandbox. */
|
|
170
|
-
export declare function resolveSandboxMountPath(p: string): string;
|
|
171
|
-
export interface SandboxOverlayPaths {
|
|
172
|
-
sessionRoot: string;
|
|
173
|
-
runtimeRoot: string;
|
|
174
|
-
projectMerged: string;
|
|
175
|
-
homeMerged: string;
|
|
176
|
-
legacyProjectMerged: string;
|
|
177
|
-
legacyHomeMerged: string;
|
|
178
|
-
}
|
|
179
|
-
/** Host-side overlay mountpoints must not live below HOME, because HOME is the
|
|
180
|
-
* lower layer of the home overlay. The old layout did exactly that and allowed
|
|
181
|
-
* fuse-overlayfs to recursively expose its own mountpoint. Keep the legacy
|
|
182
|
-
* paths here only so upgrades can tear down pre-fix sessions safely. */
|
|
183
|
-
export declare function sandboxOverlayPaths(dataDir: string, sessionId: string): SandboxOverlayPaths;
|
|
37
|
+
/** Is the file sandbox globally forced for this daemon? The real per-bot
|
|
38
|
+
* BotConfig.sandbox flag is decided by the caller. */
|
|
39
|
+
export declare function sandboxEnabled(): boolean;
|
|
184
40
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* path so a symlink (`/tmp/ref -> /repo`) or a non-normalized string (`/repo/`,
|
|
191
|
-
* `/repo/../repo`) can't alias past the guard. Entries strictly UNDER an overlay
|
|
192
|
-
* root stay allowed: that's the documented "reference material, read-only,
|
|
193
|
-
* excluded from /land" use case. Returns the tilde-expanded original paths (the
|
|
194
|
-
* docs promise "mounted at the same path"); bwrap resolves any symlink source.
|
|
195
|
-
* Exported for tests.
|
|
41
|
+
* Whether a LOCAL sandbox engine applies to this backend at all. riff has NO
|
|
42
|
+
* local CLI process to wrap (execution happens in riff's own remote sandbox);
|
|
43
|
+
* without this bypass the worker's fail-safe "backend not sandboxable" hard
|
|
44
|
+
* error would brick every sandbox-enabled bot the moment it switches to riff.
|
|
45
|
+
* Platform is no longer a factor — fs-policy sandboxes darwin AND linux.
|
|
196
46
|
*/
|
|
197
|
-
export declare function
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
47
|
+
export declare function localSandboxApplies(backendType: string): boolean;
|
|
48
|
+
interface MaskMountEntry {
|
|
49
|
+
path: string;
|
|
50
|
+
kind: 'dir' | 'file';
|
|
51
|
+
/** Host device + inode captured right after WE created the mountpoint. The
|
|
52
|
+
* delete-time identity check: only remove if lstat still reports these. */
|
|
53
|
+
dev: number;
|
|
54
|
+
ino: number;
|
|
55
|
+
}
|
|
56
|
+
/** Atomically persist the created-mountpoint manifest (0600). Returns false on
|
|
57
|
+
* failure so the caller can FAIL CLOSED (roll back + abort spawn) rather than
|
|
58
|
+
* start a session whose pre-created host mountpoints could later leak. */
|
|
59
|
+
declare function writeMaskManifest(sessionRoot: string, created: MaskMountEntry[]): boolean;
|
|
60
|
+
/** Reclaim a list of created-mountpoint entries (the IN-MEMORY truth). Runs on
|
|
61
|
+
* ALL teardown paths — normal close reads the entries back from the manifest,
|
|
62
|
+
* spawn-failure rollback passes the in-memory accumulator directly (the
|
|
63
|
+
* manifest may never have been written). Fail-safe & NON-RECURSIVE:
|
|
64
|
+
* - rejects any entry whose path is non-absolute, contains `..`, or is a
|
|
65
|
+
* symlink on disk (a swapped entry can't trick us into deleting elsewhere);
|
|
66
|
+
* - IDENTITY-BINDS: removes only when the on-disk (dev, ino) still matches what
|
|
67
|
+
* WE recorded at creation — so a tampered manifest pointing at a pre-existing
|
|
68
|
+
* victim, or a path whose empty object was replaced after we created ours,
|
|
69
|
+
* is left untouched;
|
|
70
|
+
* - a dir is removed with `rmdir` only (throws ENOTEMPTY if the host/a
|
|
71
|
+
* concurrent process wrote into it → content preserved, never rm -rf);
|
|
72
|
+
* - a file is `unlink`ed only when it is a regular, zero-byte file.
|
|
73
|
+
* Entries are processed in order; the caller records them deepest-first so a
|
|
74
|
+
* child is removed before its now-empty parent. */
|
|
75
|
+
declare function reclaimMaskEntries(entries: unknown): void;
|
|
76
|
+
/** Reclaim the empty deny-mask mountpoints recorded in the persisted manifest,
|
|
77
|
+
* then (implicitly) the manifest goes with the sessionRoot. Used by the NORMAL
|
|
78
|
+
* teardown paths (close, reattach-close, stale sweep) — where the manifest was
|
|
79
|
+
* written successfully. Spawn-failure rollback does NOT use this (it can't
|
|
80
|
+
* trust a manifest that may never have been written); it passes the in-memory
|
|
81
|
+
* accumulator to reclaimMaskEntries directly. MUST run BEFORE removing
|
|
82
|
+
* sessionRoot (which holds the manifest). */
|
|
83
|
+
declare function reclaimMaskMounts(sessionRoot: string): void;
|
|
84
|
+
/** Create a mask mountpoint on the host (all missing ancestors too), pushing
|
|
85
|
+
* EACH level we actually create — deepest first — into the caller-owned
|
|
86
|
+
* `sink` accumulator IMMEDIATELY (before attempting the next level), each with
|
|
87
|
+
* its (dev, ino). This is what lets rollback reclaim partially-created chains:
|
|
88
|
+
* if a deeper level throws (e.g. ENAMETOOLONG on the leaf), every ancestor we
|
|
89
|
+
* already made is already in `sink` for the caller's rollback. `kind` applies
|
|
90
|
+
* to the leaf; ancestors are always dirs. No-op when the leaf already exists
|
|
91
|
+
* (a pre-existing host path is never our cleanup target). Throws on failure so
|
|
92
|
+
* the caller can fail closed — with `sink` holding whatever succeeded. */
|
|
93
|
+
declare function createMaskMount(leaf: string, kind: 'dir' | 'file', sink: MaskMountEntry[]): void;
|
|
94
|
+
export declare const __testOnly_maskMounts: {
|
|
95
|
+
MASK_MANIFEST_NAME: string;
|
|
96
|
+
createMaskMount: typeof createMaskMount;
|
|
97
|
+
writeMaskManifest: typeof writeMaskManifest;
|
|
98
|
+
reclaimMaskMounts: typeof reclaimMaskMounts;
|
|
99
|
+
reclaimMaskEntries: typeof reclaimMaskEntries;
|
|
100
|
+
};
|
|
101
|
+
export interface DirectSandboxSpawn {
|
|
202
102
|
/** Replace the CLI binary with this (always 'bwrap'). */
|
|
203
103
|
bin: string;
|
|
204
104
|
/** bwrap args + '--' + original (bin, ...args). */
|
|
@@ -207,140 +107,59 @@ export interface SandboxSpawn {
|
|
|
207
107
|
env: Record<string, string>;
|
|
208
108
|
/** Outbox dir the daemon watcher must service. */
|
|
209
109
|
outbox: string;
|
|
210
|
-
/**
|
|
211
|
-
workDir: string;
|
|
212
|
-
/** HOME overlay UPPER dir (/var/tmp/botmux-sbx/<sid>/home-upper). When the
|
|
213
|
-
* project mount equals HOME, the project overlay is the single winning
|
|
214
|
-
* layer and this directory is intentionally unused. */
|
|
215
|
-
homeUpper: string;
|
|
216
|
-
/** Unmount the overlays + remove the per-session sandbox tree. */
|
|
110
|
+
/** Remove the per-session sandbox tree (plain rm — no mounts exist). */
|
|
217
111
|
cleanup: () => void;
|
|
218
112
|
}
|
|
219
|
-
/** The host path where a sandboxed session actually writes a Claude-family
|
|
220
|
-
* data dir. Usually this is the HOME overlay upper. If the project mount is
|
|
221
|
-
* HOME (or otherwise contains the data dir), the later project overlay is the
|
|
222
|
-
* winning mount and the data lands in proj-upper instead.
|
|
223
|
-
*
|
|
224
|
-
* The home overlay is bound (and $HOME set) at the CANONICAL home, so copy-ups
|
|
225
|
-
* land relative to that root. Compute the in-home relative path robustly whether
|
|
226
|
-
* realDataDir arrives in symlink or canonical form: adapters build it from the
|
|
227
|
-
* raw homedir() (so the raw base cancels cleanly in the common case), but a
|
|
228
|
-
* canonicalized dataDir under a symlink home would otherwise escape via `..`.
|
|
229
|
-
* Data roots outside both HOME and the project are returned unchanged because
|
|
230
|
-
* neither overlay owns them (Claude read isolation normally relocates those
|
|
231
|
-
* roots into BOT_HOME before spawn). */
|
|
232
|
-
export declare function sandboxedClaudeDataDir(sessionId: string, realDataDir: string, context?: {
|
|
233
|
-
sourceWorkingDir?: string;
|
|
234
|
-
dataDir?: string;
|
|
235
|
-
}): string;
|
|
236
|
-
/** Credential roots that must never be readable inside the file sandbox.
|
|
237
|
-
* Relay mode is the only credentialed send path; otherwise an agent could
|
|
238
|
-
* unset BOTMUX_SEND_RELAY and execute an absolute botmux binary against the
|
|
239
|
-
* real bots.json/send-cred files exposed by the HOME overlay lowerdir. */
|
|
240
|
-
export declare function sandboxCredentialHidePaths(home: string, botmuxHome?: string): string[];
|
|
241
|
-
/**
|
|
242
|
-
* Whether the LOCAL bwrap file sandbox applies to this spawn at all.
|
|
243
|
-
* - macOS enforces `sandbox: true` via the Seatbelt write-sandbox instead.
|
|
244
|
-
* - riff has NO local CLI process to wrap (execution happens in riff's own
|
|
245
|
-
* remote sandbox); without this bypass the worker's fail-safe "backend not
|
|
246
|
-
* sandboxable" hard error would brick every sandbox-enabled bot the moment
|
|
247
|
-
* it switches to riff (the dashboard agent switch does not clear `sandbox`).
|
|
248
|
-
*/
|
|
249
|
-
export declare function localSandboxApplies(platform: NodeJS.Platform, backendType: string): boolean;
|
|
250
113
|
/**
|
|
251
|
-
* Build the
|
|
252
|
-
*
|
|
253
|
-
*
|
|
114
|
+
* Build the bwrap DIRECT-mode spawn for a CLI session, or return null when the
|
|
115
|
+
* runtime deps are unavailable / setup fails (fail-safe: the worker treats
|
|
116
|
+
* null as a hard error and never silently runs unsandboxed).
|
|
254
117
|
*
|
|
255
|
-
* Layout under <dataDir>/sandboxes/<sessionId>/: outbox, shimbin,
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
* overlay upper/work never sit inside their own lower. Host-only merged
|
|
259
|
-
* mountpoints and the HOME overlay upper/work also live under that runtime root.
|
|
118
|
+
* Layout under <dataDir>/sandboxes/<sessionId>/: outbox, shimbin, empties.
|
|
119
|
+
* No overlays, no upper/work dirs — writes inside readWrite zones hit the
|
|
120
|
+
* real filesystem directly.
|
|
260
121
|
*/
|
|
261
|
-
export declare function
|
|
262
|
-
/** Whether the sandbox is on for THIS session (per-bot BotConfig.sandbox OR
|
|
263
|
-
* the BOTMUX_SANDBOX env force). Decided by the caller — prepareSandbox does
|
|
264
|
-
* NOT re-read the env, so the dashboard per-bot toggle actually takes effect. */
|
|
265
|
-
enabled: boolean;
|
|
266
|
-
cliId: string;
|
|
122
|
+
export declare function prepareDirectSandbox(opts: {
|
|
267
123
|
sessionId: string;
|
|
268
|
-
sourceWorkingDir: string;
|
|
269
124
|
dataDir: string;
|
|
125
|
+
/** Compile-ready policy (canonical + existence-filtered by the worker). */
|
|
126
|
+
policy: FsPolicy;
|
|
127
|
+
/** Child chdir (the canonical project working dir). */
|
|
128
|
+
chdir: string;
|
|
129
|
+
/** Canonical $HOME to set for the child. */
|
|
130
|
+
home: string;
|
|
270
131
|
cliBin: string;
|
|
271
132
|
cliArgs: string[];
|
|
272
|
-
/**
|
|
273
|
-
*
|
|
274
|
-
|
|
275
|
-
/** This CLI's auth/login paths (CliAdapter.authPaths) to keep real+writable so
|
|
276
|
-
* token refresh / login persists. `~` expanded; missing paths skipped. */
|
|
277
|
-
authPaths?: readonly string[];
|
|
278
|
-
/** Adapter-declared SECOND-STAGE executables (CliAdapter.sandboxExtraExecPaths)
|
|
279
|
-
* spawned inside the sandbox beyond cliBin — re-exposed if under /run. ONLY
|
|
280
|
-
* executable paths (never cwd/path args). undefined → none. */
|
|
281
|
-
extraExecPaths?: readonly string[];
|
|
282
|
-
/** Runtime-generated roots that should be visible read-only inside bwrap.
|
|
283
|
-
* Trusted (daemon-produced) — bound after the privacy masks. */
|
|
284
|
-
readonlyRoots?: readonly string[];
|
|
285
|
-
/** Sensitive descendants of readonlyRoots that are re-masked after those
|
|
286
|
-
* roots are mounted. */
|
|
287
|
-
postReadonlyHidePaths?: readonly string[];
|
|
288
|
-
/** Absolute Botmux command paths already written into a CLI's MCP config.
|
|
289
|
-
* When a target lives below the masked BOTMUX_HOME, bind the trusted relay
|
|
290
|
-
* shim at that exact path so an absolute MCP command remains executable. */
|
|
133
|
+
/** Absolute Botmux command paths already persisted in CLI MCP configs.
|
|
134
|
+
* Bind the worker-generated relay shim at those exact paths so a stale or
|
|
135
|
+
* tampered host wrapper cannot replace the trusted gateway entry. */
|
|
291
136
|
trustedBotmuxCommandPaths?: readonly string[];
|
|
292
|
-
/** Daemon-derived private roots to re-open writable after mandatory masks. */
|
|
293
|
-
trustedWritablePaths?: readonly string[];
|
|
294
|
-
/** Credential paths to re-mask after trusted writable carve-outs. */
|
|
295
|
-
finalHidePaths?: readonly string[];
|
|
296
|
-
/** User-configured extra read-only inputs (per-bot sandboxReadonlyPaths).
|
|
297
|
-
* Bound before the privacy masks (masks win) and rejected when they would
|
|
298
|
-
* shadow the home/project overlay roots. */
|
|
299
|
-
userReadonlyPaths?: readonly string[];
|
|
300
|
-
/** Keep network egress. Defaults to true for backwards compatibility. */
|
|
301
|
-
net?: boolean;
|
|
302
137
|
/** Worker-owned Unix socket for the credential-bearing MCP Gateway. */
|
|
303
138
|
mcpGatewaySocketPath?: string;
|
|
304
|
-
}):
|
|
139
|
+
}): DirectSandboxSpawn | null;
|
|
305
140
|
/**
|
|
306
|
-
* Re-attach the daemon/worker side to an ALREADY-spawned sandbox session
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* the workDir (upper changeset for landing) and a cleanup that tears the residue
|
|
313
|
-
* down at close/exit. Returns null if the session has no sandbox tree on disk
|
|
314
|
-
* (never sandboxed). Linux-only, mirrors prepareSandbox's layout.
|
|
141
|
+
* Re-attach the daemon/worker side to an ALREADY-spawned sandbox session (a
|
|
142
|
+
* live bwrap'd CLI surviving in a tmux/herdr/zellij pane across a daemon
|
|
143
|
+
* restart). Only the outbox path is needed back so the watcher keeps servicing
|
|
144
|
+
* the live CLI's `botmux send`, plus a cleanup that removes the tree at
|
|
145
|
+
* close/exit. Returns null if the session has no sandbox tree on disk (never
|
|
146
|
+
* sandboxed). Linux-only, mirrors prepareDirectSandbox's layout.
|
|
315
147
|
*/
|
|
316
148
|
export declare function attachSandboxOutbox(opts: {
|
|
317
149
|
sessionId: string;
|
|
318
150
|
dataDir: string;
|
|
319
151
|
}): {
|
|
320
152
|
outbox: string;
|
|
321
|
-
workDir: string;
|
|
322
153
|
cleanup: () => void;
|
|
323
154
|
} | null;
|
|
324
155
|
/**
|
|
325
|
-
* Reclaim leaked sandbox
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
* overlays is still mounted. This closes the blind spot where a sandboxed
|
|
333
|
-
* worker was SIGKILL'd (straggler reaper) or crashed: the session stays
|
|
334
|
-
* status='active' on disk, so the old "skip if active" rule would let the
|
|
335
|
-
* leaked upper/work dirs survive across restarts indefinitely. We only GC an
|
|
336
|
-
* active sid when its mounts are ALREADY gone — we NEVER tear down a live
|
|
337
|
-
* mount (a CLI persisting in a tmux/herdr/zellij pane is still bound to it),
|
|
338
|
-
* so a genuinely-live persistent session keeps its changeset.
|
|
339
|
-
*
|
|
340
|
-
* Safe to call repeatedly: wire once at daemon bootstrap AND on a periodic timer
|
|
341
|
-
* (the SIGKILL/straggler path can't run worker-side killCli(), so a startup-only
|
|
342
|
-
* sweep would let a crashed-active session's mount survive for the whole next
|
|
343
|
-
* daemon lifetime — one daemon per bot can run for days).
|
|
156
|
+
* Reclaim leaked per-session sandbox trees (outbox/shim/empties of sessions
|
|
157
|
+
* that no longer exist) — plain directory residue in the direct model, no
|
|
158
|
+
* mounts. Guards: never touch an ACTIVE session's tree (it may be suspended,
|
|
159
|
+
* intending to resume — its outbox must survive) and never touch a tree
|
|
160
|
+
* referenced by a live process (a reattached pane whose session record was
|
|
161
|
+
* lost). Safe to call repeatedly: wired at daemon bootstrap AND on a periodic
|
|
162
|
+
* timer.
|
|
344
163
|
*/
|
|
345
164
|
export declare function sweepOrphanSandboxes(dataDir: string, activeSessionIds: Set<string>): void;
|
|
346
165
|
export interface RelayRequest {
|
|
@@ -425,4 +244,5 @@ export declare function startOutboxWatcher(outbox: string, baseEnv: NodeJS.Proce
|
|
|
425
244
|
};
|
|
426
245
|
cliPath?: string;
|
|
427
246
|
}): () => void;
|
|
247
|
+
export {};
|
|
428
248
|
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/sandbox.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/sandbox.ts"],"names":[],"mappings":"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"}
|