@axiom-lattice/microsandbox-service 0.1.12 → 1.0.0
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/CHANGELOG.md +52 -0
- package/dist/{chunk-Z6NN3T6H.mjs → chunk-2DPF6PW2.mjs} +21 -3
- package/dist/chunk-2DPF6PW2.mjs.map +1 -0
- package/dist/{chunk-O5VQK7SY.mjs → chunk-K6J5TLVU.mjs} +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/index.d.mts +10 -3
- package/dist/index.mjs +1 -1
- package/dist/server.mjs +2 -2
- package/package.json +1 -1
- package/src/__tests__/MicrosandboxRuntimeService.test.ts +40 -0
- package/src/__tests__/app.test.ts +2 -2
- package/src/schemas/sandbox.ts +2 -1
- package/src/services/MicrosandboxRuntimeService.ts +34 -5
- package/dist/chunk-Z6NN3T6H.mjs.map +0 -1
- /package/dist/{chunk-O5VQK7SY.mjs.map → chunk-K6J5TLVU.mjs.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# @axiom-lattice/microsandbox-service
|
|
2
2
|
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 726c98a: Consolidated release notes for all pending changesets. Each package takes the highest bump type among the merged entries.
|
|
8
|
+
|
|
9
|
+
## Sandbox shell-exec timeout unified on milliseconds (ADR-178, breaking)
|
|
10
|
+
|
|
11
|
+
Unify the sandbox shell-exec timeout on **milliseconds** across the framework.
|
|
12
|
+
|
|
13
|
+
Breaking changes:
|
|
14
|
+
|
|
15
|
+
- `SandboxShellService.execCommand` now takes `timeoutMs` (milliseconds) instead of `timeout` (seconds). Custom `SandboxInstance` implementations must rename the field and adjust units.
|
|
16
|
+
- `MicrosandboxShellExecInput.timeout` → `timeoutMs`; the `POST /api/shell/exec` wire field is now `timeoutMs` for both `microsandbox-service` and `opensandbox-gateway`.
|
|
17
|
+
- `PACK_DIRECTORY_TIMEOUT_SECONDS` → `PACK_DIRECTORY_TIMEOUT_MS` (public core export via `sandbox_lattice`).
|
|
18
|
+
- `sandbox-console` `SandboxExecInput.timeout` → `timeoutMs`.
|
|
19
|
+
|
|
20
|
+
Behavior:
|
|
21
|
+
|
|
22
|
+
- Provider adapters convert once at their boundary: Daytona / agent-infra (`remote`) / OpenSandbox convert ms→seconds; E2B and Local pass milliseconds directly.
|
|
23
|
+
- **Fix:** `opensandbox-gateway` no longer divides an already-seconds value by 1000 (which capped every command at 1s); it now converts `timeoutMs` → the SDK's `timeoutSeconds` (floored to at least 1s).
|
|
24
|
+
- **Fix:** `microsandbox-service` now honors the timeout by streaming the shell and killing it on expiry; previously `timeout` was accepted but ignored.
|
|
25
|
+
- LLM-facing tools `shell_exec` (`timeout`, seconds) and `code_eval` (`timeout_sec`, seconds) intentionally keep seconds and convert once; documented as exceptions.
|
|
26
|
+
- Sandbox lifetime `timeoutSeconds` (create/renew/idle) is unchanged and remains in seconds.
|
|
27
|
+
|
|
28
|
+
## Sandbox service base URL + missing-file semantics (ADR-174 / ADR-175)
|
|
29
|
+
|
|
30
|
+
Unify the sandbox service base-URL env and treat missing sandbox files as a structured not-found.
|
|
31
|
+
|
|
32
|
+
The resident plugin deployment runtime now reads `MICROSANDBOX_SERVICE_BASE_URL` only (dropping `MICROSANDBOX_SERVICE_URL`), so a provider-only config also enables `manage_plugin` deploy/undeploy/status; `sandbox-console` reads `VITE_MICROSANDBOX_SERVICE_BASE_URL`. `MICROSANDBOX_SERVICE_URL` no longer has any effect.
|
|
33
|
+
|
|
34
|
+
`opensandbox-gateway` now preserves the sandbox's upstream HTTP status (and surfaces execd's `{ code, message }`) instead of collapsing every failure to `500 "Download failed"`, and `MicrosandboxServiceClient` attaches the HTTP status to request errors; `microsandbox-service` `readFile`/`downloadFile` map missing files to `404 FILE_NOT_FOUND` (matching `deleteFile`). A missing sandbox file (e.g. the plugin-skill manifest) is therefore classified as not-found rather than a hard failure, fixing `Error loading skill content: ... Download failed`.
|
|
35
|
+
|
|
36
|
+
## Sandbox plugin result contract (ADR-177)
|
|
37
|
+
|
|
38
|
+
- `invokePluginTool` no longer returns `undefined` when a sandbox plugin handler reports `ok:true` without a `result` field. That `undefined` made the MCP App `tools/call` route (`/api/mcp-apps/rpc`) send an empty body (client `Response.json()` threw "Unexpected end of JSON input"). It now falls back to the handler's raw stdout via core's new `handlerResultText`; handlers that supply `result` are unchanged. `handlerResultText` is exported from `@axiom-lattice/core`.
|
|
39
|
+
- Sandbox plugin tool results no longer collapse to the string `"null"` when a handler reports `ok:true` but omits the `result` field. The normalized text now falls back to the handler's raw stdout via the new `handlerResultText` helper (used by `SandboxPluginCompiler`), and `manage_plugin test` returns that same normalized text so authors catch the missing `result` wrapper instead of seeing the raw envelope in `stdout` while the inline result is `"null"`.
|
|
40
|
+
- The sandbox plugin authoring skills now show an explicit ✅/❌ for the required `result` wrapper (payload must go under `result`, not the envelope top level), and the UI skill states that `ui/notifications/tool-result` is a `CallToolResult` read via `params.content[0].text` rather than the handler payload at the top level.
|
|
41
|
+
|
|
42
|
+
## Plugin Builder skills
|
|
43
|
+
|
|
44
|
+
- Plugin Builder's `skill` middleware now uses `readAll: true` instead of a sandbox-plugin-only whitelist, so built-in skills (e.g. `ptc`) are actually loadable rather than merely advertised in `<available_skills>` (loading them previously returned `RESOURCE_NOT_ALLOWED`).
|
|
45
|
+
- Close three Plugin Builder capability gaps: add `sandbox-plugins-consume-open` (how a handler calls the platform's Open MCP surface via the injected `API_GATEWAY_URL`/`OPEN_API_TOKEN` + `listTools()`/`callTool()`), add a "Scenarios → skills" routing table to `sandbox-plugins-patterns`, and document in `sandbox-plugins-ui` that a View `tools/call` response is the handler's `result` value directly (not a `CallToolResult` wrapper) plus a self-check/debug section. The Plugin Builder prompt now routes to the new skill.
|
|
46
|
+
|
|
47
|
+
## MCP App UI push semantics
|
|
48
|
+
|
|
49
|
+
Document the MCP App push semantics in `sandbox-plugins-ui`: `ui/notifications/tool-result` replays the tool result **recorded when the agent ran** (it does not re-execute the handler), whereas a View `tools/call` re-executes the handler live. This is why a stale/`"null"` push can coexist with a correct `tools/call` — re-run the tool for a fresh push instead of debugging the host.
|
|
50
|
+
|
|
51
|
+
## MCP App same-origin rendering
|
|
52
|
+
|
|
53
|
+
`McpAppRenderer` no longer refuses to render when the gateway shares the console origin. Single-origin deployments previously saw "MCP App unavailable" because the outer sandbox proxy iframe (which carries `allow-same-origin`) was required to be cross-origin per the MCP Apps spec. The renderer now only requires that a gateway origin can be derived from `client.config.baseURL`; `event.origin`/`event.source` validation is unchanged, and the untrusted View still runs in an opaque-origin inner frame. Cross-origin deployments keep the stronger containment and are unchanged; the trade-off is documented in ADR-117.
|
|
54
|
+
|
|
3
55
|
## 0.1.12
|
|
4
56
|
|
|
5
57
|
### Patch Changes
|
|
@@ -1089,13 +1089,30 @@ var MicrosandboxRuntimeService = class {
|
|
|
1089
1089
|
}
|
|
1090
1090
|
async execCommand(input) {
|
|
1091
1091
|
const native = await this.getOrEnsureNative(input.sandboxName);
|
|
1092
|
-
const output = await native.shell(input.command);
|
|
1092
|
+
const output = input.timeoutMs ? await this.runShellWithTimeout(native, input.command, input.timeoutMs) : await native.shell(input.command);
|
|
1093
1093
|
return {
|
|
1094
1094
|
stdout: output.stdout(),
|
|
1095
1095
|
stderr: output.stderr(),
|
|
1096
1096
|
exitCode: output.code ?? 0
|
|
1097
1097
|
};
|
|
1098
1098
|
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Run a shell command with a hard timeout by streaming it and killing the
|
|
1101
|
+
* handle once `timeoutMs` elapses, preserving the same shell semantics as
|
|
1102
|
+
* {@link RuntimeNative.shell} (which has no timeout knob).
|
|
1103
|
+
*/
|
|
1104
|
+
async runShellWithTimeout(native, command, timeoutMs) {
|
|
1105
|
+
const handle = await native.shellStream(command);
|
|
1106
|
+
const timer = setTimeout(() => {
|
|
1107
|
+
void handle.kill().catch(() => {
|
|
1108
|
+
});
|
|
1109
|
+
}, timeoutMs);
|
|
1110
|
+
try {
|
|
1111
|
+
return await handle.collect();
|
|
1112
|
+
} finally {
|
|
1113
|
+
clearTimeout(timer);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1099
1116
|
async getSandboxLogs(name, opts) {
|
|
1100
1117
|
const handle = await Sandbox2.get(name);
|
|
1101
1118
|
const logOpts = {};
|
|
@@ -1278,7 +1295,8 @@ var shellExecSchema = z2.object({
|
|
|
1278
1295
|
sandboxName: z2.string().min(1),
|
|
1279
1296
|
command: z2.string().min(1),
|
|
1280
1297
|
exec_dir: z2.string().optional(),
|
|
1281
|
-
|
|
1298
|
+
/** Maximum execution time in milliseconds. */
|
|
1299
|
+
timeoutMs: z2.number().int().positive().optional()
|
|
1282
1300
|
});
|
|
1283
1301
|
var sandboxLogsSchema = z2.object({
|
|
1284
1302
|
tail: z2.number().int().positive().optional(),
|
|
@@ -1999,4 +2017,4 @@ export {
|
|
|
1999
2017
|
MicrosandboxRuntimeService,
|
|
2000
2018
|
buildApp
|
|
2001
2019
|
};
|
|
2002
|
-
//# sourceMappingURL=chunk-
|
|
2020
|
+
//# sourceMappingURL=chunk-2DPF6PW2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/lib/errors.ts","../src/services/publishedPorts.ts","../src/services/MicrosandboxRuntimeService.ts","../src/lib/msb.ts","../src/app.ts","../src/lib/http.ts","../src/routes/health.ts","../src/controllers/images.ts","../src/schemas/images.ts","../src/routes/images.ts","../src/routes/sandbox.ts","../src/schemas/sandbox.ts","../src/lib/proxy.ts","../src/controllers/sandbox.ts","../src/controllers/volume-fs.ts","../src/schemas/volume-fs.ts","../src/routes/volume-fs.ts","../src/services/ImageService.ts","../src/swagger.ts"],"sourcesContent":["import { Sandbox, MountBuilder } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport { readdirSync, readFileSync, unlinkSync } from \"fs\";\nimport { join } from \"path\";\nimport { HttpError } from \"../lib/errors\";\nimport {\n allocateHostPort,\n decodePublishedPorts,\n encodePublishedPorts,\n PUBLISHED_PORTS_ENV,\n resolveHostPortRange,\n} from \"./publishedPorts\";\n\nconst DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? \"daytonaio/sandbox:0.6.0\";\nconst DEFAULT_IDLE_TIMEOUT_MS = Number(process.env.MICROSANDBOX_IDLE_TIMEOUT_MS) || 600_000;\nconst DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1000;\nconst SWEEP_INTERVAL_MS = 30_000;\nconst SWEEP_STOP_TIMEOUT_MS = 60_000;\nconst HEALTH_CHECK_TIMEOUT_MS = 2_000;\nconst HEALTH_CHECK_INTERVAL_MS = 30_000;\nconst SANDBOX_AGENT_SOCKET_DIR = \"/root/.microsandbox/run/agent\";\n\ntype CacheEntry = {\n native: unknown | null;\n lastAccessedAt: number;\n pausedAt?: number;\n lastCheckedAt?: number;\n broken?: boolean;\n createOptions?: Record<string, unknown>;\n /**\n * When true the idle sweeper never pauses or removes this sandbox.\n *\n * Set for residents created with `timeoutSeconds: null` (`alwaysOn`), whose\n * lifecycle is owned by the deployment service rather than idle pressure.\n */\n idleExempt?: boolean;\n /** Guest port -> host port mapping published for this sandbox. */\n publishedPorts?: Record<number, number>;\n};\n\nfunction extractConfig(configJson: string): {\n image: string;\n cpus: number;\n memoryMib: number;\n env: Record<string, string>;\n mounts: Array<{ guest: string; type: string; source?: string; name?: string; size_mib?: number; readonly?: boolean }>;\n entrypoint: string[] | undefined;\n publishedPorts: Record<number, number>;\n} | undefined {\n try {\n const raw = JSON.parse(configJson);\n const image = typeof raw.image === \"string\" ? raw.image\n : raw.image?.Oci?.reference ?? \"\";\n // The raw persisted config keeps resources snake_case (`resources.memory_mib`);\n // the public `Sandbox.builder().build()` wrapper camelCases it before\n // returning, so tolerate both casings plus legacy top-level `cpus` fields.\n const rawResources = raw.resources as\n | { cpus?: number; memory_mib?: number; memoryMib?: number }\n | undefined;\n const env: Record<string, string> = {};\n const rawEnv = raw.env;\n // The SDK persists env as an array of `{ key, value }` objects (EnvVar);\n // tolerate legacy `[key, value]` tuples and plain records as well.\n if (Array.isArray(rawEnv)) {\n for (const entry of rawEnv) {\n if (Array.isArray(entry) && entry.length >= 2) {\n env[String(entry[0])] = String(entry[1]);\n } else if (entry && typeof entry === \"object\" && \"key\" in entry) {\n const { key, value } = entry as { key?: unknown; value?: unknown };\n if (key !== undefined) {\n env[String(key)] = String(value ?? \"\");\n }\n }\n }\n } else if (rawEnv && typeof rawEnv === \"object\") {\n for (const [key, value] of Object.entries(rawEnv as Record<string, unknown>)) {\n env[key] = String(value);\n }\n }\n\n // The SDK serializes the flattened `SandboxSpec`, whose `runtime.entrypoint`\n // is the effective entrypoint override (`raw.runtime.entrypoint`).\n const rawEntrypoint = raw.runtime?.entrypoint;\n const entrypoint = Array.isArray(rawEntrypoint) ? rawEntrypoint.map(String) : undefined;\n\n const publishedPorts: Record<number, number> = {};\n const rawPorts = raw.network?.ports;\n if (Array.isArray(rawPorts)) {\n for (const port of rawPorts) {\n const guest = Number(port?.guest_port ?? port?.guestPort);\n const host = Number(port?.host_port ?? port?.hostPort);\n if (\n Number.isInteger(guest) &&\n guest > 0 &&\n guest <= 65535 &&\n Number.isInteger(host) &&\n host > 0 &&\n host <= 65535\n ) {\n publishedPorts[guest] = host;\n }\n }\n }\n if (Object.keys(publishedPorts).length === 0) {\n Object.assign(publishedPorts, decodePublishedPorts(env[PUBLISHED_PORTS_ENV]));\n }\n\n return {\n image,\n cpus: rawResources?.cpus ?? raw.cpus ?? 1,\n memoryMib: rawResources?.memory_mib ?? rawResources?.memoryMib ?? raw.memory_mib ?? raw.memoryMib ?? 512,\n env,\n mounts: Array.isArray(raw.mounts) ? raw.mounts : [],\n entrypoint,\n publishedPorts,\n };\n } catch {\n return undefined;\n }\n}\n\nexport class SandboxRegistry {\n private handles = new Map<string, CacheEntry>();\n private creating = new Map<string, Promise<unknown>>();\n private stopping = new Set<string>();\n private readonly idleTimeoutMs: number;\n private sweepTimer?: ReturnType<typeof setInterval>;\n\n constructor(idleTimeoutMs?: number) {\n this.idleTimeoutMs = idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.cleanupOrphanedSockets();\n if (this.idleTimeoutMs > 0) {\n this.startSweeper();\n }\n }\n\n private startSweeper(): void {\n this.sweepTimer = setInterval(() => {\n const now = Date.now();\n for (const [name, entry] of this.handles) {\n if (entry.idleExempt) {\n continue;\n }\n if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {\n if (this.stopping.has(name)) {\n continue;\n }\n console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);\n this.stopping.add(name);\n void Promise.race([\n (entry.native as { stop(): Promise<void> }).stop(),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"stop timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]).then(() => {\n console.log(`[SandboxRegistry] sweeper paused name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper pause failed name=${name} err=${err.message}`);\n }).finally(() => {\n entry.native = null;\n entry.pausedAt = Date.now();\n this.stopping.delete(name);\n });\n } else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {\n console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);\n void this.removeAndDelete(name).then(() => {\n console.log(`[SandboxRegistry] sweeper removed name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper remove failed name=${name} err=${err.message}`);\n });\n }\n }\n }, SWEEP_INTERVAL_MS);\n (this.sweepTimer as { unref?: () => void }).unref?.();\n }\n\n destroy(): void {\n if (this.sweepTimer) {\n clearInterval(this.sweepTimer);\n this.sweepTimer = undefined;\n }\n this.handles.clear();\n this.creating.clear();\n }\n\n remove(name: string): void {\n this.handles.delete(name);\n this.creating.delete(name);\n }\n\n /**\n * Return the guest->host port map published for a sandbox.\n *\n * @param name - Sandbox name\n * @returns A shallow copy of the guest->host map (empty when unknown), so\n * callers cannot mutate the cached entry.\n */\n getPublishedPorts(name: string): Record<number, number> {\n return { ...(this.handles.get(name)?.publishedPorts ?? {}) };\n }\n\n /**\n * Resolve the relative proxy path for a published guest port.\n *\n * A loopback `host:port` is unreachable from other Gateway replicas, so the\n * value points at this service's own proxy route instead. Callers compose the\n * absolute URL from their configured service base and the proxy dials the\n * loopback target internally (see {@link getProxyTarget}).\n *\n * @param name - Sandbox name\n * @param guestPort - Guest port passed via `createOptions.exposePorts`\n * @returns The relative proxy path\n * @throws HttpError `ENDPOINT_NOT_PUBLISHED` when the port was not published\n */\n getEndpoint(name: string, guestPort: number): { endpoint: string; headers?: Record<string, string> } {\n const hostPort = this.getPublishedPorts(name)[guestPort];\n if (!hostPort) {\n throw new HttpError(404, \"ENDPOINT_NOT_PUBLISHED\", `Port ${guestPort} is not published for ${name}`);\n }\n return { endpoint: `/api/sandboxes/${encodeURIComponent(name)}/proxy/${guestPort}` };\n }\n\n /**\n * Resolve the loopback `host:port` the proxy dials for a published guest port.\n *\n * @param name - Sandbox name\n * @param guestPort - Guest port passed via `createOptions.exposePorts`\n * @returns The loopback `host:port` target\n * @throws HttpError `ENDPOINT_NOT_PUBLISHED` when the port was not published\n */\n getProxyTarget(name: string, guestPort: number): string {\n const hostPort = this.getPublishedPorts(name)[guestPort];\n if (!hostPort) {\n throw new HttpError(404, \"ENDPOINT_NOT_PUBLISHED\", `Port ${guestPort} is not published for ${name}`);\n }\n return `127.0.0.1:${hostPort}`;\n }\n\n cleanupOrphanedSockets(): void {\n try {\n const activeSockets = new Set<string>();\n const unixSockets = readFileSync(\"/proc/net/unix\", \"utf-8\");\n for (const line of unixSockets.split(\"\\n\")) {\n const path = line.trim().split(\" \").pop();\n if (path && path.startsWith(SANDBOX_AGENT_SOCKET_DIR)) {\n activeSockets.add(path);\n }\n }\n for (const entry of readdirSync(SANDBOX_AGENT_SOCKET_DIR)) {\n const fullPath = join(SANDBOX_AGENT_SOCKET_DIR, entry);\n if (!activeSockets.has(fullPath)) {\n unlinkSync(fullPath);\n console.log(`[SandboxRegistry] removed orphaned socket: ${entry}`);\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n console.log(`[SandboxRegistry] socket cleanup skipped: ${(err as Error).message}`);\n }\n }\n }\n\n async removeAndDelete(name: string): Promise<void> {\n try {\n const handle = await Promise.race([\n Sandbox.get(name),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"Sandbox.get timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n if (handle.status === \"running\") {\n try {\n const native = await Promise.race([\n handle.connect(),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"handle.connect timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n await Promise.race([\n (native as { stop(): Promise<void> }).stop(),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"stop timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n } catch { /* ignore */ }\n }\n await Promise.race([\n Sandbox.remove(name),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"Sandbox.remove timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n } catch { /* best effort, always clean cache */ }\n this.remove(name);\n this.cleanupOrphanedSockets();\n }\n\n async pause(name: string): Promise<void> {\n const entry = this.handles.get(name);\n if (!entry) {\n await Sandbox.get(name);\n return;\n }\n if (!entry.native) return;\n const handle = await Sandbox.get(name);\n if (handle.status === \"running\") {\n try {\n await (entry.native as { stop(): Promise<void> }).stop();\n } catch { /* ignore */ }\n }\n entry.native = null;\n entry.pausedAt = Date.now();\n }\n\n private async healthCheck(native: unknown): Promise<boolean> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n try {\n await Promise.race([\n fs.list(\"/\"),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"health check timed out\")), HEALTH_CHECK_TIMEOUT_MS)),\n ]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async waitForFs(native: unknown, maxRetries = 10): Promise<void> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n for (let i = 0; i < maxRetries; i++) {\n try {\n await Promise.race([\n fs.list(\"/\"),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"FS check timed out\")), 5000)),\n ]);\n return;\n } catch {\n await new Promise((r) => setTimeout(r, 200));\n }\n }\n throw new Error(\"FS not ready after start\");\n }\n\n private hasConfigMismatch(\n originalConfig: ReturnType<typeof extractConfig>,\n createOptions: Record<string, unknown>\n ): boolean {\n const volumeDefs = createOptions.volumes as Record<string, { type: string }> | undefined;\n const requestEnv = createOptions.env as Record<string, string> | undefined;\n const requestExposePorts = createOptions.exposePorts as number[] | undefined;\n const requestEntrypoint = createOptions.entrypoint as string[] | undefined;\n\n if (requestEntrypoint) {\n const existingEntrypoint = originalConfig?.entrypoint;\n // Fail-safe: only recreate when the existing config POSITIVELY records a\n // different entrypoint. An absent one may be serialization drift (or a\n // sandbox created without an override), so keep the running sandbox.\n if (\n existingEntrypoint !== undefined &&\n JSON.stringify(requestEntrypoint) !== JSON.stringify(existingEntrypoint)\n ) {\n console.log(`[SandboxRegistry] entrypoint mismatch, recreating...`);\n return true;\n }\n }\n\n if (volumeDefs && Object.keys(volumeDefs).length > 0) {\n const existingGuests = new Set((originalConfig?.mounts ?? []).map((m: { guest: string }) => m.guest));\n const requestedGuests = Object.keys(volumeDefs);\n const missing = requestedGuests.filter(g => !existingGuests.has(g));\n if (missing.length > 0) {\n console.log(`[SandboxRegistry] volumes mismatch, missing=${missing.join(\",\")}, recreating...`);\n return true;\n }\n }\n\n if (requestEnv && originalConfig?.env) {\n for (const [key, value] of Object.entries(requestEnv)) {\n if (originalConfig.env[key] !== value) {\n console.log(`[SandboxRegistry] env mismatch (key=${key}), recreating...`);\n return true;\n }\n }\n }\n\n if (requestExposePorts) {\n // Compare guest-port sets only: host ports are allocated deterministically\n // from (name, guestPort), so a changed guest set is the meaningful signal.\n const existingGuests = new Set(Object.keys(originalConfig?.publishedPorts ?? {}));\n const requested = new Set(requestExposePorts.map(String));\n const same = existingGuests.size === requested.size && [...requested].every(g => existingGuests.has(g));\n if (!same) {\n console.log(`[SandboxRegistry] exposePorts mismatch, recreating...`);\n return true;\n }\n }\n\n return false;\n }\n\n async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {\n const tStart = Date.now();\n\n const cached = this.handles.get(name);\n\n if (cached?.native && !this.stopping.has(name)) {\n const now = Date.now();\n if (!cached.lastCheckedAt || now - cached.lastCheckedAt > HEALTH_CHECK_INTERVAL_MS) {\n const tCheck = Date.now();\n const ok = await this.healthCheck(cached.native);\n cached.lastCheckedAt = now;\n if (ok) {\n cached.lastAccessedAt = now;\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms health_ok elapsed=${Date.now() - tCheck}ms`);\n return cached.native;\n }\n console.log(`[SandboxRegistry] ensure name=${name} HEALTH_FAIL will_recreate elapsed=${Date.now() - tStart}ms`);\n cached.native = null;\n cached.broken = true;\n } else {\n cached.lastAccessedAt = now;\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);\n return cached.native;\n }\n }\n\n if (cached?.native && this.stopping.has(name)) {\n console.log(`[SandboxRegistry] ensure name=${name} STALE_NATIVE (being stopped), forcing revive`);\n cached.native = null;\n }\n\n if (cached && !cached.native) {\n cached.pausedAt = undefined;\n console.log(`[SandboxRegistry] ensure name=${name} REVIVE idled=${Date.now() - cached.lastAccessedAt}ms`);\n }\n\n const inflight = this.creating.get(name);\n if (inflight) {\n console.log(`[SandboxRegistry] ensure name=${name} AWAITING_INFLIGHT`);\n return inflight;\n }\n\n const creation = (async () => {\n const tCreate = Date.now();\n let native: unknown;\n const image = (createOptions?.image as string) ?? DEFAULT_IMAGE;\n const cpus = (createOptions?.cpus as number) ?? 1;\n const memoryMib = (createOptions?.memoryMib as number) ?? 512;\n const env = (createOptions?.env as Record<string, string>) ?? undefined;\n\n let originalConfig: ReturnType<typeof extractConfig>;\n let publishedPorts: Record<number, number> = {};\n\n const existing = this.handles.get(name);\n if (existing?.broken) {\n console.log(`[SandboxRegistry] ensure name=${name} BROKEN removing before recreate`);\n await this.removeAndDelete(name);\n this.handles.set(name, { native: null, lastAccessedAt: Date.now(), createOptions: existing.createOptions ?? cached?.createOptions });\n } else {\n try {\n const tGet = Date.now();\n const handle: SandboxHandle = await Sandbox.get(name);\n console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);\n\n originalConfig = extractConfig(handle.configJson);\n\n const recoveredPorts = originalConfig?.publishedPorts ?? {};\n if (Object.keys(recoveredPorts).length > 0) {\n publishedPorts = recoveredPorts;\n }\n\n if (handle.status === \"running\" || handle.status === \"stopped\") {\n const isNewConnection = !cached;\n if (isNewConnection && createOptions && this.hasConfigMismatch(originalConfig, createOptions)) {\n await this.removeAndDelete(name);\n native = undefined;\n } else if (handle.status === \"running\") {\n const tConnect = Date.now();\n native = await Promise.race([\n handle.connect(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"handle.connect timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } else {\n try {\n const tStart2 = Date.now();\n native = await Promise.race([\n Sandbox.startDetached(name),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"startDetached timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } catch {\n if (!native) {\n await this.removeAndDelete(name);\n }\n }\n }\n } else if (handle.status === \"crashed\" || handle.status === \"draining\") {\n await this.removeAndDelete(name);\n } else {\n await this.removeAndDelete(name);\n }\n } catch (err) {\n console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${(err as Error).message}`);\n native = undefined;\n }\n }\n console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);\n\n if (!native) {\n const effectiveOptions = createOptions ?? cached?.createOptions;\n if (!effectiveOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} NOT_FOUND elapsed=${Date.now() - tStart}ms`);\n throw new Error(`Sandbox ${name} not found`);\n }\n if (!createOptions && cached?.createOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} RECOVER_OPTIONS elapsed=${Date.now() - tStart}ms`);\n }\n const tBuild = Date.now();\n const volumeDefs = effectiveOptions?.volumes as Record<string, { type: string; source?: string; name?: string; sizeMib?: number; readonly?: boolean }> | undefined;\n const resolvedImage = (effectiveOptions?.image as string) ?? originalConfig?.image ?? image;\n console.log(\n `[SandboxRegistry] create sandbox=${name} image=${resolvedImage} ` +\n `from=${(effectiveOptions?.image as string) ? \"request\" : originalConfig?.image ? \"originalConfig\" : \"default\"}`\n );\n const resolvedCpus = (effectiveOptions?.cpus as number) ?? originalConfig?.cpus ?? cpus;\n const resolvedMemoryMib = (effectiveOptions?.memoryMib as number) ?? originalConfig?.memoryMib ?? memoryMib;\n const resolvedEnv = (effectiveOptions?.env as Record<string, string>) ?? originalConfig?.env ?? env;\n const resolvedMounts = originalConfig?.mounts ?? [];\n // `timeoutSeconds` maps to microsandbox's only lifetime knob, the\n // builder's `idleTimeout(secs)`. A positive value is applied as the\n // sandbox's idle lifetime below; `null` marks the entry idle-exempt so\n // the sweeper never pauses it (`alwaysOn` residents); `undefined`\n // keeps the registry default (`MICROSANDBOX_IDLE_TIMEOUT_MS`).\n const timeoutSeconds = effectiveOptions?.timeoutSeconds;\n\n // Allocate host ports synchronously, consulting ports already committed by\n // other entries. Per-name safety comes from the single-flight `creating`\n // map: concurrent `ensure` calls for the same name share one creation.\n // Concurrent creates of *different* names are not reserved in flight, so a\n // collision is possible (though improbable with the 20k-port range) and\n // surfaces as a bind failure; an in-flight reservation map is a Plan 2\n // follow-up.\n const exposePorts = (effectiveOptions?.exposePorts as number[] | undefined) ?? [];\n const portRange = resolveHostPortRange();\n const taken = new Set<number>();\n for (const [otherName, otherEntry] of this.handles) {\n if (otherName === name) continue;\n for (const host of Object.values(otherEntry.publishedPorts ?? {})) taken.add(host);\n }\n publishedPorts = {};\n for (const guestPort of new Set(exposePorts)) {\n publishedPorts[guestPort] = allocateHostPort(name, guestPort, portRange, (p) => taken.has(p));\n taken.add(publishedPorts[guestPort]);\n }\n const resolvedEntrypoint = effectiveOptions?.entrypoint as string[] | undefined;\n const resolvedEnvWithPorts = exposePorts.length > 0\n ? { ...(resolvedEnv ?? {}), [PUBLISHED_PORTS_ENV]: encodePublishedPorts(publishedPorts) }\n : resolvedEnv;\n\n const applyVolumes = (b: ReturnType<typeof Sandbox.builder>): void => {\n if (volumeDefs) {\n for (const [guestPath, def] of Object.entries(volumeDefs)) {\n const mb = new MountBuilder(guestPath);\n if (def.type === \"bind\" && def.source) {\n mb.bind(def.source);\n } else if (def.type === \"named\" && def.name) {\n mb.named(def.name);\n } else if (def.type === \"tmpfs\") {\n mb.tmpfs();\n if (def.sizeMib) {\n mb.size(def.sizeMib);\n }\n }\n if (def.readonly) {\n mb.readonly();\n }\n b.volume(guestPath, () => mb);\n }\n } else {\n for (const mount of resolvedMounts) {\n const mb = new MountBuilder(mount.guest);\n if (mount.type === \"Bind\" || mount.type === \"bind\") {\n if (mount.source) mb.bind(mount.source);\n } else if (mount.type === \"Named\" || mount.type === \"named\") {\n if (mount.name) mb.named(mount.name);\n } else if (mount.type === \"Tmpfs\" || mount.type === \"tmpfs\") {\n mb.tmpfs();\n if (mount.size_mib) mb.size(mount.size_mib);\n }\n if (mount.readonly) {\n mb.readonly();\n }\n b.volume(mount.guest, () => mb);\n }\n }\n };\n\n const tryCreate = async () => {\n const builder = Sandbox.builder(name)\n .detached(true)\n .image(resolvedImage)\n .cpus(resolvedCpus)\n .memory(resolvedMemoryMib);\n if (typeof timeoutSeconds === \"number\" && timeoutSeconds > 0) {\n builder.idleTimeout(timeoutSeconds);\n }\n if (resolvedEntrypoint) {\n builder.entrypoint(resolvedEntrypoint);\n }\n if (resolvedEnvWithPorts) {\n builder.envs(resolvedEnvWithPorts);\n }\n applyVolumes(builder);\n for (const [guestPort, hostPort] of Object.entries(publishedPorts)) {\n builder.port(hostPort, Number(guestPort));\n }\n const tCreateInner = Date.now();\n const result = await Promise.race([\n builder.create(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"builder.create timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(\n `[SandboxRegistry] builder.create name=${name} image=${resolvedImage} ` +\n `elapsed=${Date.now() - tCreateInner}ms ` +\n `envKeys=${resolvedEnvWithPorts ? Object.keys(resolvedEnvWithPorts).join(\",\") : \"none\"} ` +\n `volumes=${volumeDefs ? Object.keys(volumeDefs).join(\",\") : \"none\"}`\n );\n return result;\n };\n try {\n native = await tryCreate();\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"already exists\")) {\n await this.removeAndDelete(name);\n native = await tryCreate();\n } else {\n throw err;\n }\n }\n console.log(`[SandboxRegistry] phase=create_sandbox name=${name} elapsed=${Date.now() - tBuild}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n }\n\n const totalElapsed = Date.now() - tStart;\n const entryOptions = createOptions ?? cached?.createOptions;\n const entry: CacheEntry = {\n native,\n lastAccessedAt: Date.now(),\n lastCheckedAt: Date.now(),\n createOptions: entryOptions,\n idleExempt: entryOptions?.timeoutSeconds === null,\n publishedPorts,\n };\n this.handles.set(name, entry);\n console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1000)}s`);\n return native;\n })();\n\n this.creating.set(name, creation);\n void creation.finally(() => this.creating.delete(name)).catch(() => {});\n creation.catch(() => {});\n\n return creation;\n }\n}\n","export class HttpError extends Error {\n constructor(\n public statusCode: number,\n public code: string,\n message: string\n ) {\n super(message);\n }\n}\n\nexport function toErrorResponse(error: unknown): {\n statusCode: number;\n body: {\n success: false;\n error: {\n code: string;\n message: string;\n };\n };\n} {\n if (error instanceof HttpError) {\n return {\n statusCode: error.statusCode,\n body: {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n },\n };\n }\n\n return {\n statusCode: 500,\n body: {\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : String(error),\n },\n },\n };\n}\n","import { HttpError } from \"../lib/errors\";\n\n/** Env var that mirrors the guest->host port map inside the sandbox. */\nexport const PUBLISHED_PORTS_ENV = \"LATTICE_PUBLISHED_PORTS\";\n\nconst DEFAULT_HOST_PORT_MIN = 40000;\nconst DEFAULT_HOST_PORT_MAX = 60000;\n\n/** Inclusive host-port range. */\nexport interface HostPortRange {\n min: number;\n max: number;\n}\n\nfunction parsePort(raw: string | undefined, fallback: number): number {\n if (raw === undefined) return fallback;\n const n = Number(raw);\n return Number.isInteger(n) && n > 0 && n <= 65535 ? n : fallback;\n}\n\n/**\n * Resolve the host-port range used when publishing guest ports.\n *\n * @param env - Process environment (injectable for tests)\n * @returns A valid inclusive `{ min, max }` range, defaulting to 40000-60000\n */\nexport function resolveHostPortRange(env: Record<string, string | undefined> = process.env): HostPortRange {\n const min = parsePort(env.MICROSANDBOX_HOST_PORT_MIN, DEFAULT_HOST_PORT_MIN);\n const max = parsePort(env.MICROSANDBOX_HOST_PORT_MAX, DEFAULT_HOST_PORT_MAX);\n if (min > max) return { min: DEFAULT_HOST_PORT_MIN, max: DEFAULT_HOST_PORT_MAX };\n return { min, max };\n}\n\n/** FNV-1a 32-bit hash of a string. */\nfunction hash32(input: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n\n/**\n * Deterministically allocate a host port for a `(sandboxName, guestPort)` pair,\n * probing forward (with wrap-around) when a candidate is already taken.\n *\n * @param name - Sandbox name\n * @param guestPort - Guest-side port being published\n * @param range - Inclusive host-port range\n * @param isTaken - Predicate reporting whether a host port is in use\n * @returns A free host port inside `range`\n * @throws HttpError `PORT_RANGE_EXHAUSTED` when no port is free\n */\nexport function allocateHostPort(\n name: string,\n guestPort: number,\n range: HostPortRange,\n isTaken: (port: number) => boolean\n): number {\n const span = range.max - range.min + 1;\n let candidate = range.min + (hash32(`${name}:${guestPort}`) % span);\n for (let i = 0; i < span; i++) {\n if (!isTaken(candidate)) return candidate;\n candidate = candidate >= range.max ? range.min : candidate + 1;\n }\n throw new HttpError(503, \"PORT_RANGE_EXHAUSTED\", `No free host port for ${name}:${guestPort}`);\n}\n\n/**\n * Encode a guest->host port map for the `LATTICE_PUBLISHED_PORTS` env var.\n *\n * @param ports - Map of guest port to host port\n * @returns JSON string\n */\nexport function encodePublishedPorts(ports: Record<number, number>): string {\n return JSON.stringify(ports);\n}\n\n/**\n * Decode the `LATTICE_PUBLISHED_PORTS` env var.\n *\n * @param raw - Raw env value\n * @returns A guest->host port map; `{}` when missing or malformed\n */\nexport function decodePublishedPorts(raw: string | undefined): Record<number, number> {\n if (!raw) return {};\n try {\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return {};\n const out: Record<number, number> = {};\n for (const [guest, host] of Object.entries(parsed as Record<string, unknown>)) {\n const g = Number(guest);\n if (\n Number.isInteger(g) &&\n g > 0 &&\n g <= 65535 &&\n typeof host === \"number\" &&\n Number.isInteger(host) &&\n host > 0 &&\n host <= 65535\n ) {\n out[g] = host;\n }\n }\n return out;\n } catch {\n return {};\n }\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { Sandbox, Volume } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport type { LogReadSource } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxLogsInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { HttpError } from \"../lib/errors\";\nimport { getMsbPath } from \"../lib/msb\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\n\nconst execAsync = promisify(exec);\n\ntype VolumeConfig = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\ntype ExecOutputLike = {\n stdout(): string;\n stderr(): string;\n get code(): number;\n};\n\ntype RuntimeNative = {\n fs(): {\n readString(path: string): Promise<string>;\n readToString(path: string): Promise<string>;\n write(path: string, data: Buffer): Promise<void>;\n list(path: string): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n mkdir(path: string): Promise<void>;\n remove(path: string): Promise<void>;\n stat(path: string): Promise<{ kind: \"file\" | \"directory\" | \"symlink\" | \"other\" }>;\n };\n exec(cmd: string, args?: string[]): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n shell(script: string): Promise<ExecOutputLike>;\n shellStream(script: string): Promise<{\n collect(): Promise<ExecOutputLike>;\n kill(): Promise<void>;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\ntype SandboxConfig = {\n name: string;\n image: unknown;\n memoryMib?: number;\n cpus?: number;\n env?: unknown;\n volumes?: Record<string, unknown>;\n};\n\nfunction parseConfigJson(configJson: string): SandboxConfig {\n try {\n const raw = JSON.parse(configJson);\n const rawVolumes = raw.volumes ?? raw.mounts;\n const volumes: Record<string, unknown> = {};\n if (Array.isArray(rawVolumes)) {\n for (const mount of rawVolumes) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n } else if (rawVolumes && typeof rawVolumes === \"object\") {\n Object.assign(volumes, rawVolumes);\n }\n return {\n name: raw.name ?? \"\",\n image: raw.image ?? \"\",\n memoryMib: raw.memoryMib ?? raw.memory_mib,\n cpus: raw.cpus,\n env: raw.env ?? {},\n volumes,\n };\n } catch {\n return { name: \"\", image: \"\" };\n }\n}\n\nfunction msToIsoString(ms: number | Date | null | undefined): string {\n if (ms == null) return \"\";\n if (ms instanceof Date) return ms.toISOString();\n return new Date(ms).toISOString();\n}\n\ntype MsbInspectEnvVolumes = {\n env: unknown;\n volumes: Record<string, unknown>;\n};\n\nfunction parseMsbInspectEnvVolumes(stdout: string): MsbInspectEnvVolumes {\n const data = JSON.parse(stdout);\n const env = data?.config?.env ?? {};\n\n const volumes: Record<string, unknown> = {};\n const rawMounts = data?.config?.mounts;\n if (Array.isArray(rawMounts)) {\n for (const mount of rawMounts) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n }\n\n return { env, volumes };\n}\n\nfunction isFileNotFoundError(error: unknown): boolean {\n if (typeof error === \"string\") {\n const message = error.toLowerCase();\n return message.includes(\"not found\") || message.includes(\"no such file\");\n }\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const candidate = error as { code?: unknown; message?: unknown };\n if (candidate.code === \"ENOENT\") {\n return true;\n }\n if (typeof candidate.message !== \"string\") {\n return false;\n }\n const message = candidate.message.toLowerCase();\n return message.includes(\"not found\") || message.includes(\"no such file\");\n}\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") {\n return \"/\";\n }\n if (path.startsWith(\"~/\")) {\n return `/${path.slice(2)}`;\n }\n return path;\n }\n\n private resolveDeletePath(path: string): string {\n const resolvedPath = this.resolvePath(path);\n if (resolvedPath.replace(/\\\\/g, \"/\").split(\"/\").includes(\"..\")) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", `Path traversal denied: ${path}`);\n }\n return resolvedPath;\n }\n\n private toListItem(info: {\n name: string;\n status: string;\n configJson: string;\n createdAt?: number | Date | null;\n updatedAt?: number | Date | null;\n }): {\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n } {\n const config = parseConfigJson(info.configJson);\n const env = config.env ? (Array.isArray(config.env) ? config.env : config.env) : [];\n const envCount = Array.isArray(env) ? env.length : Object.keys(env as Record<string, unknown>).length;\n const volumes = config.volumes ?? {};\n\n return {\n name: info.name,\n status: info.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n envCount,\n volumeCount: Object.keys(volumes).length,\n createdAt: msToIsoString(info.createdAt),\n updatedAt: msToIsoString(info.updatedAt),\n };\n }\n\n private async readMsbInspect(name: string): Promise<MsbInspectEnvVolumes | undefined> {\n try {\n const { stdout } = await execAsync(\n `${getMsbPath()} inspect ${name} --format json`,\n { timeout: 5000 }\n );\n return parseMsbInspectEnvVolumes(stdout);\n } catch {\n return undefined;\n }\n }\n\n private async ensureNamedVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Promise<void> {\n if (!volumes) {\n return;\n }\n\n const defaultQuotaMib = Number(process.env.MICROSANDBOX_VOLUME_QUOTA_MIB ?? \"2048\");\n\n const namedVolumes = Object.values(volumes).filter(\n (v): v is Extract<VolumeConfig, { type: \"named\" }> => v.type === \"named\"\n );\n\n await Promise.all(\n namedVolumes.map(async (definition) => {\n try {\n await Volume.get(definition.name);\n } catch {\n await Volume.builder(definition.name).quota(defaultQuotaMib).create();\n }\n })\n );\n }\n\n private async getOrEnsureNative(name: string): Promise<RuntimeNative> {\n return (await this.registry.ensure(name)) as RuntimeNative;\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{\n name: string;\n status: string;\n }> {\n const image = input.image ?? process.env.MICROSANDBOX_IMAGE ?? \"python:3.11-slim\";\n const cpus = input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? \"1\");\n const memoryMib = input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? \"512\");\n\n await this.ensureNamedVolumes(input.volumes);\n\n // Lifecycle governance is applied by SandboxRegistry: a positive\n // `timeoutSeconds` is mapped to the microsandbox builder's `idleTimeout`\n // (the sandbox's idle lifetime); `timeoutSeconds: null` marks the resident\n // idle-exempt so the idle sweeper never pauses it (`alwaysOn`);\n // `undefined` keeps the registry default (`MICROSANDBOX_IDLE_TIMEOUT_MS`).\n // The lifetime is applied at create time only — changing it for an\n // existing sandbox does not force a recreate.\n await this.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: input.volumes,\n entrypoint: input.entrypoint,\n timeoutSeconds: input.timeoutSeconds,\n exposePorts: input.exposePorts,\n });\n\n return {\n name,\n status: \"running\",\n };\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n await this.registry.ensure(name);\n return { name, status: \"running\" };\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.pause(name);\n return { name, status: \"stopped\" };\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n let handle;\n try {\n handle = await Sandbox.get(name);\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n try {\n if (handle.status === \"running\") {\n const native = await handle.connect();\n await native.kill();\n }\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"write to relay\")) {\n return { name, status: \"unknown\" };\n }\n throw error;\n } finally {\n this.registry.remove(name);\n }\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.removeAndDelete(name);\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof HttpError) throw error;\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n const all: SandboxHandle[] = await Sandbox.list();\n\n const items = all\n .map((info) =>\n this.toListItem({\n name: info.name,\n status: info.status,\n configJson: info.configJson,\n createdAt: info.createdAt,\n updatedAt: info.updatedAt,\n })\n )\n .filter((item) => {\n if (_query.status && item.status !== _query.status) {\n return false;\n }\n\n if (_query.image && item.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [item.name, item.image]\n .filter((value): value is string => Boolean(value))\n .join(\" \")\n .toLowerCase();\n\n if (!haystack.includes(_query.search.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n\n return { items, total: items.length };\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n env: unknown;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n const config = parseConfigJson(handle.configJson);\n\n const msbData = await this.readMsbInspect(name);\n const env = msbData?.env ?? config.env ?? {};\n const volumes = msbData?.volumes ?? config.volumes ?? {};\n\n let metrics: SandboxRuntimeMetrics | undefined;\n\n try {\n const m = await handle.metrics();\n metrics = {\n cpuPercent: m.cpuPercent,\n memoryBytes: m.memoryBytes,\n memoryLimitBytes: m.memoryLimitBytes,\n diskReadBytes: m.diskReadBytes,\n diskWriteBytes: m.diskWriteBytes,\n netRxBytes: m.netRxBytes,\n netTxBytes: m.netTxBytes,\n uptimeMs: m.uptimeMs,\n timestampMs: m.timestamp.getTime(),\n };\n } catch {\n metrics = undefined;\n }\n\n return {\n name: handle.name,\n status: handle.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n env,\n volumes,\n metrics,\n createdAt: msToIsoString(handle.createdAt),\n updatedAt: msToIsoString(handle.updatedAt),\n };\n } catch {\n return undefined;\n }\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n return { name, status: handle.status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n /**\n * Resolve the relative proxy path for a guest port published at create time.\n *\n * @param name - Sandbox name\n * @param port - Guest port passed via `ensureSandbox({ exposePorts })`\n * @returns The relative proxy path and any required headers\n * @throws {HttpError} ENDPOINT_NOT_PUBLISHED when the port was never published\n */\n async getEndpoint(\n name: string,\n port: number\n ): Promise<{ endpoint: string; headers?: Record<string, string> }> {\n return this.registry.getEndpoint(name, port);\n }\n\n /**\n * Resolve the loopback `host:port` the sandbox proxy dials for a published port.\n *\n * @param name - Sandbox name\n * @param port - Guest port passed via `ensureSandbox({ exposePorts })`\n * @returns The loopback `host:port` target\n * @throws {HttpError} ENDPOINT_NOT_PUBLISHED when the port was never published\n */\n resolveProxyTarget(name: string, port: number): string {\n return this.registry.getProxyTarget(name, port);\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n try {\n const content = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n return { path: resolvedPath, content };\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n throw error;\n }\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const parts = resolvedPath.split(\"/\").filter(Boolean);\n for (let i = 1; i < parts.length; i++) {\n const dir = \"/\" + parts.slice(0, i).join(\"/\");\n try {\n await native.fs().mkdir(dir);\n } catch {\n // directory may already exist or parent missing, continue\n }\n }\n await native.fs().write(resolvedPath, Buffer.from(content));\n return { path: resolvedPath };\n }\n\n async deleteFile(sandboxName: string, path: string): Promise<{ path: string }> {\n const resolvedPath = this.resolveDeletePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const sandboxFs = native.fs();\n let metadata: Awaited<ReturnType<typeof sandboxFs.stat>>;\n try {\n metadata = await sandboxFs.stat(resolvedPath);\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new HttpError(500, \"FILE_STAT_ERROR\", `Failed to inspect '${path}': ${message}`);\n }\n\n if (metadata.kind === \"symlink\") {\n throw new HttpError(400, \"FILE_NOT_REGULAR\", `Cannot delete '${path}': symlinks are not allowed`);\n }\n if (metadata.kind === \"directory\") {\n throw new HttpError(400, \"FILE_NOT_REGULAR\", `Cannot delete '${path}': target is a directory`);\n }\n if (metadata.kind !== \"file\") {\n throw new HttpError(400, \"FILE_NOT_REGULAR\", `Cannot delete '${path}': target is not a regular file`);\n }\n\n try {\n await sandboxFs.remove(resolvedPath);\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new HttpError(500, \"FILE_DELETE_ERROR\", `Failed to delete '${path}': ${message}`);\n }\n return { path: resolvedPath };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const entries: Array<{ path: string; type: string }> = [];\n const visited = new Set<string>();\n\n const visit = async (dir: string): Promise<void> => {\n if (visited.has(dir)) return;\n visited.add(dir);\n const listed = await native.fs().list(dir);\n for (const entry of listed) {\n entries.push({ path: entry.path, type: entry.kind });\n if (recursive && entry.kind === \"directory\") {\n await visit(entry.path);\n }\n }\n };\n\n await visit(resolvedPath);\n return { entries };\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const matchFlag = pattern.includes(\"/\") ? \"-path\" : \"-name\";\n const output = await native.exec(\"find\", [resolvedPath, matchFlag, pattern, \"-type\", \"f\"]);\n return { files: output.stdout().split(\"\\n\").filter(Boolean) };\n }\n\n async searchInFile(\n sandboxName: string,\n path: string,\n query: string\n ): Promise<{ matches: Array<{ line: number; content: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n let stdout: string;\n\n try {\n const output = await native.exec(\"grep\", [\"-n\", \"-E\", query, resolvedPath]);\n stdout = output.stdout();\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === 1) {\n return { matches: [] };\n }\n\n throw error;\n }\n\n return {\n matches: stdout\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const separator = line.indexOf(\":\");\n return {\n line: Number(line.slice(0, separator)),\n content: line.slice(separator + 1),\n };\n }),\n };\n }\n\n async replaceInFile(\n sandboxName: string,\n input: { path: string; search: string; replace: string }\n ): Promise<{ replaced: number }> {\n const resolvedPath = this.resolvePath(input.path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n const original = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n\n if (!input.search) {\n return { replaced: 0 };\n }\n\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) {\n return { replaced: 0 };\n }\n\n const updated = original.split(input.search).join(input.replace);\n await fs.write(resolvedPath, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n await native.fs().write(resolvedPath, Buffer.from(contentBase64, \"base64\"));\n return { path: resolvedPath };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n try {\n const data = await native.fs().read(resolvedPath);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path: resolvedPath, contentBase64: buffer.toString(\"base64\") };\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n throw error;\n }\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const native = await this.getOrEnsureNative(input.sandboxName);\n const output = input.timeoutMs\n ? await this.runShellWithTimeout(native, input.command, input.timeoutMs)\n : await native.shell(input.command);\n\n return {\n stdout: output.stdout(),\n stderr: output.stderr(),\n exitCode: output.code ?? 0,\n };\n }\n\n /**\n * Run a shell command with a hard timeout by streaming it and killing the\n * handle once `timeoutMs` elapses, preserving the same shell semantics as\n * {@link RuntimeNative.shell} (which has no timeout knob).\n */\n private async runShellWithTimeout(\n native: RuntimeNative,\n command: string,\n timeoutMs: number\n ): Promise<ExecOutputLike> {\n const handle = await native.shellStream(command);\n const timer = setTimeout(() => {\n void handle.kill().catch(() => {});\n }, timeoutMs);\n try {\n return await handle.collect();\n } finally {\n clearTimeout(timer);\n }\n }\n\n async getSandboxLogs(\n name: string,\n opts: SandboxLogsInput\n ): Promise<{\n entries: Array<{\n timestamp: string;\n source: string;\n sessionId: number | null;\n text: string;\n }>;\n }> {\n const handle: SandboxHandle = await Sandbox.get(name);\n\n const logOpts: { tail?: number; since?: Date; until?: Date; sources?: readonly LogReadSource[] } = {};\n\n if (opts.tail !== undefined) {\n logOpts.tail = opts.tail;\n }\n\n if (opts.since) {\n logOpts.since = new Date(opts.since);\n }\n\n if (opts.until) {\n logOpts.until = new Date(opts.until);\n }\n\n if (opts.sources && opts.sources.length > 0) {\n logOpts.sources = opts.sources as LogReadSource[];\n } else {\n logOpts.sources = [\"all\" as LogReadSource];\n }\n\n const entries = await handle.logs(logOpts);\n\n return {\n entries: entries.map((entry) => ({\n timestamp: entry.timestamp.toISOString(),\n source: entry.source,\n sessionId: entry.sessionId,\n text: entry.text(),\n })),\n };\n }\n}\n","export function getMsbPath(): string {\n return process.env.MICROSANDBOX_CLI_PATH ?? `${process.env.HOME ?? \"/root\"}/.microsandbox/bin/msb`;\n}\n","import cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify, { type FastifyInstance } from \"fastify\";\nimport { toErrorResponse } from \"./lib/errors\";\nimport { registerHealthRoutes } from \"./routes/health\";\nimport { registerImageRoutes } from \"./routes/images\";\nimport { registerSandboxRoutes } from \"./routes/sandbox\";\nimport { registerVolumeFsRoutes } from \"./routes/volume-fs\";\nimport { ImageService } from \"./services/ImageService\";\nimport { MicrosandboxRuntimeService } from \"./services/MicrosandboxRuntimeService\";\nimport { configureSwagger } from \"./swagger\";\nimport type { RuntimeService } from \"./types/runtime-service\";\n\nexport async function buildApp({\n runtimeService = new MicrosandboxRuntimeService(),\n imageService = new ImageService(),\n apiKey,\n}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n apiKey?: string;\n} = {}): Promise<FastifyInstance> {\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024,\n });\n\n app.register(cors, {\n delegator: (request, callback) => {\n callback(null, {\n origin: true,\n methods: request.headers[\"access-control-request-method\"] ?? \"*\",\n allowedHeaders: request.headers[\"access-control-request-headers\"],\n });\n },\n });\n app.register(sensible);\n app.register(multipart);\n\n if (apiKey) {\n app.addHook(\"onRequest\", async (request, reply) => {\n if (request.method === \"OPTIONS\" || !request.url.startsWith(\"/api/\")) {\n return;\n }\n\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: {\n code: \"UNAUTHORIZED\",\n message: \"Unauthorized\",\n },\n });\n }\n });\n }\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\n registerVolumeFsRoutes(app);\n\n app.setErrorHandler((error, _request, reply) => {\n const { statusCode, body } = toErrorResponse(error);\n reply.status(statusCode).send(body);\n });\n\n await configureSwagger(app);\n\n return app;\n}\n","export type SuccessResponse<T> = {\n success: true;\n data: T;\n};\n\nexport function ok<T>(data: T): SuccessResponse<T> {\n return {\n success: true,\n data,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { ok } from \"../lib/http\";\n\nexport function registerHealthRoutes(app: FastifyInstance): void {\n app.get(\"/health\", async () => ok({ status: \"ok\" }));\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { ZodError } from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { ImageService } from \"../services/ImageService\";\nimport { imageRefQuerySchema, pullImageSchema } from \"../schemas/images\";\n\nfunction parseOrThrow<T>(parse: () => T): T {\n try {\n return parse();\n } catch (error) {\n if (error instanceof ZodError) {\n throw new HttpError(400, \"INVALID_REQUEST\", error.issues[0]?.message ?? \"Invalid request\");\n }\n\n throw error;\n }\n}\n\nexport function createImageController(imageService: ImageService) {\n return {\n listImages: async (_request: FastifyRequest, reply: FastifyReply) => {\n return reply.send(ok(await imageService.listImages()));\n },\n pullImage: async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => {\n const body = parseOrThrow(() => pullImageSchema.parse(request.body ?? {}));\n return reply.send(ok(await imageService.pullImage(body)));\n },\n getImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.getImage(query.ref)));\n },\n deleteImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.deleteImage(query.ref)));\n },\n };\n}\n","import z from \"zod\";\n\nexport const imageRefQuerySchema = z.object({\n ref: z.string().min(1),\n});\n\nexport const pullImageSchema = z.object({\n ref: z.string().min(1),\n});\n\nexport type ImageRefQuery = z.infer<typeof imageRefQuerySchema>;\nexport type PullImageInput = z.infer<typeof pullImageSchema>;\n","import type { FastifyInstance } from \"fastify\";\nimport { createImageController } from \"../controllers/images\";\nimport { ImageService } from \"../services/ImageService\";\n\nexport function registerImageRoutes(app: FastifyInstance, imageService: ImageService): void {\n const controller = createImageController(imageService);\n\n app.get(\"/api/images\", controller.listImages);\n app.post(\"/api/images/pull\", controller.pullImage);\n app.get(\"/api/images/detail\", controller.getImage);\n app.delete(\"/api/images/detail\", controller.deleteImage);\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { Transform } from \"node:stream\";\nimport { createSandboxController } from \"../controllers/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function registerSandboxRoutes(\n app: FastifyInstance,\n runtimeService: RuntimeService\n): void {\n const controller = createSandboxController(runtimeService);\n\n app.get(\"/api/sandboxes\", controller.listSandboxes);\n app.get(\"/api/sandboxes/:name\", controller.getSandbox);\n app.put(\"/api/sandboxes/:name\", controller.ensureSandbox);\n app.post(\"/api/sandboxes/:name/start\", controller.startSandbox);\n app.post(\"/api/sandboxes/:name/stop\", controller.stopSandbox);\n app.post(\"/api/sandboxes/:name/kill\", controller.killSandbox);\n app.delete(\"/api/sandboxes/:name\", controller.deleteSandbox);\n app.get(\"/api/sandboxes/:name/status\", controller.getStatus);\n app.get(\"/api/sandboxes/:name/endpoints/:port\", controller.getEndpoint);\n app.post(\"/api/sandboxes/:name/logs\", controller.getSandboxLogs);\n\n app.post(\"/api/files/read\", controller.readFile);\n app.post(\"/api/files/write\", controller.writeFile);\n app.post(\"/api/files/delete\", controller.deleteFile);\n app.post(\"/api/files/list\", controller.listPath);\n app.post(\"/api/files/find\", controller.findFiles);\n app.post(\"/api/files/search\", controller.searchInFile);\n app.post(\"/api/files/replace\", controller.replaceInFile);\n app.post(\"/api/files/upload\", controller.uploadFile);\n app.get(\"/api/files/download\", controller.downloadFile);\n\n app.post(\"/api/shell/exec\", controller.execCommand);\n\n // Scoped plugin: the streaming pass-through parser must not leak to the JSON\n // routes above, so it and the proxy route live in their own encapsulation\n // context.\n app.register(async (instance) => {\n // Fastify does not apply `bodyLimit` to stream parsers, so enforce the\n // configured limit here while still passing bytes through unbuffered.\n const bodyLimit = instance.initialConfig.bodyLimit ?? 100 * 1024 * 1024;\n // The inherited default `application/json` parser would otherwise consume\n // the body before the proxy sees it; dropping every parser for this scope\n // only makes the `\"*\"` parser the effective one.\n instance.removeAllContentTypeParsers();\n instance.addContentTypeParser(\"*\", (_request, payload, done) => {\n let received = 0;\n const limiter = new Transform({\n transform(chunk: Buffer, _encoding, callback) {\n received += chunk.length;\n if (received > bodyLimit) {\n callback(new HttpError(413, \"PAYLOAD_TOO_LARGE\", \"Request body is too large\"));\n return;\n }\n callback(null, chunk);\n },\n });\n payload.pipe(limiter);\n done(null, limiter);\n });\n instance.all(\"/api/sandboxes/:name/proxy/:port/*\", controller.proxyRequest);\n });\n}\n","import z from \"zod\";\n\nconst bindMountSchema = z.object({\n type: z.literal(\"bind\"),\n source: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst namedMountSchema = z.object({\n type: z.literal(\"named\"),\n name: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst tmpfsMountSchema = z.object({\n type: z.literal(\"tmpfs\"),\n sizeMib: z.number().int().positive().optional(),\n});\n\nexport const volumeSchema = z.union([\n bindMountSchema,\n namedMountSchema,\n tmpfsMountSchema,\n]);\n\nexport const ensureSandboxSchema = z.object({\n image: z.string().optional(),\n cpus: z.number().int().positive().optional(),\n memoryMib: z.number().int().positive().optional(),\n env: z.record(z.string()).optional(),\n volumes: z.record(volumeSchema).optional(),\n /** Main process command; replaces the default `tail -f /dev/null`. */\n entrypoint: z.array(z.string().min(1)).nonempty().optional(),\n /** Absolute lifetime in seconds; `null` means no expiry (caller-managed). */\n timeoutSeconds: z.number().int().positive().nullable().optional(),\n /** Guest ports to publish; each is mapped to a deterministic host port. */\n exposePorts: z.array(z.number().int().positive().max(65535)).optional(),\n});\n\nexport const sandboxEndpointParamsSchema = z.object({\n name: z.string().min(1),\n port: z.coerce.number().int().positive().max(65535),\n});\n\nexport const sandboxNameParamsSchema = z.object({\n name: z.string().min(1),\n});\n\nexport const listSandboxesQuerySchema = z.object({\n status: z.enum([\"running\", \"stopped\", \"crashed\", \"unknown\"]).optional(),\n image: z.string().min(1).optional(),\n search: z.string().min(1).optional(),\n});\n\nconst sandboxAndPathSchema = z.object({\n sandboxName: z.string().min(1),\n path: z.string().min(1),\n});\n\nexport const readFileSchema = sandboxAndPathSchema;\n\nexport const writeFileSchema = sandboxAndPathSchema.extend({\n content: z.string(),\n});\n\nexport const deleteFileSchema = sandboxAndPathSchema;\n\nexport const listPathSchema = sandboxAndPathSchema.extend({\n recursive: z.boolean().optional(),\n});\n\nexport const findFilesSchema = sandboxAndPathSchema.extend({\n pattern: z.string().min(1),\n});\n\nexport const searchInFileSchema = sandboxAndPathSchema.extend({\n query: z.string().min(1),\n});\n\nexport const replaceInFileSchema = sandboxAndPathSchema.extend({\n search: z.string(),\n replace: z.string(),\n});\n\nexport const uploadFileSchema = sandboxAndPathSchema.and(\n z.union([\n z.object({ contentBase64: z.string() }),\n z.object({ content: z.string().transform((content) => Buffer.from(content).toString(\"base64\")) }),\n ])\n);\n\nexport const downloadFileSchema = sandboxAndPathSchema;\n\nexport const shellExecSchema = z.object({\n sandboxName: z.string().min(1),\n command: z.string().min(1),\n exec_dir: z.string().optional(),\n /** Maximum execution time in milliseconds. */\n timeoutMs: z.number().int().positive().optional(),\n});\n\nexport const sandboxLogsSchema = z.object({\n tail: z.number().int().positive().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n sources: z.array(z.string()).optional(),\n});\n\nexport type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\nexport type SandboxLogsInput = z.infer<typeof sandboxLogsSchema>;\nexport type SandboxEndpointParams = z.infer<typeof sandboxEndpointParamsSchema>;\n","import http from \"node:http\";\nimport type { Readable } from \"node:stream\";\nimport { HttpError } from \"./errors\";\n\nconst HOP_BY_HOP_HEADERS = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n]);\n\n/** Incoming request headers as exposed by Fastify (values may be arrays). */\nexport type ProxyIncomingHeaders = Record<\n string,\n string | string[] | undefined\n>;\n\n/** Minimal Fastify reply surface needed to stream an upstream response back. */\nexport interface ProxyReply {\n code(status: number): unknown;\n headers(headers: Record<string, string | string[]>): unknown;\n send(payload: Readable | Buffer | string): unknown;\n}\n\n/** Options accepted by {@link pipeRequestUpstream}. */\nexport interface ProxyUpstreamOptions {\n /** Loopback `host:port` the proxy dials (never the public endpoint). */\n target: string;\n /** HTTP method to replay upstream. */\n method: string;\n /** Upstream request path, including any query string. */\n path: string;\n /** Already-sanitized headers to send upstream (see {@link buildProxyHeaders}). */\n headers: Record<string, string>;\n /** Raw request body stream; piped straight through without buffering. */\n body: NodeJS.ReadableStream;\n /** Fastify reply used to stream the upstream response back. */\n reply: ProxyReply;\n}\n\nfunction isHopByHop(header: string): boolean {\n return HOP_BY_HOP_HEADERS.has(header) || header.startsWith(\"proxy-\");\n}\n\n/**\n * Build the header set to send upstream.\n *\n * Lowercases all keys, drops hop-by-hop headers, `host`, and `content-length`\n * (the body is re-streamed), and strips the incoming `authorization` so the\n * sandbox-service key is never forwarded to the sandbox host. The host is\n * unauthenticated: the service-key-authenticated proxy route plus the\n * loopback-bound published port are the security boundary.\n *\n * @param incoming Raw incoming request headers.\n * @param requestPath Reserved for future path-based routing policy; unused today.\n */\nexport function buildProxyHeaders(\n incoming: ProxyIncomingHeaders,\n requestPath: string\n): Record<string, string> {\n void requestPath;\n\n const headers: Record<string, string> = {};\n\n for (const [rawKey, rawValue] of Object.entries(incoming)) {\n if (rawValue === undefined) continue;\n const key = rawKey.toLowerCase();\n if (isHopByHop(key)) continue;\n if (key === \"host\" || key === \"content-length\") continue;\n if (key === \"authorization\") continue;\n headers[key] = Array.isArray(rawValue) ? rawValue.join(\", \") : rawValue;\n }\n\n return headers;\n}\n\nfunction parseTarget(target: string): { hostname: string; port: number } {\n const url = new URL(target.includes(\"://\") ? target : `http://${target}`);\n return {\n hostname: url.hostname,\n port: url.port.length > 0 ? Number(url.port) : 80,\n };\n}\n\nfunction toProxyError(error: unknown): HttpError {\n if (error instanceof HttpError) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new HttpError(502, \"PROXY_ERROR\", message);\n}\n\nfunction filterResponseHeaders(\n headers: http.IncomingHttpHeaders\n): Record<string, string | string[]> {\n const filtered: Record<string, string | string[]> = {};\n for (const [rawKey, rawValue] of Object.entries(headers)) {\n if (rawValue === undefined) continue;\n const key = rawKey.toLowerCase();\n if (isHopByHop(key)) continue;\n filtered[key] = rawValue;\n }\n return filtered;\n}\n\n/**\n * Open an upstream HTTP connection to `target`, pipe the incoming `body` into\n * it, and stream the upstream response (status, headers, body) back through\n * `reply` without buffering, so SSE and large payloads pass through.\n *\n * Redirects are not followed. Any connection or request error is surfaced as\n * an {@link HttpError} with status `502` and code `PROXY_ERROR`.\n */\nexport function pipeRequestUpstream(\n options: ProxyUpstreamOptions\n): Promise<void> {\n const { target, method, path, headers, body, reply } = options;\n const { hostname, port } = parseTarget(target);\n\n return new Promise<void>((resolve, reject) => {\n const upstream = http.request(\n { hostname, port, method, path, headers },\n (upstreamResponse) => {\n try {\n reply.code(upstreamResponse.statusCode ?? 502);\n reply.headers(filterResponseHeaders(upstreamResponse.headers));\n reply.send(upstreamResponse);\n resolve();\n } catch (error) {\n upstreamResponse.destroy();\n reject(toProxyError(error));\n }\n }\n );\n\n upstream.on(\"error\", (error) => reject(toProxyError(error)));\n\n body.on(\"error\", (error) => {\n upstream.destroy();\n reject(toProxyError(error));\n });\n\n const source = body as NodeJS.ReadableStream & {\n readableEnded?: boolean;\n destroyed?: boolean;\n };\n if (source.readableEnded === true || source.destroyed === true) {\n upstream.end();\n } else {\n body.pipe(upstream);\n }\n });\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n deleteFileSchema,\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\n sandboxEndpointParamsSchema,\n sandboxLogsSchema,\n sandboxNameParamsSchema,\n searchInFileSchema,\n shellExecSchema,\n uploadFileSchema,\n writeFileSchema,\n} from \"../schemas/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { buildProxyHeaders, pipeRequestUpstream } from \"../lib/proxy\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function createSandboxController(runtimeService: RuntimeService): {\n ensureSandbox(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n startSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n stopSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n killSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listSandboxes(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getStatus(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getEndpoint(\n request: FastifyRequest<{ Params: { name: string; port: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n proxyRequest(\n request: FastifyRequest<{ Params: { name: string; port: string; \"*\": string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply | void>;\n getSandboxLogs(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n readFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n writeFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n deleteFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n listPath(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n findFiles(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n searchInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n replaceInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n uploadFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n execCommand(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n} {\n return {\n ensureSandbox: async (\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ) => {\n const body = ensureSandboxSchema.parse(request.body ?? {});\n const result = await runtimeService.ensureSandbox(request.params.name, body);\n return reply.send(ok(result));\n },\n\n startSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.startSandbox(request.params.name)));\n },\n\n stopSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.stopSandbox(request.params.name)));\n },\n\n killSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.killSandbox(request.params.name)));\n },\n\n deleteSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.deleteSandbox(request.params.name)));\n },\n\n listSandboxes: async (request, reply) => {\n const query = listSandboxesQuerySchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.listSandboxes(query)));\n },\n\n getSandbox: async (request, reply) => {\n const params = sandboxNameParamsSchema.parse(request.params ?? {});\n const sandbox = await runtimeService.getSandbox(params.name);\n\n if (!sandbox) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${params.name}' not found`);\n }\n\n return reply.send(ok(sandbox));\n },\n\n getStatus: async (request, reply) => {\n return reply.send(ok(await runtimeService.getStatus(request.params.name)));\n },\n\n getEndpoint: async (request, reply) => {\n const parsed = sandboxEndpointParamsSchema.safeParse(request.params ?? {});\n if (!parsed.success) {\n throw new HttpError(400, \"INVALID_REQUEST\", parsed.error.issues[0]?.message ?? \"Invalid request\");\n }\n return reply.send(ok(await runtimeService.getEndpoint(parsed.data.name, parsed.data.port)));\n },\n\n /**\n * Stream a request through to a sandbox's published guest port.\n *\n * The caller authenticates to this service with its `Authorization` header;\n * {@link buildProxyHeaders} strips that service key so it is not forwarded\n * to the (unauthenticated) sandbox host. The live request stream\n * (body-limited by the scoped parser, or the raw request for bodyless\n * methods) is piped upstream without buffering.\n *\n * @throws {HttpError} 404 `ENDPOINT_NOT_PUBLISHED` when the port is not exposed,\n * or 413 `PAYLOAD_TOO_LARGE` when the streaming body exceeds `bodyLimit`.\n */\n proxyRequest: async (request, reply) => {\n const { name, port } = request.params;\n const rest = request.params[\"*\"] ?? \"\";\n const target = runtimeService.resolveProxyTarget(name, Number(port));\n const path = `/${rest}`;\n const headers = buildProxyHeaders(\n request.headers as Record<string, string | string[] | undefined>,\n path\n );\n // The scoped parser hands us a size-limited pass-through stream; fall\n // back to the raw request for bodyless methods (e.g. GET), where the\n // parser never runs.\n const body = (request.body as NodeJS.ReadableStream | undefined) ?? request.raw;\n await pipeRequestUpstream({\n target,\n method: request.method,\n path,\n headers,\n body,\n reply,\n });\n },\n\n getSandboxLogs: async (request, reply) => {\n const body = sandboxLogsSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.getSandboxLogs(request.params.name, body)));\n },\n\n readFile: async (request, reply) => {\n const body = readFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.readFile(body.sandboxName, body.path)));\n },\n\n writeFile: async (request, reply) => {\n const body = writeFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.writeFile(body.sandboxName, body.path, body.content)));\n },\n\n deleteFile: async (request, reply) => {\n const parsed = deleteFileSchema.safeParse(request.body ?? {});\n if (!parsed.success) {\n throw new HttpError(400, \"VALIDATION_ERROR\", parsed.error.message);\n }\n return reply.send(ok(await runtimeService.deleteFile(parsed.data.sandboxName, parsed.data.path)));\n },\n\n listPath: async (request, reply) => {\n const body = listPathSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.listPath(body.sandboxName, body.path, body.recursive)));\n },\n\n findFiles: async (request, reply) => {\n const body = findFilesSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.findFiles(body.sandboxName, body.path, body.pattern)));\n },\n\n searchInFile: async (request, reply) => {\n const body = searchInFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.searchInFile(body.sandboxName, body.path, body.query)));\n },\n\n replaceInFile: async (request, reply) => {\n const body = replaceInFileSchema.parse(request.body ?? {});\n return reply.send(\n ok(\n await runtimeService.replaceInFile(body.sandboxName, {\n path: body.path,\n search: body.search,\n replace: body.replace,\n })\n )\n );\n },\n\n uploadFile: async (request, reply) => {\n const body = uploadFileSchema.parse(request.body ?? {});\n const contentBase64 = \"contentBase64\" in body ? body.contentBase64 : Buffer.from(body.content).toString(\"base64\");\n return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, contentBase64)));\n },\n\n downloadFile: async (request, reply) => {\n const query = downloadFileSchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.downloadFile(query.sandboxName, query.path)));\n },\n\n execCommand: async (request, reply) => {\n const body = shellExecSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.execCommand(body)));\n },\n };\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport { Volume } from \"microsandbox\";\nimport z from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport {\n volumeFsDeleteSchema,\n volumeFsReadSchema,\n volumeFsWriteSchema,\n volumeFsListSchema,\n volumeFsUploadSchema,\n volumeFsDownloadSchema,\n volumeFsMkdirSchema,\n} from \"../schemas/volume-fs\";\n\ninterface VolumeFsParams {\n name: string;\n}\n\nconst MSB_DATA_DIR = path.join(os.homedir(), \".microsandbox\");\nconst VOLUME_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\ntype VolumeFileStat = Awaited<ReturnType<typeof fs.lstat>>;\n\nfunction assertVolumeName(name: string): void {\n if (name === \".\" || name === \"..\" || !VOLUME_NAME_PATTERN.test(name)) {\n throw new HttpError(400, \"INVALID_VOLUME_NAME\", \"Invalid volume name\");\n }\n}\n\nfunction assertRegularVolumeFile(guestPath: string, stat: VolumeFileStat): void {\n if (stat.isSymbolicLink()) {\n throw new HttpError(\n 400,\n \"VOLUME_FILE_NOT_REGULAR\",\n `Cannot delete '${guestPath}': symlinks are not allowed`\n );\n }\n if (stat.isDirectory()) {\n throw new HttpError(\n 400,\n \"VOLUME_FILE_NOT_REGULAR\",\n `Cannot delete '${guestPath}': target is a directory`\n );\n }\n if (!stat.isFile()) {\n throw new HttpError(\n 400,\n \"VOLUME_FILE_NOT_REGULAR\",\n `Cannot delete '${guestPath}': target is not a regular file`\n );\n }\n}\n\nasync function resolveVolumeHostPath(name: string): Promise<string> {\n assertVolumeName(name);\n try {\n const handle = await Volume.get(name);\n assertVolumeName(handle.name);\n const vol = await Volume.builder(handle.name).create();\n return vol.path;\n } catch {\n try {\n const vol = await Volume.builder(name).create();\n return vol.path;\n } catch {\n return path.join(MSB_DATA_DIR, \"volumes\", name);\n }\n }\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(hostRoot, path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\"));\n if (!resolved.startsWith(hostRoot + path.sep) && resolved !== hostRoot) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolved;\n}\n\nfunction resolveDeleteGuestPath(hostRoot: string, guestPath: string): string {\n const pathSegments = guestPath.replace(/\\\\/g, \"/\").split(\"/\");\n if (pathSegments.includes(\"..\")) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolveGuestPath(hostRoot, guestPath);\n}\n\nasync function assertDeleteParentContained(hostRoot: string, fullPath: string): Promise<void> {\n const [rootPath, parentPath] = await Promise.all([\n fs.realpath(hostRoot),\n fs.realpath(path.dirname(fullPath)),\n ]);\n const relative = path.relative(rootPath, parentPath);\n if (\n relative === \"..\" ||\n relative.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relative)\n ) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n}\n\nexport function createVolumeFsController(): {\n readFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n writeFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; content: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listPath(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Querystring: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n uploadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; contentBase64: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n mkdir(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n} {\n return {\n readFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsReadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const content = await fs.readFile(fullPath, \"utf-8\");\n return reply.send(ok({ path: guestPath, content }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_READ_ERROR\", `Failed to read from volume '${name}': ${String(err)}`);\n }\n },\n\n writeFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_WRITE_ERROR\", `Failed to write to volume '${name}': ${String(err)}`);\n }\n },\n\n deleteFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDeleteSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveDeleteGuestPath(hostRoot, guestPath);\n await assertDeleteParentContained(hostRoot, fullPath);\n const stat = await fs.lstat(fullPath);\n assertRegularVolumeFile(guestPath, stat);\n\n const currentStat = await fs.lstat(fullPath);\n assertRegularVolumeFile(guestPath, currentStat);\n if (currentStat.dev !== stat.dev || currentStat.ino !== stat.ino) {\n throw new HttpError(\n 409,\n \"VOLUME_FILE_CHANGED\",\n `Cannot delete '${guestPath}': target changed during deletion`\n );\n }\n\n await assertDeleteParentContained(hostRoot, fullPath);\n await fs.unlink(fullPath);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new HttpError(\n 404,\n \"VOLUME_FILE_NOT_FOUND\",\n `File not found in volume '${name}'`\n );\n }\n throw new HttpError(\n 500,\n \"VOLUME_DELETE_ERROR\",\n `Failed to delete from volume '${name}': ${String(err)}`\n );\n }\n },\n\n listPath: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsListSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const dirents = await fs.readdir(fullPath, { withFileTypes: true });\n const entries = [];\n for (const d of dirents) {\n let size = 0;\n let modified: string | null = null;\n let created: string | null = null;\n try {\n const stat = await fs.lstat(path.join(fullPath, d.name));\n size = stat.size;\n modified = stat.mtime.toISOString();\n created = stat.birthtime.getTime() > 0 ? stat.birthtime.toISOString() : null;\n } catch {\n // Leave size/modified/created unset for entries that cannot be stat-ed.\n }\n entries.push({\n path: guestPath ? `${guestPath}/${d.name}` : d.name,\n kind: d.isDirectory() ? \"directory\" : d.isSymbolicLink() ? \"symlink\" : \"file\",\n size,\n mode: 0,\n modified,\n created,\n });\n }\n return reply.send(ok({ entries }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_LIST_ERROR\", `Failed to list volume '${name}': ${String(err)}`);\n }\n },\n\n downloadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDownloadSchema.parse(request.query ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const buf = await fs.readFile(fullPath);\n const contentBase64 = buf.toString(\"base64\");\n return reply.send(ok({ path: guestPath, contentBase64 }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_DOWNLOAD_ERROR\", `Failed to download from volume '${name}': ${String(err)}`);\n }\n },\n\n uploadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const data = Buffer.from(contentBase64, \"base64\");\n await fs.writeFile(fullPath, data);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_UPLOAD_ERROR\", `Failed to upload to volume '${name}': ${String(err)}`);\n }\n },\n\n mkdir: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsMkdirSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(fullPath, { recursive: true });\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_MKDIR_ERROR\", `Failed to create directory in volume '${name}': ${String(err)}`);\n }\n },\n };\n}\n","import z from \"zod\";\n\nexport const volumeFsReadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsWriteSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport const volumeFsDeleteSchema = z.object({\n path: z.string().min(1),\n});\n\nexport const volumeFsListSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsUploadSchema = z.object({\n path: z.string(),\n contentBase64: z.string().min(1),\n});\n\nexport const volumeFsDownloadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsMkdirSchema = z.object({\n path: z.string(),\n});\n","import type { FastifyInstance } from \"fastify\";\nimport { createVolumeFsController } from \"../controllers/volume-fs\";\n\nexport function registerVolumeFsRoutes(app: FastifyInstance): void {\n const controller = createVolumeFsController();\n\n app.post(\"/api/volumes/:name/fs/read\", controller.readFile);\n app.post(\"/api/volumes/:name/fs/write\", controller.writeFile);\n app.post(\"/api/volumes/:name/fs/delete\", controller.deleteFile);\n app.post(\"/api/volumes/:name/fs/list\", controller.listPath);\n app.get(\"/api/volumes/:name/fs/download\", controller.downloadFile);\n app.post(\"/api/volumes/:name/fs/upload\", controller.uploadFile);\n app.post(\"/api/volumes/:name/fs/mkdir\", controller.mkdir);\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PullImageInput } from \"../schemas/images\";\nimport { getMsbPath } from \"../lib/msb\";\n\nconst execAsync = promisify(exec);\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\ntype ImageBindings = {\n list(): Promise<ImageRecord[]>;\n pull(ref: string): Promise<ImageRecord>;\n inspect(ref: string): Promise<ImageRecord>;\n remove(ref: string): Promise<void>;\n};\n\ntype CliImageInfo = {\n architecture: string;\n created_at: string;\n digest: string;\n layer_count: number;\n os: string;\n reference: string;\n size_bytes: number;\n};\n\nclass MicrosandboxImageBindings implements ImageBindings {\n private get msb(): string {\n return getMsbPath();\n }\n\n async list(): Promise<ImageRecord[]> {\n const { stdout } = await execAsync(`${this.msb} image ls --format json`);\n const images: CliImageInfo[] = JSON.parse(stdout);\n return images.map((img) => ({\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n }));\n }\n\n async pull(ref: string): Promise<ImageRecord> {\n await execAsync(`${this.msb} image pull ${ref}`);\n return this.inspect(ref);\n }\n\n async inspect(ref: string): Promise<ImageRecord> {\n const { stdout } = await execAsync(`${this.msb} image inspect ${ref} --format json`);\n const img: CliImageInfo = JSON.parse(stdout);\n return {\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n };\n }\n\n async remove(ref: string): Promise<void> {\n await execAsync(`${this.msb} image rm ${ref}`);\n }\n}\n\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return this.deps.bindings ?? new MicrosandboxImageBindings();\n }\n\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n const items = await this.bindings.list();\n return { items, total: items.length };\n }\n\n async pullImage(input: PullImageInput): Promise<ImageRecord> {\n return await this.bindings.pull(input.ref);\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return await this.bindings.inspect(ref);\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n await this.bindings.remove(ref);\n return { ref };\n }\n}\n","import type { FastifyInstance } from \"fastify\";\nimport swagger from \"@fastify/swagger\";\nimport swaggerUi from \"@fastify/swagger-ui\";\n\nexport const defaultSwaggerConfig = {\n openapi: {\n openapi: \"3.0.0\",\n info: {\n title: \"Microsandbox Service API\",\n description:\n \"Sandbox lifecycle management, file operations, shell execution, and image registry\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"http://localhost:4002\",\n description: \"Local development\",\n },\n ],\n components: {\n securitySchemes: {\n bearerAuth: {\n type: \"http\" as const,\n scheme: \"bearer\" as const,\n bearerFormat: \"API Key\",\n },\n },\n },\n tags: [\n { name: \"Sandboxes\", description: \"Sandbox lifecycle (CRUD, start, stop, kill)\" },\n { name: \"Files\", description: \"Read, write, list, search, upload, download files inside sandboxes\" },\n { name: \"Shell\", description: \"Execute commands inside sandboxes\" },\n { name: \"Images\", description: \"OCI image management (list, pull, inspect, delete)\" },\n { name: \"Volumes\", description: \"Named volume filesystem operations\" },\n { name: \"Health\", description: \"Service health check\" },\n ],\n },\n};\n\nexport const defaultSwaggerUiConfig = {\n routePrefix: \"/api-docs\",\n uiConfig: {\n docExpansion: \"list\" as const,\n deepLinking: true,\n },\n staticCSP: true,\n transformStaticCSP: (header: string) => header,\n};\n\nexport async function configureSwagger(\n app: FastifyInstance,\n customSwaggerConfig?: Partial<typeof defaultSwaggerConfig>,\n customSwaggerUiConfig?: Partial<typeof defaultSwaggerUiConfig>\n) {\n const swaggerConfig = { ...defaultSwaggerConfig, ...customSwaggerConfig };\n const swaggerUiConfig = {\n ...defaultSwaggerUiConfig,\n ...customSwaggerUiConfig,\n };\n\n await app.register(swagger, swaggerConfig);\n await app.register(swaggerUi, swaggerUiConfig);\n}\n"],"mappings":"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","names":["path","fs","ok","Sandbox","message","path","Sandbox","fs","z","path","path","Volume","z","z","Volume","z","exec","promisify","execAsync","promisify","exec"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildApp
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2DPF6PW2.mjs";
|
|
4
4
|
|
|
5
5
|
// src/lib/server-cli.ts
|
|
6
6
|
function parsePort(raw, source) {
|
|
@@ -97,4 +97,4 @@ async function startServer({
|
|
|
97
97
|
export {
|
|
98
98
|
startServer
|
|
99
99
|
};
|
|
100
|
-
//# sourceMappingURL=chunk-
|
|
100
|
+
//# sourceMappingURL=chunk-K6J5TLVU.mjs.map
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -144,17 +144,18 @@ declare const shellExecSchema: z.ZodObject<{
|
|
|
144
144
|
sandboxName: z.ZodString;
|
|
145
145
|
command: z.ZodString;
|
|
146
146
|
exec_dir: z.ZodOptional<z.ZodString>;
|
|
147
|
-
|
|
147
|
+
/** Maximum execution time in milliseconds. */
|
|
148
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
148
149
|
}, "strip", z.ZodTypeAny, {
|
|
149
150
|
sandboxName: string;
|
|
150
151
|
command: string;
|
|
151
|
-
timeout?: number | undefined;
|
|
152
152
|
exec_dir?: string | undefined;
|
|
153
|
+
timeoutMs?: number | undefined;
|
|
153
154
|
}, {
|
|
154
155
|
sandboxName: string;
|
|
155
156
|
command: string;
|
|
156
|
-
timeout?: number | undefined;
|
|
157
157
|
exec_dir?: string | undefined;
|
|
158
|
+
timeoutMs?: number | undefined;
|
|
158
159
|
}>;
|
|
159
160
|
declare const sandboxLogsSchema: z.ZodObject<{
|
|
160
161
|
tail: z.ZodOptional<z.ZodNumber>;
|
|
@@ -489,6 +490,12 @@ declare class MicrosandboxRuntimeService {
|
|
|
489
490
|
stderr: string;
|
|
490
491
|
exitCode: number;
|
|
491
492
|
}>;
|
|
493
|
+
/**
|
|
494
|
+
* Run a shell command with a hard timeout by streaming it and killing the
|
|
495
|
+
* handle once `timeoutMs` elapses, preserving the same shell semantics as
|
|
496
|
+
* {@link RuntimeNative.shell} (which has no timeout knob).
|
|
497
|
+
*/
|
|
498
|
+
private runShellWithTimeout;
|
|
492
499
|
getSandboxLogs(name: string, opts: SandboxLogsInput): Promise<{
|
|
493
500
|
entries: Array<{
|
|
494
501
|
timestamp: string;
|
package/dist/index.mjs
CHANGED
package/dist/server.mjs
CHANGED
package/package.json
CHANGED
|
@@ -725,3 +725,43 @@ describe("MicrosandboxRuntimeService", () => {
|
|
|
725
725
|
expect(getEndpoint).toHaveBeenCalledWith("plugin-abc", 8080);
|
|
726
726
|
});
|
|
727
727
|
});
|
|
728
|
+
|
|
729
|
+
describe("MicrosandboxRuntimeService.execCommand timeout", () => {
|
|
730
|
+
it("uses the plain shell when no timeout is supplied", async () => {
|
|
731
|
+
const shell = jest.fn().mockResolvedValue({ stdout: () => "ok", stderr: () => "", code: 0 });
|
|
732
|
+
const shellStream = jest.fn();
|
|
733
|
+
const registry = {
|
|
734
|
+
ensure: jest.fn().mockResolvedValue({ shell, shellStream }),
|
|
735
|
+
} as unknown as SandboxRegistry;
|
|
736
|
+
const service = new MicrosandboxRuntimeService({ registry });
|
|
737
|
+
|
|
738
|
+
await service.execCommand({ sandboxName: "sb", command: "echo hi" });
|
|
739
|
+
|
|
740
|
+
expect(shell).toHaveBeenCalledWith("echo hi");
|
|
741
|
+
expect(shellStream).not.toHaveBeenCalled();
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it("streams the shell and kills it once the timeout elapses", async () => {
|
|
745
|
+
let resolveCollect!: (value: unknown) => void;
|
|
746
|
+
const collect = jest.fn().mockImplementation(
|
|
747
|
+
() => new Promise((resolve) => { resolveCollect = resolve; }),
|
|
748
|
+
);
|
|
749
|
+
const kill = jest.fn().mockImplementation(async () => {
|
|
750
|
+
resolveCollect({ stdout: () => "", stderr: () => "", code: 137 });
|
|
751
|
+
});
|
|
752
|
+
const shellStream = jest.fn().mockResolvedValue({ collect, kill });
|
|
753
|
+
const shell = jest.fn();
|
|
754
|
+
const registry = {
|
|
755
|
+
ensure: jest.fn().mockResolvedValue({ shell, shellStream }),
|
|
756
|
+
} as unknown as SandboxRegistry;
|
|
757
|
+
const service = new MicrosandboxRuntimeService({ registry });
|
|
758
|
+
|
|
759
|
+
const result = await service.execCommand({ sandboxName: "sb", command: "sleep 99", timeoutMs: 20 });
|
|
760
|
+
|
|
761
|
+
expect(shell).not.toHaveBeenCalled();
|
|
762
|
+
expect(shellStream).toHaveBeenCalledWith("sleep 99");
|
|
763
|
+
expect(kill).toHaveBeenCalledTimes(1);
|
|
764
|
+
expect(collect).toHaveBeenCalledTimes(1);
|
|
765
|
+
expect(result.exitCode).toBe(137);
|
|
766
|
+
});
|
|
767
|
+
});
|
|
@@ -395,7 +395,7 @@ describe("microsandbox-service routes", () => {
|
|
|
395
395
|
const execResponse = await app.inject({
|
|
396
396
|
method: "POST",
|
|
397
397
|
url: "/api/shell/exec",
|
|
398
|
-
payload: { sandboxName: "tenant-project", command: "pwd", exec_dir: "/tmp",
|
|
398
|
+
payload: { sandboxName: "tenant-project", command: "pwd", exec_dir: "/tmp", timeoutMs: 10_000 },
|
|
399
399
|
});
|
|
400
400
|
|
|
401
401
|
expect(startResponse.statusCode).toBe(200);
|
|
@@ -440,7 +440,7 @@ describe("microsandbox-service routes", () => {
|
|
|
440
440
|
sandboxName: "tenant-project",
|
|
441
441
|
command: "pwd",
|
|
442
442
|
exec_dir: "/tmp",
|
|
443
|
-
|
|
443
|
+
timeoutMs: 10_000,
|
|
444
444
|
});
|
|
445
445
|
expect(startResponse.json()).toEqual({
|
|
446
446
|
success: true,
|
package/src/schemas/sandbox.ts
CHANGED
|
@@ -95,7 +95,8 @@ export const shellExecSchema = z.object({
|
|
|
95
95
|
sandboxName: z.string().min(1),
|
|
96
96
|
command: z.string().min(1),
|
|
97
97
|
exec_dir: z.string().optional(),
|
|
98
|
-
|
|
98
|
+
/** Maximum execution time in milliseconds. */
|
|
99
|
+
timeoutMs: z.number().int().positive().optional(),
|
|
99
100
|
});
|
|
100
101
|
|
|
101
102
|
export const sandboxLogsSchema = z.object({
|
|
@@ -14,6 +14,12 @@ const execAsync = promisify(exec);
|
|
|
14
14
|
|
|
15
15
|
type VolumeConfig = NonNullable<EnsureSandboxInput["volumes"]>[string];
|
|
16
16
|
|
|
17
|
+
type ExecOutputLike = {
|
|
18
|
+
stdout(): string;
|
|
19
|
+
stderr(): string;
|
|
20
|
+
get code(): number;
|
|
21
|
+
};
|
|
22
|
+
|
|
17
23
|
type RuntimeNative = {
|
|
18
24
|
fs(): {
|
|
19
25
|
readString(path: string): Promise<string>;
|
|
@@ -30,10 +36,10 @@ type RuntimeNative = {
|
|
|
30
36
|
stderr(): string;
|
|
31
37
|
get code(): number;
|
|
32
38
|
}>;
|
|
33
|
-
shell(script: string): Promise<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
shell(script: string): Promise<ExecOutputLike>;
|
|
40
|
+
shellStream(script: string): Promise<{
|
|
41
|
+
collect(): Promise<ExecOutputLike>;
|
|
42
|
+
kill(): Promise<void>;
|
|
37
43
|
}>;
|
|
38
44
|
stop(): Promise<void>;
|
|
39
45
|
kill(): Promise<void>;
|
|
@@ -638,7 +644,9 @@ export class MicrosandboxRuntimeService {
|
|
|
638
644
|
|
|
639
645
|
async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {
|
|
640
646
|
const native = await this.getOrEnsureNative(input.sandboxName);
|
|
641
|
-
const output =
|
|
647
|
+
const output = input.timeoutMs
|
|
648
|
+
? await this.runShellWithTimeout(native, input.command, input.timeoutMs)
|
|
649
|
+
: await native.shell(input.command);
|
|
642
650
|
|
|
643
651
|
return {
|
|
644
652
|
stdout: output.stdout(),
|
|
@@ -647,6 +655,27 @@ export class MicrosandboxRuntimeService {
|
|
|
647
655
|
};
|
|
648
656
|
}
|
|
649
657
|
|
|
658
|
+
/**
|
|
659
|
+
* Run a shell command with a hard timeout by streaming it and killing the
|
|
660
|
+
* handle once `timeoutMs` elapses, preserving the same shell semantics as
|
|
661
|
+
* {@link RuntimeNative.shell} (which has no timeout knob).
|
|
662
|
+
*/
|
|
663
|
+
private async runShellWithTimeout(
|
|
664
|
+
native: RuntimeNative,
|
|
665
|
+
command: string,
|
|
666
|
+
timeoutMs: number
|
|
667
|
+
): Promise<ExecOutputLike> {
|
|
668
|
+
const handle = await native.shellStream(command);
|
|
669
|
+
const timer = setTimeout(() => {
|
|
670
|
+
void handle.kill().catch(() => {});
|
|
671
|
+
}, timeoutMs);
|
|
672
|
+
try {
|
|
673
|
+
return await handle.collect();
|
|
674
|
+
} finally {
|
|
675
|
+
clearTimeout(timer);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
650
679
|
async getSandboxLogs(
|
|
651
680
|
name: string,
|
|
652
681
|
opts: SandboxLogsInput
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/SandboxRegistry.ts","../src/lib/errors.ts","../src/services/publishedPorts.ts","../src/services/MicrosandboxRuntimeService.ts","../src/lib/msb.ts","../src/app.ts","../src/lib/http.ts","../src/routes/health.ts","../src/controllers/images.ts","../src/schemas/images.ts","../src/routes/images.ts","../src/routes/sandbox.ts","../src/schemas/sandbox.ts","../src/lib/proxy.ts","../src/controllers/sandbox.ts","../src/controllers/volume-fs.ts","../src/schemas/volume-fs.ts","../src/routes/volume-fs.ts","../src/services/ImageService.ts","../src/swagger.ts"],"sourcesContent":["import { Sandbox, MountBuilder } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport { readdirSync, readFileSync, unlinkSync } from \"fs\";\nimport { join } from \"path\";\nimport { HttpError } from \"../lib/errors\";\nimport {\n allocateHostPort,\n decodePublishedPorts,\n encodePublishedPorts,\n PUBLISHED_PORTS_ENV,\n resolveHostPortRange,\n} from \"./publishedPorts\";\n\nconst DEFAULT_IMAGE = process.env.MICROSANDBOX_IMAGE ?? \"daytonaio/sandbox:0.6.0\";\nconst DEFAULT_IDLE_TIMEOUT_MS = Number(process.env.MICROSANDBOX_IDLE_TIMEOUT_MS) || 600_000;\nconst DEFAULT_REMOVE_AFTER_PAUSED_MS = 7 * 24 * 60 * 60 * 1000;\nconst SWEEP_INTERVAL_MS = 30_000;\nconst SWEEP_STOP_TIMEOUT_MS = 60_000;\nconst HEALTH_CHECK_TIMEOUT_MS = 2_000;\nconst HEALTH_CHECK_INTERVAL_MS = 30_000;\nconst SANDBOX_AGENT_SOCKET_DIR = \"/root/.microsandbox/run/agent\";\n\ntype CacheEntry = {\n native: unknown | null;\n lastAccessedAt: number;\n pausedAt?: number;\n lastCheckedAt?: number;\n broken?: boolean;\n createOptions?: Record<string, unknown>;\n /**\n * When true the idle sweeper never pauses or removes this sandbox.\n *\n * Set for residents created with `timeoutSeconds: null` (`alwaysOn`), whose\n * lifecycle is owned by the deployment service rather than idle pressure.\n */\n idleExempt?: boolean;\n /** Guest port -> host port mapping published for this sandbox. */\n publishedPorts?: Record<number, number>;\n};\n\nfunction extractConfig(configJson: string): {\n image: string;\n cpus: number;\n memoryMib: number;\n env: Record<string, string>;\n mounts: Array<{ guest: string; type: string; source?: string; name?: string; size_mib?: number; readonly?: boolean }>;\n entrypoint: string[] | undefined;\n publishedPorts: Record<number, number>;\n} | undefined {\n try {\n const raw = JSON.parse(configJson);\n const image = typeof raw.image === \"string\" ? raw.image\n : raw.image?.Oci?.reference ?? \"\";\n // The raw persisted config keeps resources snake_case (`resources.memory_mib`);\n // the public `Sandbox.builder().build()` wrapper camelCases it before\n // returning, so tolerate both casings plus legacy top-level `cpus` fields.\n const rawResources = raw.resources as\n | { cpus?: number; memory_mib?: number; memoryMib?: number }\n | undefined;\n const env: Record<string, string> = {};\n const rawEnv = raw.env;\n // The SDK persists env as an array of `{ key, value }` objects (EnvVar);\n // tolerate legacy `[key, value]` tuples and plain records as well.\n if (Array.isArray(rawEnv)) {\n for (const entry of rawEnv) {\n if (Array.isArray(entry) && entry.length >= 2) {\n env[String(entry[0])] = String(entry[1]);\n } else if (entry && typeof entry === \"object\" && \"key\" in entry) {\n const { key, value } = entry as { key?: unknown; value?: unknown };\n if (key !== undefined) {\n env[String(key)] = String(value ?? \"\");\n }\n }\n }\n } else if (rawEnv && typeof rawEnv === \"object\") {\n for (const [key, value] of Object.entries(rawEnv as Record<string, unknown>)) {\n env[key] = String(value);\n }\n }\n\n // The SDK serializes the flattened `SandboxSpec`, whose `runtime.entrypoint`\n // is the effective entrypoint override (`raw.runtime.entrypoint`).\n const rawEntrypoint = raw.runtime?.entrypoint;\n const entrypoint = Array.isArray(rawEntrypoint) ? rawEntrypoint.map(String) : undefined;\n\n const publishedPorts: Record<number, number> = {};\n const rawPorts = raw.network?.ports;\n if (Array.isArray(rawPorts)) {\n for (const port of rawPorts) {\n const guest = Number(port?.guest_port ?? port?.guestPort);\n const host = Number(port?.host_port ?? port?.hostPort);\n if (\n Number.isInteger(guest) &&\n guest > 0 &&\n guest <= 65535 &&\n Number.isInteger(host) &&\n host > 0 &&\n host <= 65535\n ) {\n publishedPorts[guest] = host;\n }\n }\n }\n if (Object.keys(publishedPorts).length === 0) {\n Object.assign(publishedPorts, decodePublishedPorts(env[PUBLISHED_PORTS_ENV]));\n }\n\n return {\n image,\n cpus: rawResources?.cpus ?? raw.cpus ?? 1,\n memoryMib: rawResources?.memory_mib ?? rawResources?.memoryMib ?? raw.memory_mib ?? raw.memoryMib ?? 512,\n env,\n mounts: Array.isArray(raw.mounts) ? raw.mounts : [],\n entrypoint,\n publishedPorts,\n };\n } catch {\n return undefined;\n }\n}\n\nexport class SandboxRegistry {\n private handles = new Map<string, CacheEntry>();\n private creating = new Map<string, Promise<unknown>>();\n private stopping = new Set<string>();\n private readonly idleTimeoutMs: number;\n private sweepTimer?: ReturnType<typeof setInterval>;\n\n constructor(idleTimeoutMs?: number) {\n this.idleTimeoutMs = idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n this.cleanupOrphanedSockets();\n if (this.idleTimeoutMs > 0) {\n this.startSweeper();\n }\n }\n\n private startSweeper(): void {\n this.sweepTimer = setInterval(() => {\n const now = Date.now();\n for (const [name, entry] of this.handles) {\n if (entry.idleExempt) {\n continue;\n }\n if (entry.native && now - entry.lastAccessedAt > this.idleTimeoutMs) {\n if (this.stopping.has(name)) {\n continue;\n }\n console.log(`[SandboxRegistry] sweeper pausing idle sandbox name=${name} idleMs=${now - entry.lastAccessedAt}`);\n this.stopping.add(name);\n void Promise.race([\n (entry.native as { stop(): Promise<void> }).stop(),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"stop timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]).then(() => {\n console.log(`[SandboxRegistry] sweeper paused name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper pause failed name=${name} err=${err.message}`);\n }).finally(() => {\n entry.native = null;\n entry.pausedAt = Date.now();\n this.stopping.delete(name);\n });\n } else if (!entry.native && entry.pausedAt && now - entry.pausedAt > DEFAULT_REMOVE_AFTER_PAUSED_MS) {\n console.log(`[SandboxRegistry] sweeper removing paused sandbox name=${name} pausedMs=${now - entry.pausedAt}`);\n void this.removeAndDelete(name).then(() => {\n console.log(`[SandboxRegistry] sweeper removed name=${name}`);\n }).catch((err: Error) => {\n console.log(`[SandboxRegistry] sweeper remove failed name=${name} err=${err.message}`);\n });\n }\n }\n }, SWEEP_INTERVAL_MS);\n (this.sweepTimer as { unref?: () => void }).unref?.();\n }\n\n destroy(): void {\n if (this.sweepTimer) {\n clearInterval(this.sweepTimer);\n this.sweepTimer = undefined;\n }\n this.handles.clear();\n this.creating.clear();\n }\n\n remove(name: string): void {\n this.handles.delete(name);\n this.creating.delete(name);\n }\n\n /**\n * Return the guest->host port map published for a sandbox.\n *\n * @param name - Sandbox name\n * @returns A shallow copy of the guest->host map (empty when unknown), so\n * callers cannot mutate the cached entry.\n */\n getPublishedPorts(name: string): Record<number, number> {\n return { ...(this.handles.get(name)?.publishedPorts ?? {}) };\n }\n\n /**\n * Resolve the relative proxy path for a published guest port.\n *\n * A loopback `host:port` is unreachable from other Gateway replicas, so the\n * value points at this service's own proxy route instead. Callers compose the\n * absolute URL from their configured service base and the proxy dials the\n * loopback target internally (see {@link getProxyTarget}).\n *\n * @param name - Sandbox name\n * @param guestPort - Guest port passed via `createOptions.exposePorts`\n * @returns The relative proxy path\n * @throws HttpError `ENDPOINT_NOT_PUBLISHED` when the port was not published\n */\n getEndpoint(name: string, guestPort: number): { endpoint: string; headers?: Record<string, string> } {\n const hostPort = this.getPublishedPorts(name)[guestPort];\n if (!hostPort) {\n throw new HttpError(404, \"ENDPOINT_NOT_PUBLISHED\", `Port ${guestPort} is not published for ${name}`);\n }\n return { endpoint: `/api/sandboxes/${encodeURIComponent(name)}/proxy/${guestPort}` };\n }\n\n /**\n * Resolve the loopback `host:port` the proxy dials for a published guest port.\n *\n * @param name - Sandbox name\n * @param guestPort - Guest port passed via `createOptions.exposePorts`\n * @returns The loopback `host:port` target\n * @throws HttpError `ENDPOINT_NOT_PUBLISHED` when the port was not published\n */\n getProxyTarget(name: string, guestPort: number): string {\n const hostPort = this.getPublishedPorts(name)[guestPort];\n if (!hostPort) {\n throw new HttpError(404, \"ENDPOINT_NOT_PUBLISHED\", `Port ${guestPort} is not published for ${name}`);\n }\n return `127.0.0.1:${hostPort}`;\n }\n\n cleanupOrphanedSockets(): void {\n try {\n const activeSockets = new Set<string>();\n const unixSockets = readFileSync(\"/proc/net/unix\", \"utf-8\");\n for (const line of unixSockets.split(\"\\n\")) {\n const path = line.trim().split(\" \").pop();\n if (path && path.startsWith(SANDBOX_AGENT_SOCKET_DIR)) {\n activeSockets.add(path);\n }\n }\n for (const entry of readdirSync(SANDBOX_AGENT_SOCKET_DIR)) {\n const fullPath = join(SANDBOX_AGENT_SOCKET_DIR, entry);\n if (!activeSockets.has(fullPath)) {\n unlinkSync(fullPath);\n console.log(`[SandboxRegistry] removed orphaned socket: ${entry}`);\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n console.log(`[SandboxRegistry] socket cleanup skipped: ${(err as Error).message}`);\n }\n }\n }\n\n async removeAndDelete(name: string): Promise<void> {\n try {\n const handle = await Promise.race([\n Sandbox.get(name),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"Sandbox.get timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n if (handle.status === \"running\") {\n try {\n const native = await Promise.race([\n handle.connect(),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"handle.connect timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n await Promise.race([\n (native as { stop(): Promise<void> }).stop(),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"stop timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n } catch { /* ignore */ }\n }\n await Promise.race([\n Sandbox.remove(name),\n new Promise<void>((_, reject) => setTimeout(() => reject(new Error(\"Sandbox.remove timed out\")), SWEEP_STOP_TIMEOUT_MS)),\n ]);\n } catch { /* best effort, always clean cache */ }\n this.remove(name);\n this.cleanupOrphanedSockets();\n }\n\n async pause(name: string): Promise<void> {\n const entry = this.handles.get(name);\n if (!entry) {\n await Sandbox.get(name);\n return;\n }\n if (!entry.native) return;\n const handle = await Sandbox.get(name);\n if (handle.status === \"running\") {\n try {\n await (entry.native as { stop(): Promise<void> }).stop();\n } catch { /* ignore */ }\n }\n entry.native = null;\n entry.pausedAt = Date.now();\n }\n\n private async healthCheck(native: unknown): Promise<boolean> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n try {\n await Promise.race([\n fs.list(\"/\"),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"health check timed out\")), HEALTH_CHECK_TIMEOUT_MS)),\n ]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async waitForFs(native: unknown, maxRetries = 10): Promise<void> {\n const fs = (native as { fs(): { list(path: string): Promise<unknown> } }).fs();\n for (let i = 0; i < maxRetries; i++) {\n try {\n await Promise.race([\n fs.list(\"/\"),\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error(\"FS check timed out\")), 5000)),\n ]);\n return;\n } catch {\n await new Promise((r) => setTimeout(r, 200));\n }\n }\n throw new Error(\"FS not ready after start\");\n }\n\n private hasConfigMismatch(\n originalConfig: ReturnType<typeof extractConfig>,\n createOptions: Record<string, unknown>\n ): boolean {\n const volumeDefs = createOptions.volumes as Record<string, { type: string }> | undefined;\n const requestEnv = createOptions.env as Record<string, string> | undefined;\n const requestExposePorts = createOptions.exposePorts as number[] | undefined;\n const requestEntrypoint = createOptions.entrypoint as string[] | undefined;\n\n if (requestEntrypoint) {\n const existingEntrypoint = originalConfig?.entrypoint;\n // Fail-safe: only recreate when the existing config POSITIVELY records a\n // different entrypoint. An absent one may be serialization drift (or a\n // sandbox created without an override), so keep the running sandbox.\n if (\n existingEntrypoint !== undefined &&\n JSON.stringify(requestEntrypoint) !== JSON.stringify(existingEntrypoint)\n ) {\n console.log(`[SandboxRegistry] entrypoint mismatch, recreating...`);\n return true;\n }\n }\n\n if (volumeDefs && Object.keys(volumeDefs).length > 0) {\n const existingGuests = new Set((originalConfig?.mounts ?? []).map((m: { guest: string }) => m.guest));\n const requestedGuests = Object.keys(volumeDefs);\n const missing = requestedGuests.filter(g => !existingGuests.has(g));\n if (missing.length > 0) {\n console.log(`[SandboxRegistry] volumes mismatch, missing=${missing.join(\",\")}, recreating...`);\n return true;\n }\n }\n\n if (requestEnv && originalConfig?.env) {\n for (const [key, value] of Object.entries(requestEnv)) {\n if (originalConfig.env[key] !== value) {\n console.log(`[SandboxRegistry] env mismatch (key=${key}), recreating...`);\n return true;\n }\n }\n }\n\n if (requestExposePorts) {\n // Compare guest-port sets only: host ports are allocated deterministically\n // from (name, guestPort), so a changed guest set is the meaningful signal.\n const existingGuests = new Set(Object.keys(originalConfig?.publishedPorts ?? {}));\n const requested = new Set(requestExposePorts.map(String));\n const same = existingGuests.size === requested.size && [...requested].every(g => existingGuests.has(g));\n if (!same) {\n console.log(`[SandboxRegistry] exposePorts mismatch, recreating...`);\n return true;\n }\n }\n\n return false;\n }\n\n async ensure(name: string, createOptions?: Record<string, unknown>): Promise<unknown> {\n const tStart = Date.now();\n\n const cached = this.handles.get(name);\n\n if (cached?.native && !this.stopping.has(name)) {\n const now = Date.now();\n if (!cached.lastCheckedAt || now - cached.lastCheckedAt > HEALTH_CHECK_INTERVAL_MS) {\n const tCheck = Date.now();\n const ok = await this.healthCheck(cached.native);\n cached.lastCheckedAt = now;\n if (ok) {\n cached.lastAccessedAt = now;\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms health_ok elapsed=${Date.now() - tCheck}ms`);\n return cached.native;\n }\n console.log(`[SandboxRegistry] ensure name=${name} HEALTH_FAIL will_recreate elapsed=${Date.now() - tStart}ms`);\n cached.native = null;\n cached.broken = true;\n } else {\n cached.lastAccessedAt = now;\n console.log(`[SandboxRegistry] ensure name=${name} CACHE_HIT elapsed=${Date.now() - tStart}ms`);\n return cached.native;\n }\n }\n\n if (cached?.native && this.stopping.has(name)) {\n console.log(`[SandboxRegistry] ensure name=${name} STALE_NATIVE (being stopped), forcing revive`);\n cached.native = null;\n }\n\n if (cached && !cached.native) {\n cached.pausedAt = undefined;\n console.log(`[SandboxRegistry] ensure name=${name} REVIVE idled=${Date.now() - cached.lastAccessedAt}ms`);\n }\n\n const inflight = this.creating.get(name);\n if (inflight) {\n console.log(`[SandboxRegistry] ensure name=${name} AWAITING_INFLIGHT`);\n return inflight;\n }\n\n const creation = (async () => {\n const tCreate = Date.now();\n let native: unknown;\n const image = (createOptions?.image as string) ?? DEFAULT_IMAGE;\n const cpus = (createOptions?.cpus as number) ?? 1;\n const memoryMib = (createOptions?.memoryMib as number) ?? 512;\n const env = (createOptions?.env as Record<string, string>) ?? undefined;\n\n let originalConfig: ReturnType<typeof extractConfig>;\n let publishedPorts: Record<number, number> = {};\n\n const existing = this.handles.get(name);\n if (existing?.broken) {\n console.log(`[SandboxRegistry] ensure name=${name} BROKEN removing before recreate`);\n await this.removeAndDelete(name);\n this.handles.set(name, { native: null, lastAccessedAt: Date.now(), createOptions: existing.createOptions ?? cached?.createOptions });\n } else {\n try {\n const tGet = Date.now();\n const handle: SandboxHandle = await Sandbox.get(name);\n console.log(`[SandboxRegistry] Sandbox.get name=${name} status=${handle.status} elapsed=${Date.now() - tGet}ms`);\n\n originalConfig = extractConfig(handle.configJson);\n\n const recoveredPorts = originalConfig?.publishedPorts ?? {};\n if (Object.keys(recoveredPorts).length > 0) {\n publishedPorts = recoveredPorts;\n }\n\n if (handle.status === \"running\" || handle.status === \"stopped\") {\n const isNewConnection = !cached;\n if (isNewConnection && createOptions && this.hasConfigMismatch(originalConfig, createOptions)) {\n await this.removeAndDelete(name);\n native = undefined;\n } else if (handle.status === \"running\") {\n const tConnect = Date.now();\n native = await Promise.race([\n handle.connect(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"handle.connect timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(`[SandboxRegistry] handle.connect name=${name} elapsed=${Date.now() - tConnect}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } else {\n try {\n const tStart2 = Date.now();\n native = await Promise.race([\n Sandbox.startDetached(name),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"startDetached timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(`[SandboxRegistry] startDetached name=${name} elapsed=${Date.now() - tStart2}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n } catch {\n if (!native) {\n await this.removeAndDelete(name);\n }\n }\n }\n } else if (handle.status === \"crashed\" || handle.status === \"draining\") {\n await this.removeAndDelete(name);\n } else {\n await this.removeAndDelete(name);\n }\n } catch (err) {\n console.log(`[SandboxRegistry] ensure name=${name} existing_check failed err=${(err as Error).message}`);\n native = undefined;\n }\n }\n console.log(`[SandboxRegistry] phase=existing_check name=${name} hasNative=${!!native} elapsed=${Date.now() - tCreate}ms`);\n\n if (!native) {\n const effectiveOptions = createOptions ?? cached?.createOptions;\n if (!effectiveOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} NOT_FOUND elapsed=${Date.now() - tStart}ms`);\n throw new Error(`Sandbox ${name} not found`);\n }\n if (!createOptions && cached?.createOptions) {\n console.log(`[SandboxRegistry] ensure name=${name} RECOVER_OPTIONS elapsed=${Date.now() - tStart}ms`);\n }\n const tBuild = Date.now();\n const volumeDefs = effectiveOptions?.volumes as Record<string, { type: string; source?: string; name?: string; sizeMib?: number; readonly?: boolean }> | undefined;\n const resolvedImage = (effectiveOptions?.image as string) ?? originalConfig?.image ?? image;\n console.log(\n `[SandboxRegistry] create sandbox=${name} image=${resolvedImage} ` +\n `from=${(effectiveOptions?.image as string) ? \"request\" : originalConfig?.image ? \"originalConfig\" : \"default\"}`\n );\n const resolvedCpus = (effectiveOptions?.cpus as number) ?? originalConfig?.cpus ?? cpus;\n const resolvedMemoryMib = (effectiveOptions?.memoryMib as number) ?? originalConfig?.memoryMib ?? memoryMib;\n const resolvedEnv = (effectiveOptions?.env as Record<string, string>) ?? originalConfig?.env ?? env;\n const resolvedMounts = originalConfig?.mounts ?? [];\n // `timeoutSeconds` maps to microsandbox's only lifetime knob, the\n // builder's `idleTimeout(secs)`. A positive value is applied as the\n // sandbox's idle lifetime below; `null` marks the entry idle-exempt so\n // the sweeper never pauses it (`alwaysOn` residents); `undefined`\n // keeps the registry default (`MICROSANDBOX_IDLE_TIMEOUT_MS`).\n const timeoutSeconds = effectiveOptions?.timeoutSeconds;\n\n // Allocate host ports synchronously, consulting ports already committed by\n // other entries. Per-name safety comes from the single-flight `creating`\n // map: concurrent `ensure` calls for the same name share one creation.\n // Concurrent creates of *different* names are not reserved in flight, so a\n // collision is possible (though improbable with the 20k-port range) and\n // surfaces as a bind failure; an in-flight reservation map is a Plan 2\n // follow-up.\n const exposePorts = (effectiveOptions?.exposePorts as number[] | undefined) ?? [];\n const portRange = resolveHostPortRange();\n const taken = new Set<number>();\n for (const [otherName, otherEntry] of this.handles) {\n if (otherName === name) continue;\n for (const host of Object.values(otherEntry.publishedPorts ?? {})) taken.add(host);\n }\n publishedPorts = {};\n for (const guestPort of new Set(exposePorts)) {\n publishedPorts[guestPort] = allocateHostPort(name, guestPort, portRange, (p) => taken.has(p));\n taken.add(publishedPorts[guestPort]);\n }\n const resolvedEntrypoint = effectiveOptions?.entrypoint as string[] | undefined;\n const resolvedEnvWithPorts = exposePorts.length > 0\n ? { ...(resolvedEnv ?? {}), [PUBLISHED_PORTS_ENV]: encodePublishedPorts(publishedPorts) }\n : resolvedEnv;\n\n const applyVolumes = (b: ReturnType<typeof Sandbox.builder>): void => {\n if (volumeDefs) {\n for (const [guestPath, def] of Object.entries(volumeDefs)) {\n const mb = new MountBuilder(guestPath);\n if (def.type === \"bind\" && def.source) {\n mb.bind(def.source);\n } else if (def.type === \"named\" && def.name) {\n mb.named(def.name);\n } else if (def.type === \"tmpfs\") {\n mb.tmpfs();\n if (def.sizeMib) {\n mb.size(def.sizeMib);\n }\n }\n if (def.readonly) {\n mb.readonly();\n }\n b.volume(guestPath, () => mb);\n }\n } else {\n for (const mount of resolvedMounts) {\n const mb = new MountBuilder(mount.guest);\n if (mount.type === \"Bind\" || mount.type === \"bind\") {\n if (mount.source) mb.bind(mount.source);\n } else if (mount.type === \"Named\" || mount.type === \"named\") {\n if (mount.name) mb.named(mount.name);\n } else if (mount.type === \"Tmpfs\" || mount.type === \"tmpfs\") {\n mb.tmpfs();\n if (mount.size_mib) mb.size(mount.size_mib);\n }\n if (mount.readonly) {\n mb.readonly();\n }\n b.volume(mount.guest, () => mb);\n }\n }\n };\n\n const tryCreate = async () => {\n const builder = Sandbox.builder(name)\n .detached(true)\n .image(resolvedImage)\n .cpus(resolvedCpus)\n .memory(resolvedMemoryMib);\n if (typeof timeoutSeconds === \"number\" && timeoutSeconds > 0) {\n builder.idleTimeout(timeoutSeconds);\n }\n if (resolvedEntrypoint) {\n builder.entrypoint(resolvedEntrypoint);\n }\n if (resolvedEnvWithPorts) {\n builder.envs(resolvedEnvWithPorts);\n }\n applyVolumes(builder);\n for (const [guestPort, hostPort] of Object.entries(publishedPorts)) {\n builder.port(hostPort, Number(guestPort));\n }\n const tCreateInner = Date.now();\n const result = await Promise.race([\n builder.create(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error(\"builder.create timed out\")), SWEEP_STOP_TIMEOUT_MS)\n ),\n ]);\n console.log(\n `[SandboxRegistry] builder.create name=${name} image=${resolvedImage} ` +\n `elapsed=${Date.now() - tCreateInner}ms ` +\n `envKeys=${resolvedEnvWithPorts ? Object.keys(resolvedEnvWithPorts).join(\",\") : \"none\"} ` +\n `volumes=${volumeDefs ? Object.keys(volumeDefs).join(\",\") : \"none\"}`\n );\n return result;\n };\n try {\n native = await tryCreate();\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"already exists\")) {\n await this.removeAndDelete(name);\n native = await tryCreate();\n } else {\n throw err;\n }\n }\n console.log(`[SandboxRegistry] phase=create_sandbox name=${name} elapsed=${Date.now() - tBuild}ms`);\n const tFs = Date.now();\n await this.waitForFs(native);\n console.log(`[SandboxRegistry] waitForFs name=${name} elapsed=${Date.now() - tFs}ms`);\n }\n\n const totalElapsed = Date.now() - tStart;\n const entryOptions = createOptions ?? cached?.createOptions;\n const entry: CacheEntry = {\n native,\n lastAccessedAt: Date.now(),\n lastCheckedAt: Date.now(),\n createOptions: entryOptions,\n idleExempt: entryOptions?.timeoutSeconds === null,\n publishedPorts,\n };\n this.handles.set(name, entry);\n console.log(`[SandboxRegistry] ensure DONE name=${name} total=${totalElapsed}ms idleTimeout=${Math.round(this.idleTimeoutMs / 1000)}s`);\n return native;\n })();\n\n this.creating.set(name, creation);\n void creation.finally(() => this.creating.delete(name)).catch(() => {});\n creation.catch(() => {});\n\n return creation;\n }\n}\n","export class HttpError extends Error {\n constructor(\n public statusCode: number,\n public code: string,\n message: string\n ) {\n super(message);\n }\n}\n\nexport function toErrorResponse(error: unknown): {\n statusCode: number;\n body: {\n success: false;\n error: {\n code: string;\n message: string;\n };\n };\n} {\n if (error instanceof HttpError) {\n return {\n statusCode: error.statusCode,\n body: {\n success: false,\n error: {\n code: error.code,\n message: error.message,\n },\n },\n };\n }\n\n return {\n statusCode: 500,\n body: {\n success: false,\n error: {\n code: \"INTERNAL_ERROR\",\n message: error instanceof Error ? error.message : String(error),\n },\n },\n };\n}\n","import { HttpError } from \"../lib/errors\";\n\n/** Env var that mirrors the guest->host port map inside the sandbox. */\nexport const PUBLISHED_PORTS_ENV = \"LATTICE_PUBLISHED_PORTS\";\n\nconst DEFAULT_HOST_PORT_MIN = 40000;\nconst DEFAULT_HOST_PORT_MAX = 60000;\n\n/** Inclusive host-port range. */\nexport interface HostPortRange {\n min: number;\n max: number;\n}\n\nfunction parsePort(raw: string | undefined, fallback: number): number {\n if (raw === undefined) return fallback;\n const n = Number(raw);\n return Number.isInteger(n) && n > 0 && n <= 65535 ? n : fallback;\n}\n\n/**\n * Resolve the host-port range used when publishing guest ports.\n *\n * @param env - Process environment (injectable for tests)\n * @returns A valid inclusive `{ min, max }` range, defaulting to 40000-60000\n */\nexport function resolveHostPortRange(env: Record<string, string | undefined> = process.env): HostPortRange {\n const min = parsePort(env.MICROSANDBOX_HOST_PORT_MIN, DEFAULT_HOST_PORT_MIN);\n const max = parsePort(env.MICROSANDBOX_HOST_PORT_MAX, DEFAULT_HOST_PORT_MAX);\n if (min > max) return { min: DEFAULT_HOST_PORT_MIN, max: DEFAULT_HOST_PORT_MAX };\n return { min, max };\n}\n\n/** FNV-1a 32-bit hash of a string. */\nfunction hash32(input: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n\n/**\n * Deterministically allocate a host port for a `(sandboxName, guestPort)` pair,\n * probing forward (with wrap-around) when a candidate is already taken.\n *\n * @param name - Sandbox name\n * @param guestPort - Guest-side port being published\n * @param range - Inclusive host-port range\n * @param isTaken - Predicate reporting whether a host port is in use\n * @returns A free host port inside `range`\n * @throws HttpError `PORT_RANGE_EXHAUSTED` when no port is free\n */\nexport function allocateHostPort(\n name: string,\n guestPort: number,\n range: HostPortRange,\n isTaken: (port: number) => boolean\n): number {\n const span = range.max - range.min + 1;\n let candidate = range.min + (hash32(`${name}:${guestPort}`) % span);\n for (let i = 0; i < span; i++) {\n if (!isTaken(candidate)) return candidate;\n candidate = candidate >= range.max ? range.min : candidate + 1;\n }\n throw new HttpError(503, \"PORT_RANGE_EXHAUSTED\", `No free host port for ${name}:${guestPort}`);\n}\n\n/**\n * Encode a guest->host port map for the `LATTICE_PUBLISHED_PORTS` env var.\n *\n * @param ports - Map of guest port to host port\n * @returns JSON string\n */\nexport function encodePublishedPorts(ports: Record<number, number>): string {\n return JSON.stringify(ports);\n}\n\n/**\n * Decode the `LATTICE_PUBLISHED_PORTS` env var.\n *\n * @param raw - Raw env value\n * @returns A guest->host port map; `{}` when missing or malformed\n */\nexport function decodePublishedPorts(raw: string | undefined): Record<number, number> {\n if (!raw) return {};\n try {\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return {};\n const out: Record<number, number> = {};\n for (const [guest, host] of Object.entries(parsed as Record<string, unknown>)) {\n const g = Number(guest);\n if (\n Number.isInteger(g) &&\n g > 0 &&\n g <= 65535 &&\n typeof host === \"number\" &&\n Number.isInteger(host) &&\n host > 0 &&\n host <= 65535\n ) {\n out[g] = host;\n }\n }\n return out;\n } catch {\n return {};\n }\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { Sandbox, Volume } from \"microsandbox\";\nimport type { SandboxHandle } from \"microsandbox\";\nimport type { LogReadSource } from \"microsandbox\";\nimport type { EnsureSandboxInput, ListSandboxesQuery, ShellExecInput } from \"../schemas/sandbox\";\nimport type { SandboxLogsInput } from \"../schemas/sandbox\";\nimport type { SandboxRuntimeMetrics } from \"../types/runtime-service\";\nimport { HttpError } from \"../lib/errors\";\nimport { getMsbPath } from \"../lib/msb\";\nimport { SandboxRegistry } from \"./SandboxRegistry\";\n\nconst execAsync = promisify(exec);\n\ntype VolumeConfig = NonNullable<EnsureSandboxInput[\"volumes\"]>[string];\n\ntype RuntimeNative = {\n fs(): {\n readString(path: string): Promise<string>;\n readToString(path: string): Promise<string>;\n write(path: string, data: Buffer): Promise<void>;\n list(path: string): Promise<Array<{ path: string; kind: string; size?: number; modified?: unknown }>>;\n read(path: string): Promise<Buffer | Uint8Array | string>;\n mkdir(path: string): Promise<void>;\n remove(path: string): Promise<void>;\n stat(path: string): Promise<{ kind: \"file\" | \"directory\" | \"symlink\" | \"other\" }>;\n };\n exec(cmd: string, args?: string[]): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n shell(script: string): Promise<{\n stdout(): string;\n stderr(): string;\n get code(): number;\n }>;\n stop(): Promise<void>;\n kill(): Promise<void>;\n};\n\ntype SandboxConfig = {\n name: string;\n image: unknown;\n memoryMib?: number;\n cpus?: number;\n env?: unknown;\n volumes?: Record<string, unknown>;\n};\n\nfunction parseConfigJson(configJson: string): SandboxConfig {\n try {\n const raw = JSON.parse(configJson);\n const rawVolumes = raw.volumes ?? raw.mounts;\n const volumes: Record<string, unknown> = {};\n if (Array.isArray(rawVolumes)) {\n for (const mount of rawVolumes) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n } else if (rawVolumes && typeof rawVolumes === \"object\") {\n Object.assign(volumes, rawVolumes);\n }\n return {\n name: raw.name ?? \"\",\n image: raw.image ?? \"\",\n memoryMib: raw.memoryMib ?? raw.memory_mib,\n cpus: raw.cpus,\n env: raw.env ?? {},\n volumes,\n };\n } catch {\n return { name: \"\", image: \"\" };\n }\n}\n\nfunction msToIsoString(ms: number | Date | null | undefined): string {\n if (ms == null) return \"\";\n if (ms instanceof Date) return ms.toISOString();\n return new Date(ms).toISOString();\n}\n\ntype MsbInspectEnvVolumes = {\n env: unknown;\n volumes: Record<string, unknown>;\n};\n\nfunction parseMsbInspectEnvVolumes(stdout: string): MsbInspectEnvVolumes {\n const data = JSON.parse(stdout);\n const env = data?.config?.env ?? {};\n\n const volumes: Record<string, unknown> = {};\n const rawMounts = data?.config?.mounts;\n if (Array.isArray(rawMounts)) {\n for (const mount of rawMounts) {\n if (mount && typeof mount === \"object\" && \"guest\" in mount) {\n volumes[String(mount.guest)] = mount;\n }\n }\n }\n\n return { env, volumes };\n}\n\nfunction isFileNotFoundError(error: unknown): boolean {\n if (typeof error === \"string\") {\n const message = error.toLowerCase();\n return message.includes(\"not found\") || message.includes(\"no such file\");\n }\n if (!error || typeof error !== \"object\") {\n return false;\n }\n const candidate = error as { code?: unknown; message?: unknown };\n if (candidate.code === \"ENOENT\") {\n return true;\n }\n if (typeof candidate.message !== \"string\") {\n return false;\n }\n const message = candidate.message.toLowerCase();\n return message.includes(\"not found\") || message.includes(\"no such file\");\n}\n\nexport class MicrosandboxRuntimeService {\n constructor(private deps: { registry?: SandboxRegistry } = {}) {}\n\n private get registry(): SandboxRegistry {\n return this.deps.registry ?? (this.deps.registry = new SandboxRegistry());\n }\n\n private resolvePath(path: string): string {\n if (path === \"~\" || path === \"~/\") {\n return \"/\";\n }\n if (path.startsWith(\"~/\")) {\n return `/${path.slice(2)}`;\n }\n return path;\n }\n\n private resolveDeletePath(path: string): string {\n const resolvedPath = this.resolvePath(path);\n if (resolvedPath.replace(/\\\\/g, \"/\").split(\"/\").includes(\"..\")) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", `Path traversal denied: ${path}`);\n }\n return resolvedPath;\n }\n\n private toListItem(info: {\n name: string;\n status: string;\n configJson: string;\n createdAt?: number | Date | null;\n updatedAt?: number | Date | null;\n }): {\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n } {\n const config = parseConfigJson(info.configJson);\n const env = config.env ? (Array.isArray(config.env) ? config.env : config.env) : [];\n const envCount = Array.isArray(env) ? env.length : Object.keys(env as Record<string, unknown>).length;\n const volumes = config.volumes ?? {};\n\n return {\n name: info.name,\n status: info.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n envCount,\n volumeCount: Object.keys(volumes).length,\n createdAt: msToIsoString(info.createdAt),\n updatedAt: msToIsoString(info.updatedAt),\n };\n }\n\n private async readMsbInspect(name: string): Promise<MsbInspectEnvVolumes | undefined> {\n try {\n const { stdout } = await execAsync(\n `${getMsbPath()} inspect ${name} --format json`,\n { timeout: 5000 }\n );\n return parseMsbInspectEnvVolumes(stdout);\n } catch {\n return undefined;\n }\n }\n\n private async ensureNamedVolumes(volumes?: EnsureSandboxInput[\"volumes\"]): Promise<void> {\n if (!volumes) {\n return;\n }\n\n const defaultQuotaMib = Number(process.env.MICROSANDBOX_VOLUME_QUOTA_MIB ?? \"2048\");\n\n const namedVolumes = Object.values(volumes).filter(\n (v): v is Extract<VolumeConfig, { type: \"named\" }> => v.type === \"named\"\n );\n\n await Promise.all(\n namedVolumes.map(async (definition) => {\n try {\n await Volume.get(definition.name);\n } catch {\n await Volume.builder(definition.name).quota(defaultQuotaMib).create();\n }\n })\n );\n }\n\n private async getOrEnsureNative(name: string): Promise<RuntimeNative> {\n return (await this.registry.ensure(name)) as RuntimeNative;\n }\n\n async ensureSandbox(\n name: string,\n input: EnsureSandboxInput\n ): Promise<{\n name: string;\n status: string;\n }> {\n const image = input.image ?? process.env.MICROSANDBOX_IMAGE ?? \"python:3.11-slim\";\n const cpus = input.cpus ?? Number(process.env.MICROSANDBOX_CPUS ?? \"1\");\n const memoryMib = input.memoryMib ?? Number(process.env.MICROSANDBOX_MEMORY ?? \"512\");\n\n await this.ensureNamedVolumes(input.volumes);\n\n // Lifecycle governance is applied by SandboxRegistry: a positive\n // `timeoutSeconds` is mapped to the microsandbox builder's `idleTimeout`\n // (the sandbox's idle lifetime); `timeoutSeconds: null` marks the resident\n // idle-exempt so the idle sweeper never pauses it (`alwaysOn`);\n // `undefined` keeps the registry default (`MICROSANDBOX_IDLE_TIMEOUT_MS`).\n // The lifetime is applied at create time only — changing it for an\n // existing sandbox does not force a recreate.\n await this.registry.ensure(name, {\n image,\n cpus,\n memoryMib,\n env: input.env,\n volumes: input.volumes,\n entrypoint: input.entrypoint,\n timeoutSeconds: input.timeoutSeconds,\n exposePorts: input.exposePorts,\n });\n\n return {\n name,\n status: \"running\",\n };\n }\n\n async startSandbox(name: string): Promise<{ name: string; status: string }> {\n await this.registry.ensure(name);\n return { name, status: \"running\" };\n }\n\n async stopSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.pause(name);\n return { name, status: \"stopped\" };\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async killSandbox(name: string): Promise<{ name: string; status: string }> {\n let handle;\n try {\n handle = await Sandbox.get(name);\n } catch {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n try {\n if (handle.status === \"running\") {\n const native = await handle.connect();\n await native.kill();\n }\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"write to relay\")) {\n return { name, status: \"unknown\" };\n }\n throw error;\n } finally {\n this.registry.remove(name);\n }\n }\n\n async deleteSandbox(name: string): Promise<{ name: string; status: string }> {\n try {\n await this.registry.removeAndDelete(name);\n return { name, status: \"unknown\" };\n } catch (error) {\n if (error instanceof HttpError) throw error;\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${name}' not found`);\n }\n }\n\n async listSandboxes(_query: ListSandboxesQuery): Promise<{\n items: Array<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n envCount: number;\n volumeCount: number;\n createdAt: string;\n updatedAt: string;\n }>;\n total: number;\n }> {\n const all: SandboxHandle[] = await Sandbox.list();\n\n const items = all\n .map((info) =>\n this.toListItem({\n name: info.name,\n status: info.status,\n configJson: info.configJson,\n createdAt: info.createdAt,\n updatedAt: info.updatedAt,\n })\n )\n .filter((item) => {\n if (_query.status && item.status !== _query.status) {\n return false;\n }\n\n if (_query.image && item.image !== _query.image) {\n return false;\n }\n\n if (_query.search) {\n const haystack = [item.name, item.image]\n .filter((value): value is string => Boolean(value))\n .join(\" \")\n .toLowerCase();\n\n if (!haystack.includes(_query.search.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n\n return { items, total: items.length };\n }\n\n async getSandbox(\n name: string\n ): Promise<{\n name: string;\n status: string;\n image: unknown;\n cpus?: number;\n memoryMib?: number;\n env: unknown;\n volumes: Record<string, unknown>;\n metrics?: SandboxRuntimeMetrics;\n createdAt: string;\n updatedAt: string;\n } | undefined> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n const config = parseConfigJson(handle.configJson);\n\n const msbData = await this.readMsbInspect(name);\n const env = msbData?.env ?? config.env ?? {};\n const volumes = msbData?.volumes ?? config.volumes ?? {};\n\n let metrics: SandboxRuntimeMetrics | undefined;\n\n try {\n const m = await handle.metrics();\n metrics = {\n cpuPercent: m.cpuPercent,\n memoryBytes: m.memoryBytes,\n memoryLimitBytes: m.memoryLimitBytes,\n diskReadBytes: m.diskReadBytes,\n diskWriteBytes: m.diskWriteBytes,\n netRxBytes: m.netRxBytes,\n netTxBytes: m.netTxBytes,\n uptimeMs: m.uptimeMs,\n timestampMs: m.timestamp.getTime(),\n };\n } catch {\n metrics = undefined;\n }\n\n return {\n name: handle.name,\n status: handle.status,\n image: config.image,\n cpus: config.cpus,\n memoryMib: config.memoryMib,\n env,\n volumes,\n metrics,\n createdAt: msToIsoString(handle.createdAt),\n updatedAt: msToIsoString(handle.updatedAt),\n };\n } catch {\n return undefined;\n }\n }\n\n async getStatus(name: string): Promise<{ name: string; status: string }> {\n try {\n const handle: SandboxHandle = await Sandbox.get(name);\n return { name, status: handle.status };\n } catch {\n return { name, status: \"unknown\" };\n }\n }\n\n /**\n * Resolve the relative proxy path for a guest port published at create time.\n *\n * @param name - Sandbox name\n * @param port - Guest port passed via `ensureSandbox({ exposePorts })`\n * @returns The relative proxy path and any required headers\n * @throws {HttpError} ENDPOINT_NOT_PUBLISHED when the port was never published\n */\n async getEndpoint(\n name: string,\n port: number\n ): Promise<{ endpoint: string; headers?: Record<string, string> }> {\n return this.registry.getEndpoint(name, port);\n }\n\n /**\n * Resolve the loopback `host:port` the sandbox proxy dials for a published port.\n *\n * @param name - Sandbox name\n * @param port - Guest port passed via `ensureSandbox({ exposePorts })`\n * @returns The loopback `host:port` target\n * @throws {HttpError} ENDPOINT_NOT_PUBLISHED when the port was never published\n */\n resolveProxyTarget(name: string, port: number): string {\n return this.registry.getProxyTarget(name, port);\n }\n\n async readFile(sandboxName: string, path: string): Promise<{ path: string; content: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n try {\n const content = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n return { path: resolvedPath, content };\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n throw error;\n }\n }\n\n async writeFile(sandboxName: string, path: string, content: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const parts = resolvedPath.split(\"/\").filter(Boolean);\n for (let i = 1; i < parts.length; i++) {\n const dir = \"/\" + parts.slice(0, i).join(\"/\");\n try {\n await native.fs().mkdir(dir);\n } catch {\n // directory may already exist or parent missing, continue\n }\n }\n await native.fs().write(resolvedPath, Buffer.from(content));\n return { path: resolvedPath };\n }\n\n async deleteFile(sandboxName: string, path: string): Promise<{ path: string }> {\n const resolvedPath = this.resolveDeletePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const sandboxFs = native.fs();\n let metadata: Awaited<ReturnType<typeof sandboxFs.stat>>;\n try {\n metadata = await sandboxFs.stat(resolvedPath);\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new HttpError(500, \"FILE_STAT_ERROR\", `Failed to inspect '${path}': ${message}`);\n }\n\n if (metadata.kind === \"symlink\") {\n throw new HttpError(400, \"FILE_NOT_REGULAR\", `Cannot delete '${path}': symlinks are not allowed`);\n }\n if (metadata.kind === \"directory\") {\n throw new HttpError(400, \"FILE_NOT_REGULAR\", `Cannot delete '${path}': target is a directory`);\n }\n if (metadata.kind !== \"file\") {\n throw new HttpError(400, \"FILE_NOT_REGULAR\", `Cannot delete '${path}': target is not a regular file`);\n }\n\n try {\n await sandboxFs.remove(resolvedPath);\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new HttpError(500, \"FILE_DELETE_ERROR\", `Failed to delete '${path}': ${message}`);\n }\n return { path: resolvedPath };\n }\n\n async listPath(\n sandboxName: string,\n path: string,\n recursive?: boolean\n ): Promise<{ entries: Array<{ path: string; type: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const entries: Array<{ path: string; type: string }> = [];\n const visited = new Set<string>();\n\n const visit = async (dir: string): Promise<void> => {\n if (visited.has(dir)) return;\n visited.add(dir);\n const listed = await native.fs().list(dir);\n for (const entry of listed) {\n entries.push({ path: entry.path, type: entry.kind });\n if (recursive && entry.kind === \"directory\") {\n await visit(entry.path);\n }\n }\n };\n\n await visit(resolvedPath);\n return { entries };\n }\n\n async findFiles(sandboxName: string, path: string, pattern: string): Promise<{ files: string[] }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n const matchFlag = pattern.includes(\"/\") ? \"-path\" : \"-name\";\n const output = await native.exec(\"find\", [resolvedPath, matchFlag, pattern, \"-type\", \"f\"]);\n return { files: output.stdout().split(\"\\n\").filter(Boolean) };\n }\n\n async searchInFile(\n sandboxName: string,\n path: string,\n query: string\n ): Promise<{ matches: Array<{ line: number; content: string }> }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n let stdout: string;\n\n try {\n const output = await native.exec(\"grep\", [\"-n\", \"-E\", query, resolvedPath]);\n stdout = output.stdout();\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === 1) {\n return { matches: [] };\n }\n\n throw error;\n }\n\n return {\n matches: stdout\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const separator = line.indexOf(\":\");\n return {\n line: Number(line.slice(0, separator)),\n content: line.slice(separator + 1),\n };\n }),\n };\n }\n\n async replaceInFile(\n sandboxName: string,\n input: { path: string; search: string; replace: string }\n ): Promise<{ replaced: number }> {\n const resolvedPath = this.resolvePath(input.path);\n const native = await this.getOrEnsureNative(sandboxName);\n const fs = native.fs();\n const original = typeof fs.readToString === \"function\"\n ? await fs.readToString(resolvedPath)\n : await fs.readString(resolvedPath);\n\n if (!input.search) {\n return { replaced: 0 };\n }\n\n const occurrences = original.split(input.search).length - 1;\n if (occurrences === 0) {\n return { replaced: 0 };\n }\n\n const updated = original.split(input.search).join(input.replace);\n await fs.write(resolvedPath, Buffer.from(updated));\n\n return { replaced: occurrences };\n }\n\n async uploadFile(sandboxName: string, path: string, contentBase64: string): Promise<{ path: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n await native.fs().write(resolvedPath, Buffer.from(contentBase64, \"base64\"));\n return { path: resolvedPath };\n }\n\n async downloadFile(sandboxName: string, path: string): Promise<{ path: string; contentBase64: string }> {\n const resolvedPath = this.resolvePath(path);\n const native = await this.getOrEnsureNative(sandboxName);\n try {\n const data = await native.fs().read(resolvedPath);\n const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);\n return { path: resolvedPath, contentBase64: buffer.toString(\"base64\") };\n } catch (error: unknown) {\n if (isFileNotFoundError(error)) {\n throw new HttpError(404, \"FILE_NOT_FOUND\", `File '${path}' not found`);\n }\n throw error;\n }\n }\n\n async execCommand(input: ShellExecInput): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const native = await this.getOrEnsureNative(input.sandboxName);\n const output = await native.shell(input.command);\n\n return {\n stdout: output.stdout(),\n stderr: output.stderr(),\n exitCode: output.code ?? 0,\n };\n }\n\n async getSandboxLogs(\n name: string,\n opts: SandboxLogsInput\n ): Promise<{\n entries: Array<{\n timestamp: string;\n source: string;\n sessionId: number | null;\n text: string;\n }>;\n }> {\n const handle: SandboxHandle = await Sandbox.get(name);\n\n const logOpts: { tail?: number; since?: Date; until?: Date; sources?: readonly LogReadSource[] } = {};\n\n if (opts.tail !== undefined) {\n logOpts.tail = opts.tail;\n }\n\n if (opts.since) {\n logOpts.since = new Date(opts.since);\n }\n\n if (opts.until) {\n logOpts.until = new Date(opts.until);\n }\n\n if (opts.sources && opts.sources.length > 0) {\n logOpts.sources = opts.sources as LogReadSource[];\n } else {\n logOpts.sources = [\"all\" as LogReadSource];\n }\n\n const entries = await handle.logs(logOpts);\n\n return {\n entries: entries.map((entry) => ({\n timestamp: entry.timestamp.toISOString(),\n source: entry.source,\n sessionId: entry.sessionId,\n text: entry.text(),\n })),\n };\n }\n}\n","export function getMsbPath(): string {\n return process.env.MICROSANDBOX_CLI_PATH ?? `${process.env.HOME ?? \"/root\"}/.microsandbox/bin/msb`;\n}\n","import cors from \"@fastify/cors\";\nimport multipart from \"@fastify/multipart\";\nimport sensible from \"@fastify/sensible\";\nimport fastify, { type FastifyInstance } from \"fastify\";\nimport { toErrorResponse } from \"./lib/errors\";\nimport { registerHealthRoutes } from \"./routes/health\";\nimport { registerImageRoutes } from \"./routes/images\";\nimport { registerSandboxRoutes } from \"./routes/sandbox\";\nimport { registerVolumeFsRoutes } from \"./routes/volume-fs\";\nimport { ImageService } from \"./services/ImageService\";\nimport { MicrosandboxRuntimeService } from \"./services/MicrosandboxRuntimeService\";\nimport { configureSwagger } from \"./swagger\";\nimport type { RuntimeService } from \"./types/runtime-service\";\n\nexport async function buildApp({\n runtimeService = new MicrosandboxRuntimeService(),\n imageService = new ImageService(),\n apiKey,\n}: {\n runtimeService?: RuntimeService;\n imageService?: ImageService;\n apiKey?: string;\n} = {}): Promise<FastifyInstance> {\n const app = fastify({\n logger: false,\n bodyLimit: Number(process.env.BODY_LIMIT) || 100 * 1024 * 1024,\n });\n\n app.register(cors, {\n delegator: (request, callback) => {\n callback(null, {\n origin: true,\n methods: request.headers[\"access-control-request-method\"] ?? \"*\",\n allowedHeaders: request.headers[\"access-control-request-headers\"],\n });\n },\n });\n app.register(sensible);\n app.register(multipart);\n\n if (apiKey) {\n app.addHook(\"onRequest\", async (request, reply) => {\n if (request.method === \"OPTIONS\" || !request.url.startsWith(\"/api/\")) {\n return;\n }\n\n if (request.headers.authorization !== `Bearer ${apiKey}`) {\n await reply.code(401).send({\n success: false,\n error: {\n code: \"UNAUTHORIZED\",\n message: \"Unauthorized\",\n },\n });\n }\n });\n }\n\n registerHealthRoutes(app);\n registerSandboxRoutes(app, runtimeService);\n registerImageRoutes(app, imageService);\n registerVolumeFsRoutes(app);\n\n app.setErrorHandler((error, _request, reply) => {\n const { statusCode, body } = toErrorResponse(error);\n reply.status(statusCode).send(body);\n });\n\n await configureSwagger(app);\n\n return app;\n}\n","export type SuccessResponse<T> = {\n success: true;\n data: T;\n};\n\nexport function ok<T>(data: T): SuccessResponse<T> {\n return {\n success: true,\n data,\n };\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { ok } from \"../lib/http\";\n\nexport function registerHealthRoutes(app: FastifyInstance): void {\n app.get(\"/health\", async () => ok({ status: \"ok\" }));\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport { ZodError } from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { ImageService } from \"../services/ImageService\";\nimport { imageRefQuerySchema, pullImageSchema } from \"../schemas/images\";\n\nfunction parseOrThrow<T>(parse: () => T): T {\n try {\n return parse();\n } catch (error) {\n if (error instanceof ZodError) {\n throw new HttpError(400, \"INVALID_REQUEST\", error.issues[0]?.message ?? \"Invalid request\");\n }\n\n throw error;\n }\n}\n\nexport function createImageController(imageService: ImageService) {\n return {\n listImages: async (_request: FastifyRequest, reply: FastifyReply) => {\n return reply.send(ok(await imageService.listImages()));\n },\n pullImage: async (request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply) => {\n const body = parseOrThrow(() => pullImageSchema.parse(request.body ?? {}));\n return reply.send(ok(await imageService.pullImage(body)));\n },\n getImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.getImage(query.ref)));\n },\n deleteImage: async (request: FastifyRequest<{ Querystring: unknown }>, reply: FastifyReply) => {\n const query = parseOrThrow(() => imageRefQuerySchema.parse(request.query ?? {}));\n return reply.send(ok(await imageService.deleteImage(query.ref)));\n },\n };\n}\n","import z from \"zod\";\n\nexport const imageRefQuerySchema = z.object({\n ref: z.string().min(1),\n});\n\nexport const pullImageSchema = z.object({\n ref: z.string().min(1),\n});\n\nexport type ImageRefQuery = z.infer<typeof imageRefQuerySchema>;\nexport type PullImageInput = z.infer<typeof pullImageSchema>;\n","import type { FastifyInstance } from \"fastify\";\nimport { createImageController } from \"../controllers/images\";\nimport { ImageService } from \"../services/ImageService\";\n\nexport function registerImageRoutes(app: FastifyInstance, imageService: ImageService): void {\n const controller = createImageController(imageService);\n\n app.get(\"/api/images\", controller.listImages);\n app.post(\"/api/images/pull\", controller.pullImage);\n app.get(\"/api/images/detail\", controller.getImage);\n app.delete(\"/api/images/detail\", controller.deleteImage);\n}\n","import type { FastifyInstance } from \"fastify\";\nimport { Transform } from \"node:stream\";\nimport { createSandboxController } from \"../controllers/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function registerSandboxRoutes(\n app: FastifyInstance,\n runtimeService: RuntimeService\n): void {\n const controller = createSandboxController(runtimeService);\n\n app.get(\"/api/sandboxes\", controller.listSandboxes);\n app.get(\"/api/sandboxes/:name\", controller.getSandbox);\n app.put(\"/api/sandboxes/:name\", controller.ensureSandbox);\n app.post(\"/api/sandboxes/:name/start\", controller.startSandbox);\n app.post(\"/api/sandboxes/:name/stop\", controller.stopSandbox);\n app.post(\"/api/sandboxes/:name/kill\", controller.killSandbox);\n app.delete(\"/api/sandboxes/:name\", controller.deleteSandbox);\n app.get(\"/api/sandboxes/:name/status\", controller.getStatus);\n app.get(\"/api/sandboxes/:name/endpoints/:port\", controller.getEndpoint);\n app.post(\"/api/sandboxes/:name/logs\", controller.getSandboxLogs);\n\n app.post(\"/api/files/read\", controller.readFile);\n app.post(\"/api/files/write\", controller.writeFile);\n app.post(\"/api/files/delete\", controller.deleteFile);\n app.post(\"/api/files/list\", controller.listPath);\n app.post(\"/api/files/find\", controller.findFiles);\n app.post(\"/api/files/search\", controller.searchInFile);\n app.post(\"/api/files/replace\", controller.replaceInFile);\n app.post(\"/api/files/upload\", controller.uploadFile);\n app.get(\"/api/files/download\", controller.downloadFile);\n\n app.post(\"/api/shell/exec\", controller.execCommand);\n\n // Scoped plugin: the streaming pass-through parser must not leak to the JSON\n // routes above, so it and the proxy route live in their own encapsulation\n // context.\n app.register(async (instance) => {\n // Fastify does not apply `bodyLimit` to stream parsers, so enforce the\n // configured limit here while still passing bytes through unbuffered.\n const bodyLimit = instance.initialConfig.bodyLimit ?? 100 * 1024 * 1024;\n // The inherited default `application/json` parser would otherwise consume\n // the body before the proxy sees it; dropping every parser for this scope\n // only makes the `\"*\"` parser the effective one.\n instance.removeAllContentTypeParsers();\n instance.addContentTypeParser(\"*\", (_request, payload, done) => {\n let received = 0;\n const limiter = new Transform({\n transform(chunk: Buffer, _encoding, callback) {\n received += chunk.length;\n if (received > bodyLimit) {\n callback(new HttpError(413, \"PAYLOAD_TOO_LARGE\", \"Request body is too large\"));\n return;\n }\n callback(null, chunk);\n },\n });\n payload.pipe(limiter);\n done(null, limiter);\n });\n instance.all(\"/api/sandboxes/:name/proxy/:port/*\", controller.proxyRequest);\n });\n}\n","import z from \"zod\";\n\nconst bindMountSchema = z.object({\n type: z.literal(\"bind\"),\n source: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst namedMountSchema = z.object({\n type: z.literal(\"named\"),\n name: z.string().min(1),\n readonly: z.boolean().optional(),\n});\n\nconst tmpfsMountSchema = z.object({\n type: z.literal(\"tmpfs\"),\n sizeMib: z.number().int().positive().optional(),\n});\n\nexport const volumeSchema = z.union([\n bindMountSchema,\n namedMountSchema,\n tmpfsMountSchema,\n]);\n\nexport const ensureSandboxSchema = z.object({\n image: z.string().optional(),\n cpus: z.number().int().positive().optional(),\n memoryMib: z.number().int().positive().optional(),\n env: z.record(z.string()).optional(),\n volumes: z.record(volumeSchema).optional(),\n /** Main process command; replaces the default `tail -f /dev/null`. */\n entrypoint: z.array(z.string().min(1)).nonempty().optional(),\n /** Absolute lifetime in seconds; `null` means no expiry (caller-managed). */\n timeoutSeconds: z.number().int().positive().nullable().optional(),\n /** Guest ports to publish; each is mapped to a deterministic host port. */\n exposePorts: z.array(z.number().int().positive().max(65535)).optional(),\n});\n\nexport const sandboxEndpointParamsSchema = z.object({\n name: z.string().min(1),\n port: z.coerce.number().int().positive().max(65535),\n});\n\nexport const sandboxNameParamsSchema = z.object({\n name: z.string().min(1),\n});\n\nexport const listSandboxesQuerySchema = z.object({\n status: z.enum([\"running\", \"stopped\", \"crashed\", \"unknown\"]).optional(),\n image: z.string().min(1).optional(),\n search: z.string().min(1).optional(),\n});\n\nconst sandboxAndPathSchema = z.object({\n sandboxName: z.string().min(1),\n path: z.string().min(1),\n});\n\nexport const readFileSchema = sandboxAndPathSchema;\n\nexport const writeFileSchema = sandboxAndPathSchema.extend({\n content: z.string(),\n});\n\nexport const deleteFileSchema = sandboxAndPathSchema;\n\nexport const listPathSchema = sandboxAndPathSchema.extend({\n recursive: z.boolean().optional(),\n});\n\nexport const findFilesSchema = sandboxAndPathSchema.extend({\n pattern: z.string().min(1),\n});\n\nexport const searchInFileSchema = sandboxAndPathSchema.extend({\n query: z.string().min(1),\n});\n\nexport const replaceInFileSchema = sandboxAndPathSchema.extend({\n search: z.string(),\n replace: z.string(),\n});\n\nexport const uploadFileSchema = sandboxAndPathSchema.and(\n z.union([\n z.object({ contentBase64: z.string() }),\n z.object({ content: z.string().transform((content) => Buffer.from(content).toString(\"base64\")) }),\n ])\n);\n\nexport const downloadFileSchema = sandboxAndPathSchema;\n\nexport const shellExecSchema = z.object({\n sandboxName: z.string().min(1),\n command: z.string().min(1),\n exec_dir: z.string().optional(),\n timeout: z.number().int().positive().optional(),\n});\n\nexport const sandboxLogsSchema = z.object({\n tail: z.number().int().positive().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n sources: z.array(z.string()).optional(),\n});\n\nexport type EnsureSandboxInput = z.infer<typeof ensureSandboxSchema>;\nexport type ListSandboxesQuery = z.infer<typeof listSandboxesQuerySchema>;\nexport type ShellExecInput = z.infer<typeof shellExecSchema>;\nexport type SandboxLogsInput = z.infer<typeof sandboxLogsSchema>;\nexport type SandboxEndpointParams = z.infer<typeof sandboxEndpointParamsSchema>;\n","import http from \"node:http\";\nimport type { Readable } from \"node:stream\";\nimport { HttpError } from \"./errors\";\n\nconst HOP_BY_HOP_HEADERS = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n]);\n\n/** Incoming request headers as exposed by Fastify (values may be arrays). */\nexport type ProxyIncomingHeaders = Record<\n string,\n string | string[] | undefined\n>;\n\n/** Minimal Fastify reply surface needed to stream an upstream response back. */\nexport interface ProxyReply {\n code(status: number): unknown;\n headers(headers: Record<string, string | string[]>): unknown;\n send(payload: Readable | Buffer | string): unknown;\n}\n\n/** Options accepted by {@link pipeRequestUpstream}. */\nexport interface ProxyUpstreamOptions {\n /** Loopback `host:port` the proxy dials (never the public endpoint). */\n target: string;\n /** HTTP method to replay upstream. */\n method: string;\n /** Upstream request path, including any query string. */\n path: string;\n /** Already-sanitized headers to send upstream (see {@link buildProxyHeaders}). */\n headers: Record<string, string>;\n /** Raw request body stream; piped straight through without buffering. */\n body: NodeJS.ReadableStream;\n /** Fastify reply used to stream the upstream response back. */\n reply: ProxyReply;\n}\n\nfunction isHopByHop(header: string): boolean {\n return HOP_BY_HOP_HEADERS.has(header) || header.startsWith(\"proxy-\");\n}\n\n/**\n * Build the header set to send upstream.\n *\n * Lowercases all keys, drops hop-by-hop headers, `host`, and `content-length`\n * (the body is re-streamed), and strips the incoming `authorization` so the\n * sandbox-service key is never forwarded to the sandbox host. The host is\n * unauthenticated: the service-key-authenticated proxy route plus the\n * loopback-bound published port are the security boundary.\n *\n * @param incoming Raw incoming request headers.\n * @param requestPath Reserved for future path-based routing policy; unused today.\n */\nexport function buildProxyHeaders(\n incoming: ProxyIncomingHeaders,\n requestPath: string\n): Record<string, string> {\n void requestPath;\n\n const headers: Record<string, string> = {};\n\n for (const [rawKey, rawValue] of Object.entries(incoming)) {\n if (rawValue === undefined) continue;\n const key = rawKey.toLowerCase();\n if (isHopByHop(key)) continue;\n if (key === \"host\" || key === \"content-length\") continue;\n if (key === \"authorization\") continue;\n headers[key] = Array.isArray(rawValue) ? rawValue.join(\", \") : rawValue;\n }\n\n return headers;\n}\n\nfunction parseTarget(target: string): { hostname: string; port: number } {\n const url = new URL(target.includes(\"://\") ? target : `http://${target}`);\n return {\n hostname: url.hostname,\n port: url.port.length > 0 ? Number(url.port) : 80,\n };\n}\n\nfunction toProxyError(error: unknown): HttpError {\n if (error instanceof HttpError) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new HttpError(502, \"PROXY_ERROR\", message);\n}\n\nfunction filterResponseHeaders(\n headers: http.IncomingHttpHeaders\n): Record<string, string | string[]> {\n const filtered: Record<string, string | string[]> = {};\n for (const [rawKey, rawValue] of Object.entries(headers)) {\n if (rawValue === undefined) continue;\n const key = rawKey.toLowerCase();\n if (isHopByHop(key)) continue;\n filtered[key] = rawValue;\n }\n return filtered;\n}\n\n/**\n * Open an upstream HTTP connection to `target`, pipe the incoming `body` into\n * it, and stream the upstream response (status, headers, body) back through\n * `reply` without buffering, so SSE and large payloads pass through.\n *\n * Redirects are not followed. Any connection or request error is surfaced as\n * an {@link HttpError} with status `502` and code `PROXY_ERROR`.\n */\nexport function pipeRequestUpstream(\n options: ProxyUpstreamOptions\n): Promise<void> {\n const { target, method, path, headers, body, reply } = options;\n const { hostname, port } = parseTarget(target);\n\n return new Promise<void>((resolve, reject) => {\n const upstream = http.request(\n { hostname, port, method, path, headers },\n (upstreamResponse) => {\n try {\n reply.code(upstreamResponse.statusCode ?? 502);\n reply.headers(filterResponseHeaders(upstreamResponse.headers));\n reply.send(upstreamResponse);\n resolve();\n } catch (error) {\n upstreamResponse.destroy();\n reject(toProxyError(error));\n }\n }\n );\n\n upstream.on(\"error\", (error) => reject(toProxyError(error)));\n\n body.on(\"error\", (error) => {\n upstream.destroy();\n reject(toProxyError(error));\n });\n\n const source = body as NodeJS.ReadableStream & {\n readableEnded?: boolean;\n destroyed?: boolean;\n };\n if (source.readableEnded === true || source.destroyed === true) {\n upstream.end();\n } else {\n body.pipe(upstream);\n }\n });\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport {\n deleteFileSchema,\n downloadFileSchema,\n ensureSandboxSchema,\n findFilesSchema,\n listSandboxesQuerySchema,\n listPathSchema,\n readFileSchema,\n replaceInFileSchema,\n sandboxEndpointParamsSchema,\n sandboxLogsSchema,\n sandboxNameParamsSchema,\n searchInFileSchema,\n shellExecSchema,\n uploadFileSchema,\n writeFileSchema,\n} from \"../schemas/sandbox\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport { buildProxyHeaders, pipeRequestUpstream } from \"../lib/proxy\";\nimport type { RuntimeService } from \"../types/runtime-service\";\n\nexport function createSandboxController(runtimeService: RuntimeService): {\n ensureSandbox(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n startSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n stopSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n killSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listSandboxes(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getSandbox(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getStatus(\n request: FastifyRequest<{ Params: { name: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n getEndpoint(\n request: FastifyRequest<{ Params: { name: string; port: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n proxyRequest(\n request: FastifyRequest<{ Params: { name: string; port: string; \"*\": string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply | void>;\n getSandboxLogs(\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n readFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n writeFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n deleteFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n listPath(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n findFiles(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n searchInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n replaceInFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n uploadFile(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Querystring: unknown }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n execCommand(request: FastifyRequest<{ Body: unknown }>, reply: FastifyReply): Promise<FastifyReply>;\n} {\n return {\n ensureSandbox: async (\n request: FastifyRequest<{ Params: { name: string }; Body: unknown }>,\n reply: FastifyReply\n ) => {\n const body = ensureSandboxSchema.parse(request.body ?? {});\n const result = await runtimeService.ensureSandbox(request.params.name, body);\n return reply.send(ok(result));\n },\n\n startSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.startSandbox(request.params.name)));\n },\n\n stopSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.stopSandbox(request.params.name)));\n },\n\n killSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.killSandbox(request.params.name)));\n },\n\n deleteSandbox: async (request, reply) => {\n return reply.send(ok(await runtimeService.deleteSandbox(request.params.name)));\n },\n\n listSandboxes: async (request, reply) => {\n const query = listSandboxesQuerySchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.listSandboxes(query)));\n },\n\n getSandbox: async (request, reply) => {\n const params = sandboxNameParamsSchema.parse(request.params ?? {});\n const sandbox = await runtimeService.getSandbox(params.name);\n\n if (!sandbox) {\n throw new HttpError(404, \"SANDBOX_NOT_FOUND\", `Sandbox '${params.name}' not found`);\n }\n\n return reply.send(ok(sandbox));\n },\n\n getStatus: async (request, reply) => {\n return reply.send(ok(await runtimeService.getStatus(request.params.name)));\n },\n\n getEndpoint: async (request, reply) => {\n const parsed = sandboxEndpointParamsSchema.safeParse(request.params ?? {});\n if (!parsed.success) {\n throw new HttpError(400, \"INVALID_REQUEST\", parsed.error.issues[0]?.message ?? \"Invalid request\");\n }\n return reply.send(ok(await runtimeService.getEndpoint(parsed.data.name, parsed.data.port)));\n },\n\n /**\n * Stream a request through to a sandbox's published guest port.\n *\n * The caller authenticates to this service with its `Authorization` header;\n * {@link buildProxyHeaders} strips that service key so it is not forwarded\n * to the (unauthenticated) sandbox host. The live request stream\n * (body-limited by the scoped parser, or the raw request for bodyless\n * methods) is piped upstream without buffering.\n *\n * @throws {HttpError} 404 `ENDPOINT_NOT_PUBLISHED` when the port is not exposed,\n * or 413 `PAYLOAD_TOO_LARGE` when the streaming body exceeds `bodyLimit`.\n */\n proxyRequest: async (request, reply) => {\n const { name, port } = request.params;\n const rest = request.params[\"*\"] ?? \"\";\n const target = runtimeService.resolveProxyTarget(name, Number(port));\n const path = `/${rest}`;\n const headers = buildProxyHeaders(\n request.headers as Record<string, string | string[] | undefined>,\n path\n );\n // The scoped parser hands us a size-limited pass-through stream; fall\n // back to the raw request for bodyless methods (e.g. GET), where the\n // parser never runs.\n const body = (request.body as NodeJS.ReadableStream | undefined) ?? request.raw;\n await pipeRequestUpstream({\n target,\n method: request.method,\n path,\n headers,\n body,\n reply,\n });\n },\n\n getSandboxLogs: async (request, reply) => {\n const body = sandboxLogsSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.getSandboxLogs(request.params.name, body)));\n },\n\n readFile: async (request, reply) => {\n const body = readFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.readFile(body.sandboxName, body.path)));\n },\n\n writeFile: async (request, reply) => {\n const body = writeFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.writeFile(body.sandboxName, body.path, body.content)));\n },\n\n deleteFile: async (request, reply) => {\n const parsed = deleteFileSchema.safeParse(request.body ?? {});\n if (!parsed.success) {\n throw new HttpError(400, \"VALIDATION_ERROR\", parsed.error.message);\n }\n return reply.send(ok(await runtimeService.deleteFile(parsed.data.sandboxName, parsed.data.path)));\n },\n\n listPath: async (request, reply) => {\n const body = listPathSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.listPath(body.sandboxName, body.path, body.recursive)));\n },\n\n findFiles: async (request, reply) => {\n const body = findFilesSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.findFiles(body.sandboxName, body.path, body.pattern)));\n },\n\n searchInFile: async (request, reply) => {\n const body = searchInFileSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.searchInFile(body.sandboxName, body.path, body.query)));\n },\n\n replaceInFile: async (request, reply) => {\n const body = replaceInFileSchema.parse(request.body ?? {});\n return reply.send(\n ok(\n await runtimeService.replaceInFile(body.sandboxName, {\n path: body.path,\n search: body.search,\n replace: body.replace,\n })\n )\n );\n },\n\n uploadFile: async (request, reply) => {\n const body = uploadFileSchema.parse(request.body ?? {});\n const contentBase64 = \"contentBase64\" in body ? body.contentBase64 : Buffer.from(body.content).toString(\"base64\");\n return reply.send(ok(await runtimeService.uploadFile(body.sandboxName, body.path, contentBase64)));\n },\n\n downloadFile: async (request, reply) => {\n const query = downloadFileSchema.parse(request.query ?? {});\n return reply.send(ok(await runtimeService.downloadFile(query.sandboxName, query.path)));\n },\n\n execCommand: async (request, reply) => {\n const body = shellExecSchema.parse(request.body ?? {});\n return reply.send(ok(await runtimeService.execCommand(body)));\n },\n };\n}\n","import type { FastifyReply, FastifyRequest } from \"fastify\";\nimport fs from \"fs/promises\";\nimport os from \"os\";\nimport path from \"path\";\nimport { Volume } from \"microsandbox\";\nimport z from \"zod\";\nimport { HttpError } from \"../lib/errors\";\nimport { ok } from \"../lib/http\";\nimport {\n volumeFsDeleteSchema,\n volumeFsReadSchema,\n volumeFsWriteSchema,\n volumeFsListSchema,\n volumeFsUploadSchema,\n volumeFsDownloadSchema,\n volumeFsMkdirSchema,\n} from \"../schemas/volume-fs\";\n\ninterface VolumeFsParams {\n name: string;\n}\n\nconst MSB_DATA_DIR = path.join(os.homedir(), \".microsandbox\");\nconst VOLUME_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\ntype VolumeFileStat = Awaited<ReturnType<typeof fs.lstat>>;\n\nfunction assertVolumeName(name: string): void {\n if (name === \".\" || name === \"..\" || !VOLUME_NAME_PATTERN.test(name)) {\n throw new HttpError(400, \"INVALID_VOLUME_NAME\", \"Invalid volume name\");\n }\n}\n\nfunction assertRegularVolumeFile(guestPath: string, stat: VolumeFileStat): void {\n if (stat.isSymbolicLink()) {\n throw new HttpError(\n 400,\n \"VOLUME_FILE_NOT_REGULAR\",\n `Cannot delete '${guestPath}': symlinks are not allowed`\n );\n }\n if (stat.isDirectory()) {\n throw new HttpError(\n 400,\n \"VOLUME_FILE_NOT_REGULAR\",\n `Cannot delete '${guestPath}': target is a directory`\n );\n }\n if (!stat.isFile()) {\n throw new HttpError(\n 400,\n \"VOLUME_FILE_NOT_REGULAR\",\n `Cannot delete '${guestPath}': target is not a regular file`\n );\n }\n}\n\nasync function resolveVolumeHostPath(name: string): Promise<string> {\n assertVolumeName(name);\n try {\n const handle = await Volume.get(name);\n assertVolumeName(handle.name);\n const vol = await Volume.builder(handle.name).create();\n return vol.path;\n } catch {\n try {\n const vol = await Volume.builder(name).create();\n return vol.path;\n } catch {\n return path.join(MSB_DATA_DIR, \"volumes\", name);\n }\n }\n}\n\nfunction resolveGuestPath(hostRoot: string, guestPath: string): string {\n const normalized = guestPath === \"~\" ? \"\" : guestPath.replace(/^~\\//, \"\");\n const resolved = path.join(hostRoot, path.normalize(normalized).replace(/^(\\.\\.(\\/|\\\\|$))+/, \"\"));\n if (!resolved.startsWith(hostRoot + path.sep) && resolved !== hostRoot) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolved;\n}\n\nfunction resolveDeleteGuestPath(hostRoot: string, guestPath: string): string {\n const pathSegments = guestPath.replace(/\\\\/g, \"/\").split(\"/\");\n if (pathSegments.includes(\"..\")) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n return resolveGuestPath(hostRoot, guestPath);\n}\n\nasync function assertDeleteParentContained(hostRoot: string, fullPath: string): Promise<void> {\n const [rootPath, parentPath] = await Promise.all([\n fs.realpath(hostRoot),\n fs.realpath(path.dirname(fullPath)),\n ]);\n const relative = path.relative(rootPath, parentPath);\n if (\n relative === \"..\" ||\n relative.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relative)\n ) {\n throw new HttpError(403, \"PATH_TRAVERSAL\", \"Path traversal detected\");\n }\n}\n\nexport function createVolumeFsController(): {\n readFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n writeFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; content: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n deleteFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n listPath(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n downloadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Querystring: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n uploadFile(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string; contentBase64: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n mkdir(\n request: FastifyRequest<{ Params: VolumeFsParams; Body: { path: string } }>,\n reply: FastifyReply\n ): Promise<FastifyReply>;\n} {\n return {\n readFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsReadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const content = await fs.readFile(fullPath, \"utf-8\");\n return reply.send(ok({ path: guestPath, content }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_READ_ERROR\", `Failed to read from volume '${name}': ${String(err)}`);\n }\n },\n\n writeFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, content } = volumeFsWriteSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, content, \"utf-8\");\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_WRITE_ERROR\", `Failed to write to volume '${name}': ${String(err)}`);\n }\n },\n\n deleteFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDeleteSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveDeleteGuestPath(hostRoot, guestPath);\n await assertDeleteParentContained(hostRoot, fullPath);\n const stat = await fs.lstat(fullPath);\n assertRegularVolumeFile(guestPath, stat);\n\n const currentStat = await fs.lstat(fullPath);\n assertRegularVolumeFile(guestPath, currentStat);\n if (currentStat.dev !== stat.dev || currentStat.ino !== stat.ino) {\n throw new HttpError(\n 409,\n \"VOLUME_FILE_CHANGED\",\n `Cannot delete '${guestPath}': target changed during deletion`\n );\n }\n\n await assertDeleteParentContained(hostRoot, fullPath);\n await fs.unlink(fullPath);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n throw new HttpError(\n 404,\n \"VOLUME_FILE_NOT_FOUND\",\n `File not found in volume '${name}'`\n );\n }\n throw new HttpError(\n 500,\n \"VOLUME_DELETE_ERROR\",\n `Failed to delete from volume '${name}': ${String(err)}`\n );\n }\n },\n\n listPath: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsListSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const dirents = await fs.readdir(fullPath, { withFileTypes: true });\n const entries = [];\n for (const d of dirents) {\n let size = 0;\n let modified: string | null = null;\n let created: string | null = null;\n try {\n const stat = await fs.lstat(path.join(fullPath, d.name));\n size = stat.size;\n modified = stat.mtime.toISOString();\n created = stat.birthtime.getTime() > 0 ? stat.birthtime.toISOString() : null;\n } catch {\n // Leave size/modified/created unset for entries that cannot be stat-ed.\n }\n entries.push({\n path: guestPath ? `${guestPath}/${d.name}` : d.name,\n kind: d.isDirectory() ? \"directory\" : d.isSymbolicLink() ? \"symlink\" : \"file\",\n size,\n mode: 0,\n modified,\n created,\n });\n }\n return reply.send(ok({ entries }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_LIST_ERROR\", `Failed to list volume '${name}': ${String(err)}`);\n }\n },\n\n downloadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsDownloadSchema.parse(request.query ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n const buf = await fs.readFile(fullPath);\n const contentBase64 = buf.toString(\"base64\");\n return reply.send(ok({ path: guestPath, contentBase64 }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(404, \"VOLUME_DOWNLOAD_ERROR\", `Failed to download from volume '${name}': ${String(err)}`);\n }\n },\n\n uploadFile: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath, contentBase64 } = volumeFsUploadSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const data = Buffer.from(contentBase64, \"base64\");\n await fs.writeFile(fullPath, data);\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_UPLOAD_ERROR\", `Failed to upload to volume '${name}': ${String(err)}`);\n }\n },\n\n mkdir: async (request, reply) => {\n const { name } = request.params;\n\n try {\n const { path: guestPath } = volumeFsMkdirSchema.parse(request.body ?? {});\n const hostRoot = await resolveVolumeHostPath(name);\n const fullPath = resolveGuestPath(hostRoot, guestPath);\n await fs.mkdir(fullPath, { recursive: true });\n return reply.send(ok({ path: guestPath }));\n } catch (err: unknown) {\n if (err instanceof z.ZodError) {\n throw new HttpError(400, \"VALIDATION_ERROR\", err.message);\n }\n if (err instanceof HttpError) throw err;\n throw new HttpError(500, \"VOLUME_MKDIR_ERROR\", `Failed to create directory in volume '${name}': ${String(err)}`);\n }\n },\n };\n}\n","import z from \"zod\";\n\nexport const volumeFsReadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsWriteSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport const volumeFsDeleteSchema = z.object({\n path: z.string().min(1),\n});\n\nexport const volumeFsListSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsUploadSchema = z.object({\n path: z.string(),\n contentBase64: z.string().min(1),\n});\n\nexport const volumeFsDownloadSchema = z.object({\n path: z.string(),\n});\n\nexport const volumeFsMkdirSchema = z.object({\n path: z.string(),\n});\n","import type { FastifyInstance } from \"fastify\";\nimport { createVolumeFsController } from \"../controllers/volume-fs\";\n\nexport function registerVolumeFsRoutes(app: FastifyInstance): void {\n const controller = createVolumeFsController();\n\n app.post(\"/api/volumes/:name/fs/read\", controller.readFile);\n app.post(\"/api/volumes/:name/fs/write\", controller.writeFile);\n app.post(\"/api/volumes/:name/fs/delete\", controller.deleteFile);\n app.post(\"/api/volumes/:name/fs/list\", controller.listPath);\n app.get(\"/api/volumes/:name/fs/download\", controller.downloadFile);\n app.post(\"/api/volumes/:name/fs/upload\", controller.uploadFile);\n app.post(\"/api/volumes/:name/fs/mkdir\", controller.mkdir);\n}\n","import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { PullImageInput } from \"../schemas/images\";\nimport { getMsbPath } from \"../lib/msb\";\n\nconst execAsync = promisify(exec);\n\nexport type ImageRecord = {\n ref: string;\n sourceType: string;\n cached: boolean;\n size?: number;\n createdAt?: string;\n lastUsedAt?: string;\n};\n\ntype ImageBindings = {\n list(): Promise<ImageRecord[]>;\n pull(ref: string): Promise<ImageRecord>;\n inspect(ref: string): Promise<ImageRecord>;\n remove(ref: string): Promise<void>;\n};\n\ntype CliImageInfo = {\n architecture: string;\n created_at: string;\n digest: string;\n layer_count: number;\n os: string;\n reference: string;\n size_bytes: number;\n};\n\nclass MicrosandboxImageBindings implements ImageBindings {\n private get msb(): string {\n return getMsbPath();\n }\n\n async list(): Promise<ImageRecord[]> {\n const { stdout } = await execAsync(`${this.msb} image ls --format json`);\n const images: CliImageInfo[] = JSON.parse(stdout);\n return images.map((img) => ({\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n }));\n }\n\n async pull(ref: string): Promise<ImageRecord> {\n await execAsync(`${this.msb} image pull ${ref}`);\n return this.inspect(ref);\n }\n\n async inspect(ref: string): Promise<ImageRecord> {\n const { stdout } = await execAsync(`${this.msb} image inspect ${ref} --format json`);\n const img: CliImageInfo = JSON.parse(stdout);\n return {\n ref: img.reference,\n sourceType: \"oci\",\n cached: true,\n size: img.size_bytes,\n createdAt: img.created_at,\n };\n }\n\n async remove(ref: string): Promise<void> {\n await execAsync(`${this.msb} image rm ${ref}`);\n }\n}\n\nexport class ImageService {\n constructor(\n private readonly deps: {\n bindings?: ImageBindings;\n } = {}\n ) {}\n\n private get bindings(): ImageBindings {\n return this.deps.bindings ?? new MicrosandboxImageBindings();\n }\n\n async listImages(): Promise<{ items: ImageRecord[]; total: number }> {\n const items = await this.bindings.list();\n return { items, total: items.length };\n }\n\n async pullImage(input: PullImageInput): Promise<ImageRecord> {\n return await this.bindings.pull(input.ref);\n }\n\n async getImage(ref: string): Promise<ImageRecord> {\n return await this.bindings.inspect(ref);\n }\n\n async deleteImage(ref: string): Promise<{ ref: string }> {\n await this.bindings.remove(ref);\n return { ref };\n }\n}\n","import type { FastifyInstance } from \"fastify\";\nimport swagger from \"@fastify/swagger\";\nimport swaggerUi from \"@fastify/swagger-ui\";\n\nexport const defaultSwaggerConfig = {\n openapi: {\n openapi: \"3.0.0\",\n info: {\n title: \"Microsandbox Service API\",\n description:\n \"Sandbox lifecycle management, file operations, shell execution, and image registry\",\n version: \"1.0.0\",\n },\n servers: [\n {\n url: \"http://localhost:4002\",\n description: \"Local development\",\n },\n ],\n components: {\n securitySchemes: {\n bearerAuth: {\n type: \"http\" as const,\n scheme: \"bearer\" as const,\n bearerFormat: \"API Key\",\n },\n },\n },\n tags: [\n { name: \"Sandboxes\", description: \"Sandbox lifecycle (CRUD, start, stop, kill)\" },\n { name: \"Files\", description: \"Read, write, list, search, upload, download files inside sandboxes\" },\n { name: \"Shell\", description: \"Execute commands inside sandboxes\" },\n { name: \"Images\", description: \"OCI image management (list, pull, inspect, delete)\" },\n { name: \"Volumes\", description: \"Named volume filesystem operations\" },\n { name: \"Health\", description: \"Service health check\" },\n ],\n },\n};\n\nexport const defaultSwaggerUiConfig = {\n routePrefix: \"/api-docs\",\n uiConfig: {\n docExpansion: \"list\" as const,\n deepLinking: true,\n },\n staticCSP: true,\n transformStaticCSP: (header: string) => header,\n};\n\nexport async function configureSwagger(\n app: FastifyInstance,\n customSwaggerConfig?: Partial<typeof defaultSwaggerConfig>,\n customSwaggerUiConfig?: Partial<typeof defaultSwaggerUiConfig>\n) {\n const swaggerConfig = { ...defaultSwaggerConfig, ...customSwaggerConfig };\n const swaggerUiConfig = {\n ...defaultSwaggerUiConfig,\n ...customSwaggerUiConfig,\n };\n\n await app.register(swagger, swaggerConfig);\n await app.register(swaggerUi, swaggerUiConfig);\n}\n"],"mappings":"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","names":["path","fs","ok","Sandbox","message","path","Sandbox","fs","z","path","path","Volume","z","z","Volume","z","exec","promisify","execAsync","promisify","exec"]}
|
|
File without changes
|