@hotcell/daemon 0.1.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.
Files changed (142) hide show
  1. package/dist/agent-check.d.ts +1 -0
  2. package/dist/agent-check.js +105 -0
  3. package/dist/agent-check.js.map +1 -0
  4. package/dist/api/server.d.ts +64 -0
  5. package/dist/api/server.js +1368 -0
  6. package/dist/api/server.js.map +1 -0
  7. package/dist/api/ws.d.ts +14 -0
  8. package/dist/api/ws.js +214 -0
  9. package/dist/api/ws.js.map +1 -0
  10. package/dist/applevz-check.d.ts +1 -0
  11. package/dist/applevz-check.js +280 -0
  12. package/dist/applevz-check.js.map +1 -0
  13. package/dist/backups.d.ts +29 -0
  14. package/dist/backups.js +76 -0
  15. package/dist/backups.js.map +1 -0
  16. package/dist/capacity.d.ts +63 -0
  17. package/dist/capacity.js +95 -0
  18. package/dist/capacity.js.map +1 -0
  19. package/dist/config.d.ts +241 -0
  20. package/dist/config.js +152 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/cost.d.ts +9 -0
  23. package/dist/cost.js +19 -0
  24. package/dist/cost.js.map +1 -0
  25. package/dist/density-bench.d.ts +1 -0
  26. package/dist/density-bench.js +97 -0
  27. package/dist/density-bench.js.map +1 -0
  28. package/dist/driver/agent-driver.d.ts +67 -0
  29. package/dist/driver/agent-driver.js +197 -0
  30. package/dist/driver/agent-driver.js.map +1 -0
  31. package/dist/driver/agent.d.ts +94 -0
  32. package/dist/driver/agent.js +319 -0
  33. package/dist/driver/agent.js.map +1 -0
  34. package/dist/driver/applevz.d.ts +95 -0
  35. package/dist/driver/applevz.js +527 -0
  36. package/dist/driver/applevz.js.map +1 -0
  37. package/dist/driver/container.d.ts +99 -0
  38. package/dist/driver/container.js +733 -0
  39. package/dist/driver/container.js.map +1 -0
  40. package/dist/driver/fc-api.d.ts +85 -0
  41. package/dist/driver/fc-api.js +173 -0
  42. package/dist/driver/fc-api.js.map +1 -0
  43. package/dist/driver/firecracker.d.ts +126 -0
  44. package/dist/driver/firecracker.js +560 -0
  45. package/dist/driver/firecracker.js.map +1 -0
  46. package/dist/driver/index.d.ts +17 -0
  47. package/dist/driver/index.js +61 -0
  48. package/dist/driver/index.js.map +1 -0
  49. package/dist/driver/router.d.ts +82 -0
  50. package/dist/driver/router.js +159 -0
  51. package/dist/driver/router.js.map +1 -0
  52. package/dist/driver/types.d.ts +234 -0
  53. package/dist/driver/types.js +2 -0
  54. package/dist/driver/types.js.map +1 -0
  55. package/dist/driver/unsupported.d.ts +50 -0
  56. package/dist/driver/unsupported.js +81 -0
  57. package/dist/driver/unsupported.js.map +1 -0
  58. package/dist/driver/vz-image.d.ts +35 -0
  59. package/dist/driver/vz-image.js +75 -0
  60. package/dist/driver/vz-image.js.map +1 -0
  61. package/dist/e2e-harness.d.ts +1 -0
  62. package/dist/e2e-harness.js +99 -0
  63. package/dist/e2e-harness.js.map +1 -0
  64. package/dist/egress-check.d.ts +8 -0
  65. package/dist/egress-check.js +317 -0
  66. package/dist/egress-check.js.map +1 -0
  67. package/dist/fc-check.d.ts +1 -0
  68. package/dist/fc-check.js +113 -0
  69. package/dist/fc-check.js.map +1 -0
  70. package/dist/index.d.ts +2 -0
  71. package/dist/index.js +114 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/kernels.d.ts +22 -0
  74. package/dist/kernels.js +134 -0
  75. package/dist/kernels.js.map +1 -0
  76. package/dist/lifecycle.d.ts +49 -0
  77. package/dist/lifecycle.js +111 -0
  78. package/dist/lifecycle.js.map +1 -0
  79. package/dist/logger.d.ts +16 -0
  80. package/dist/logger.js +67 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/metrics.d.ts +46 -0
  83. package/dist/metrics.js +92 -0
  84. package/dist/metrics.js.map +1 -0
  85. package/dist/net/firewall.d.ts +4 -0
  86. package/dist/net/firewall.js +80 -0
  87. package/dist/net/firewall.js.map +1 -0
  88. package/dist/pricing.d.ts +36 -0
  89. package/dist/pricing.js +81 -0
  90. package/dist/pricing.js.map +1 -0
  91. package/dist/proxy/allowlist-default.d.ts +23 -0
  92. package/dist/proxy/allowlist-default.js +53 -0
  93. package/dist/proxy/allowlist-default.js.map +1 -0
  94. package/dist/proxy/allowlist.d.ts +43 -0
  95. package/dist/proxy/allowlist.js +87 -0
  96. package/dist/proxy/allowlist.js.map +1 -0
  97. package/dist/proxy/egress.d.ts +49 -0
  98. package/dist/proxy/egress.js +599 -0
  99. package/dist/proxy/egress.js.map +1 -0
  100. package/dist/proxy/ratelimit.d.ts +49 -0
  101. package/dist/proxy/ratelimit.js +74 -0
  102. package/dist/proxy/ratelimit.js.map +1 -0
  103. package/dist/proxy/server.d.ts +26 -0
  104. package/dist/proxy/server.js +202 -0
  105. package/dist/proxy/server.js.map +1 -0
  106. package/dist/router-check.d.ts +1 -0
  107. package/dist/router-check.js +97 -0
  108. package/dist/router-check.js.map +1 -0
  109. package/dist/smoke-fc.d.ts +1 -0
  110. package/dist/smoke-fc.js +183 -0
  111. package/dist/smoke-fc.js.map +1 -0
  112. package/dist/smoke-microvm.d.ts +1 -0
  113. package/dist/smoke-microvm.js +187 -0
  114. package/dist/smoke-microvm.js.map +1 -0
  115. package/dist/smoke-remote.d.ts +20 -0
  116. package/dist/smoke-remote.js +155 -0
  117. package/dist/smoke-remote.js.map +1 -0
  118. package/dist/smoke-vz.d.ts +1 -0
  119. package/dist/smoke-vz.js +161 -0
  120. package/dist/smoke-vz.js.map +1 -0
  121. package/dist/smoke.d.ts +7 -0
  122. package/dist/smoke.js +962 -0
  123. package/dist/smoke.js.map +1 -0
  124. package/dist/store.d.ts +124 -0
  125. package/dist/store.js +578 -0
  126. package/dist/store.js.map +1 -0
  127. package/dist/tracing.d.ts +45 -0
  128. package/dist/tracing.js +144 -0
  129. package/dist/tracing.js.map +1 -0
  130. package/dist/types.d.ts +274 -0
  131. package/dist/types.js +3 -0
  132. package/dist/types.js.map +1 -0
  133. package/dist/util.d.ts +27 -0
  134. package/dist/util.js +63 -0
  135. package/dist/util.js.map +1 -0
  136. package/dist/warmpool-check.d.ts +1 -0
  137. package/dist/warmpool-check.js +83 -0
  138. package/dist/warmpool-check.js.map +1 -0
  139. package/dist/web/dashboard.d.ts +1 -0
  140. package/dist/web/dashboard.js +456 -0
  141. package/dist/web/dashboard.js.map +1 -0
  142. package/package.json +53 -0
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Apple VZ driver M1 end-to-end check. Drives the real `AppleVzDriver` (which
3
+ * boots a microVM via the signed sbx-vz helper and talks to the in-guest agent
4
+ * over the relayed vsock) through the full lifecycle, including the headline M1
5
+ * gate: a file written to /workspace survives stop→start. Run on a Mac with the
6
+ * helper + guest artifacts built: `npm run check:applevz`.
7
+ */
8
+ import assert from "node:assert/strict";
9
+ import { mkdtempSync, rmSync } from "node:fs";
10
+ import { createServer as createHttpServer } from "node:http";
11
+ import { homedir, tmpdir } from "node:os";
12
+ import { join } from "node:path";
13
+ import { setTimeout as sleep } from "node:timers/promises";
14
+ import { AppleVzDriver } from "./driver/applevz.js";
15
+ async function main() {
16
+ const stateDir = mkdtempSync(join(tmpdir(), "sbx-vz-state-"));
17
+ // Mock egress gateway: guests reach it ONLY via the vsock relay (no NIC).
18
+ const EGRESS_PORT = 47522;
19
+ const gateway = createHttpServer((_req, res) => res.end("vz-egress-pong"));
20
+ await new Promise((r) => gateway.listen(EGRESS_PORT, "127.0.0.1", r));
21
+ const driver = new AppleVzDriver({
22
+ helperPath: "helpers/hotcell-vz/dist/hotcell-vz",
23
+ kernel: "helpers/hotcell-vz/guest/vmlinux-vz",
24
+ rootfs: "helpers/hotcell-vz/guest/rootfs.img",
25
+ stateDir,
26
+ diskGb: 2,
27
+ // Stable cache so converted images + the blank workspace survive across runs.
28
+ imageCacheDir: join(homedir(), ".sbx", "vz", "images"),
29
+ egressPort: EGRESS_PORT,
30
+ egressHost: "127.0.0.1",
31
+ });
32
+ const id = "vzcheck01";
33
+ let passed = 0;
34
+ const ok = (l) => {
35
+ passed++;
36
+ console.log(` ✓ ${l}`);
37
+ };
38
+ try {
39
+ await driver.ping();
40
+ ok("ping — Virtualization.framework available");
41
+ console.error("[check] booting microVM (create)…");
42
+ await driver.create({ id, image: "base", env: { SBX_TEST: "vz-ok" }, persist: true });
43
+ ok("create — VM booted and agent reachable over vsock");
44
+ let out = "";
45
+ const code = await driver.exec(id, "echo hello-from-vm && uname -sm", {}, (e) => {
46
+ if (e.type === "stdout")
47
+ out += e.data;
48
+ });
49
+ assert.equal(code, 0, "exec exit code");
50
+ assert.match(out, /hello-from-vm/, "exec stdout");
51
+ assert.match(out, /Linux aarch64/, "running inside a real arm64 Linux VM");
52
+ ok(`exec inside the VM — ${out.trim().replace(/\n/g, " | ")}`);
53
+ let envOut = "";
54
+ await driver.exec(id, "echo $SBX_TEST", {}, (e) => {
55
+ if (e.type === "stdout")
56
+ envOut += e.data;
57
+ });
58
+ assert.match(envOut, /vz-ok/, "sandbox env applied to exec");
59
+ ok("sandbox env applied");
60
+ // Egress-over-vsock: the NIC-less guest reaches the (mock) gateway through
61
+ // its loopback relay — its only route out of the VM.
62
+ let egOut = "";
63
+ const egCode = await driver.exec(id, `wget -qO- http://127.0.0.1:${EGRESS_PORT}/ping`, {}, (e) => {
64
+ if (e.type === "stdout")
65
+ egOut += e.data;
66
+ });
67
+ assert.equal(egCode, 0, "in-guest wget via the egress relay");
68
+ assert.match(egOut, /vz-egress-pong/, "egress relay reached the gateway");
69
+ ok("★ egress-over-vsock: guest loopback → vsock → gateway (no NIC)");
70
+ await driver.writeFile(id, { path: "/workspace/persist.txt", content: "persist-me-123" });
71
+ assert.equal(await driver.readFile(id, { path: "/workspace/persist.txt" }), "persist-me-123");
72
+ ok("writeFile + readFile in /workspace");
73
+ const files = await driver.listFiles(id, { path: "/workspace" });
74
+ assert.ok(files.some((f) => f.name === "persist.txt"), "listFiles sees the file");
75
+ ok("listFiles /workspace");
76
+ // ★ The M1 gate: persistence across a stop/start cycle.
77
+ console.error("[check] stop → start (workspace persistence)…");
78
+ await driver.stop(id);
79
+ await driver.start({ id, image: "base", env: {}, persist: true });
80
+ assert.equal(await driver.readFile(id, { path: "/workspace/persist.txt" }), "persist-me-123", "file persisted across stop/start");
81
+ ok("★ workspace.img persists across stop/start");
82
+ // M4a: background processes (start → list running → logs → kill → list dead).
83
+ const proc = await driver.startProcess(id, "p1", "i=0; while true; do echo tick-$i; i=$((i+1)); sleep 0.2; done", {});
84
+ assert.ok(Number.isFinite(proc.pid), "startProcess returns a pid");
85
+ await sleep(700);
86
+ const live = await driver.listProcesses(id, [{ procId: "p1", pid: proc.pid }]);
87
+ assert.ok(live[0]?.running, "process is running");
88
+ let logs = "";
89
+ await driver.streamProcessLogs(id, proc.logPath, { follow: false, signal: new AbortController().signal }, (d) => {
90
+ logs += d;
91
+ });
92
+ assert.match(logs, /tick-/, "process logs captured");
93
+ await driver.killProcess(id, proc.pid);
94
+ await sleep(400);
95
+ const dead = await driver.listProcesses(id, [{ procId: "p1", pid: proc.pid }]);
96
+ assert.ok(!dead[0]?.running, "process killed");
97
+ ok("background process: start → running → logs → kill → dead");
98
+ // M4b: preview-URL TCP bridge — a busybox `nc` loop serves a fixed HTTP
99
+ // response; fetch it through the bridge.
100
+ await driver.startProcess(id, "srv", "while true; do printf 'HTTP/1.0 200 OK\\r\\n\\r\\nbridge-works' | nc -l -p 9100 2>/dev/null; done", {});
101
+ await sleep(900);
102
+ const bridge = await driver.openTcpBridge(id, 9100, "127.0.0.1");
103
+ const resp = await new Promise((resolve) => {
104
+ let buf = "";
105
+ bridge.stream.on("data", (d) => (buf += d.toString()));
106
+ bridge.stream.on("end", () => resolve(buf));
107
+ bridge.stream.on("error", () => resolve(buf));
108
+ setTimeout(() => resolve(buf), 2500);
109
+ });
110
+ bridge.close();
111
+ assert.match(resp, /bridge-works/, "HTTP response flows through the bridge");
112
+ ok("preview TCP bridge: HTTP round-trips through the guest");
113
+ // M4c: interactive PTY terminal — type a command into a real shell, read it back.
114
+ const term = await driver.openTerminal(id, { cols: 80, rows: 24 });
115
+ const termOut = await new Promise((resolve) => {
116
+ let buf = "";
117
+ term.stream.on("data", (d) => {
118
+ buf += d.toString();
119
+ if (/TERMINAL_OK_42/.test(buf))
120
+ resolve(buf);
121
+ });
122
+ term.stream.on("error", () => resolve(buf));
123
+ setTimeout(() => term.stream.write("echo TERMINAL_OK_$((6*7))\n"), 500);
124
+ setTimeout(() => resolve(buf), 3500);
125
+ });
126
+ term.close();
127
+ assert.match(termOut, /TERMINAL_OK_42/, "PTY runs the command in a real shell");
128
+ ok("interactive PTY: command runs in a real shell");
129
+ // M5: stats from the guest /proc + cgroup (via the agent).
130
+ const stats = await driver.stats(id);
131
+ assert.ok(stats.onlineCpus >= 1, "stats reports online CPUs");
132
+ assert.ok(stats.memBytes > 0, "stats reports resident memory");
133
+ assert.ok(stats.pids > 0, "stats reports running pids");
134
+ ok(`stats: ${stats.onlineCpus} cpu / ${(stats.memBytes / 1e6).toFixed(0)}MB / ${stats.pids} pids`);
135
+ // M3: watch — open the stream, create a file, assert the event arrives.
136
+ const watchAbort = new AbortController();
137
+ const events = [];
138
+ const watching = driver.watchFiles(id, "/workspace", { intervalMs: 200, signal: watchAbort.signal }, (e) => events.push(`${e.type}:${e.path}`));
139
+ await sleep(400); // let the watcher take its baseline snapshot
140
+ await driver.writeFile(id, { path: "/workspace/watched.txt", content: "hi" });
141
+ for (let i = 0; i < 30 && !events.some((e) => /watched\.txt/.test(e)); i++)
142
+ await sleep(100);
143
+ watchAbort.abort();
144
+ await watching;
145
+ assert.ok(events.some((e) => /watched\.txt/.test(e)), "watch saw the new file");
146
+ ok(`watch: ${events.find((e) => /watched\.txt/.test(e))}`);
147
+ // M5: backup → mutate → restore → rollback round-trip.
148
+ const backupPath = join(stateDir, "backup.tar");
149
+ await driver.writeFile(id, { path: "/workspace/keep.txt", content: "in-backup" });
150
+ const { bytes } = await driver.createBackup(id, backupPath);
151
+ assert.ok(bytes > 0, "backup wrote bytes");
152
+ await driver.writeFile(id, { path: "/workspace/keep.txt", content: "MUTATED" });
153
+ await driver.writeFile(id, { path: "/workspace/extra.txt", content: "added-after-backup" });
154
+ await driver.restoreBackup(id, backupPath);
155
+ assert.equal(await driver.readFile(id, { path: "/workspace/keep.txt" }), "in-backup", "restore rolled the mutation back");
156
+ const filesAfter = await driver.listFiles(id, { path: "/workspace" });
157
+ assert.ok(!filesAfter.some((f) => f.name === "extra.txt"), "restore cleared files added after the backup");
158
+ ok("★ backup → mutate → restore → rollback");
159
+ await driver.destroy(id);
160
+ ok("destroy");
161
+ // M6b-1: two sandboxes booting the same read-only base rootfs concurrently,
162
+ // each writing to its own workspace — proves the shared base is safe.
163
+ const ca = "vzconcur-a";
164
+ const cb = "vzconcur-b";
165
+ try {
166
+ await Promise.all([
167
+ driver.create({ id: ca, image: "base", persist: true }),
168
+ driver.create({ id: cb, image: "base", persist: true }),
169
+ ]);
170
+ await Promise.all([
171
+ driver.writeFile(ca, { path: "/workspace/who.txt", content: "alpha" }),
172
+ driver.writeFile(cb, { path: "/workspace/who.txt", content: "beta" }),
173
+ ]);
174
+ const [ra, rb] = await Promise.all([
175
+ driver.readFile(ca, { path: "/workspace/who.txt" }),
176
+ driver.readFile(cb, { path: "/workspace/who.txt" }),
177
+ ]);
178
+ assert.equal(ra, "alpha", "sandbox A workspace isolated");
179
+ assert.equal(rb, "beta", "sandbox B workspace isolated");
180
+ ok("two concurrent VMs share the read-only base, isolated workspaces");
181
+ }
182
+ finally {
183
+ await Promise.all([driver.destroy(ca).catch(() => { }), driver.destroy(cb).catch(() => { })]);
184
+ }
185
+ // M6a: resource limits — a second VM capped at 256 MiB / 1 cpu / 64 pids.
186
+ // Memory + CPU are hard VM caps; pidsLimit is enforced by a guest cgroup.
187
+ const lid = "vzcheck02";
188
+ try {
189
+ await driver.create({
190
+ id: lid,
191
+ image: "base",
192
+ persist: true,
193
+ limits: { memoryMb: 256, cpus: 1, pidsLimit: 64 },
194
+ });
195
+ const read = async (cmd) => {
196
+ let o = "";
197
+ await driver.exec(lid, cmd, {}, (e) => {
198
+ if (e.type === "stdout")
199
+ o += e.data;
200
+ });
201
+ return o.trim();
202
+ };
203
+ const memKb = Number(await read("grep MemTotal /proc/meminfo | awk '{print $2}'"));
204
+ assert.ok(memKb > 0 && memKb <= 256 * 1024, `guest MemTotal ${memKb}KB within the 256 MiB cap`);
205
+ const nproc = Number(await read("nproc"));
206
+ assert.equal(nproc, 1, "guest sees exactly 1 online CPU");
207
+ const pidsMax = await read("cat /sys/fs/cgroup/sandbox/pids.max 2>/dev/null");
208
+ assert.equal(pidsMax, "64", "guest pids cgroup capped at 64");
209
+ ok(`resource limits: ${(memKb / 1024) | 0}MB mem / ${nproc} cpu / pids.max=${pidsMax}`);
210
+ }
211
+ finally {
212
+ await driver.destroy(lid).catch(() => { });
213
+ }
214
+ // M7a: snapshot/resume. VZ saveMachineStateTo saves the full VM state (RAM +
215
+ // devices); a later start() restores it (instant resume, no kernel boot),
216
+ // falling back to a cold boot if restore is unsupported. Disk state always
217
+ // survives; an in-RAM (tmpfs) marker survives only a true restore.
218
+ const snapId = "vzsnap01";
219
+ try {
220
+ await driver.create({ id: snapId, image: "base", persist: true });
221
+ await driver.writeFile(snapId, { path: "/workspace/disk.txt", content: "on-disk" });
222
+ await driver.exec(snapId, "echo SNAPSHOT_RAM_OK > /run/marker", {}, () => { }); // /run = tmpfs
223
+ await driver.snapshot(snapId); // pause + saveMachineStateTo + tear down
224
+ ok("snapshot saved (VZ saveMachineStateTo)");
225
+ const tResume = Date.now();
226
+ await driver.start({ id: snapId, image: "base", persist: true }); // restore (or cold-fallback)
227
+ const resumeMs = Date.now() - tResume;
228
+ assert.equal(await driver.readFile(snapId, { path: "/workspace/disk.txt" }), "on-disk", "workspace survives resume");
229
+ let ram = "";
230
+ await driver.exec(snapId, "cat /run/marker 2>/dev/null", {}, (e) => {
231
+ if (e.type === "stdout")
232
+ ram += e.data;
233
+ });
234
+ assert.match(ram, /SNAPSHOT_RAM_OK/, "in-RAM tmpfs marker lost — restore silently fell back to a cold boot");
235
+ ok(`★ instant restore: in-RAM state resumed in ${resumeMs}ms (no cold boot)`);
236
+ // The egress relay must survive the snapshot→resume cycle: the in-guest
237
+ // listener lives in restored RAM; the host listener is re-installed by the
238
+ // fresh helper process.
239
+ let egResume = "";
240
+ await driver.exec(snapId, `wget -qO- http://127.0.0.1:${EGRESS_PORT}/after-resume`, {}, (e) => {
241
+ if (e.type === "stdout")
242
+ egResume += e.data;
243
+ });
244
+ assert.match(egResume, /vz-egress-pong/, "egress relay must work after snapshot→resume");
245
+ ok("egress relay survives snapshot→resume");
246
+ }
247
+ finally {
248
+ await driver.destroy(snapId).catch(() => { });
249
+ }
250
+ // M6b-2: honor SBX_IMAGE — convert a real OCI image and run its own python.
251
+ const pyId = "vzpython01";
252
+ try {
253
+ console.error("[check] converting python:3.11-slim → VZ rootfs (first run pulls + builds)…");
254
+ await driver.create({ id: pyId, image: "python:3.11-slim", persist: true });
255
+ let pyOut = "";
256
+ const pc = await driver.exec(pyId, "python3 --version && echo IMG_OK", {}, (e) => {
257
+ if (e.type === "stdout")
258
+ pyOut += e.data;
259
+ });
260
+ assert.equal(pc, 0, "python3 exec exit code");
261
+ assert.match(pyOut, /Python 3\.11/, "the converted image runs its own python3");
262
+ assert.match(pyOut, /IMG_OK/, "exec works in the converted image");
263
+ ok(`SBX_IMAGE honored: ${pyOut.trim().split("\n")[0]}`);
264
+ }
265
+ finally {
266
+ await driver.destroy(pyId).catch(() => { });
267
+ }
268
+ console.log(`\napplevz-check: ${passed} checks passed`);
269
+ }
270
+ finally {
271
+ await driver.stop(id).catch(() => { });
272
+ await new Promise((r) => gateway.close(() => r()));
273
+ rmSync(stateDir, { recursive: true, force: true });
274
+ }
275
+ }
276
+ main().then(() => process.exit(0), (err) => {
277
+ console.error("applevz-check FAILED:", err);
278
+ process.exit(1);
279
+ });
280
+ //# sourceMappingURL=applevz-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applevz-check.js","sourceRoot":"","sources":["../src/applevz-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /** Metadata for a workspace backup, persisted as a JSON sidecar on the host. */
2
+ export interface BackupInfo {
3
+ backupId: string;
4
+ /** Sandbox the backup was taken from (a backup may be restored elsewhere). */
5
+ sandboxId: string;
6
+ createdAt: string;
7
+ /** Size of the tarball in bytes. */
8
+ bytes: number;
9
+ }
10
+ /**
11
+ * On-disk registry of workspace backups. Unlike the in-memory `SandboxStore`,
12
+ * backups must survive daemon restarts, so each backup is a `<id>.tar` tarball
13
+ * plus a `<id>.json` metadata sidecar in `dir`; `list` rescans the directory.
14
+ */
15
+ export declare class BackupRegistry {
16
+ private readonly dir;
17
+ constructor(dir: string);
18
+ /** Host path of a backup's tarball (managed by the driver). */
19
+ tarPath(backupId: string): string;
20
+ private metaPath;
21
+ ensureDir(): Promise<void>;
22
+ /** Persist a backup's metadata. The tarball is written separately. */
23
+ save(info: BackupInfo): Promise<void>;
24
+ get(backupId: string): Promise<BackupInfo | undefined>;
25
+ /** List all backups, newest first. */
26
+ list(): Promise<BackupInfo[]>;
27
+ /** Remove a backup's tarball and metadata. Returns false if unknown. */
28
+ remove(backupId: string): Promise<boolean>;
29
+ }
@@ -0,0 +1,76 @@
1
+ import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ /**
4
+ * On-disk registry of workspace backups. Unlike the in-memory `SandboxStore`,
5
+ * backups must survive daemon restarts, so each backup is a `<id>.tar` tarball
6
+ * plus a `<id>.json` metadata sidecar in `dir`; `list` rescans the directory.
7
+ */
8
+ export class BackupRegistry {
9
+ dir;
10
+ constructor(dir) {
11
+ this.dir = dir;
12
+ }
13
+ /** Host path of a backup's tarball (managed by the driver). */
14
+ tarPath(backupId) {
15
+ return join(this.dir, `${backupId}.tar`);
16
+ }
17
+ metaPath(backupId) {
18
+ return join(this.dir, `${backupId}.json`);
19
+ }
20
+ async ensureDir() {
21
+ await mkdir(this.dir, { recursive: true });
22
+ }
23
+ /** Persist a backup's metadata. The tarball is written separately. */
24
+ async save(info) {
25
+ await this.ensureDir();
26
+ await writeFile(this.metaPath(info.backupId), JSON.stringify(info, null, 2));
27
+ }
28
+ async get(backupId) {
29
+ try {
30
+ const raw = await readFile(this.metaPath(backupId), "utf8");
31
+ return JSON.parse(raw);
32
+ }
33
+ catch (err) {
34
+ if (isNotFound(err))
35
+ return undefined;
36
+ throw err;
37
+ }
38
+ }
39
+ /** List all backups, newest first. */
40
+ async list() {
41
+ let names;
42
+ try {
43
+ names = await readdir(this.dir);
44
+ }
45
+ catch (err) {
46
+ if (isNotFound(err))
47
+ return [];
48
+ throw err;
49
+ }
50
+ const infos = [];
51
+ for (const name of names) {
52
+ if (!name.endsWith(".json"))
53
+ continue;
54
+ const info = await this.get(name.slice(0, -".json".length));
55
+ if (info)
56
+ infos.push(info);
57
+ }
58
+ return infos.sort((a, b) => (a.createdAt < b.createdAt ? 1 : -1));
59
+ }
60
+ /** Remove a backup's tarball and metadata. Returns false if unknown. */
61
+ async remove(backupId) {
62
+ const info = await this.get(backupId);
63
+ if (!info)
64
+ return false;
65
+ await rm(this.tarPath(backupId), { force: true });
66
+ await rm(this.metaPath(backupId), { force: true });
67
+ return true;
68
+ }
69
+ }
70
+ function isNotFound(err) {
71
+ return (typeof err === "object" &&
72
+ err !== null &&
73
+ "code" in err &&
74
+ err.code === "ENOENT");
75
+ }
76
+ //# sourceMappingURL=backups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backups.js","sourceRoot":"","sources":["../src/backups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { Config } from "./config.js";
2
+ import type { HostInfo } from "./driver/types.js";
3
+ import type { MetricsHistory } from "./metrics.js";
4
+ import type { SandboxStore } from "./store.js";
5
+ /** Host capacity + what's currently committed by running sandboxes. */
6
+ export interface CapacitySnapshot {
7
+ /** Whether admission control is actively rejecting over-budget creates. */
8
+ enforced: boolean;
9
+ overcommit: number;
10
+ defaultReservationMb: number;
11
+ memory: {
12
+ budgetMb: number;
13
+ committedMb: number;
14
+ availableMb: number;
15
+ };
16
+ cpu: {
17
+ budget: number;
18
+ committed: number;
19
+ available: number;
20
+ };
21
+ running: number;
22
+ /** Approx. number of additional default-reservation sandboxes that still fit. */
23
+ fits: number;
24
+ }
25
+ /**
26
+ * Capacity meter + admission control — **usage-based**, so light and heavy
27
+ * sandboxes size themselves without anyone declaring a tier:
28
+ * - a **capped** sandbox reserves its hard cap (exact, kernel-enforced ceiling);
29
+ * - an **uncapped** sandbox reserves `max(its most-recent sampled RSS, floor)` —
30
+ * measured, not guessed, so an idle box packs many while a busy box admits few.
31
+ * The `floor` (`SBX_DEFAULT_RESERVATION_MB`) covers a just-started sandbox that
32
+ * hasn't grown (or been sampled) yet. A new sandbox is admitted only if it fits
33
+ * within the host memory budget × overcommit. Memory is the hard gate (OOM kills);
34
+ * CPU is reported but not gated (throttled, not fatal). Without a metrics history
35
+ * (e.g. tests) it falls back to floor-only accounting.
36
+ */
37
+ export declare class Capacity {
38
+ private readonly store;
39
+ private readonly config;
40
+ private readonly history?;
41
+ /** Effective memory budget (MiB) after overcommit; 0 = unknown → admission off. */
42
+ private readonly budgetMemMb;
43
+ private readonly budgetCpus;
44
+ constructor(store: SandboxStore, config: Config, host: HostInfo | null, history?: MetricsHistory | undefined);
45
+ /** Admission is active only when enabled AND the budget is known. */
46
+ get enforced(): boolean;
47
+ /** The floor counted for an uncapped/just-started sandbox. */
48
+ private get floorMb();
49
+ /**
50
+ * Memory an existing running sandbox is charged: its hard cap when set
51
+ * (the guaranteed ceiling), else `max(measured RSS, floor)`.
52
+ */
53
+ private reservationFor;
54
+ private committed;
55
+ /** Decide whether a new sandbox with `requestMemoryMb` can be admitted. */
56
+ admit(requestMemoryMb?: number): {
57
+ ok: true;
58
+ } | {
59
+ ok: false;
60
+ reason: string;
61
+ };
62
+ snapshot(): CapacitySnapshot;
63
+ }
@@ -0,0 +1,95 @@
1
+ const MIB = 1024 * 1024;
2
+ /**
3
+ * Capacity meter + admission control — **usage-based**, so light and heavy
4
+ * sandboxes size themselves without anyone declaring a tier:
5
+ * - a **capped** sandbox reserves its hard cap (exact, kernel-enforced ceiling);
6
+ * - an **uncapped** sandbox reserves `max(its most-recent sampled RSS, floor)` —
7
+ * measured, not guessed, so an idle box packs many while a busy box admits few.
8
+ * The `floor` (`SBX_DEFAULT_RESERVATION_MB`) covers a just-started sandbox that
9
+ * hasn't grown (or been sampled) yet. A new sandbox is admitted only if it fits
10
+ * within the host memory budget × overcommit. Memory is the hard gate (OOM kills);
11
+ * CPU is reported but not gated (throttled, not fatal). Without a metrics history
12
+ * (e.g. tests) it falls back to floor-only accounting.
13
+ */
14
+ export class Capacity {
15
+ store;
16
+ config;
17
+ history;
18
+ /** Effective memory budget (MiB) after overcommit; 0 = unknown → admission off. */
19
+ budgetMemMb;
20
+ budgetCpus;
21
+ constructor(store, config, host, history) {
22
+ this.store = store;
23
+ this.config = config;
24
+ this.history = history;
25
+ const baseMem = config.hostMemoryMb > 0 ? config.hostMemoryMb : (host?.memoryMb ?? 0);
26
+ this.budgetMemMb = Math.floor(baseMem * (config.overcommit || 1));
27
+ this.budgetCpus = config.hostCpus > 0 ? config.hostCpus : (host?.cpus ?? 0);
28
+ }
29
+ /** Admission is active only when enabled AND the budget is known. */
30
+ get enforced() {
31
+ return this.config.admission === "enforce" && this.budgetMemMb > 0;
32
+ }
33
+ /** The floor counted for an uncapped/just-started sandbox. */
34
+ get floorMb() {
35
+ return this.config.defaultReservationMb;
36
+ }
37
+ /**
38
+ * Memory an existing running sandbox is charged: its hard cap when set
39
+ * (the guaranteed ceiling), else `max(measured RSS, floor)`.
40
+ */
41
+ reservationFor(id, memoryCapMb) {
42
+ if (memoryCapMb && memoryCapMb > 0)
43
+ return memoryCapMb;
44
+ const rssBytes = this.history?.latestMemBytes(id) ?? 0;
45
+ return Math.max(Math.round(rssBytes / MIB), this.floorMb);
46
+ }
47
+ committed() {
48
+ let mem = 0;
49
+ let cpu = 0;
50
+ for (const r of this.store.list()) {
51
+ if (r.status !== "running")
52
+ continue; // paused/stopped free their compute
53
+ mem += this.reservationFor(r.id, r.limits.memoryMb);
54
+ cpu += r.limits.cpus && r.limits.cpus > 0 ? r.limits.cpus : 0;
55
+ }
56
+ return { mem, cpu };
57
+ }
58
+ /** Decide whether a new sandbox with `requestMemoryMb` can be admitted. */
59
+ admit(requestMemoryMb) {
60
+ if (!this.enforced)
61
+ return { ok: true };
62
+ const { mem } = this.committed();
63
+ // A new sandbox hasn't run yet: charge its cap if set, else the floor.
64
+ const req = requestMemoryMb && requestMemoryMb > 0 ? requestMemoryMb : this.floorMb;
65
+ if (mem + req > this.budgetMemMb) {
66
+ return {
67
+ ok: false,
68
+ reason: `host memory budget exhausted: ${mem}/${this.budgetMemMb} MiB committed, ` +
69
+ `this sandbox needs ${req} MiB. Free a sandbox, set a smaller --memory, ` +
70
+ `or raise SBX_OVERCOMMIT / SBX_HOST_MEMORY_MB.`,
71
+ };
72
+ }
73
+ return { ok: true };
74
+ }
75
+ snapshot() {
76
+ const { mem, cpu } = this.committed();
77
+ const availableMb = Math.max(0, this.budgetMemMb - mem);
78
+ return {
79
+ enforced: this.enforced,
80
+ overcommit: this.config.overcommit || 1,
81
+ defaultReservationMb: this.config.defaultReservationMb,
82
+ memory: { budgetMb: this.budgetMemMb, committedMb: mem, availableMb },
83
+ cpu: {
84
+ budget: this.budgetCpus,
85
+ committed: Math.round(cpu * 100) / 100,
86
+ available: Math.max(0, Math.round((this.budgetCpus - cpu) * 100) / 100),
87
+ },
88
+ running: this.store.list().filter((r) => r.status === "running").length,
89
+ fits: this.config.defaultReservationMb > 0
90
+ ? Math.floor(availableMb / this.config.defaultReservationMb)
91
+ : 0,
92
+ };
93
+ }
94
+ }
95
+ //# sourceMappingURL=capacity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capacity.js","sourceRoot":"","sources":["../src/capacity.ts"],"names":[],"mappings":"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"}