@ghalex/kvbox-server 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../shared/src/errors.ts","../../shared/src/paths.ts","../src/core/config.ts","../../shared/src/sizes.ts","../src/core/refs.ts","../src/core/network.ts","../src/core/exec.ts","../src/listen.ts","../src/core/state.ts","../src/core/migrate.ts","../src/core/db.ts","../src/core/machines.ts","../src/core/agent.ts","../src/core/capacity.ts","../src/core/firecracker.ts","../src/core/usage.ts","../src/app.ts","../../shared/src/version.ts","../src/version.ts","../src/caller.ts","../src/routes/capacity.ts","../src/routes/machines.ts","../../shared/src/api.ts","../src/routes/snapshots.ts","../src/core/snapshots.ts"],"sourcesContent":["/**\n * kvbox-server: the host daemon. `kvbox-server` (or `kvbox-server start`) serves\n * the kvbox API on ~/.kvbox/server.sock in the foreground; the CLI's\n * `kvbox server start` spawns it detached. M2 adds `register`.\n */\nimport { spawnSync } from \"node:child_process\";\nimport { Command } from \"commander\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths } from \"@kvbox/shared/paths\";\nimport { loadConfig } from \"./core/config.js\";\nimport { ensureHostNetwork, netSetupScript } from \"./core/network.js\";\nimport { listen } from \"./listen.js\";\nimport { VERSION } from \"./version.js\";\n\nconst program = new Command(\"kvbox-server\")\n .description(\"kvbox host daemon: owns Firecracker and ~/.kvbox, serves the kvbox API\")\n .version(VERSION, \"-v, --version\")\n .showHelpAfterError();\n\nprogram\n .command(\"start\", { isDefault: true })\n .description(\"serve the API on the local Unix socket (foreground)\")\n .option(\"--socket <path>\", \"socket to listen on (default: $KVBOX_HOME/server.sock)\")\n .action(async (opts: { socket?: string }) => {\n const { socketPath } = await listen(opts.socket ? { socketPath: opts.socket } : {});\n console.log(`kvbox-server ${VERSION} listening on ${socketPath} (pid ${process.pid})`);\n // The bridge vanishes on host reboot; recreate it. Not fatal: ls/status must still work.\n try {\n const cfg = await loadConfig(paths());\n const state = await ensureHostNetwork(cfg);\n console.log(`host network: bridge ${cfg.bridge} ${state}`);\n } catch (err) {\n console.error(`warning: host network not ready (${(err as Error).message}); run: kvbox-server net up`);\n }\n });\n\nprogram\n .command(\"net <action>\")\n .description(\"host network: up | down | status (bridge, forwarding, NAT; uses sudo)\")\n .action(async (action: string) => {\n if (![\"up\", \"down\", \"status\"].includes(action)) throw new KvboxError(\"net: expected up, down or status\");\n const cfg = await loadConfig(paths());\n const res = spawnSync(netSetupScript(), [action], {\n stdio: \"inherit\",\n env: { ...process.env, KVBOX_BRIDGE: cfg.bridge, KVBOX_SUBNET: cfg.subnet, KVBOX_GATEWAY: cfg.gateway },\n });\n process.exit(res.status ?? 1);\n });\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err) {\n if (err instanceof KvboxError) {\n console.error(`error: ${err.message}`);\n process.exit(err.exitCode);\n }\n throw err;\n}\n","/** Errors with an exit code; the entry point prints `message` and exits with `exitCode`. */\nexport class KvboxError extends Error {\n constructor(\n message: string,\n public readonly exitCode: number = 1,\n ) {\n super(message);\n this.name = \"KvboxError\";\n }\n}\n\nexport class NotImplementedError extends KvboxError {\n constructor(what: string) {\n super(`${what}: not implemented yet`, 2);\n this.name = \"NotImplementedError\";\n }\n}\n\n/** The named box/snapshot/host does not exist: HTTP 404, exit 1. */\nexport class NotFoundError extends KvboxError {\n constructor(what: string) {\n super(`${what}: not found`, 1);\n this.name = \"NotFoundError\";\n }\n}\n","/**\n * Host state layout. The filesystem is the database and `~/.kvbox` is its root.\n * This module is dependency-free so both the CLI (socket path, hosts.json)\n * and core (everything else) can use it without crossing the layer boundary.\n *\n * `KVBOX_HOME` overrides the root, mainly for tests.\n */\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport function kvboxHome(): string {\n return process.env[\"KVBOX_HOME\"] ?? join(homedir(), \".kvbox\");\n}\n\nexport function paths(home: string = kvboxHome()) {\n return {\n home,\n config: join(home, \"config.json\"),\n /** The host's ledgers (SQLite via node:sqlite): usage events today. Boxes and snapshots stay files; see server core/db.ts. */\n db: join(home, \"kvbox.db\"),\n serverSock: join(home, \"server.sock\"),\n serverPid: join(home, \"server.pid\"),\n serverLog: join(home, \"server.log\"),\n hosts: join(home, \"hosts.json\"),\n ssh: join(home, \"ssh\"),\n sshKey: join(home, \"ssh\", \"id_ed25519\"),\n bin: join(home, \"bin\"),\n firecracker: join(home, \"bin\", \"firecracker\"),\n /** Firecracker's snapshot-editor, from the same release: merges a diff snapshot onto a full memory image. */\n snapshotEditor: join(home, \"bin\", \"snapshot-editor\"),\n assets: join(home, \"assets\"),\n kernel: join(home, \"assets\", \"vmlinux\"),\n /** Symlink to the current base image, assets/rootfs-<version>.ext4; boxes keep using the version they were made from. */\n rootfs: join(home, \"assets\", \"rootfs.ext4\"),\n baseImage: (version: string) => join(home, \"assets\", `rootfs-${version}.ext4`),\n machines: join(home, \"machines\"),\n snapshots: join(home, \"snapshots\"),\n /** Boxes and snapshots are filed by owner: machines/<owner>/<name>. The owner is part of a box's identity. */\n ownerMachines: (owner: string) => join(home, \"machines\", owner),\n ownerSnapshots: (owner: string) => join(home, \"snapshots\", owner),\n machine: (owner: string, name: string) => {\n const dir = join(home, \"machines\", owner, name);\n return {\n dir,\n meta: join(dir, \"meta.json\"),\n /** The box's writable layer, stacked on the read-only base image inside the guest. */\n overlay: join(dir, \"overlay.ext4\"),\n /** Boxes made before overlays: a full copy of the base image. Kept bootable, never created anymore. */\n disk: join(dir, \"disk.ext4\"),\n /**\n * The box's memory as of its last snapshot (a hard link to that snapshot's `mem`, never modified).\n * The next snapshot is a diff of the pages dirtied since, merged onto this. Absent after a boot.\n */\n memBase: join(dir, \"mem.base\"),\n sock: join(dir, \"fc.sock\"),\n /** Firecracker's vsock endpoint: the host connects here to reach kvbox-agent inside the box (core/agent.ts). */\n vsock: join(dir, \"vsock.sock\"),\n log: join(dir, \"fc.log\"),\n };\n },\n snapshot: (owner: string, name: string) => {\n const dir = join(home, \"snapshots\", owner, name);\n return {\n dir,\n meta: join(dir, \"meta.json\"),\n vmstate: join(dir, \"vmstate\"),\n mem: join(dir, \"mem\"),\n /** Copy of the box's overlay at the moment of the snapshot; the base image is referenced by version in meta.json. */\n overlay: join(dir, \"overlay.ext4\"),\n };\n },\n } as const;\n}\n\nexport type Paths = ReturnType<typeof paths>;\n","/** `~/.kvbox/config.json`: asset paths, subnet, default size, owner. Written with defaults on first run. */\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { DEFAULT_SIZE, SIZE_NAMES } from \"@kvbox/shared/sizes\";\nimport { LOCAL_OWNER_RE, localOwner } from \"./refs.js\";\n\n/** What an hour of each resource costs, for `kvbox vm usage`'s estimated cost. Absent by default: no cost row. */\nexport const PricingSchema = z.object({\n currency: z.string().min(1),\n vcpuHour: z.number().nonnegative(),\n ramGibHour: z.number().nonnegative(),\n diskGibHour: z.number().nonnegative(),\n});\nexport type Pricing = z.infer<typeof PricingSchema>;\n\nexport const ConfigSchema = z.object({\n kernel: z.string(),\n rootfs: z.string(),\n firecracker: z.string(),\n snapshotEditor: z.string().optional(), // default: bin/snapshot-editor next to firecracker\n bridge: z.string().default(\"kvbox0\"),\n subnet: z.string().default(\"172.30.0.0/24\"),\n gateway: z.string().default(\"172.30.0.1\"),\n defaultSize: z.enum(SIZE_NAMES as [string, ...string[]]).default(DEFAULT_SIZE),\n /** Who boxes made over the local socket belong to: the Unix user running the server unless set here. No `@`, no `/`. */\n owner: z.string().regex(LOCAL_OWNER_RE, \"owner: letters, digits, '.', '_', '-'; no '@' or '/'\").default(localOwner),\n pricing: PricingSchema.optional(),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport function defaultConfig(p: Paths = paths()): Config {\n return ConfigSchema.parse({\n kernel: p.kernel,\n rootfs: p.rootfs,\n firecracker: p.firecracker,\n snapshotEditor: p.snapshotEditor,\n owner: localOwner(),\n });\n}\n\nexport async function loadConfig(p: Paths = paths()): Promise<Config> {\n try {\n const raw = await readFile(p.config, \"utf8\");\n return ConfigSchema.parse(JSON.parse(raw));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n const cfg = defaultConfig(p);\n await writeFile(p.config, JSON.stringify(cfg, null, 2) + \"\\n\");\n return cfg;\n }\n throw err;\n }\n}\n","/**\n * Fixed box sizes. Firecracker backs guest memory lazily and the disk is a sparse overlay on the\n * shared base image, so a box only costs what the guest actually touches.\n */\nexport const SIZES = {\n s: { vcpu: 2, memMib: 4096, diskGib: 8 },\n m: { vcpu: 4, memMib: 8192, diskGib: 16 },\n l: { vcpu: 8, memMib: 16384, diskGib: 32 },\n} as const;\n\nexport type SizeName = keyof typeof SIZES;\nexport const SIZE_NAMES = Object.keys(SIZES) as SizeName[];\nexport const DEFAULT_SIZE: SizeName = \"s\";\n\nexport function isSizeName(value: string): value is SizeName {\n return value in SIZES;\n}\n\n/**\n * \"16GB\", \"16G\", \"16\", \"4096MB\", \"4096M\", \"0.5GB\" -> MiB. A bare number is GB: that is how\n * people say it (\"16gb\", \"4 vcpu 16gb\"). Returns undefined when it is not a size.\n */\nexport function parseMib(text: string): number | undefined {\n const m = /^\\s*(\\d+(?:\\.\\d+)?)\\s*([gm]i?b?)?\\s*$/i.exec(text);\n if (!m) return undefined;\n const n = Number(m[1]);\n const unit = (m[2] ?? \"g\").toLowerCase();\n const mib = unit.startsWith(\"m\") ? n : n * 1024;\n return Number.isInteger(mib) && mib > 0 ? mib : undefined;\n}\n","/**\n * Who a box belongs to. Names are unique per owner, not per host, so a box is addressed as\n * `owner/name`; a bare `name` means the caller's own. The owner is part of the box's identity and\n * lives with it on disk (machines/<owner>/<name>, `owner` in meta.json), never in a database.\n * Decision \"Owner realms\": a bare owner is local to this host (the Unix user running kvbox-server);\n * a control plane's users arrive as `user@<control plane>` later (#18), so the two never collide.\n */\nimport { userInfo } from \"node:os\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nexport interface BoxRef {\n owner: string;\n name: string;\n /** How the caller wrote it: `lab1` for their own, `user2/lab1` for someone else's. Set by parseRef, used in messages. */\n display?: string;\n}\n\n/** The ref as the caller knows it (see BoxRef.display); bare name when nothing else is known. */\nexport function shown(ref: BoxRef): string {\n return ref.display ?? ref.name;\n}\n\n/** A local owner is a Unix user name: no `@` (that marks a control-plane realm) and no `/`. */\nexport const LOCAL_OWNER_RE = /^[A-Za-z0-9_][A-Za-z0-9._-]{0,63}$/;\n/** Any owner, local or `user@realm`. */\nexport const OWNER_RE = /^[A-Za-z0-9_][A-Za-z0-9._-]{0,63}(@[A-Za-z0-9.-]{1,128})?$/;\n\n/** The Unix user running this server: what boxes made over the local socket belong to. */\nexport function localOwner(): string {\n try {\n const name = userInfo().username;\n if (LOCAL_OWNER_RE.test(name)) return name;\n } catch {\n /* no passwd entry */\n }\n const env = process.env[\"USER\"];\n return env !== undefined && LOCAL_OWNER_RE.test(env) ? env : \"kvbox\";\n}\n\n/** `lab1` → the caller's box; `user2/lab1` → that owner's. */\nexport function parseRef(text: string, caller: string): BoxRef {\n const slash = text.indexOf(\"/\");\n if (slash === -1) return { owner: caller, name: text, display: text };\n const owner = text.slice(0, slash);\n const name = text.slice(slash + 1);\n if (!OWNER_RE.test(owner) || name.length === 0 || name.includes(\"/\")) {\n throw new KvboxError(`invalid box reference \"${text}\": use <name> or <owner>/<name>`);\n }\n return { owner, name, display: owner === caller ? name : text };\n}\n\n/** `owner/name`: how a ref is written down (snapshot sources, box sources, admin listings). */\nexport function refKey(ref: BoxRef): string {\n return `${ref.owner}/${ref.name}`;\n}\n","/**\n * Host networking: bridge `kvbox0`, one tap `kv-<box>` per box, IP allocation\n * inside the subnet. Everything that needs root goes through one script,\n * `net-setup.sh`, which re-execs itself with `sudo -n` when run from here.\n * `install-server.sh` installs a root-owned copy at PRIVILEGED_SCRIPT plus a\n * sudoers rule for exactly that path; the package copy is the dev fallback.\n */\nimport { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { Config } from \"./config.js\";\nimport { run } from \"./exec.js\";\n\nexport const TAP_PREFIX = \"kv-\";\nexport const PRIVILEGED_SCRIPT = \"/usr/local/lib/kvbox/net-setup.sh\";\n\ntype NetConfig = Pick<Config, \"bridge\" | \"subnet\" | \"gateway\">;\n\nexport function tapName(box: string): string {\n // Linux interface names are limited to 15 characters.\n return `${TAP_PREFIX}${box}`.slice(0, 15);\n}\n\n/** The script to run: KVBOX_NET_SETUP override, the root-owned install, else the package copy (dist/ or src/core/). */\nexport function netSetupScript(): string {\n const override = process.env[\"KVBOX_NET_SETUP\"];\n if (override) return override;\n if (existsSync(PRIVILEGED_SCRIPT)) return PRIVILEGED_SCRIPT;\n for (const rel of [\"../scripts/net-setup.sh\", \"../../scripts/net-setup.sh\"]) {\n const candidate = fileURLToPath(new URL(rel, import.meta.url));\n if (existsSync(candidate)) return candidate;\n }\n throw new KvboxError(\"net-setup.sh not found next to kvbox-server\");\n}\n\nexport function bridgeExists(bridge: string): boolean {\n return existsSync(`/sys/class/net/${bridge}`);\n}\n\nfunction netRun(cfg: NetConfig, args: string[]) {\n return run([netSetupScript(), ...args], {\n env: { ...process.env, KVBOX_BRIDGE: cfg.bridge, KVBOX_SUBNET: cfg.subnet, KVBOX_GATEWAY: cfg.gateway },\n }).catch((err: Error) => {\n throw new KvboxError(\n `${err.message}\\n (root is needed for host networking; install-server.sh sets up a sudoers rule for ${PRIVILEGED_SCRIPT})`,\n );\n });\n}\n\n/** Run `net-setup.sh up` when the bridge is missing, which is the case after every host reboot. */\nexport async function ensureHostNetwork(cfg: NetConfig): Promise<\"present\" | \"created\"> {\n if (bridgeExists(cfg.bridge)) return \"present\";\n await netRun(cfg, [\"up\"]);\n return \"created\";\n}\n\n/**\n * Create the box's tap (owned by this user) and return its name. Plugged into the bridge unless\n * `detached`: a box restored from a snapshot still carries the source box's MAC and IP, so its tap\n * stays off the switch until kvbox-agent has given it its own (attachTap).\n */\nexport async function createTap(box: string, cfg: NetConfig, opts: { detached?: boolean } = {}): Promise<string> {\n const tap = tapName(box);\n await netRun(cfg, [\"tap\", \"add\", tap, ...(opts.detached ? [\"detached\"] : [])]);\n return tap;\n}\n\nexport async function attachTap(box: string, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"tap\", \"attach\", tapName(box)]);\n}\n\nexport async function deleteTap(box: string, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"tap\", \"del\", tapName(box)]);\n}\n\n// ── addresses ────────────────────────────────────────────────────────────────\nconst ipToInt = (ip: string) => ip.split(\".\").reduce((acc, o) => (acc << 8) + Number(o), 0) >>> 0;\nconst intToIp = (n: number) => [24, 16, 8, 0].map((s) => (n >>> s) & 255).join(\".\");\n\n/** Lowest free host address in `subnet` (a.b.c.d/len), skipping network, gateway (.1) and broadcast. */\nexport function nextFreeIp(subnet: string, inUse: readonly string[]): string {\n const [base, lenStr] = subnet.split(\"/\");\n const len = Number(lenStr);\n if (!base || !Number.isInteger(len) || len < 8 || len > 30) throw new KvboxError(`bad subnet: ${subnet}`);\n const mask = len === 0 ? 0 : (~0 << (32 - len)) >>> 0;\n const network = (ipToInt(base) & mask) >>> 0;\n const broadcast = (network | (~mask >>> 0)) >>> 0;\n const used = new Set(inUse.map(ipToInt));\n for (let n = network + 2; n < broadcast; n++) {\n if (!used.has(n)) return intToIp(n);\n }\n throw new KvboxError(`no free IP left in ${subnet}`);\n}\n\n/** Locally administered MAC derived from the IP: 06:00:<a>:<b>:<c>:<d>, unique per box and readable. */\nexport function macFor(ip: string): string {\n const hex = ip.split(\".\").map((o) => Number(o).toString(16).padStart(2, \"0\").toUpperCase());\n return [\"06\", \"00\", ...hex].join(\":\");\n}\n","/**\n * The one shell-out helper. Every `firecracker`, `ip`, `ssh`, `cp` call goes\n * through here: argv arrays only (never a shell string), the command is logged,\n * and stderr ends up in the thrown error.\n */\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface RunOptions {\n sudo?: boolean;\n cwd?: string;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n /** Non-zero exit codes that are not failures (e2fsck: 1 = \"errors corrected\"). */\n okExitCodes?: readonly number[];\n}\n\nexport interface RunResult {\n stdout: string;\n stderr: string;\n}\n\nexport async function run(argv: readonly string[], opts: RunOptions = {}): Promise<RunResult> {\n const [cmd, ...args] = opts.sudo ? [\"sudo\", \"-n\", ...argv] : argv;\n if (!cmd) throw new KvboxError(\"run: empty argv\");\n if (process.env[\"KVBOX_DEBUG\"]) console.error(`[exec] ${[cmd, ...args].join(\" \")}`);\n try {\n const { stdout, stderr } = await execFileAsync(cmd, args, {\n cwd: opts.cwd,\n env: opts.env ?? process.env,\n timeout: opts.timeoutMs ?? 30_000,\n maxBuffer: 8 * 1024 * 1024,\n });\n return { stdout, stderr };\n } catch (err) {\n const e = err as NodeJS.ErrnoException & { stdout?: string; stderr?: string; code?: number | string };\n if (typeof e.code === \"number\" && opts.okExitCodes?.includes(e.code)) return { stdout: e.stdout ?? \"\", stderr: e.stderr ?? \"\" };\n const detail = (e.stderr ?? e.message ?? \"\").trim();\n throw new KvboxError(`${[cmd, ...args].join(\" \")} failed${detail ? `: ${detail}` : \"\"}`);\n }\n}\n","/** Bind the app to the local Unix socket and write the pid file. */\nimport { rm, writeFile } from \"node:fs/promises\";\nimport { createAdaptorServer } from \"@hono/node-server\";\nimport { ensureLayout } from \"./core/state.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { migrateOwnerLayout } from \"./core/migrate.js\";\nimport { seedUsageLedger } from \"./core/usage.js\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths } from \"@kvbox/shared/paths\";\nimport { createApp } from \"./app.js\";\n\nexport interface ListenOptions {\n socketPath?: string;\n}\n\nexport async function listen(opts: ListenOptions = {}) {\n const p = await ensureLayout(paths());\n const cfg = await loadConfig(p);\n const moved = await migrateOwnerLayout(cfg.owner, p);\n if (moved.boxes.length + moved.snapshots.length > 0) {\n console.error(`boxes and snapshots now belong to an owner: moved ${moved.boxes.length} box(es) and ${moved.snapshots.length} snapshot(s) under ${cfg.owner}/`);\n }\n for (const c of moved.conflicts) console.error(`warning: ${c} left in place: ${cfg.owner} already has one with that name`);\n const seeded = await seedUsageLedger(p);\n if (seeded > 0) console.error(`usage: started keeping time for ${seeded} box(es) made before this version; kvbox vm usage counts from now for them`);\n const socketPath = opts.socketPath ?? p.serverSock;\n // Linux limits a Unix socket path (sun_path) to 108 bytes; bind() fails with EINVAL past it.\n if (Buffer.byteLength(socketPath) > 100) {\n throw new KvboxError(`socket path too long for a Unix socket (${socketPath}); set KVBOX_HOME to a shorter path`);\n }\n\n // A stale socket file from a crashed server blocks bind(); the pid file tells\n // `server status` whether anything is actually alive.\n await rm(socketPath, { force: true });\n\n const server = createAdaptorServer({ fetch: createApp().fetch });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(socketPath, () => resolve());\n });\n await writeFile(p.serverPid, `${process.pid}\\n`);\n\n const shutdown = async () => {\n server.close();\n await rm(socketPath, { force: true });\n await rm(p.serverPid, { force: true });\n process.exit(0);\n };\n process.once(\"SIGINT\", () => void shutdown());\n process.once(\"SIGTERM\", () => void shutdown());\n\n return { socketPath, server };\n}\n","/**\n * The `~/.kvbox` layout and the per-box / per-snapshot `meta.json` files.\n * The server is the only writer; every read is validated with zod.\n */\nimport { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport type { BoxRef } from \"./refs.js\";\n\nexport const MachineMetaSchema = z.object({\n name: z.string(),\n /** Part of the box's identity: machines/<owner>/<name>. See refs.ts. */\n owner: z.string(),\n ip: z.string(),\n mac: z.string(),\n pid: z.number().int().nullable(), // null: stopped on purpose, disk kept\n vcpu: z.number().int(),\n memMib: z.number().int(),\n createdAt: z.string(),\n source: z.string(),\n /** Base image version (assets/rootfs-<version>.ext4) the box overlays. Absent: a pre-overlay box with its own disk.ext4. */\n base: z.string().optional(),\n /**\n * Snapshots taken since this VM started (boot or restore). Firecracker resets its dirty-page bitmap at\n * each one, so when this is > 0 the next diff is only standalone merged onto `mem.base`; if that file\n * is missing the lineage is broken and the next snapshot has to be a full dump. Absent: 0.\n */\n memSnapshots: z.number().int().optional(),\n});\nexport type MachineMeta = z.infer<typeof MachineMetaSchema>;\n\nexport const SnapshotMetaSchema = z.object({\n name: z.string(),\n owner: z.string(),\n /** The box it was taken from, as owner/name. */\n source: z.string(),\n base: z.string(),\n vcpu: z.number().int(),\n memMib: z.number().int(),\n sizeBytes: z.number().int(),\n createdAt: z.string(),\n});\nexport type SnapshotMeta = z.infer<typeof SnapshotMetaSchema>;\n\n/** Create every directory of the layout. Idempotent; called by `kvbox server start`. */\nexport async function ensureLayout(p: Paths = paths()): Promise<Paths> {\n for (const dir of [p.home, p.ssh, p.bin, p.assets, p.machines, p.snapshots]) {\n await mkdir(dir, { recursive: true, mode: 0o700 });\n }\n return p;\n}\n\nasync function readJson<T>(file: string, schema: z.ZodType<T>): Promise<T> {\n return schema.parse(JSON.parse(await readFile(file, \"utf8\")));\n}\n\nasync function listDirs(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n}\n\nexport async function readMachineMeta(ref: BoxRef, p: Paths = paths()) {\n return readJson(p.machine(ref.owner, ref.name).meta, MachineMetaSchema);\n}\n\nexport async function writeMachineMeta(meta: MachineMeta, p: Paths = paths()) {\n const m = p.machine(meta.owner, meta.name);\n await mkdir(m.dir, { recursive: true });\n await writeFile(m.meta, JSON.stringify(meta, null, 2) + \"\\n\");\n}\n\n/** Every box on the host, all owners: machines/<owner>/<name>. */\nexport async function listMachineRefs(p: Paths = paths()) {\n return listRefs(p.machines);\n}\n\nexport async function readSnapshotMeta(ref: BoxRef, p: Paths = paths()) {\n return readJson(p.snapshot(ref.owner, ref.name).meta, SnapshotMetaSchema);\n}\n\nexport async function writeSnapshotMeta(meta: SnapshotMeta, p: Paths = paths()) {\n const s = p.snapshot(meta.owner, meta.name);\n await mkdir(s.dir, { recursive: true });\n await writeFile(s.meta, JSON.stringify(meta, null, 2) + \"\\n\");\n}\n\nexport async function listSnapshotRefs(p: Paths = paths()) {\n return listRefs(p.snapshots);\n}\n\n/** Two levels: <root>/<owner>/<name>. A directory at the first level with its own meta.json is the pre-owner layout, migrated at server start and skipped here. */\nasync function listRefs(root: string): Promise<BoxRef[]> {\n const out: BoxRef[] = [];\n for (const owner of await listDirs(root)) {\n for (const name of await listDirs(`${root}/${owner}`)) {\n out.push({ owner, name });\n }\n }\n return out;\n}\n\n/** True when a pid is alive (signal 0). */\nexport function pidAlive(pid: number | null): boolean {\n if (pid === null || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n","/**\n * One-time layout upgrades of the state dir, run by `kvbox-server start` before it listens.\n * Each one is idempotent and leaves a running box alone: Firecracker keeps its working directory\n * and open files by inode, and the server re-derives every path on each call, so a box directory\n * can be renamed under it.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\n\nexport interface OwnerMigration {\n boxes: string[];\n snapshots: string[];\n /** Entries left where they were because the owner already has one with that name. */\n conflicts: string[];\n}\n\n/**\n * Pre-owner layout (`machines/<name>`, `snapshots/<name>`) → `machines/<owner>/<name>`. Everything\n * found at the old depth belonged to the host owner, since nobody else could make boxes.\n * The meta gets `owner` first, in place, then the directory moves: a crash between the two\n * leaves an old-depth entry that the next start picks up again.\n */\nexport async function migrateOwnerLayout(owner: string, p: Paths = paths()): Promise<OwnerMigration> {\n const done: OwnerMigration = { boxes: [], snapshots: [], conflicts: [] };\n for (const name of await oldDepthEntries(p.machines)) {\n const from = join(p.machines, name);\n const to = p.machine(owner, name).dir;\n if (existsSync(to)) {\n done.conflicts.push(`machines/${name}`);\n continue;\n }\n await patchJson(join(from, \"meta.json\"), (meta) => ({\n ...meta,\n owner,\n // a restored box names its snapshot: that moved under the same owner\n source: typeof meta[\"source\"] === \"string\" && meta[\"source\"].startsWith(\"snapshot:\") && !meta[\"source\"].includes(\"/\")\n ? `snapshot:${owner}/${meta[\"source\"].slice(\"snapshot:\".length)}`\n : meta[\"source\"],\n }));\n await mkdir(p.ownerMachines(owner), { recursive: true, mode: 0o700 });\n await rename(from, to);\n done.boxes.push(name);\n }\n for (const name of await oldDepthEntries(p.snapshots)) {\n const from = join(p.snapshots, name);\n const to = p.snapshot(owner, name).dir;\n if (existsSync(to)) {\n done.conflicts.push(`snapshots/${name}`);\n continue;\n }\n await patchJson(join(from, \"meta.json\"), (meta) => ({\n ...meta,\n owner,\n source: typeof meta[\"source\"] === \"string\" && !meta[\"source\"].includes(\"/\") ? `${owner}/${meta[\"source\"]}` : meta[\"source\"],\n }));\n await mkdir(p.ownerSnapshots(owner), { recursive: true, mode: 0o700 });\n await rename(from, to);\n done.snapshots.push(name);\n }\n return done;\n}\n\n/** Directories directly under `root` that hold a meta.json themselves: the pre-owner layout. An owner dir holds dirs, not a meta. */\nasync function oldDepthEntries(root: string): Promise<string[]> {\n let entries;\n try {\n entries = await readdir(root, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n return entries.filter((e) => e.isDirectory() && existsSync(join(root, e.name, \"meta.json\"))).map((e) => e.name).sort();\n}\n\nasync function patchJson(file: string, patch: (raw: Record<string, unknown>) => Record<string, unknown>): Promise<void> {\n const raw = JSON.parse(await readFile(file, \"utf8\")) as Record<string, unknown>;\n await writeFile(file, JSON.stringify(patch(raw), null, 2) + \"\\n\");\n}\n","/**\n * `~/.kvbox/kvbox.db`: the host's ledgers, through Node's built-in SQLite (node:sqlite, Node >= 22.13;\n * no dependency). Decision \"Hosts keep boxes as files + SQLite ledgers\": a box is still its directory\n * and meta.json, the database only holds what has to be appended to over time and summed later.\n * First table: `usage_events`, one row per state change of a box, the source of `kvbox vm usage`.\n *\n * One handle per database file for the life of the process; WAL so readers never block the writer.\n * The file is created 0600 before SQLite opens it, so the -wal and -shm files it makes next to it\n * inherit the mode.\n */\nimport { chmodSync, closeSync, mkdirSync, openSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\n\n/** Each entry upgrades the schema one version; `schema_version` records how far a file has come. */\nconst MIGRATIONS: string[] = [\n `create table usage_events (\n id integer primary key,\n box_id text not null,\n owner text not null,\n name text not null,\n at text not null,\n state text not null,\n vcpu integer not null,\n mem_mib integer not null,\n disk_gib integer not null,\n by text not null\n );\n create index usage_events_box_at on usage_events (box_id, at);`,\n];\n\nconst handles = new Map<string, DatabaseSync>();\n\nexport function openDb(p: Paths = paths()): DatabaseSync {\n const have = handles.get(p.db);\n if (have !== undefined) return have;\n mkdirSync(dirname(p.db), { recursive: true, mode: 0o700 });\n closeSync(openSync(p.db, \"a\", 0o600));\n chmodSync(p.db, 0o600);\n const db = new DatabaseSync(p.db);\n db.exec(\"pragma journal_mode = wal\");\n db.exec(\"pragma busy_timeout = 5000\");\n migrate(db);\n handles.set(p.db, db);\n return db;\n}\n\n/** Close the handle for this home (tests; the daemon keeps its open until exit). */\nexport function closeDb(p: Paths = paths()): void {\n const db = handles.get(p.db);\n if (db === undefined) return;\n db.close();\n handles.delete(p.db);\n}\n\nfunction migrate(db: DatabaseSync): void {\n db.exec(\"create table if not exists schema_version (version integer not null)\");\n const row = db.prepare(\"select version from schema_version\").get() as { version: number } | undefined;\n let version = row?.version ?? 0;\n if (row === undefined) db.prepare(\"insert into schema_version (version) values (0)\").run();\n while (version < MIGRATIONS.length) {\n db.exec(\"begin\");\n try {\n db.exec(MIGRATIONS[version]!);\n version += 1;\n db.prepare(\"update schema_version set version = ?\").run(version);\n db.exec(\"commit\");\n } catch (err) {\n db.exec(\"rollback\");\n throw err;\n }\n }\n}\n\n// ---- usage_events --------------------------------------------------------------------------------\n\nexport type UsageState = \"running\" | \"stopped\";\n\n/** One state change. Sizes ride on every row so a rescale changes the rate from that moment on. */\nexport interface UsageEvent {\n at: string;\n state: UsageState;\n vcpu: number;\n memMib: number;\n diskGib: number;\n /** What made it: new, start, stop, rescale, update, rm, upgrade (first row of a box older than the ledger), server (a stop the server did not see). */\n by: string;\n}\n\nexport interface UsageEventRow extends UsageEvent {\n /** `owner/name` until #39 gives boxes an id of their own; owner and name are kept beside it so the ledger reads alone after a box is gone. */\n boxId: string;\n owner: string;\n name: string;\n}\n\ninterface Raw {\n box_id: string;\n owner: string;\n name: string;\n at: string;\n state: string;\n vcpu: number;\n mem_mib: number;\n disk_gib: number;\n by: string;\n}\n\nfunction fromRaw(r: Raw): UsageEventRow {\n return { boxId: r.box_id, owner: r.owner, name: r.name, at: r.at, state: r.state as UsageState, vcpu: r.vcpu, memMib: r.mem_mib, diskGib: r.disk_gib, by: r.by };\n}\n\nfunction lastEvent(boxId: string, db: DatabaseSync): UsageEventRow | undefined {\n const raw = db.prepare(\"select * from usage_events where box_id = ? order by at desc, id desc limit 1\").get(boxId) as Raw | undefined;\n return raw === undefined ? undefined : fromRaw(raw);\n}\n\nfunction insertRaw(e: UsageEventRow, db: DatabaseSync): void {\n db.prepare(\n \"insert into usage_events (box_id, owner, name, at, state, vcpu, mem_mib, disk_gib, by) values (?, ?, ?, ?, ?, ?, ?, ?, ?)\",\n ).run(e.boxId, e.owner, e.name, e.at, e.state, e.vcpu, e.memMib, e.diskGib, e.by);\n}\n\n/**\n * Append a state change. A `running` on top of an open run means the box stopped without the\n * server knowing (Firecracker died, host rebooted): that run is closed first, dated now, by `server`.\n */\nexport function insertUsageEvent(e: UsageEventRow, p: Paths = paths()): void {\n const db = openDb(p);\n if (e.state === \"running\") closeOpenRun(e.boxId, e.at, p);\n insertRaw(e, db);\n}\n\n/** If the box's last event is `running`, add the `stopped` the server never saw, at `at`. True when one was added. */\nexport function closeOpenRun(boxId: string, at: string, p: Paths = paths()): boolean {\n const db = openDb(p);\n const last = lastEvent(boxId, db);\n if (last === undefined || last.state !== \"running\") return false;\n insertRaw({ ...last, at, state: \"stopped\", by: \"server\" }, db);\n return true;\n}\n\n/** The box's events from `since` on, oldest first. */\nexport function usageEventsFor(boxId: string, since: string, p: Paths = paths()): UsageEventRow[] {\n const rows = openDb(p).prepare(\"select * from usage_events where box_id = ? and at >= ? order by at, id\").all(boxId, since) as unknown as Raw[];\n return rows.map(fromRaw);\n}\n","/**\n * Create, list and destroy boxes: what spikes #4 and #6 did by hand.\n * See architecture \"Process model\". The server is the only writer of ~/.kvbox/machines.\n */\nimport { spawn } from \"node:child_process\";\nimport { closeSync, existsSync, openSync, statSync } from \"node:fs\";\nimport { link, mkdir, readFile, realpath, rm, truncate, writeFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport type { CreateMachineRequest, Machine, RescaleMachineRequest } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { SIZES, isSizeName } from \"@kvbox/shared/sizes\";\nimport { setIdentity } from \"./agent.js\";\nimport { assertRoomFor } from \"./capacity.js\";\nimport { closeOpenRun, insertUsageEvent, type UsageState } from \"./db.js\";\nimport { parseRef, refKey, shown, type BoxRef } from \"./refs.js\";\nimport { loadConfig, type Config } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { FirecrackerClient } from \"./firecracker.js\";\nimport { attachTap, createTap, deleteTap, ensureHostNetwork, macFor, nextFreeIp } from \"./network.js\";\nimport {\n listMachineRefs,\n pidAlive,\n readMachineMeta,\n readSnapshotMeta,\n writeMachineMeta,\n type MachineMeta,\n type SnapshotMeta,\n} from \"./state.js\";\n\n/** Box names double as hostnames and tap suffixes (kv- + name ≤ 15 chars). */\nconst NAME_RE = /^[a-z0-9][a-z0-9-]{0,11}$/;\nconst AUTO_PREFIX = \"box\";\n/** Every box's vsock address. Firecracker's vsock is per process, so the number need not be unique on the host. */\nconst GUEST_CID = 3;\n/** The overlay drive's path as Firecracker sees it: relative to the box dir, see spawnFirecracker. */\nconst OVERLAY_REL = \"overlay.ext4\";\n\nfunction diskStats(disk: string): { diskBytes: number; diskUsedBytes: number } {\n try {\n const st = statSync(disk);\n return { diskBytes: st.size, diskUsedBytes: st.blocks * 512 };\n } catch {\n return { diskBytes: 0, diskUsedBytes: 0 };\n }\n}\n\n/** A box's own disk file: its overlay, or the full copy pre-overlay boxes were made with. */\nfunction ownDisk(meta: MachineMeta, p: Paths): string {\n const m = p.machine(meta.owner, meta.name);\n return meta.base === undefined ? m.disk : m.overlay;\n}\n\n/** Whole GiB of the box's own disk file (its size as the guest sees it, not what it occupies). */\nfunction diskGibOf(meta: MachineMeta, p: Paths): number {\n try {\n return Math.round(statSync(ownDisk(meta, p)).size / 1024 ** 3);\n } catch {\n return 0;\n }\n}\n\n/**\n * Append the box's state change to the usage ledger (core/db.ts). Bookkeeping never fails the\n * operation it records: a ledger problem is logged and the box carries on.\n */\nfunction recordState(meta: MachineMeta, state: UsageState, by: string, p: Paths, at = new Date().toISOString()): void {\n try {\n insertUsageEvent({ boxId: refKey(meta), owner: meta.owner, name: meta.name, at, state, by, vcpu: meta.vcpu, memMib: meta.memMib, diskGib: diskGibOf(meta, p) }, p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n}\n\nfunction toMachine(meta: MachineMeta, p: Paths = paths()): Machine {\n const alive = pidAlive(meta.pid);\n // A pid the server set that is no longer alive: Firecracker died on its own (crash, host reboot,\n // kill). The ledger's open run is closed now, by `server`: the box's stop time is estimated, and\n // `usage` says so. Nothing is written to meta.json here (listing stays read-only on the state dir).\n if (!alive && meta.pid !== null) {\n try {\n closeOpenRun(refKey(meta), new Date().toISOString(), p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n }\n return {\n name: meta.name,\n owner: meta.owner,\n ip: meta.ip,\n mac: meta.mac,\n pid: alive ? meta.pid : null,\n vcpu: meta.vcpu,\n memMib: meta.memMib,\n ...diskStats(ownDisk(meta, p)),\n base: meta.base ?? null,\n createdAt: meta.createdAt,\n source: meta.source,\n status: alive ? \"running\" : \"stopped\",\n };\n}\n\nasync function readAllMeta(p: Paths): Promise<MachineMeta[]> {\n const metas: MachineMeta[] = [];\n for (const ref of await listMachineRefs(p)) {\n try {\n metas.push(await readMachineMeta(ref, p));\n } catch (err) {\n console.error(`warning: skipping machines/${refKey(ref)}: ${(err as Error).message}`);\n }\n }\n return metas;\n}\n\n/** The boxes of one owner, or every box on the host when `owner` is null (the host operator's view). */\nexport async function listMachines(owner: string | null, p: Paths = paths()): Promise<Machine[]> {\n return (await readAllMeta(p)).filter((m) => owner === null || m.owner === owner).map((m) => toMachine(m, p));\n}\n\nexport async function getMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n return toMachine(await readMeta(ref, p), p);\n}\n\nfunction pickName(requested: string | undefined, taken: Set<string>): string {\n if (requested !== undefined) {\n if (!NAME_RE.test(requested)) {\n throw new KvboxError(`invalid box name \"${requested}\": 1-12 chars, lowercase letters, digits and '-', starting with a letter or digit`);\n }\n if (taken.has(requested)) throw new KvboxError(`box ${requested} already exists`);\n return requested;\n }\n for (let i = 1; ; i++) {\n const candidate = `${AUTO_PREFIX}${i}`;\n if (!taken.has(candidate)) return candidate;\n }\n}\n\nexport function bootArgs(name: string, ip: string, cfg: Config, pubkeyB64: string, mode: { overlay: boolean }): string {\n // Firecracker appends `pci=off root=/dev/vda` plus ro/rw itself. ip= is read by the guest\n // kernel, kvbox.name= / kvbox.sshkey= by kvbox-init on first boot (the kvbox-images contract).\n // With an overlay, /sbin/overlay-init in the image stacks the box's disk (/dev/vdb) on the\n // read-only base before systemd starts.\n const init = mode.overlay ? \" init=/sbin/overlay-init kvbox.overlay=/dev/vdb\" : \"\";\n const args = `console=ttyS0 reboot=k panic=1${init} ip=${ip}::${cfg.gateway}:255.255.255.0:${name}:eth0:off kvbox.name=${name} kvbox.sshkey=${pubkeyB64}`;\n return process.arch === \"arm64\" ? `keep_bootcon ${args}` : args;\n}\n\n/** `assets/rootfs-<version>.ext4` -> `<version>`; anything else is the layout from before overlays. */\nexport function baseVersionOf(file: string): string {\n const m = /^rootfs-(.+)\\.ext4$/.exec(basename(file));\n if (!m) throw new KvboxError(`base image ${file} is not versioned (expected assets/rootfs-<version>.ext4); run install-server.sh`);\n return m[1]!;\n}\n\n/** Follow config's rootfs symlink to the base image a new box should be made from. */\nasync function currentBase(cfg: Config, p: Paths): Promise<{ version: string; file: string }> {\n const file = await realpath(cfg.rootfs);\n const version = baseVersionOf(file);\n const expected = p.baseImage(version);\n if (file !== expected) throw new KvboxError(`base image ${cfg.rootfs} points outside ${p.assets} (${file})`);\n return { version, file };\n}\n\n/** The base image this box boots from; a pre-overlay box has none (its own disk copy is the root). */\nfunction baseFileFor(meta: Pick<MachineMeta, \"name\" | \"base\">, p: Paths): string | undefined {\n if (meta.base === undefined) return undefined;\n const file = p.baseImage(meta.base);\n if (!existsSync(file)) throw new KvboxError(`box ${meta.name} runs on base image ${meta.base}, which is gone from ${p.assets}`);\n return file;\n}\n\nconst overlayCapable = new Map<string, boolean>();\n\n/** A base image older than the overlay layout has no /sbin/overlay-init and would panic at boot. debugfs reads the ext4 without mounting it. */\nasync function assertOverlayCapable(baseFile: string, version: string): Promise<void> {\n let ok = overlayCapable.get(baseFile);\n if (ok === undefined) {\n const { stdout } = await run([\"debugfs\", \"-R\", \"stat /sbin/overlay-init\", baseFile]);\n ok = /Type:\\s+regular/.test(stdout);\n overlayCapable.set(baseFile, ok);\n }\n if (!ok) throw new KvboxError(`base image ${version} is too old for this server (no /sbin/overlay-init); rerun install-server.sh to get a newer one`);\n}\n\n/** The box's writable disk: a sparse ext4 of `gib` GiB, ready in milliseconds and occupying a few MB until written to. */\nexport async function createOverlay(file: string, gib: number): Promise<void> {\n await writeFile(file, \"\", { mode: 0o600 });\n await truncate(file, gib * 1024 ** 3);\n // -F: it is a file, not a block device. -m 0: no blocks held back for root, the whole disk is the box's.\n // Lazy init: the inode tables are zeroed by the guest kernel as it goes, so mkfs writes almost nothing.\n await run([\"mkfs.ext4\", \"-q\", \"-F\", \"-m\", \"0\", \"-L\", \"kvbox-box\", \"-E\", \"lazy_itable_init=1,lazy_journal_init=1\", file]);\n}\n\nasync function waitFor(pred: () => boolean, timeoutMs: number, stepMs = 50): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (pred()) return true;\n await sleep(stepMs);\n }\n return pred();\n}\n\nasync function tailOf(file: string, lines = 5): Promise<string> {\n try {\n return (await readFile(file, \"utf8\")).trim().split(\"\\n\").slice(-lines).join(\"\\n\");\n } catch {\n return \"\";\n }\n}\n\ninterface LaunchSpec {\n name: string;\n owner: string;\n ip: string;\n mac: string;\n vcpu: number;\n memMib: number;\n base?: string | undefined;\n}\n\n/**\n * Spawn Firecracker detached for box `name` and wait for its API socket. Returns the pid; the\n * caller kills it on any later failure. Its working directory is the box dir and the overlay drive\n * is given as a relative path (OVERLAY_REL): a snapshot's vmstate stores drive paths verbatim, so a\n * relative one resolves to whichever box dir the snapshot is restored into.\n */\nasync function spawnFirecracker(ref: BoxRef, cfg: Config, p: Paths): Promise<number> {\n const m = p.machine(ref.owner, ref.name);\n await rm(m.sock, { force: true });\n await rm(m.vsock, { force: true });\n const logFd = openSync(m.log, \"a\");\n let child;\n try {\n child = spawn(cfg.firecracker, [\"--api-sock\", m.sock, \"--id\", ref.name, \"--level\", \"Error\"], {\n cwd: m.dir,\n detached: true,\n stdio: [\"ignore\", logFd, logFd],\n });\n } finally {\n closeSync(logFd);\n }\n child.unref();\n const pid = child.pid;\n if (pid === undefined) throw new KvboxError(\"could not start firecracker\");\n if (!(await waitFor(() => existsSync(m.sock), 3000))) {\n killQuietly(pid);\n throw new KvboxError(`firecracker did not open its API socket; last log lines:\\n${await tailOf(m.log)}`);\n }\n return pid;\n}\n\nfunction killQuietly(pid: number): void {\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n /* already gone */\n }\n}\n\n/** Spawn Firecracker, configure it over its socket, InstanceStart. Returns the pid. Caller rolls back on throw. */\nasync function launch(spec: LaunchSpec, tap: string, cfg: Config, pubkeyB64: string, p: Paths): Promise<number> {\n const m = p.machine(spec.owner, spec.name);\n const baseFile = baseFileFor(spec, p);\n const pid = await spawnFirecracker(spec, cfg, p);\n try {\n const fc = new FirecrackerClient(m.sock);\n try {\n await fc.bootSource(cfg.kernel, bootArgs(spec.name, spec.ip, cfg, pubkeyB64, { overlay: baseFile !== undefined }));\n if (baseFile !== undefined) {\n await fc.rootDrive(baseFile, true);\n await fc.overlayDrive(OVERLAY_REL);\n } else {\n await fc.rootDrive(m.disk, false);\n }\n await fc.machineConfig(spec.vcpu, spec.memMib);\n await fc.networkInterface(\"eth0\", tap, spec.mac);\n await fc.vsock(GUEST_CID, m.vsock);\n await fc.start();\n } finally {\n await fc.close();\n }\n return pid;\n } catch (err) {\n killQuietly(pid);\n throw err;\n }\n}\n\n/**\n * Spawn Firecracker and restore the snapshot into it, still paused, with this box's tap and vsock\n * in place of the source box's. Drive paths cannot be overridden at load: a vmstate written by this\n * server names the overlay relatively and already resolves to this box's copy, while one from an\n * older server names the source box's file (which must still exist for the load to succeed) and is\n * re-pointed afterwards. Returns the pid; the caller resumes and rolls back on throw.\n */\nasync function loadSnapshot(spec: LaunchSpec, snapshot: BoxRef, tap: string, cfg: Config, p: Paths): Promise<number> {\n const m = p.machine(spec.owner, spec.name);\n const s = p.snapshot(snapshot.owner, snapshot.name);\n const pid = await spawnFirecracker(spec, cfg, p);\n try {\n const fc = new FirecrackerClient(m.sock);\n try {\n try {\n await fc.snapshotLoad({\n snapshotPath: s.vmstate,\n memFilePath: s.mem,\n tap: { ifaceId: \"eth0\", hostDevName: tap },\n vsockPath: m.vsock,\n trackDirtyPages: true,\n resume: false,\n });\n } catch (err) {\n // No vsock device in the vmstate: the source box predates kvbox-agent, so nothing inside could take the new identity.\n if (/Unknown Vsock Device/.test((err as Error).message)) throw new KvboxError(tooOldToRestore(shown(snapshot)));\n throw err;\n }\n if (await namesOverlayAbsolutely(s.vmstate)) await fc.patchDrivePath(\"overlay\", m.overlay);\n } finally {\n await fc.close();\n }\n return pid;\n } catch (err) {\n killQuietly(pid);\n throw err;\n }\n}\n\nfunction tooOldToRestore(snapshot: string): string {\n return `snapshot ${snapshot} was taken from a box made before kvbox-agent existed (older base image) and cannot be restored: make a fresh box with this kvbox, set it up, and snapshot that one`;\n}\n\n/** The base image version `kvbox new` uses right now (what `assets/rootfs.ext4` points at). */\nexport async function currentBaseVersion(p: Paths = paths()): Promise<string> {\n return (await currentBase(await loadConfig(p), p)).version;\n}\n\n/** The vmstate stores drive paths as plain strings; one with a directory in front is the pre-relative layout. */\nasync function namesOverlayAbsolutely(vmstate: string): Promise<boolean> {\n return (await readFile(vmstate)).includes(`/${OVERLAY_REL}`);\n}\n\nasync function readPubkeyB64(p: Paths): Promise<string> {\n try {\n return Buffer.from((await readFile(`${p.sshKey}.pub`, \"utf8\")).trim()).toString(\"base64\");\n } catch {\n throw new KvboxError(`SSH key missing at ${p.sshKey}.pub; run install-server.sh`);\n }\n}\n\nfunction assertAssets(cfg: Config): void {\n for (const [what, file] of [[\"kernel\", cfg.kernel], [\"base image\", cfg.rootfs], [\"firecracker\", cfg.firecracker]] as const) {\n if (!existsSync(file)) throw new KvboxError(`${what} missing at ${file}; run install-server.sh`);\n }\n}\n\n/**\n * `owner` is who the box belongs to: the caller, as the route resolved it (the host owner over the\n * local socket). `req.owner` is not read here on purpose: a caller does not get to pick.\n */\nexport async function createMachine(req: CreateMachineRequest, owner: string, p: Paths = paths()): Promise<Machine> {\n const cfg = await loadConfig(p);\n if (req.from !== undefined) return restoreMachine(req.from, owner, req, cfg, p);\n const sizeName = req.size ?? cfg.defaultSize;\n if (!isSizeName(sizeName)) throw new KvboxError(`unknown size \"${sizeName}\"; use one of ${Object.keys(SIZES).join(\", \")}`);\n const size = SIZES[sizeName];\n assertAssets(cfg);\n await assertRoomFor(size.vcpu, size.memMib, req.force ?? false, p);\n const pubkeyB64 = await readPubkeyB64(p);\n\n const existing = await readAllMeta(p);\n // names are per owner; IPs and taps are per host\n const name = pickName(req.name, new Set(existing.filter((m) => m.owner === owner).map((m) => m.name)));\n const ip = nextFreeIp(cfg.subnet, [...existing.map((m) => m.ip), cfg.gateway]);\n const mac = macFor(ip);\n const m = p.machine(owner, name);\n\n const base = await currentBase(cfg, p);\n await assertOverlayCapable(base.file, base.version);\n\n await ensureHostNetwork(cfg);\n await mkdir(m.dir, { recursive: true, mode: 0o700 });\n let tapCreated = false;\n try {\n // The base image is shared read-only by every box; only the box's own writes land in its overlay.\n await createOverlay(m.overlay, size.diskGib);\n const tap = await createTap(name, cfg);\n tapCreated = true;\n const spec: LaunchSpec = { name, owner, ip, mac, vcpu: size.vcpu, memMib: size.memMib, base: base.version };\n const pid = await launch(spec, tap, cfg, pubkeyB64, p);\n const meta: MachineMeta = { ...spec, pid, createdAt: new Date().toISOString(), source: \"base\" };\n await writeMachineMeta(meta, p);\n recordState(meta, \"running\", \"new\", p, meta.createdAt);\n return toMachine(meta, p);\n } catch (err) {\n // leave nothing half-made behind\n if (tapCreated) await deleteTap(name, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n }\n}\n\n\nasync function readSnap(ref: BoxRef, p: Paths): Promise<SnapshotMeta> {\n try {\n return await readSnapshotMeta(ref, p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") throw new NotFoundError(`snapshot ${shown(ref)}`);\n throw err;\n }\n}\n\n/** a.b.c.d/len -> len */\nfunction prefixLenOf(subnet: string): number {\n return Number(subnet.split(\"/\")[1]);\n}\n\n/**\n * `kvbox new --from <snapshot>`: a warm box. The snapshot's memory and overlay come back exactly as\n * frozen, processes included, under a new name, IP and MAC. The guest itself still remembers the\n * source box's identity, so its tap stays off the bridge until kvbox-agent (reached over vsock, not\n * the network) has applied the new one and set the clock. Sub-second: the memory file is mapped,\n * not read, and the overlay copy is sparse.\n */\nasync function restoreMachine(fromText: string, owner: string, req: CreateMachineRequest, cfg: Config, p: Paths): Promise<Machine> {\n const from = parseRef(fromText, owner);\n const snap = await readSnap(from, p);\n if (req.size !== undefined) {\n throw new KvboxError(`--size cannot be combined with --from: a restored box has the snapshot's size (${shown(from)}: ${snap.vcpu} vCPU, ${snap.memMib} MiB)`);\n }\n assertAssets(cfg);\n if (!existsSync(p.baseImage(snap.base))) {\n throw new KvboxError(`snapshot ${shown(from)} stacks on base image ${snap.base}, which is gone from ${p.assets}`);\n }\n await assertRoomFor(snap.vcpu, snap.memMib, req.force ?? false, p);\n\n const existing = await readAllMeta(p);\n const name = pickName(req.name, new Set(existing.filter((m) => m.owner === owner).map((m) => m.name)));\n const ip = nextFreeIp(cfg.subnet, [...existing.map((m) => m.ip), cfg.gateway]);\n const mac = macFor(ip);\n const m = p.machine(owner, name);\n const s = p.snapshot(from.owner, from.name);\n\n await ensureHostNetwork(cfg);\n await mkdir(m.dir, { recursive: true, mode: 0o700 });\n let tapCreated = false;\n let pid: number | undefined;\n try {\n await run([\"cp\", \"--sparse=always\", \"--reflink=auto\", s.overlay, m.overlay]);\n // The box's memory lineage starts at the snapshot's image: its first snapshot is a diff merged onto it.\n await link(s.mem, m.memBase);\n const tap = await createTap(name, cfg, { detached: true });\n tapCreated = true;\n const spec: LaunchSpec = { name, owner, ip, mac, vcpu: snap.vcpu, memMib: snap.memMib, base: snap.base };\n pid = await loadSnapshot(spec, from, tap, cfg, p);\n const fc = new FirecrackerClient(m.sock);\n try {\n await fc.resume();\n } finally {\n await fc.close();\n }\n await introduce(spec, m.vsock, cfg, shown(from));\n await attachTap(name, cfg);\n const meta: MachineMeta = { ...spec, pid, createdAt: new Date().toISOString(), source: `snapshot:${refKey(from)}`, memSnapshots: 1 };\n await writeMachineMeta(meta, p);\n recordState(meta, \"running\", \"new\", p, meta.createdAt);\n return toMachine(meta, p);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n if (tapCreated) await deleteTap(name, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n }\n}\n\n/**\n * Hand the restored guest its identity through kvbox-agent. The agent is already running (it was\n * in memory at the snapshot), but the vsock path to it comes up with the VM, so refused connections\n * are retried for a moment. Once it has accepted, it gets a generous wait: the guest's memory is\n * paged in from the snapshot file on first touch, which on a cold, busy disk can take seconds\n * (seen on the dev host right after install-server.sh had written a new base image).\n */\nconst AGENT_REPLY_MS = 20_000;\n\nasync function introduce(spec: LaunchSpec, vsock: string, cfg: Config, from: string): Promise<void> {\n const id = { name: spec.name, ip: spec.ip, prefixLen: prefixLenOf(cfg.subnet), gateway: cfg.gateway, mac: spec.mac, time: Math.floor(Date.now() / 1000) };\n const deadline = Date.now() + 3000;\n for (;;) {\n try {\n await setIdentity(vsock, id, AGENT_REPLY_MS);\n return;\n } catch (err) {\n const msg = (err as Error).message;\n const transient = /unreachable|refused|before the guest accepted/.test(msg);\n if (transient && Date.now() < deadline) {\n await sleep(100);\n continue;\n }\n if (transient) throw new KvboxError(`${msg}\\n nothing answered on the restored box's control channel for 3 s; ${tooOldToRestore(from)}`);\n throw new KvboxError(`${msg}\\n the restored box was discarded. kvbox-agent inside it took the request but gave no answer; try again, and if it keeps happening look at the box's journal (kvbox exec <box> -- sudo journalctl -u kvbox-agent) on a box started from the same snapshot.`);\n }\n }\n}\n\n/** Clean guest shutdown (Ctrl+Alt+Del), SIGKILL after `graceMs`; tap removed; disk and meta kept. */\nasync function shutdown(meta: MachineMeta, cfg: Config, p: Paths, graceMs: number): Promise<void> {\n const pid = meta.pid;\n if (pidAlive(pid)) {\n const fc = new FirecrackerClient(p.machine(meta.owner, meta.name).sock);\n try {\n await fc.sendCtrlAltDel();\n } catch {\n process.kill(pid!, \"SIGTERM\");\n } finally {\n await fc.close();\n }\n if (!(await waitFor(() => !pidAlive(pid), graceMs, 100))) {\n try {\n process.kill(pid!, \"SIGKILL\");\n } catch {\n /* exited meanwhile */\n }\n await waitFor(() => !pidAlive(pid), 1000, 50);\n }\n }\n await deleteTap(meta.name, cfg);\n const m = p.machine(meta.owner, meta.name);\n await rm(m.sock, { force: true });\n await rm(m.vsock, { force: true });\n}\n\nexport async function stopMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n if (!pidAlive(meta.pid)) throw new KvboxError(`box ${shown(ref)} is already stopped`);\n await shutdown(meta, cfg, p, 10_000);\n // A stopped box boots from scratch next time, so its memory lineage (see state.ts memSnapshots) starts over.\n await rm(p.machine(ref.owner, ref.name).memBase, { force: true });\n const stopped: MachineMeta = { ...meta, pid: null, memSnapshots: undefined };\n await writeMachineMeta(stopped, p);\n recordState(stopped, \"stopped\", \"stop\", p);\n return toMachine(stopped, p);\n}\n\nexport async function startMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n if (pidAlive(meta.pid)) throw new KvboxError(`box ${shown(ref)} is already running`);\n assertAssets(cfg);\n const pubkeyB64 = await readPubkeyB64(p);\n await ensureHostNetwork(cfg);\n const tap = await createTap(ref.name, cfg);\n try {\n const pid = await launch(meta, tap, cfg, pubkeyB64, p);\n const started: MachineMeta = { ...meta, pid };\n await writeMachineMeta(started, p);\n recordState(started, \"running\", \"start\", p);\n return toMachine(started, p);\n } catch (err) {\n await deleteTap(ref.name, cfg).catch(() => undefined);\n throw err;\n }\n}\n\n/**\n * Change a box's shape or base. Both only take effect at boot (Firecracker fixes vCPU and memory\n * when the VM starts, the base is stacked by overlay-init), so a running box is shut down and\n * started again; a stopped one just gets its meta updated. `whileStopped` runs in between, for\n * work that needs the disk unmounted. Returns the box, running again if it was.\n */\nasync function applyAtNextBoot(\n meta: MachineMeta,\n changes: Partial<MachineMeta>,\n by: \"rescale\" | \"update\",\n cfg: Config,\n p: Paths,\n whileStopped?: () => Promise<void>,\n): Promise<Machine> {\n const wasRunning = pidAlive(meta.pid);\n if (wasRunning) {\n await shutdown(meta, cfg, p, 10_000);\n await rm(p.machine(meta.owner, meta.name).memBase, { force: true });\n }\n const updated: MachineMeta = { ...meta, ...changes, pid: null, memSnapshots: undefined };\n await writeMachineMeta(updated, p);\n if (whileStopped) await whileStopped();\n // The new shape is on this row (after the disk grew), so usage rates change from here on.\n recordState(updated, \"stopped\", by, p);\n return wasRunning ? startMachine(meta, p) : toMachine(updated, p);\n}\n\n/** `kvbox vm update <box>`: move the box onto the base image new boxes get. Its overlay (its own writes) stays. */\nexport async function updateMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n if (meta.base === undefined) {\n throw new KvboxError(`box ${shown(ref)} was made before overlays and runs on its own disk copy; it cannot be moved to another base image`);\n }\n assertAssets(cfg);\n const base = await currentBase(cfg, p);\n if (base.version === meta.base) return toMachine(meta, p);\n await assertOverlayCapable(base.file, base.version);\n return applyAtNextBoot(meta, { base: base.version }, \"update\", cfg, p);\n}\n\n/**\n * `kvbox vm rescale <box>`: new vCPU count, memory and/or disk. The disk can only grow: the overlay\n * file is extended and its ext4 resized while the box is down (e2fsck first, resize2fs refuses\n * a filesystem that was mounted since its last check).\n */\nexport async function rescaleMachine(ref: BoxRef, req: RescaleMachineRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const disk = ownDisk(meta, p);\n const currentDiskGib = Math.round(statSync(disk).size / 1024 ** 3);\n const preset = req.size !== undefined && isSizeName(req.size) ? SIZES[req.size] : undefined;\n const target = {\n vcpu: req.vcpu ?? preset?.vcpu ?? meta.vcpu,\n memMib: req.memMib ?? preset?.memMib ?? meta.memMib,\n diskGib: req.diskGib ?? preset?.diskGib ?? currentDiskGib,\n };\n if (target.diskGib < currentDiskGib) {\n throw new KvboxError(`box ${shown(ref)} has a ${currentDiskGib} GB disk and a disk cannot shrink; ${target.diskGib} GB is smaller`);\n }\n const changes: Partial<MachineMeta> = {};\n if (target.vcpu !== meta.vcpu) changes.vcpu = target.vcpu;\n if (target.memMib !== meta.memMib) changes.memMib = target.memMib;\n const growTo = target.diskGib > currentDiskGib ? target.diskGib : undefined;\n if (Object.keys(changes).length === 0 && growTo === undefined) return toMachine(meta, p);\n return applyAtNextBoot(meta, changes, \"rescale\", cfg, p, growTo === undefined ? undefined : () => growDisk(disk, growTo));\n}\n\n/** Extend a box's (unmounted) ext4 disk file to `gib` GiB. */\nexport async function growDisk(file: string, gib: number): Promise<void> {\n await truncate(file, gib * 1024 ** 3);\n await run([\"e2fsck\", \"-f\", \"-p\", file], { okExitCodes: [1] });\n await run([\"resize2fs\", file]);\n}\n\nasync function readMeta(ref: BoxRef, p: Paths): Promise<MachineMeta> {\n try {\n return await readMachineMeta(ref, p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") throw new NotFoundError(`box ${shown(ref)}`);\n throw err;\n }\n}\n\nexport async function destroyMachine(ref: BoxRef, p: Paths = paths()): Promise<void> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n await shutdown(meta, cfg, p, 2000);\n // The ledger keeps the box's history after it is gone: a final row, while the disk is still there to measure.\n recordState(meta, \"stopped\", \"rm\", p);\n await rm(p.machine(ref.owner, ref.name).dir, { recursive: true, force: true });\n}\n","/**\n * Client for kvbox-agent, the small service every box runs (kvbox-images, /usr/local/sbin/kvbox-agent).\n * It listens on a vsock port, and Firecracker exposes that as a Unix socket next to the box's API\n * socket: connect, send `CONNECT <port>\\n`, get `OK <n>\\n` back once the guest accepted, then the\n * stream is the guest's. The agent speaks one JSON object per line, one request per connection.\n * Vsock does not touch the box's network, so this works whatever the box did to its own eth0.\n */\nimport { connect } from \"node:net\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\n/** The vsock port kvbox-agent listens on; fixed in the image. */\nexport const AGENT_PORT = 52;\n\nexport interface Identity {\n name: string;\n ip: string;\n prefixLen: number;\n gateway: string;\n mac: string;\n /** Unix seconds for the guest's clock, which stopped at the snapshot. */\n time: number;\n}\n\ntype AgentReply = { ok: true; [k: string]: unknown } | { ok: false; error: string };\n\n/** One request/reply exchange with the agent behind `udsPath`. Rejects on connection errors, timeout or `ok: false`. */\nexport async function agentCall(udsPath: string, req: Record<string, unknown>, timeoutMs = 5000): Promise<Record<string, unknown>> {\n const reply = await new Promise<string>((resolve, reject) => {\n const sock = connect(udsPath);\n let buf = \"\";\n let handshaken = false;\n const fail = (err: Error) => {\n sock.destroy();\n reject(err);\n };\n sock.setTimeout(timeoutMs, () => fail(new KvboxError(`kvbox-agent did not answer within ${timeoutMs} ms`)));\n sock.once(\"error\", (err) => fail(new KvboxError(`kvbox-agent unreachable: ${err.message}`)));\n sock.once(\"connect\", () => sock.write(`CONNECT ${AGENT_PORT}\\n`));\n sock.on(\"data\", (chunk) => {\n buf += chunk.toString(\"utf8\");\n let nl: number;\n while ((nl = buf.indexOf(\"\\n\")) !== -1) {\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + 1);\n if (!handshaken) {\n if (!line.startsWith(\"OK \")) return fail(new KvboxError(`vsock connect refused: ${line}`));\n handshaken = true;\n sock.write(JSON.stringify(req) + \"\\n\");\n } else {\n sock.end();\n return resolve(line);\n }\n }\n });\n sock.once(\"close\", () => {\n if (!handshaken) fail(new KvboxError(\"vsock connection closed before the guest accepted\"));\n else fail(new KvboxError(\"kvbox-agent closed the connection without a reply\"));\n });\n });\n let parsed: AgentReply;\n try {\n parsed = JSON.parse(reply) as AgentReply;\n } catch {\n throw new KvboxError(`kvbox-agent sent something that is not JSON: ${reply}`);\n }\n if (!parsed.ok) throw new KvboxError(`kvbox-agent: ${parsed.error}`);\n return parsed;\n}\n\nexport function ping(udsPath: string, timeoutMs?: number) {\n return agentCall(udsPath, { op: \"ping\" }, timeoutMs);\n}\n\n/** Tell a restored box who it is now; it renames itself, re-addresses eth0 and sets its clock. */\nexport function setIdentity(udsPath: string, id: Identity, timeoutMs?: number) {\n return agentCall(udsPath, { op: \"identity\", ...id }, timeoutMs);\n}\n","/**\n * The capacity guard. Firecracker reserves neither RAM nor cores on the host, so without a rule\n * of our own the kernel's OOM-killer is what ends an over-full host: a Firecracker process dies\n * and a box vanishes without a trace. Before a box is started, `kvbox new` adds it to what the\n * running boxes already reserve (their sizes, not what they touch right now) and refuses when\n * memory: reserved + new > host RAM - 2 GB (hard: the host needs room of its own), or\n * vCPU: reserved + new > 2 x host cores (soft: vCPUs time-slice fine, this stops the absurd).\n * `--force` skips both. Decision \"`zbox new` guards host capacity\".\n */\nimport { cpus, totalmem } from \"node:os\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { Capacity } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { listMachineRefs, pidAlive, readMachineMeta } from \"./state.js\";\n\nexport const MEM_HEADROOM_MIB = 2048;\nexport const VCPU_OVERSUBSCRIPTION = 2;\n\nexport interface Host {\n memMib: number;\n cores: number;\n}\nexport interface Reservation {\n name: string;\n vcpu: number;\n memMib: number;\n}\n\nexport function hostResources(): Host {\n return { memMib: Math.floor(totalmem() / 1024 ** 2), cores: cpus().length };\n}\n\n/** The sizes of every box whose Firecracker process is alive; a dead pid reserves nothing. */\nexport async function runningReservations(p: Paths = paths()): Promise<Reservation[]> {\n const out: Reservation[] = [];\n for (const ref of await listMachineRefs(p)) {\n try {\n const meta = await readMachineMeta(ref, p);\n if (pidAlive(meta.pid)) out.push({ name: meta.name, vcpu: meta.vcpu, memMib: meta.memMib });\n } catch {\n // unreadable meta: not a running box we can account for\n }\n }\n return out;\n}\n\nexport async function capacity(p: Paths = paths()): Promise<Capacity> {\n const host = hostResources();\n const running = await runningReservations(p);\n return {\n hostMemMib: host.memMib,\n hostCores: host.cores,\n reservedMemMib: running.reduce((n, r) => n + r.memMib, 0),\n reservedVcpu: running.reduce((n, r) => n + r.vcpu, 0),\n running: running.length,\n };\n}\n\nfunction gb(mib: number): string {\n const g = mib / 1024;\n return `${Number.isInteger(g) ? g : g.toFixed(1)} GB`;\n}\n\nfunction describeRunning(running: Reservation[]): string {\n if (running.length === 0) return \"no box is running\";\n const list = running.map((r) => `${r.name} ${r.vcpu} vCPU/${gb(r.memMib)}`).join(\", \");\n const vcpu = running.reduce((n, r) => n + r.vcpu, 0);\n const mem = running.reduce((n, r) => n + r.memMib, 0);\n return `${running.length} running ${running.length === 1 ? \"box reserves\" : \"boxes reserve\"} ${vcpu} vCPU and ${gb(mem)} (${list})`;\n}\n\n/**\n * Why a box of `want` cannot start on `host` next to `running`, or undefined when it can.\n * Pure, so the rule is testable without a host.\n */\nexport function roomFor(host: Host, running: Reservation[], want: { vcpu: number; memMib: number }): string | undefined {\n const reservedMem = running.reduce((n, r) => n + r.memMib, 0);\n const reservedVcpu = running.reduce((n, r) => n + r.vcpu, 0);\n const memLimit = host.memMib - MEM_HEADROOM_MIB;\n const vcpuLimit = host.cores * VCPU_OVERSUBSCRIPTION;\n const hint = \"stop or remove a box (kvbox stop, kvbox rm), pick a smaller --size, or pass --force to start it anyway\";\n if (reservedMem + want.memMib > memLimit) {\n return (\n `not enough memory for a ${gb(want.memMib)} box: ${describeRunning(running)}; ` +\n `this host has ${gb(host.memMib)} and keeps ${gb(MEM_HEADROOM_MIB)} for itself, so boxes may reserve ${gb(memLimit)} in total. ` +\n hint\n );\n }\n if (reservedVcpu + want.vcpu > vcpuLimit) {\n return (\n `too many vCPUs for a ${want.vcpu} vCPU box: ${describeRunning(running)}; ` +\n `this host has ${host.cores} cores and allows ${vcpuLimit} vCPUs in total (${VCPU_OVERSUBSCRIPTION}x). ` +\n hint\n );\n }\n return undefined;\n}\n\n/** Throws (HTTP 400, exit 1) when the host cannot take another box of this size; `force` skips the check. */\nexport async function assertRoomFor(vcpu: number, memMib: number, force: boolean, p: Paths = paths()): Promise<void> {\n if (force) return;\n const reason = roomFor(hostResources(), await runningReservations(p), { vcpu, memMib });\n if (reason !== undefined) throw new KvboxError(reason);\n}\n","/**\n * Client for one Firecracker process's API socket. Ten-odd endpoints, all\n * PUT/PATCH with JSON bodies, so a thin wrapper over undici beats an SDK.\n */\nimport { Agent, request } from \"undici\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nexport class FirecrackerClient {\n private readonly agent: Agent;\n\n constructor(readonly socketPath: string) {\n this.agent = new Agent({ connect: { socketPath } });\n }\n\n private async call(method: \"GET\" | \"PUT\" | \"PATCH\", path: string, body?: unknown): Promise<unknown> {\n const res = await request(`http://localhost${path}`, {\n dispatcher: this.agent,\n method,\n headers: body === undefined ? {} : { \"content-type\": \"application/json\" },\n body: body === undefined ? null : JSON.stringify(body),\n });\n const text = await res.body.text();\n if (res.statusCode >= 300) {\n throw new KvboxError(`firecracker ${method} ${path} -> ${res.statusCode}: ${text}`);\n }\n return text ? JSON.parse(text) : undefined;\n }\n\n bootSource(kernelImagePath: string, bootArgs: string) {\n return this.call(\"PUT\", \"/boot-source\", { kernel_image_path: kernelImagePath, boot_args: bootArgs });\n }\n\n /**\n * /dev/vda. Firecracker adds `root=/dev/vda` plus `ro` or `rw` to the boot args to match.\n * Read-only for the shared base image; read-write only for pre-overlay boxes with their own copy.\n */\n rootDrive(pathOnHost: string, readOnly: boolean) {\n return this.drive(\"rootfs\", pathOnHost, { root: true, readOnly });\n }\n\n /** The box's own writable disk, /dev/vdb: the guest stacks it on the base as an overlay. */\n overlayDrive(pathOnHost: string) {\n return this.drive(\"overlay\", pathOnHost, { root: false, readOnly: false });\n }\n\n private drive(id: string, pathOnHost: string, opts: { root: boolean; readOnly: boolean }) {\n return this.call(\"PUT\", `/drives/${id}`, {\n drive_id: id,\n path_on_host: pathOnHost,\n is_root_device: opts.root,\n is_read_only: opts.readOnly,\n // \"Unsafe\" (the default) acks guest flushes without doing anything, so the last journal\n // commit of a clean shutdown can be lost when the guest resets and Firecracker exits.\n // Writeback makes a guest flush a real fsync; a box's writes must survive `kvbox stop`.\n cache_type: \"Writeback\",\n });\n }\n\n /** Swap the file behind a drive while the VM runs or is paused; the guest is told the config changed. */\n patchDrivePath(id: string, pathOnHost: string) {\n return this.call(\"PATCH\", `/drives/${id}`, { drive_id: id, path_on_host: pathOnHost });\n }\n\n /**\n * The host's control channel into the box: Firecracker listens on `udsPath`, a connection there\n * followed by `CONNECT <port>\\n` reaches whatever listens on that vsock port in the guest (kvbox-agent).\n */\n vsock(guestCid: number, udsPath: string) {\n return this.call(\"PUT\", \"/vsock\", { guest_cid: guestCid, uds_path: udsPath });\n }\n\n machineConfig(vcpuCount: number, memSizeMib: number) {\n // Dirty page tracking lets a snapshot write only the pages the guest touched since the last one\n // (a \"Diff\" snapshot) instead of dumping all of guest memory: sub-second instead of ~10 s frozen.\n return this.call(\"PUT\", \"/machine-config\", { vcpu_count: vcpuCount, mem_size_mib: memSizeMib, track_dirty_pages: true });\n }\n\n networkInterface(ifaceId: string, hostDevName: string, guestMac: string) {\n return this.call(\"PUT\", `/network-interfaces/${ifaceId}`, {\n iface_id: ifaceId,\n host_dev_name: hostDevName,\n guest_mac: guestMac,\n });\n }\n\n start() {\n return this.call(\"PUT\", \"/actions\", { action_type: \"InstanceStart\" });\n }\n\n /** Ask the guest to shut down cleanly (systemd handles Ctrl+Alt+Del as poweroff on Firecracker). */\n sendCtrlAltDel() {\n return this.call(\"PUT\", \"/actions\", { action_type: \"SendCtrlAltDel\" });\n }\n\n pause() {\n return this.call(\"PATCH\", \"/vm\", { state: \"Paused\" });\n }\n\n resume() {\n return this.call(\"PATCH\", \"/vm\", { state: \"Resumed\" });\n }\n\n /** `track_dirty_pages` is what matters: a box from an older server runs without it. */\n async machineConfigInfo(): Promise<{ vcpu_count: number; mem_size_mib: number; track_dirty_pages: boolean }> {\n return (await this.call(\"GET\", \"/machine-config\")) as { vcpu_count: number; mem_size_mib: number; track_dirty_pages: boolean };\n }\n\n /**\n * Full: all of guest memory, dense (seconds for a 4 GB box). Diff: only pages dirtied since the last\n * snapshot (or since boot), written sparse; needs dirty page tracking and resets its bitmap.\n */\n snapshotCreate(snapshotPath: string, memFilePath: string, type: \"Full\" | \"Diff\" = \"Full\") {\n return this.call(\"PUT\", \"/snapshot/create\", {\n snapshot_type: type,\n snapshot_path: snapshotPath,\n mem_file_path: memFilePath,\n });\n }\n\n /**\n * Restore a snapshot into this (fresh) process. The memory file is mapped privately: the guest's\n * writes never reach the snapshot. The vmstate carries the source box's tap and vsock paths; the\n * overrides point them at this box's. Drive paths are not overridable here: see patchDrivePath.\n */\n snapshotLoad(opts: {\n snapshotPath: string;\n memFilePath: string;\n tap: { ifaceId: string; hostDevName: string };\n vsockPath: string;\n /** Required for diff snapshots later: the flag is not part of the vmstate. */\n trackDirtyPages: boolean;\n resume: boolean;\n }) {\n return this.call(\"PUT\", \"/snapshot/load\", {\n snapshot_path: opts.snapshotPath,\n mem_backend: { backend_type: \"File\", backend_path: opts.memFilePath },\n network_overrides: [{ iface_id: opts.tap.ifaceId, host_dev_name: opts.tap.hostDevName }],\n vsock_override: { uds_path: opts.vsockPath },\n track_dirty_pages: opts.trackDirtyPages,\n resume_vm: opts.resume,\n });\n }\n\n info() {\n return this.call(\"GET\", \"/\");\n }\n\n async close() {\n await this.agent.close();\n }\n}\n","/**\n * `kvbox vm usage <box>`: what the usage_events ledger (db.ts) adds up to over a window.\n * `computeUsage` is pure over the rows; `machineUsage` reads the box and the ledger around it.\n */\nimport type { MachineUsage } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { loadConfig, type Pricing } from \"./config.js\";\nimport { insertUsageEvent, usageEventsFor, type UsageEvent, type UsageState } from \"./db.js\";\nimport { getMachine, listMachines } from \"./machines.js\";\nimport { refKey, type BoxRef } from \"./refs.js\";\n\nexport type { UsageEvent, UsageState };\n\nexport interface UsageWindow {\n from: string;\n to: string;\n pricing?: Pricing | undefined;\n}\n\nexport type UsageTotals = Pick<MachineUsage, \"seconds\" | \"vcpuHours\" | \"ramGibHours\" | \"diskGibHours\" | \"cost\" | \"estimatedStops\" | \"historyFrom\">;\n\nconst HOUR_MS = 3_600_000;\nconst round = (n: number, places: number) => Math.round(n * 10 ** places) / 10 ** places;\n\n/**\n * Each event opens an interval that lasts until the next one (or `to`); intervals are clipped to the\n * window, so the event before `from` supplies the state the window starts in. Time before the first\n * event belongs to no state: it was never recorded. Running hours earn vCPU and RAM; every hour the\n * box exists earns disk (its overlay is there while it is stopped too). A repeated state continues it.\n */\nexport function computeUsage(events: readonly UsageEvent[], w: UsageWindow): UsageTotals {\n const sorted = [...events].sort((a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : 0));\n const from = Date.parse(w.from);\n const to = Date.parse(w.to);\n const ms = { running: 0, stopped: 0 };\n let vcpuHours = 0;\n let ramGibHours = 0;\n let diskGibHours = 0;\n sorted.forEach((e, i) => {\n const start = Math.max(Date.parse(e.at), from);\n const next = sorted[i + 1];\n const end = Math.min(next === undefined ? to : Date.parse(next.at), to);\n if (end <= start) return;\n const h = (end - start) / HOUR_MS;\n ms[e.state] += end - start;\n if (e.state === \"running\") {\n vcpuHours += h * e.vcpu;\n ramGibHours += (h * e.memMib) / 1024;\n }\n diskGibHours += h * e.diskGib;\n });\n const totals: UsageTotals = {\n seconds: { running: Math.round(ms.running / 1000), stopped: Math.round(ms.stopped / 1000) },\n vcpuHours: round(vcpuHours, 3),\n ramGibHours: round(ramGibHours, 3),\n diskGibHours: round(diskGibHours, 3),\n estimatedStops: sorted.filter((e) => e.state === \"stopped\" && e.by === \"server\" && e.at >= w.from).length,\n historyFrom: sorted[0]?.at ?? null,\n };\n if (w.pricing !== undefined) {\n const amount = vcpuHours * w.pricing.vcpuHour + ramGibHours * w.pricing.ramGibHour + diskGibHours * w.pricing.diskGibHour;\n totals.cost = { amount: round(amount, 4), currency: w.pricing.currency };\n }\n return totals;\n}\n\nconst GIB = 1024 ** 3;\n\n/**\n * Usage of one box from its creation (or `since`, already an ISO string) until now. Reading the box\n * (getMachine) also closes the run of a box whose Firecracker died, so the ledger is current before\n * it is summed. A box with no rows since its creation predates the ledger: its history starts now,\n * in whatever state it is in, and `historyFrom` says so.\n */\nexport async function machineUsage(ref: BoxRef, since: string | undefined, p: Paths = paths()): Promise<MachineUsage> {\n const box = await getMachine(ref, p);\n const cfg = await loadConfig(p);\n const now = new Date().toISOString();\n const boxId = refKey(ref);\n let events = usageEventsFor(boxId, box.createdAt, p);\n if (events.length === 0) {\n insertUsageEvent(\n { boxId, owner: box.owner, name: box.name, at: now, state: box.status, by: \"upgrade\", vcpu: box.vcpu, memMib: box.memMib, diskGib: Math.round(box.diskBytes / GIB) },\n p,\n );\n events = usageEventsFor(boxId, box.createdAt, p);\n }\n const window = { from: since ?? box.createdAt, to: now };\n return { name: box.name, owner: box.owner, status: box.status, window, ...computeUsage(events, { ...window, pricing: cfg.pricing }) };\n}\n\n/**\n * Run at server start: every box the ledger has never heard of gets its first row now, in its current\n * state, so the history of boxes made before this server version begins at the upgrade rather than at\n * their first `usage` call. Returns how many were seeded.\n */\nexport async function seedUsageLedger(p: Paths = paths()): Promise<number> {\n let seeded = 0;\n for (const box of await listMachines(null, p)) {\n const boxId = `${box.owner}/${box.name}`;\n if (usageEventsFor(boxId, box.createdAt, p).length > 0) continue;\n insertUsageEvent(\n { boxId, owner: box.owner, name: box.name, at: new Date().toISOString(), state: box.status, by: \"upgrade\", vcpu: box.vcpu, memMib: box.memMib, diskGib: Math.round(box.diskBytes / GIB) },\n p,\n );\n seeded += 1;\n }\n return seeded;\n}\n","/**\n * The hono app behind `kvbox-server`. Served over `~/.kvbox/server.sock`\n * in M1; the same app goes behind HTTPS in M2.\n */\nimport { Hono } from \"hono\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport { VERSION } from \"./version.js\";\nimport { resolveCaller, type Env } from \"./caller.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { currentBaseVersion } from \"./core/machines.js\";\nimport { capacityRoutes } from \"./routes/capacity.js\";\nimport { machineRoutes } from \"./routes/machines.js\";\nimport { snapshotRoutes } from \"./routes/snapshots.js\";\n\nexport function createApp() {\n const app = new Hono<Env>();\n app.use(resolveCaller());\n\n app.get(\"/health\", async (c) =>\n c.json({\n ok: true as const,\n version: VERSION,\n pid: process.pid,\n base: await currentBaseVersion().catch(() => null),\n owner: (await loadConfig()).owner,\n }),\n );\n app.route(\"/machines\", machineRoutes());\n app.route(\"/snapshots\", snapshotRoutes());\n app.route(\"/capacity\", capacityRoutes());\n\n app.notFound((c) => c.json({ error: `no route: ${c.req.method} ${c.req.path}` }, 404));\n app.onError((err, c) => {\n if (err instanceof NotFoundError) return c.json({ error: err.message }, 404);\n if (err instanceof KvboxError) {\n return c.json({ error: err.message }, err.exitCode === 2 ? 501 : 400);\n }\n console.error(err);\n return c.json({ error: err.message }, 500);\n });\n\n return app;\n}\n\nexport type App = ReturnType<typeof createApp>;\n","/**\n * Each binary's version comes from its own package.json: tsup injects\n * `__KVBOX_VERSION__` at build time; the dev path (tsx) reads the file.\n * Usage in a package: `versionOf(import.meta.url)` from its `src/version.ts`.\n */\nimport { createRequire } from \"node:module\";\n\nexport function versionOf(srcFileUrl: string, injected?: string): string {\n if (typeof injected === \"string\") return injected;\n try {\n const require = createRequire(srcFileUrl);\n return (require(\"../package.json\") as { version: string }).version;\n } catch {\n return \"0.0.0-dev\";\n }\n}\n","import { versionOf } from \"@kvbox/shared/version\";\n\ndeclare const __KVBOX_VERSION__: string | undefined;\n\nexport const VERSION: string = versionOf(import.meta.url, typeof __KVBOX_VERSION__ === \"string\" ? __KVBOX_VERSION__ : undefined);\n","/**\n * Who is calling. Every request carries an `owner` the routes file boxes under and scope listings\n * to. Today there is one caller: the host owner over the local Unix socket, which is the server's\n * configured `owner` (the Unix user running it). The control plane (#18) adds the other branch:\n * an HTTPS caller whose owner is `<user>@<control plane>`, qualified here and nowhere else.\n */\nimport type { MiddlewareHandler } from \"hono\";\nimport { loadConfig } from \"./core/config.js\";\n\nexport type Env = { Variables: { owner: string } };\n\nexport function resolveCaller(): MiddlewareHandler<Env> {\n return async (c, next) => {\n const cfg = await loadConfig();\n c.set(\"owner\", cfg.owner);\n await next();\n };\n}\n","import { Hono } from \"hono\";\nimport { capacity } from \"../core/capacity.js\";\n\nexport function capacityRoutes() {\n const r = new Hono();\n r.get(\"/\", async (c) => c.json(await capacity()));\n return r;\n}\n","import { Hono } from \"hono\";\nimport { CreateMachineRequest, RescaleMachineRequest } from \"@kvbox/shared/api\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { createMachine, destroyMachine, listMachines, rescaleMachine, startMachine, stopMachine, updateMachine } from \"../core/machines.js\";\nimport { parseRef } from \"../core/refs.js\";\nimport { machineUsage } from \"../core/usage.js\";\nimport type { Env } from \"../caller.js\";\n\nexport function machineRoutes() {\n const r = new Hono<Env>();\n r.get(\"/\", async (c) => c.json(await listMachines(c.get(\"owner\"))));\n r.post(\"/\", async (c) => {\n const body = CreateMachineRequest.parse(await c.req.json().catch(() => ({})));\n return c.json(await createMachine(body, c.get(\"owner\")), 201);\n });\n r.post(\"/:name/stop\", async (c) => c.json(await stopMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/start\", async (c) => c.json(await startMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/update\", async (c) => c.json(await updateMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/rescale\", async (c) => {\n const body = RescaleMachineRequest.parse(await c.req.json().catch(() => ({})));\n return c.json(await rescaleMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body));\n });\n r.get(\"/:name/usage\", async (c) => {\n const since = c.req.query(\"since\");\n let from: string | undefined;\n if (since !== undefined) {\n const t = Date.parse(since);\n if (Number.isNaN(t)) throw new KvboxError(`since: \"${since}\" is not a date; write it like 2026-10-19 or 2026-10-19T08:00:00Z`);\n from = new Date(t).toISOString();\n }\n return c.json(await machineUsage(parseRef(c.req.param(\"name\"), c.get(\"owner\")), from));\n });\n r.delete(\"/:name\", async (c) => {\n await destroyMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")));\n return c.body(null, 204);\n });\n return r;\n}\n","/**\n * Wire shapes of the kvbox HTTP API, shared by the client (src/cli) and the\n * server (src/server). Validated with zod on both sides because the client\n * may be talking to an older or newer server.\n */\nimport { z } from \"zod\";\nimport { SIZE_NAMES } from \"./sizes.js\";\n\nexport const SizeSchema = z.enum(SIZE_NAMES as [string, ...string[]]);\n\nexport const MachineSchema = z.object({\n name: z.string(),\n /** Who the box belongs to; names are unique per owner. A bare name is local to the host, `user@control-plane` later. */\n owner: z.string(),\n ip: z.string(),\n mac: z.string(),\n pid: z.number().int().nullable(),\n vcpu: z.number().int(),\n memMib: z.number().int(),\n diskBytes: z.number().int(), // the box's own writable disk, as the guest sees it\n diskUsedBytes: z.number().int(), // what that sparse file really occupies on the host\n base: z.string().nullable(), // base image version the box runs on (null: pre-overlay box with its own copy)\n createdAt: z.string(),\n source: z.string(), // \"base\" or \"snapshot:<name>\"\n status: z.enum([\"running\", \"stopped\"]),\n});\nexport type Machine = z.infer<typeof MachineSchema>;\n\nexport const CreateMachineRequest = z.object({\n name: z.string().optional(),\n /** Ignored over the local socket (the caller is the host owner); the control plane sets it over HTTPS. */\n owner: z.string().optional(),\n size: SizeSchema.optional(),\n from: z.string().optional(),\n force: z.boolean().optional(),\n});\nexport type CreateMachineRequest = z.infer<typeof CreateMachineRequest>;\n\n/** `kvbox vm rescale`: a preset and/or explicit values; explicit ones win. Anything omitted stays as it is. */\nexport const RescaleMachineRequest = z.object({\n size: SizeSchema.optional(),\n vcpu: z.number().int().min(1).max(64).optional(),\n memMib: z.number().int().min(256).optional(),\n diskGib: z.number().int().min(1).optional(),\n});\nexport type RescaleMachineRequest = z.infer<typeof RescaleMachineRequest>;\n\nexport const SnapshotSchema = z.object({\n name: z.string(),\n owner: z.string(),\n source: z.string(), // the box it was taken from, as owner/name\n base: z.string(), // base image version the overlay stacks on; a restore needs the same one\n vcpu: z.number().int(),\n memMib: z.number().int(),\n sizeBytes: z.number().int(), // what vmstate + mem + overlay really occupy on the host\n createdAt: z.string(),\n});\nexport type Snapshot = z.infer<typeof SnapshotSchema>;\n\nexport const CreateSnapshotRequest = z.object({\n box: z.string(),\n name: z.string(),\n});\nexport type CreateSnapshotRequest = z.infer<typeof CreateSnapshotRequest>;\n\nexport const CapacitySchema = z.object({\n hostMemMib: z.number().int(),\n hostCores: z.number().int(),\n reservedMemMib: z.number().int(),\n reservedVcpu: z.number().int(),\n running: z.number().int(),\n});\nexport type Capacity = z.infer<typeof CapacitySchema>;\n\nexport const HealthSchema = z.object({\n ok: z.literal(true),\n version: z.string(),\n pid: z.number().int(),\n /** Base image version new boxes get (null when the host has no usable base image yet); absent from older servers. */\n base: z.string().nullable().optional(),\n /** Owner that boxes made over the local socket get (the Unix user running the server); absent from older servers. */\n owner: z.string().optional(),\n});\nexport type Health = z.infer<typeof HealthSchema>;\n\n/**\n * `kvbox vm usage <box>`: how long the box spent in each state over a window and what that adds up\n * to. Hours are fractional; the CLI rounds. `cost` is present only when the host prices usage.\n * `historyFrom` is the first recorded moment: later than `window.from` for a box older than the\n * ledger, null when nothing is recorded (never for a box the server knows).\n */\nexport const MachineUsageSchema = z.object({\n name: z.string(),\n owner: z.string(),\n status: z.enum([\"running\", \"stopped\"]),\n window: z.object({ from: z.string(), to: z.string() }),\n seconds: z.object({ running: z.number().int(), stopped: z.number().int() }),\n vcpuHours: z.number(),\n ramGibHours: z.number(),\n diskGibHours: z.number(),\n cost: z.object({ amount: z.number(), currency: z.string() }).optional(),\n /** Stops the server did not witness (Firecracker died, host rebooted) and dated to when it noticed. */\n estimatedStops: z.number().int(),\n historyFrom: z.string().nullable(),\n});\nexport type MachineUsage = z.infer<typeof MachineUsageSchema>;\n\nexport const ApiErrorSchema = z.object({\n error: z.string(),\n});\n","import { Hono } from \"hono\";\nimport { CreateSnapshotRequest } from \"@kvbox/shared/api\";\nimport { deleteSnapshot, listSnapshots, saveSnapshot } from \"../core/snapshots.js\";\nimport { parseRef } from \"../core/refs.js\";\nimport type { Env } from \"../caller.js\";\n\nexport function snapshotRoutes() {\n const r = new Hono<Env>();\n r.get(\"/\", async (c) => c.json(await listSnapshots(c.get(\"owner\"))));\n r.post(\"/\", async (c) => {\n const body = CreateSnapshotRequest.parse(await c.req.json());\n return c.json(await saveSnapshot(body, c.get(\"owner\")), 201);\n });\n r.delete(\"/:name\", async (c) => {\n await deleteSnapshot(parseRef(c.req.param(\"name\"), c.get(\"owner\")));\n return c.body(null, 204);\n });\n return r;\n}\n","/**\n * Snapshots: a running box frozen into `snapshots/<name>/` as vmstate + mem (a complete memory image)\n * + a copy of the box's overlay. The base image is referenced by version, not copied, so a snapshot costs\n * what the guest touched (memory pages + overlay blocks), not the box's size.\n *\n * Memory is captured incrementally. Boxes run with dirty page tracking, so Firecracker can write only\n * the pages dirtied since the last snapshot (a \"Diff\": sub-second, sparse) instead of dumping all of\n * guest memory (~10 s frozen for 4 GB). A diff is only a complete image when merged onto the previous\n * one, so each box keeps `mem.base`, a hard link to its last snapshot's `mem`, and the merge happens\n * after the box is already running again. See state.ts `memSnapshots` for the bookkeeping.\n */\nimport { existsSync } from \"node:fs\";\nimport { link, mkdir, readdir, rename, rm, stat } from \"node:fs/promises\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport type { CreateSnapshotRequest, Snapshot } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { loadConfig } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { FirecrackerClient } from \"./firecracker.js\";\nimport { parseRef, refKey, shown, type BoxRef } from \"./refs.js\";\nimport {\n listSnapshotRefs,\n pidAlive,\n readMachineMeta,\n readSnapshotMeta,\n writeMachineMeta,\n writeSnapshotMeta,\n type MachineMeta,\n type SnapshotMeta,\n} from \"./state.js\";\n\n/** Snapshot names are directory names shown in tables: letters, digits, dots, dashes, underscores. */\nconst NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/;\n\nfunction toSnapshot(meta: SnapshotMeta): Snapshot {\n return {\n name: meta.name,\n owner: meta.owner,\n source: meta.source,\n base: meta.base,\n vcpu: meta.vcpu,\n memMib: meta.memMib,\n sizeBytes: meta.sizeBytes,\n createdAt: meta.createdAt,\n };\n}\n\n/** One owner's snapshots, or every snapshot on the host when `owner` is null. */\nexport async function listSnapshots(owner: string | null, p: Paths = paths()): Promise<Snapshot[]> {\n const out: Snapshot[] = [];\n for (const ref of await listSnapshotRefs(p)) {\n if (owner !== null && ref.owner !== owner) continue;\n try {\n out.push(toSnapshot(await readSnapshotMeta(ref, p)));\n } catch (err) {\n console.error(`warning: skipping snapshots/${refKey(ref)}: ${(err as Error).message}`);\n }\n }\n return out;\n}\n\n/** Bytes the snapshot really occupies: its files are sparse, so allocated blocks, not sizes. */\nasync function usedBytes(dir: string): Promise<number> {\n let total = 0;\n for (const entry of await readdir(dir)) {\n total += (await stat(`${dir}/${entry}`)).blocks * 512;\n }\n return total;\n}\n\nasync function readBox(ref: BoxRef, p: Paths): Promise<MachineMeta> {\n try {\n return await readMachineMeta(ref, p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") throw new NotFoundError(`box ${shown(ref)}`);\n throw err;\n }\n}\n\n/** The snapshot belongs to `owner` (the caller); `req.box` may name another owner's box as owner/name. */\nexport async function saveSnapshot(req: CreateSnapshotRequest, owner: string, p: Paths = paths()): Promise<Snapshot> {\n if (!NAME_RE.test(req.name)) {\n throw new KvboxError(`invalid snapshot name \"${req.name}\": 1-64 chars, lowercase letters, digits, '.', '_' and '-', starting with a letter or digit`);\n }\n const box = await readBox(parseRef(req.box, owner), p);\n if (box.base === undefined) {\n throw new KvboxError(`box ${req.box} was made before overlays and runs on its own disk copy; snapshots need a box made by this version of kvbox (kvbox new)`);\n }\n if (!pidAlive(box.pid)) {\n throw new KvboxError(`box ${req.box} is not running; a snapshot freezes a running box (kvbox start ${req.box} first)`);\n }\n const s = p.snapshot(owner, req.name);\n if (existsSync(s.dir)) throw new KvboxError(`snapshot ${req.name} already exists`);\n const cfg = await loadConfig(p);\n const m = p.machine(box.owner, box.name);\n\n await mkdir(s.dir, { recursive: true, mode: 0o700 });\n const fc = new FirecrackerClient(m.sock);\n let lineageTouched = false;\n try {\n const tracked = (await fc.machineConfigInfo()).track_dirty_pages;\n const since = box.memSnapshots ?? 0;\n // A diff is standalone right after boot, or once merged onto the previous image. Otherwise (a box\n // from an older server without tracking, or a lineage broken by an earlier failure) dump everything.\n const mode: \"Diff\" | \"Full\" = tracked && (since === 0 || existsSync(m.memBase)) ? \"Diff\" : \"Full\";\n\n // The guest is frozen for the whole capture so memory and overlay describe the same instant.\n let failure: unknown;\n await fc.pause();\n try {\n await fc.snapshotCreate(s.vmstate, s.mem, mode);\n lineageTouched = tracked; // Firecracker reset its dirty bitmap: the box's next diff is relative to this image\n await run([\"cp\", \"--sparse=always\", \"--reflink=auto\", m.overlay, s.overlay]);\n } catch (err) {\n failure = err;\n } finally {\n await fc.resume();\n }\n if (lineageTouched) {\n // Recorded before anything else can fail: memSnapshots > 0 without mem.base reads as a broken\n // lineage, and the next snapshot falls back to a full dump instead of a diff missing pages.\n await writeMachineMeta({ ...box, memSnapshots: since + 1 }, p);\n }\n if (failure !== undefined) throw failure;\n\n if (mode === \"Full\") {\n // A full dump is dense; pages the guest never touched are zeros, so punch them out.\n await run([\"fallocate\", \"--dig-holes\", s.mem]);\n } else if (since > 0) {\n await mergeOntoPrevious(m.memBase, s.mem, cfg.snapshotEditor ?? p.snapshotEditor);\n }\n if (tracked) {\n await rm(m.memBase, { force: true });\n await link(s.mem, m.memBase);\n }\n\n const meta: SnapshotMeta = {\n name: req.name,\n owner,\n source: refKey(box),\n base: box.base,\n vcpu: box.vcpu,\n memMib: box.memMib,\n sizeBytes: await usedBytes(s.dir),\n createdAt: new Date().toISOString(),\n };\n await writeSnapshotMeta(meta, p);\n return toSnapshot(meta);\n } catch (err) {\n // The diff that was just discarded took pages with it: never let the next diff build on the old image.\n if (lineageTouched) await rm(m.memBase, { force: true }).catch(() => undefined);\n await rm(s.dir, { recursive: true, force: true });\n throw err;\n } finally {\n await fc.close();\n }\n}\n\n/**\n * Turn the diff at `diffFile` into a complete image: copy the previous image and apply the diff's pages\n * over it. Holes in the diff are untouched pages; a page dirtied to zeros is data and overwrites.\n */\nasync function mergeOntoPrevious(previous: string, diffFile: string, editor: string): Promise<void> {\n if (!existsSync(editor)) throw new KvboxError(`snapshot-editor missing at ${editor}; rerun install-server.sh`);\n const merged = `${diffFile}.merged`;\n await run([\"cp\", \"--sparse=always\", \"--reflink=auto\", previous, merged]);\n await run([editor, \"edit-memory\", \"rebase\", \"--memory-path\", merged, \"--diff-path\", diffFile]);\n await rename(merged, diffFile);\n}\n\nexport async function deleteSnapshot(ref: BoxRef, p: Paths = paths()): Promise<void> {\n const dir = p.snapshot(ref.owner, ref.name).dir;\n if (!existsSync(dir)) throw new NotFoundError(`snapshot ${shown(ref)}`);\n await rm(dir, { recursive: true, force: true });\n}\n"],"mappings":"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","names":["rm","writeFile","readFile","writeFile","z","z","readFile","writeFile","existsSync","mkdir","readdir","readFile","writeFile","join","join","existsSync","mkdir","readdir","readFile","writeFile","closeSync","existsSync","openSync","mkdir","readFile","writeFile","bootArgs","existsSync","writeFile","readFile","openSync","closeSync","m","mkdir","Hono","require","Hono","z","z","Hono","Hono","existsSync","link","mkdir","readdir","rename","rm","NAME_RE","readdir","existsSync","mkdir","rm","link","rename","Hono","Hono","rm","writeFile","shutdown"]}
1
+ {"version":3,"sources":["../src/index.ts","../../shared/src/errors.ts","../../shared/src/paths.ts","../src/core/config.ts","../../shared/src/sizes.ts","../src/core/refs.ts","../src/core/network.ts","../src/core/exec.ts","../src/listen.ts","../src/core/state.ts","../src/core/migrate.ts","../src/core/db.ts","../src/core/machines.ts","../src/core/agent.ts","../src/core/capacity.ts","../src/core/firecracker.ts","../src/core/usage.ts","../src/app.ts","../../shared/src/version.ts","../src/version.ts","../src/caller.ts","../src/routes/capacity.ts","../src/routes/machines.ts","../../shared/src/api.ts","../src/routes/snapshots.ts","../src/core/snapshots.ts"],"sourcesContent":["/**\n * kvbox-server: the host daemon. `kvbox-server` (or `kvbox-server start`) serves\n * the kvbox API on ~/.kvbox/server.sock in the foreground; the CLI's\n * `kvbox server start` spawns it detached. M2 adds `register`.\n */\nimport { spawnSync } from \"node:child_process\";\nimport { Command } from \"commander\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths } from \"@kvbox/shared/paths\";\nimport { loadConfig } from \"./core/config.js\";\nimport { ensureHostNetwork, netSetupScript } from \"./core/network.js\";\nimport { listen } from \"./listen.js\";\nimport { VERSION } from \"./version.js\";\n\nconst program = new Command(\"kvbox-server\")\n .description(\"kvbox host daemon: owns Firecracker and ~/.kvbox, serves the kvbox API\")\n .version(VERSION, \"-v, --version\")\n .showHelpAfterError();\n\nprogram\n .command(\"start\", { isDefault: true })\n .description(\"serve the API on the local Unix socket (foreground)\")\n .option(\"--socket <path>\", \"socket to listen on (default: $KVBOX_HOME/server.sock)\")\n .action(async (opts: { socket?: string }) => {\n const { socketPath } = await listen(opts.socket ? { socketPath: opts.socket } : {});\n console.log(`kvbox-server ${VERSION} listening on ${socketPath} (pid ${process.pid})`);\n // The bridge vanishes on host reboot; recreate it. Not fatal: ls/status must still work.\n try {\n const cfg = await loadConfig(paths());\n const state = await ensureHostNetwork(cfg);\n console.log(`host network: bridge ${cfg.bridge} ${state}`);\n } catch (err) {\n console.error(`warning: host network not ready (${(err as Error).message}); run: kvbox-server net up`);\n }\n });\n\nprogram\n .command(\"net <action>\")\n .description(\"host network: up | down | status (bridge, forwarding, NAT; uses sudo)\")\n .action(async (action: string) => {\n if (![\"up\", \"down\", \"status\"].includes(action)) throw new KvboxError(\"net: expected up, down or status\");\n const cfg = await loadConfig(paths());\n const res = spawnSync(netSetupScript(), [action], {\n stdio: \"inherit\",\n env: { ...process.env, KVBOX_BRIDGE: cfg.bridge, KVBOX_SUBNET: cfg.subnet, KVBOX_GATEWAY: cfg.gateway },\n });\n process.exit(res.status ?? 1);\n });\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err) {\n if (err instanceof KvboxError) {\n console.error(`error: ${err.message}`);\n process.exit(err.exitCode);\n }\n throw err;\n}\n","/** Errors with an exit code; the entry point prints `message` and exits with `exitCode`. */\nexport class KvboxError extends Error {\n constructor(\n message: string,\n public readonly exitCode: number = 1,\n ) {\n super(message);\n this.name = \"KvboxError\";\n }\n}\n\nexport class NotImplementedError extends KvboxError {\n constructor(what: string) {\n super(`${what}: not implemented yet`, 2);\n this.name = \"NotImplementedError\";\n }\n}\n\n/** The named box/snapshot/host does not exist: HTTP 404, exit 1. */\nexport class NotFoundError extends KvboxError {\n constructor(what: string) {\n super(`${what}: not found`, 1);\n this.name = \"NotFoundError\";\n }\n}\n","/**\n * Host state layout. The filesystem is the database and `~/.kvbox` is its root.\n * This module is dependency-free so both the CLI (socket path, hosts.json)\n * and core (everything else) can use it without crossing the layer boundary.\n *\n * `KVBOX_HOME` overrides the root, mainly for tests.\n */\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport function kvboxHome(): string {\n return process.env[\"KVBOX_HOME\"] ?? join(homedir(), \".kvbox\");\n}\n\nexport function paths(home: string = kvboxHome()) {\n return {\n home,\n config: join(home, \"config.json\"),\n /** The host's ledgers (SQLite via node:sqlite): usage events today. Boxes and snapshots stay files; see server core/db.ts. */\n db: join(home, \"kvbox.db\"),\n serverSock: join(home, \"server.sock\"),\n serverPid: join(home, \"server.pid\"),\n serverLog: join(home, \"server.log\"),\n hosts: join(home, \"hosts.json\"),\n ssh: join(home, \"ssh\"),\n sshKey: join(home, \"ssh\", \"id_ed25519\"),\n bin: join(home, \"bin\"),\n firecracker: join(home, \"bin\", \"firecracker\"),\n /** Firecracker's snapshot-editor, from the same release: merges a diff snapshot onto a full memory image. */\n snapshotEditor: join(home, \"bin\", \"snapshot-editor\"),\n assets: join(home, \"assets\"),\n kernel: join(home, \"assets\", \"vmlinux\"),\n /** Symlink to the current base image, assets/rootfs-<version>.ext4; boxes keep using the version they were made from. */\n rootfs: join(home, \"assets\", \"rootfs.ext4\"),\n baseImage: (version: string) => join(home, \"assets\", `rootfs-${version}.ext4`),\n machines: join(home, \"machines\"),\n snapshots: join(home, \"snapshots\"),\n /** Boxes and snapshots are filed by owner: machines/<owner>/<name>. The owner is part of a box's identity. */\n ownerMachines: (owner: string) => join(home, \"machines\", owner),\n ownerSnapshots: (owner: string) => join(home, \"snapshots\", owner),\n machine: (owner: string, name: string) => {\n const dir = join(home, \"machines\", owner, name);\n return {\n dir,\n meta: join(dir, \"meta.json\"),\n /** The box's writable layer, stacked on the read-only base image inside the guest. */\n overlay: join(dir, \"overlay.ext4\"),\n /** Boxes made before overlays: a full copy of the base image. Kept bootable, never created anymore. */\n disk: join(dir, \"disk.ext4\"),\n /**\n * The box's memory as of its last snapshot (a hard link to that snapshot's `mem`, never modified).\n * The next snapshot is a diff of the pages dirtied since, merged onto this. Absent after a boot.\n */\n memBase: join(dir, \"mem.base\"),\n /** `kvbox hibernate`: the box's memory image and VM state while it is hibernated; gone again after `wake` or `stop`. */\n hibernateDir: join(dir, \"hibernate\"),\n hibernateVmstate: join(dir, \"hibernate\", \"vmstate\"),\n hibernateMem: join(dir, \"hibernate\", \"mem\"),\n sock: join(dir, \"fc.sock\"),\n /** Firecracker's vsock endpoint: the host connects here to reach kvbox-agent inside the box (core/agent.ts). */\n vsock: join(dir, \"vsock.sock\"),\n log: join(dir, \"fc.log\"),\n };\n },\n snapshot: (owner: string, name: string) => {\n const dir = join(home, \"snapshots\", owner, name);\n return {\n dir,\n meta: join(dir, \"meta.json\"),\n vmstate: join(dir, \"vmstate\"),\n mem: join(dir, \"mem\"),\n /** Copy of the box's overlay at the moment of the snapshot; the base image is referenced by version in meta.json. */\n overlay: join(dir, \"overlay.ext4\"),\n };\n },\n } as const;\n}\n\nexport type Paths = ReturnType<typeof paths>;\n","/** `~/.kvbox/config.json`: asset paths, subnet, default size, owner. Written with defaults on first run. */\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { DEFAULT_SIZE, SIZE_NAMES } from \"@kvbox/shared/sizes\";\nimport { LOCAL_OWNER_RE, localOwner } from \"./refs.js\";\n\n/** What an hour of each resource costs, for `kvbox vm usage`'s estimated cost. Absent by default: no cost row. */\nexport const PricingSchema = z.object({\n currency: z.string().min(1),\n vcpuHour: z.number().nonnegative(),\n ramGibHour: z.number().nonnegative(),\n diskGibHour: z.number().nonnegative(),\n});\nexport type Pricing = z.infer<typeof PricingSchema>;\n\nexport const ConfigSchema = z.object({\n kernel: z.string(),\n rootfs: z.string(),\n firecracker: z.string(),\n snapshotEditor: z.string().optional(), // default: bin/snapshot-editor next to firecracker\n bridge: z.string().default(\"kvbox0\"),\n subnet: z.string().default(\"172.30.0.0/24\"),\n gateway: z.string().default(\"172.30.0.1\"),\n defaultSize: z.enum(SIZE_NAMES as [string, ...string[]]).default(DEFAULT_SIZE),\n /** Who boxes made over the local socket belong to: the Unix user running the server unless set here. No `@`, no `/`. */\n owner: z.string().regex(LOCAL_OWNER_RE, \"owner: letters, digits, '.', '_', '-'; no '@' or '/'\").default(localOwner),\n pricing: PricingSchema.optional(),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport function defaultConfig(p: Paths = paths()): Config {\n return ConfigSchema.parse({\n kernel: p.kernel,\n rootfs: p.rootfs,\n firecracker: p.firecracker,\n snapshotEditor: p.snapshotEditor,\n owner: localOwner(),\n });\n}\n\nexport async function loadConfig(p: Paths = paths()): Promise<Config> {\n try {\n const raw = await readFile(p.config, \"utf8\");\n return ConfigSchema.parse(JSON.parse(raw));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n const cfg = defaultConfig(p);\n await writeFile(p.config, JSON.stringify(cfg, null, 2) + \"\\n\");\n return cfg;\n }\n throw err;\n }\n}\n","/**\n * Fixed box sizes. Firecracker backs guest memory lazily and the disk is a sparse overlay on the\n * shared base image, so a box only costs what the guest actually touches.\n */\nexport const SIZES = {\n s: { vcpu: 2, memMib: 4096, diskGib: 8 },\n m: { vcpu: 4, memMib: 8192, diskGib: 16 },\n l: { vcpu: 8, memMib: 16384, diskGib: 32 },\n} as const;\n\nexport type SizeName = keyof typeof SIZES;\nexport const SIZE_NAMES = Object.keys(SIZES) as SizeName[];\nexport const DEFAULT_SIZE: SizeName = \"s\";\n\nexport function isSizeName(value: string): value is SizeName {\n return value in SIZES;\n}\n\n/**\n * \"16GB\", \"16G\", \"16\", \"4096MB\", \"4096M\", \"0.5GB\" -> MiB. A bare number is GB: that is how\n * people say it (\"16gb\", \"4 vcpu 16gb\"). Returns undefined when it is not a size.\n */\nexport function parseMib(text: string): number | undefined {\n const m = /^\\s*(\\d+(?:\\.\\d+)?)\\s*([gm]i?b?)?\\s*$/i.exec(text);\n if (!m) return undefined;\n const n = Number(m[1]);\n const unit = (m[2] ?? \"g\").toLowerCase();\n const mib = unit.startsWith(\"m\") ? n : n * 1024;\n return Number.isInteger(mib) && mib > 0 ? mib : undefined;\n}\n","/**\n * Who a box belongs to. Names are unique per owner, not per host, so a box is addressed as\n * `owner/name`; a bare `name` means the caller's own. The owner is part of the box's identity and\n * lives with it on disk (machines/<owner>/<name>, `owner` in meta.json), never in a database.\n * Decision \"Owner realms\": a bare owner is local to this host (the Unix user running kvbox-server);\n * a control plane's users arrive as `user@<control plane>` later (#18), so the two never collide.\n */\nimport { userInfo } from \"node:os\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nexport interface BoxRef {\n owner: string;\n name: string;\n /** How the caller wrote it: `lab1` for their own, `user2/lab1` for someone else's. Set by parseRef, used in messages. */\n display?: string;\n}\n\n/** The ref as the caller knows it (see BoxRef.display); bare name when nothing else is known. */\nexport function shown(ref: BoxRef): string {\n return ref.display ?? ref.name;\n}\n\n/** A local owner is a Unix user name: no `@` (that marks a control-plane realm) and no `/`. */\nexport const LOCAL_OWNER_RE = /^[A-Za-z0-9_][A-Za-z0-9._-]{0,63}$/;\n/** Any owner, local or `user@realm`. */\nexport const OWNER_RE = /^[A-Za-z0-9_][A-Za-z0-9._-]{0,63}(@[A-Za-z0-9.-]{1,128})?$/;\n\n/** The Unix user running this server: what boxes made over the local socket belong to. */\nexport function localOwner(): string {\n try {\n const name = userInfo().username;\n if (LOCAL_OWNER_RE.test(name)) return name;\n } catch {\n /* no passwd entry */\n }\n const env = process.env[\"USER\"];\n return env !== undefined && LOCAL_OWNER_RE.test(env) ? env : \"kvbox\";\n}\n\n/** `lab1` → the caller's box; `user2/lab1` → that owner's. */\nexport function parseRef(text: string, caller: string): BoxRef {\n const slash = text.indexOf(\"/\");\n if (slash === -1) return { owner: caller, name: text, display: text };\n const owner = text.slice(0, slash);\n const name = text.slice(slash + 1);\n if (!OWNER_RE.test(owner) || name.length === 0 || name.includes(\"/\")) {\n throw new KvboxError(`invalid box reference \"${text}\": use <name> or <owner>/<name>`);\n }\n return { owner, name, display: owner === caller ? name : text };\n}\n\n/** `owner/name`: how a ref is written down (snapshot sources, box sources, admin listings). */\nexport function refKey(ref: BoxRef): string {\n return `${ref.owner}/${ref.name}`;\n}\n","/**\n * Host networking: bridge `kvbox0`, one tap `kv-<box>` per box, IP allocation\n * inside the subnet. Everything that needs root goes through one script,\n * `net-setup.sh`, which re-execs itself with `sudo -n` when run from here.\n * `install-server.sh` installs a root-owned copy at PRIVILEGED_SCRIPT plus a\n * sudoers rule for exactly that path; the package copy is the dev fallback.\n */\nimport { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { Config } from \"./config.js\";\nimport { run } from \"./exec.js\";\n\nexport const TAP_PREFIX = \"kv-\";\nexport const PRIVILEGED_SCRIPT = \"/usr/local/lib/kvbox/net-setup.sh\";\n\ntype NetConfig = Pick<Config, \"bridge\" | \"subnet\" | \"gateway\">;\n\nexport function tapName(box: string): string {\n // Linux interface names are limited to 15 characters.\n return `${TAP_PREFIX}${box}`.slice(0, 15);\n}\n\n/** The script to run: KVBOX_NET_SETUP override, the root-owned install, else the package copy (dist/ or src/core/). */\nexport function netSetupScript(): string {\n const override = process.env[\"KVBOX_NET_SETUP\"];\n if (override) return override;\n if (existsSync(PRIVILEGED_SCRIPT)) return PRIVILEGED_SCRIPT;\n for (const rel of [\"../scripts/net-setup.sh\", \"../../scripts/net-setup.sh\"]) {\n const candidate = fileURLToPath(new URL(rel, import.meta.url));\n if (existsSync(candidate)) return candidate;\n }\n throw new KvboxError(\"net-setup.sh not found next to kvbox-server\");\n}\n\nexport function bridgeExists(bridge: string): boolean {\n return existsSync(`/sys/class/net/${bridge}`);\n}\n\nfunction netRun(cfg: NetConfig, args: string[]) {\n return run([netSetupScript(), ...args], {\n env: { ...process.env, KVBOX_BRIDGE: cfg.bridge, KVBOX_SUBNET: cfg.subnet, KVBOX_GATEWAY: cfg.gateway },\n }).catch((err: Error) => {\n throw new KvboxError(\n `${err.message}\\n (root is needed for host networking; install-server.sh sets up a sudoers rule for ${PRIVILEGED_SCRIPT})`,\n );\n });\n}\n\n/** Run `net-setup.sh up` when the bridge is missing, which is the case after every host reboot. */\nexport async function ensureHostNetwork(cfg: NetConfig): Promise<\"present\" | \"created\"> {\n if (bridgeExists(cfg.bridge)) return \"present\";\n await netRun(cfg, [\"up\"]);\n return \"created\";\n}\n\n/**\n * Create the box's tap (owned by this user) and return its name. Plugged into the bridge unless\n * `detached`: a box restored from a snapshot still carries the source box's MAC and IP, so its tap\n * stays off the switch until kvbox-agent has given it its own (attachTap).\n */\nexport async function createTap(box: string, cfg: NetConfig, opts: { detached?: boolean } = {}): Promise<string> {\n const tap = tapName(box);\n await netRun(cfg, [\"tap\", \"add\", tap, ...(opts.detached ? [\"detached\"] : [])]);\n return tap;\n}\n\nexport async function attachTap(box: string, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"tap\", \"attach\", tapName(box)]);\n}\n\nexport async function deleteTap(box: string, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"tap\", \"del\", tapName(box)]);\n}\n\n// ── addresses ────────────────────────────────────────────────────────────────\nconst ipToInt = (ip: string) => ip.split(\".\").reduce((acc, o) => (acc << 8) + Number(o), 0) >>> 0;\nconst intToIp = (n: number) => [24, 16, 8, 0].map((s) => (n >>> s) & 255).join(\".\");\n\n/** Lowest free host address in `subnet` (a.b.c.d/len), skipping network, gateway (.1) and broadcast. */\nexport function nextFreeIp(subnet: string, inUse: readonly string[]): string {\n const [base, lenStr] = subnet.split(\"/\");\n const len = Number(lenStr);\n if (!base || !Number.isInteger(len) || len < 8 || len > 30) throw new KvboxError(`bad subnet: ${subnet}`);\n const mask = len === 0 ? 0 : (~0 << (32 - len)) >>> 0;\n const network = (ipToInt(base) & mask) >>> 0;\n const broadcast = (network | (~mask >>> 0)) >>> 0;\n const used = new Set(inUse.map(ipToInt));\n for (let n = network + 2; n < broadcast; n++) {\n if (!used.has(n)) return intToIp(n);\n }\n throw new KvboxError(`no free IP left in ${subnet}`);\n}\n\n/** Locally administered MAC derived from the IP: 06:00:<a>:<b>:<c>:<d>, unique per box and readable. */\nexport function macFor(ip: string): string {\n const hex = ip.split(\".\").map((o) => Number(o).toString(16).padStart(2, \"0\").toUpperCase());\n return [\"06\", \"00\", ...hex].join(\":\");\n}\n","/**\n * The one shell-out helper. Every `firecracker`, `ip`, `ssh`, `cp` call goes\n * through here: argv arrays only (never a shell string), the command is logged,\n * and stderr ends up in the thrown error.\n */\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nconst execFileAsync = promisify(execFile);\n\nexport interface RunOptions {\n sudo?: boolean;\n cwd?: string;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n /** Non-zero exit codes that are not failures (e2fsck: 1 = \"errors corrected\"). */\n okExitCodes?: readonly number[];\n}\n\nexport interface RunResult {\n stdout: string;\n stderr: string;\n}\n\nexport async function run(argv: readonly string[], opts: RunOptions = {}): Promise<RunResult> {\n const [cmd, ...args] = opts.sudo ? [\"sudo\", \"-n\", ...argv] : argv;\n if (!cmd) throw new KvboxError(\"run: empty argv\");\n if (process.env[\"KVBOX_DEBUG\"]) console.error(`[exec] ${[cmd, ...args].join(\" \")}`);\n try {\n const { stdout, stderr } = await execFileAsync(cmd, args, {\n cwd: opts.cwd,\n env: opts.env ?? process.env,\n timeout: opts.timeoutMs ?? 30_000,\n maxBuffer: 8 * 1024 * 1024,\n });\n return { stdout, stderr };\n } catch (err) {\n const e = err as NodeJS.ErrnoException & { stdout?: string; stderr?: string; code?: number | string };\n if (typeof e.code === \"number\" && opts.okExitCodes?.includes(e.code)) return { stdout: e.stdout ?? \"\", stderr: e.stderr ?? \"\" };\n const detail = (e.stderr ?? e.message ?? \"\").trim();\n throw new KvboxError(`${[cmd, ...args].join(\" \")} failed${detail ? `: ${detail}` : \"\"}`);\n }\n}\n","/** Bind the app to the local Unix socket and write the pid file. */\nimport { rm, writeFile } from \"node:fs/promises\";\nimport { createAdaptorServer } from \"@hono/node-server\";\nimport { ensureLayout } from \"./core/state.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { migrateOwnerLayout } from \"./core/migrate.js\";\nimport { seedUsageLedger } from \"./core/usage.js\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths } from \"@kvbox/shared/paths\";\nimport { createApp } from \"./app.js\";\n\nexport interface ListenOptions {\n socketPath?: string;\n}\n\nexport async function listen(opts: ListenOptions = {}) {\n const p = await ensureLayout(paths());\n const cfg = await loadConfig(p);\n const moved = await migrateOwnerLayout(cfg.owner, p);\n if (moved.boxes.length + moved.snapshots.length > 0) {\n console.error(`boxes and snapshots now belong to an owner: moved ${moved.boxes.length} box(es) and ${moved.snapshots.length} snapshot(s) under ${cfg.owner}/`);\n }\n for (const c of moved.conflicts) console.error(`warning: ${c} left in place: ${cfg.owner} already has one with that name`);\n const seeded = await seedUsageLedger(p);\n if (seeded > 0) console.error(`usage: started keeping time for ${seeded} box(es) made before this version; kvbox vm usage counts from now for them`);\n const socketPath = opts.socketPath ?? p.serverSock;\n // Linux limits a Unix socket path (sun_path) to 108 bytes; bind() fails with EINVAL past it.\n if (Buffer.byteLength(socketPath) > 100) {\n throw new KvboxError(`socket path too long for a Unix socket (${socketPath}); set KVBOX_HOME to a shorter path`);\n }\n\n // A stale socket file from a crashed server blocks bind(); the pid file tells\n // `server status` whether anything is actually alive.\n await rm(socketPath, { force: true });\n\n const server = createAdaptorServer({ fetch: createApp().fetch });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(socketPath, () => resolve());\n });\n await writeFile(p.serverPid, `${process.pid}\\n`);\n\n const shutdown = async () => {\n server.close();\n await rm(socketPath, { force: true });\n await rm(p.serverPid, { force: true });\n process.exit(0);\n };\n process.once(\"SIGINT\", () => void shutdown());\n process.once(\"SIGTERM\", () => void shutdown());\n\n return { socketPath, server };\n}\n","/**\n * The `~/.kvbox` layout and the per-box / per-snapshot `meta.json` files.\n * The server is the only writer; every read is validated with zod.\n */\nimport { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport type { BoxRef } from \"./refs.js\";\n\nexport const MachineMetaSchema = z.object({\n name: z.string(),\n /** Part of the box's identity: machines/<owner>/<name>. See refs.ts. */\n owner: z.string(),\n ip: z.string(),\n mac: z.string(),\n pid: z.number().int().nullable(), // null: stopped on purpose, disk kept\n vcpu: z.number().int(),\n memMib: z.number().int(),\n createdAt: z.string(),\n source: z.string(),\n /** Base image version (assets/rootfs-<version>.ext4) the box overlays. Absent: a pre-overlay box with its own disk.ext4. */\n base: z.string().optional(),\n /**\n * Snapshots taken since this VM started (boot or restore). Firecracker resets its dirty-page bitmap at\n * each one, so when this is > 0 the next diff is only standalone merged onto `mem.base`; if that file\n * is missing the lineage is broken and the next snapshot has to be a full dump. Absent: 0.\n */\n memSnapshots: z.number().int().optional(),\n /** `kvbox pause`: Firecracker is alive but the VM is frozen (standby). Absent: not paused. */\n paused: z.boolean().optional(),\n});\nexport type MachineMeta = z.infer<typeof MachineMetaSchema>;\n\nexport const SnapshotMetaSchema = z.object({\n name: z.string(),\n owner: z.string(),\n /** The box it was taken from, as owner/name. */\n source: z.string(),\n base: z.string(),\n vcpu: z.number().int(),\n memMib: z.number().int(),\n sizeBytes: z.number().int(),\n createdAt: z.string(),\n});\nexport type SnapshotMeta = z.infer<typeof SnapshotMetaSchema>;\n\n/** Create every directory of the layout. Idempotent; called by `kvbox server start`. */\nexport async function ensureLayout(p: Paths = paths()): Promise<Paths> {\n for (const dir of [p.home, p.ssh, p.bin, p.assets, p.machines, p.snapshots]) {\n await mkdir(dir, { recursive: true, mode: 0o700 });\n }\n return p;\n}\n\nasync function readJson<T>(file: string, schema: z.ZodType<T>): Promise<T> {\n return schema.parse(JSON.parse(await readFile(file, \"utf8\")));\n}\n\nasync function listDirs(dir: string): Promise<string[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n}\n\nexport async function readMachineMeta(ref: BoxRef, p: Paths = paths()) {\n return readJson(p.machine(ref.owner, ref.name).meta, MachineMetaSchema);\n}\n\nexport async function writeMachineMeta(meta: MachineMeta, p: Paths = paths()) {\n const m = p.machine(meta.owner, meta.name);\n await mkdir(m.dir, { recursive: true });\n await writeFile(m.meta, JSON.stringify(meta, null, 2) + \"\\n\");\n}\n\n/** Every box on the host, all owners: machines/<owner>/<name>. */\nexport async function listMachineRefs(p: Paths = paths()) {\n return listRefs(p.machines);\n}\n\nexport async function readSnapshotMeta(ref: BoxRef, p: Paths = paths()) {\n return readJson(p.snapshot(ref.owner, ref.name).meta, SnapshotMetaSchema);\n}\n\nexport async function writeSnapshotMeta(meta: SnapshotMeta, p: Paths = paths()) {\n const s = p.snapshot(meta.owner, meta.name);\n await mkdir(s.dir, { recursive: true });\n await writeFile(s.meta, JSON.stringify(meta, null, 2) + \"\\n\");\n}\n\nexport async function listSnapshotRefs(p: Paths = paths()) {\n return listRefs(p.snapshots);\n}\n\n/** Two levels: <root>/<owner>/<name>. A directory at the first level with its own meta.json is the pre-owner layout, migrated at server start and skipped here. */\nasync function listRefs(root: string): Promise<BoxRef[]> {\n const out: BoxRef[] = [];\n for (const owner of await listDirs(root)) {\n for (const name of await listDirs(`${root}/${owner}`)) {\n out.push({ owner, name });\n }\n }\n return out;\n}\n\n/** True when a pid is alive (signal 0). */\nexport function pidAlive(pid: number | null): boolean {\n if (pid === null || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n","/**\n * One-time layout upgrades of the state dir, run by `kvbox-server start` before it listens.\n * Each one is idempotent and leaves a running box alone: Firecracker keeps its working directory\n * and open files by inode, and the server re-derives every path on each call, so a box directory\n * can be renamed under it.\n */\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\n\nexport interface OwnerMigration {\n boxes: string[];\n snapshots: string[];\n /** Entries left where they were because the owner already has one with that name. */\n conflicts: string[];\n}\n\n/**\n * Pre-owner layout (`machines/<name>`, `snapshots/<name>`) → `machines/<owner>/<name>`. Everything\n * found at the old depth belonged to the host owner, since nobody else could make boxes.\n * The meta gets `owner` first, in place, then the directory moves: a crash between the two\n * leaves an old-depth entry that the next start picks up again.\n */\nexport async function migrateOwnerLayout(owner: string, p: Paths = paths()): Promise<OwnerMigration> {\n const done: OwnerMigration = { boxes: [], snapshots: [], conflicts: [] };\n for (const name of await oldDepthEntries(p.machines)) {\n const from = join(p.machines, name);\n const to = p.machine(owner, name).dir;\n if (existsSync(to)) {\n done.conflicts.push(`machines/${name}`);\n continue;\n }\n await patchJson(join(from, \"meta.json\"), (meta) => ({\n ...meta,\n owner,\n // a restored box names its snapshot: that moved under the same owner\n source: typeof meta[\"source\"] === \"string\" && meta[\"source\"].startsWith(\"snapshot:\") && !meta[\"source\"].includes(\"/\")\n ? `snapshot:${owner}/${meta[\"source\"].slice(\"snapshot:\".length)}`\n : meta[\"source\"],\n }));\n await mkdir(p.ownerMachines(owner), { recursive: true, mode: 0o700 });\n await rename(from, to);\n done.boxes.push(name);\n }\n for (const name of await oldDepthEntries(p.snapshots)) {\n const from = join(p.snapshots, name);\n const to = p.snapshot(owner, name).dir;\n if (existsSync(to)) {\n done.conflicts.push(`snapshots/${name}`);\n continue;\n }\n await patchJson(join(from, \"meta.json\"), (meta) => ({\n ...meta,\n owner,\n source: typeof meta[\"source\"] === \"string\" && !meta[\"source\"].includes(\"/\") ? `${owner}/${meta[\"source\"]}` : meta[\"source\"],\n }));\n await mkdir(p.ownerSnapshots(owner), { recursive: true, mode: 0o700 });\n await rename(from, to);\n done.snapshots.push(name);\n }\n return done;\n}\n\n/** Directories directly under `root` that hold a meta.json themselves: the pre-owner layout. An owner dir holds dirs, not a meta. */\nasync function oldDepthEntries(root: string): Promise<string[]> {\n let entries;\n try {\n entries = await readdir(root, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw err;\n }\n return entries.filter((e) => e.isDirectory() && existsSync(join(root, e.name, \"meta.json\"))).map((e) => e.name).sort();\n}\n\nasync function patchJson(file: string, patch: (raw: Record<string, unknown>) => Record<string, unknown>): Promise<void> {\n const raw = JSON.parse(await readFile(file, \"utf8\")) as Record<string, unknown>;\n await writeFile(file, JSON.stringify(patch(raw), null, 2) + \"\\n\");\n}\n","/**\n * `~/.kvbox/kvbox.db`: the host's ledgers, through Node's built-in SQLite (node:sqlite, Node >= 22.13;\n * no dependency). Decision \"Hosts keep boxes as files + SQLite ledgers\": a box is still its directory\n * and meta.json, the database only holds what has to be appended to over time and summed later.\n * First table: `usage_events`, one row per state change of a box, the source of `kvbox vm usage`.\n *\n * One handle per database file for the life of the process; WAL so readers never block the writer.\n * The file is created 0600 before SQLite opens it, so the -wal and -shm files it makes next to it\n * inherit the mode.\n */\nimport { chmodSync, closeSync, mkdirSync, openSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\n\n/** Each entry upgrades the schema one version; `schema_version` records how far a file has come. */\nconst MIGRATIONS: string[] = [\n `create table usage_events (\n id integer primary key,\n box_id text not null,\n owner text not null,\n name text not null,\n at text not null,\n state text not null,\n vcpu integer not null,\n mem_mib integer not null,\n disk_gib integer not null,\n by text not null\n );\n create index usage_events_box_at on usage_events (box_id, at);`,\n];\n\nconst handles = new Map<string, DatabaseSync>();\n\nexport function openDb(p: Paths = paths()): DatabaseSync {\n const have = handles.get(p.db);\n if (have !== undefined) return have;\n mkdirSync(dirname(p.db), { recursive: true, mode: 0o700 });\n closeSync(openSync(p.db, \"a\", 0o600));\n chmodSync(p.db, 0o600);\n const db = new DatabaseSync(p.db);\n db.exec(\"pragma journal_mode = wal\");\n db.exec(\"pragma busy_timeout = 5000\");\n migrate(db);\n handles.set(p.db, db);\n return db;\n}\n\n/** Close the handle for this home (tests; the daemon keeps its open until exit). */\nexport function closeDb(p: Paths = paths()): void {\n const db = handles.get(p.db);\n if (db === undefined) return;\n db.close();\n handles.delete(p.db);\n}\n\nfunction migrate(db: DatabaseSync): void {\n db.exec(\"create table if not exists schema_version (version integer not null)\");\n const row = db.prepare(\"select version from schema_version\").get() as { version: number } | undefined;\n let version = row?.version ?? 0;\n if (row === undefined) db.prepare(\"insert into schema_version (version) values (0)\").run();\n while (version < MIGRATIONS.length) {\n db.exec(\"begin\");\n try {\n db.exec(MIGRATIONS[version]!);\n version += 1;\n db.prepare(\"update schema_version set version = ?\").run(version);\n db.exec(\"commit\");\n } catch (err) {\n db.exec(\"rollback\");\n throw err;\n }\n }\n}\n\n// ---- usage_events --------------------------------------------------------------------------------\n\nexport type UsageState = \"running\" | \"standby\" | \"hibernated\" | \"stopped\";\n\n/** States in which a Firecracker process exists: a run that `closeOpenRun` has to close if that process died. */\nconst LIVE_STATES: readonly UsageState[] = [\"running\", \"standby\"];\n\n/** One state change. Sizes ride on every row so a rescale changes the rate from that moment on. */\nexport interface UsageEvent {\n at: string;\n state: UsageState;\n vcpu: number;\n memMib: number;\n diskGib: number;\n /** What made it: new, start, stop, pause, resume, hibernate, wake, rescale, update, rm, upgrade (first row of a box older than the ledger), server (a stop the server did not see). */\n by: string;\n}\n\nexport interface UsageEventRow extends UsageEvent {\n /** `owner/name` until #39 gives boxes an id of their own; owner and name are kept beside it so the ledger reads alone after a box is gone. */\n boxId: string;\n owner: string;\n name: string;\n}\n\ninterface Raw {\n box_id: string;\n owner: string;\n name: string;\n at: string;\n state: string;\n vcpu: number;\n mem_mib: number;\n disk_gib: number;\n by: string;\n}\n\nfunction fromRaw(r: Raw): UsageEventRow {\n return { boxId: r.box_id, owner: r.owner, name: r.name, at: r.at, state: r.state as UsageState, vcpu: r.vcpu, memMib: r.mem_mib, diskGib: r.disk_gib, by: r.by };\n}\n\nfunction lastEvent(boxId: string, db: DatabaseSync): UsageEventRow | undefined {\n const raw = db.prepare(\"select * from usage_events where box_id = ? order by at desc, id desc limit 1\").get(boxId) as Raw | undefined;\n return raw === undefined ? undefined : fromRaw(raw);\n}\n\nfunction insertRaw(e: UsageEventRow, db: DatabaseSync): void {\n db.prepare(\n \"insert into usage_events (box_id, owner, name, at, state, vcpu, mem_mib, disk_gib, by) values (?, ?, ?, ?, ?, ?, ?, ?, ?)\",\n ).run(e.boxId, e.owner, e.name, e.at, e.state, e.vcpu, e.memMib, e.diskGib, e.by);\n}\n\n/**\n * Append a state change. A `running` on top of an open run (running or standby) means the box stopped\n * without the server knowing (Firecracker died, host rebooted): that run is closed first, dated now, by\n * `server`. The one exception is a resume, the legitimate way from standby back to running.\n */\nexport function insertUsageEvent(e: UsageEventRow, p: Paths = paths()): void {\n const db = openDb(p);\n if (e.state === \"running\" && e.by !== \"resume\") closeOpenRun(e.boxId, e.at, p);\n insertRaw(e, db);\n}\n\n/** If the box's last event has a live process (running or standby), add the `stopped` the server never saw, at `at`. True when one was added. */\nexport function closeOpenRun(boxId: string, at: string, p: Paths = paths()): boolean {\n const db = openDb(p);\n const last = lastEvent(boxId, db);\n if (last === undefined || !LIVE_STATES.includes(last.state)) return false;\n insertRaw({ ...last, at, state: \"stopped\", by: \"server\" }, db);\n return true;\n}\n\n/** The box's events from `since` on, oldest first. */\nexport function usageEventsFor(boxId: string, since: string, p: Paths = paths()): UsageEventRow[] {\n const rows = openDb(p).prepare(\"select * from usage_events where box_id = ? and at >= ? order by at, id\").all(boxId, since) as unknown as Raw[];\n return rows.map(fromRaw);\n}\n","/**\n * Create, list and destroy boxes: what spikes #4 and #6 did by hand.\n * See architecture \"Process model\". The server is the only writer of ~/.kvbox/machines.\n */\nimport { spawn } from \"node:child_process\";\nimport { closeSync, existsSync, openSync, statSync } from \"node:fs\";\nimport { link, mkdir, readFile, realpath, rm, truncate, writeFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport type { BoxStatus, CreateMachineRequest, Machine, RescaleMachineRequest } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { SIZES, isSizeName } from \"@kvbox/shared/sizes\";\nimport { setIdentity } from \"./agent.js\";\nimport { assertRoomFor } from \"./capacity.js\";\nimport { closeOpenRun, insertUsageEvent, type UsageState } from \"./db.js\";\nimport { parseRef, refKey, shown, type BoxRef } from \"./refs.js\";\nimport { loadConfig, type Config } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { FirecrackerClient } from \"./firecracker.js\";\nimport { attachTap, createTap, deleteTap, ensureHostNetwork, macFor, nextFreeIp } from \"./network.js\";\nimport {\n listMachineRefs,\n pidAlive,\n readMachineMeta,\n readSnapshotMeta,\n writeMachineMeta,\n type MachineMeta,\n type SnapshotMeta,\n} from \"./state.js\";\n\n/** Box names double as hostnames and tap suffixes (kv- + name ≤ 15 chars). */\nconst NAME_RE = /^[a-z0-9][a-z0-9-]{0,11}$/;\nconst AUTO_PREFIX = \"box\";\n/** Every box's vsock address. Firecracker's vsock is per process, so the number need not be unique on the host. */\nconst GUEST_CID = 3;\n/** The overlay drive's path as Firecracker sees it: relative to the box dir, see spawnFirecracker. */\nconst OVERLAY_REL = \"overlay.ext4\";\n\nfunction diskStats(disk: string): { diskBytes: number; diskUsedBytes: number } {\n try {\n const st = statSync(disk);\n return { diskBytes: st.size, diskUsedBytes: st.blocks * 512 };\n } catch {\n return { diskBytes: 0, diskUsedBytes: 0 };\n }\n}\n\n/** A box's own disk file: its overlay, or the full copy pre-overlay boxes were made with. */\nfunction ownDisk(meta: MachineMeta, p: Paths): string {\n const m = p.machine(meta.owner, meta.name);\n return meta.base === undefined ? m.disk : m.overlay;\n}\n\n/** Whole GiB of the box's own disk file (its size as the guest sees it, not what it occupies). */\nfunction diskGibOf(meta: MachineMeta, p: Paths): number {\n try {\n return Math.round(statSync(ownDisk(meta, p)).size / 1024 ** 3);\n } catch {\n return 0;\n }\n}\n\n/**\n * Append the box's state change to the usage ledger (core/db.ts). Bookkeeping never fails the\n * operation it records: a ledger problem is logged and the box carries on.\n */\nfunction recordState(meta: MachineMeta, state: UsageState, by: string, p: Paths, at = new Date().toISOString()): void {\n try {\n insertUsageEvent({ boxId: refKey(meta), owner: meta.owner, name: meta.name, at, state, by, vcpu: meta.vcpu, memMib: meta.memMib, diskGib: diskGibOf(meta, p) }, p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n}\n\n/** No process, but a memory dump in the box dir: `kvbox hibernate` left it, `wake` continues from it. */\nfunction isHibernated(meta: MachineMeta, p: Paths): boolean {\n return !pidAlive(meta.pid) && existsSync(p.machine(meta.owner, meta.name).hibernateVmstate);\n}\n\nexport function statusOf(meta: MachineMeta, p: Paths = paths()): BoxStatus {\n if (pidAlive(meta.pid)) return meta.paused ? \"standby\" : \"running\";\n return isHibernated(meta, p) ? \"hibernated\" : \"stopped\";\n}\n\n/** \"box lab1 is stopped\" / \"is in standby\" / \"is hibernated\", for refusals. */\nfunction stateMessage(ref: BoxRef, status: BoxStatus): string {\n return `box ${shown(ref)} is ${status === \"standby\" ? \"in standby\" : status}`;\n}\n\nfunction toMachine(meta: MachineMeta, p: Paths = paths()): Machine {\n const alive = pidAlive(meta.pid);\n // A pid the server set that is no longer alive: Firecracker died on its own (crash, host reboot,\n // kill). The ledger's open run is closed now, by `server`: the box's stop time is estimated, and\n // `usage` says so. Nothing is written to meta.json here (listing stays read-only on the state dir).\n if (!alive && meta.pid !== null) {\n try {\n closeOpenRun(refKey(meta), new Date().toISOString(), p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n }\n return {\n name: meta.name,\n owner: meta.owner,\n ip: meta.ip,\n mac: meta.mac,\n pid: alive ? meta.pid : null,\n vcpu: meta.vcpu,\n memMib: meta.memMib,\n ...diskStats(ownDisk(meta, p)),\n base: meta.base ?? null,\n createdAt: meta.createdAt,\n source: meta.source,\n status: statusOf(meta, p),\n };\n}\n\nasync function readAllMeta(p: Paths): Promise<MachineMeta[]> {\n const metas: MachineMeta[] = [];\n for (const ref of await listMachineRefs(p)) {\n try {\n metas.push(await readMachineMeta(ref, p));\n } catch (err) {\n console.error(`warning: skipping machines/${refKey(ref)}: ${(err as Error).message}`);\n }\n }\n return metas;\n}\n\n/** The boxes of one owner, or every box on the host when `owner` is null (the host operator's view). */\nexport async function listMachines(owner: string | null, p: Paths = paths()): Promise<Machine[]> {\n return (await readAllMeta(p)).filter((m) => owner === null || m.owner === owner).map((m) => toMachine(m, p));\n}\n\nexport async function getMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n return toMachine(await readMeta(ref, p), p);\n}\n\nfunction pickName(requested: string | undefined, taken: Set<string>): string {\n if (requested !== undefined) {\n if (!NAME_RE.test(requested)) {\n throw new KvboxError(`invalid box name \"${requested}\": 1-12 chars, lowercase letters, digits and '-', starting with a letter or digit`);\n }\n if (taken.has(requested)) throw new KvboxError(`box ${requested} already exists`);\n return requested;\n }\n for (let i = 1; ; i++) {\n const candidate = `${AUTO_PREFIX}${i}`;\n if (!taken.has(candidate)) return candidate;\n }\n}\n\nexport function bootArgs(name: string, ip: string, cfg: Config, pubkeyB64: string, mode: { overlay: boolean }): string {\n // Firecracker appends `pci=off root=/dev/vda` plus ro/rw itself. ip= is read by the guest\n // kernel, kvbox.name= / kvbox.sshkey= by kvbox-init on first boot (the kvbox-images contract).\n // With an overlay, /sbin/overlay-init in the image stacks the box's disk (/dev/vdb) on the\n // read-only base before systemd starts.\n const init = mode.overlay ? \" init=/sbin/overlay-init kvbox.overlay=/dev/vdb\" : \"\";\n const args = `console=ttyS0 reboot=k panic=1${init} ip=${ip}::${cfg.gateway}:255.255.255.0:${name}:eth0:off kvbox.name=${name} kvbox.sshkey=${pubkeyB64}`;\n return process.arch === \"arm64\" ? `keep_bootcon ${args}` : args;\n}\n\n/** `assets/rootfs-<version>.ext4` -> `<version>`; anything else is the layout from before overlays. */\nexport function baseVersionOf(file: string): string {\n const m = /^rootfs-(.+)\\.ext4$/.exec(basename(file));\n if (!m) throw new KvboxError(`base image ${file} is not versioned (expected assets/rootfs-<version>.ext4); run install-server.sh`);\n return m[1]!;\n}\n\n/** Follow config's rootfs symlink to the base image a new box should be made from. */\nasync function currentBase(cfg: Config, p: Paths): Promise<{ version: string; file: string }> {\n const file = await realpath(cfg.rootfs);\n const version = baseVersionOf(file);\n const expected = p.baseImage(version);\n if (file !== expected) throw new KvboxError(`base image ${cfg.rootfs} points outside ${p.assets} (${file})`);\n return { version, file };\n}\n\n/** The base image this box boots from; a pre-overlay box has none (its own disk copy is the root). */\nfunction baseFileFor(meta: Pick<MachineMeta, \"name\" | \"base\">, p: Paths): string | undefined {\n if (meta.base === undefined) return undefined;\n const file = p.baseImage(meta.base);\n if (!existsSync(file)) throw new KvboxError(`box ${meta.name} runs on base image ${meta.base}, which is gone from ${p.assets}`);\n return file;\n}\n\nconst overlayCapable = new Map<string, boolean>();\n\n/** A base image older than the overlay layout has no /sbin/overlay-init and would panic at boot. debugfs reads the ext4 without mounting it. */\nasync function assertOverlayCapable(baseFile: string, version: string): Promise<void> {\n let ok = overlayCapable.get(baseFile);\n if (ok === undefined) {\n const { stdout } = await run([\"debugfs\", \"-R\", \"stat /sbin/overlay-init\", baseFile]);\n ok = /Type:\\s+regular/.test(stdout);\n overlayCapable.set(baseFile, ok);\n }\n if (!ok) throw new KvboxError(`base image ${version} is too old for this server (no /sbin/overlay-init); rerun install-server.sh to get a newer one`);\n}\n\n/** The box's writable disk: a sparse ext4 of `gib` GiB, ready in milliseconds and occupying a few MB until written to. */\nexport async function createOverlay(file: string, gib: number): Promise<void> {\n await writeFile(file, \"\", { mode: 0o600 });\n await truncate(file, gib * 1024 ** 3);\n // -F: it is a file, not a block device. -m 0: no blocks held back for root, the whole disk is the box's.\n // Lazy init: the inode tables are zeroed by the guest kernel as it goes, so mkfs writes almost nothing.\n await run([\"mkfs.ext4\", \"-q\", \"-F\", \"-m\", \"0\", \"-L\", \"kvbox-box\", \"-E\", \"lazy_itable_init=1,lazy_journal_init=1\", file]);\n}\n\nasync function waitFor(pred: () => boolean, timeoutMs: number, stepMs = 50): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (pred()) return true;\n await sleep(stepMs);\n }\n return pred();\n}\n\nasync function tailOf(file: string, lines = 5): Promise<string> {\n try {\n return (await readFile(file, \"utf8\")).trim().split(\"\\n\").slice(-lines).join(\"\\n\");\n } catch {\n return \"\";\n }\n}\n\ninterface LaunchSpec {\n name: string;\n owner: string;\n ip: string;\n mac: string;\n vcpu: number;\n memMib: number;\n base?: string | undefined;\n}\n\n/**\n * Spawn Firecracker detached for box `name` and wait for its API socket. Returns the pid; the\n * caller kills it on any later failure. Its working directory is the box dir and the overlay drive\n * is given as a relative path (OVERLAY_REL): a snapshot's vmstate stores drive paths verbatim, so a\n * relative one resolves to whichever box dir the snapshot is restored into.\n */\nasync function spawnFirecracker(ref: BoxRef, cfg: Config, p: Paths): Promise<number> {\n const m = p.machine(ref.owner, ref.name);\n await rm(m.sock, { force: true });\n await rm(m.vsock, { force: true });\n const logFd = openSync(m.log, \"a\");\n let child;\n try {\n child = spawn(cfg.firecracker, [\"--api-sock\", m.sock, \"--id\", ref.name, \"--level\", \"Error\"], {\n cwd: m.dir,\n detached: true,\n stdio: [\"ignore\", logFd, logFd],\n });\n } finally {\n closeSync(logFd);\n }\n child.unref();\n const pid = child.pid;\n if (pid === undefined) throw new KvboxError(\"could not start firecracker\");\n if (!(await waitFor(() => existsSync(m.sock), 3000))) {\n killQuietly(pid);\n throw new KvboxError(`firecracker did not open its API socket; last log lines:\\n${await tailOf(m.log)}`);\n }\n return pid;\n}\n\nfunction killQuietly(pid: number): void {\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n /* already gone */\n }\n}\n\n/** Spawn Firecracker, configure it over its socket, InstanceStart. Returns the pid. Caller rolls back on throw. */\nasync function launch(spec: LaunchSpec, tap: string, cfg: Config, pubkeyB64: string, p: Paths): Promise<number> {\n const m = p.machine(spec.owner, spec.name);\n const baseFile = baseFileFor(spec, p);\n const pid = await spawnFirecracker(spec, cfg, p);\n try {\n const fc = new FirecrackerClient(m.sock);\n try {\n await fc.bootSource(cfg.kernel, bootArgs(spec.name, spec.ip, cfg, pubkeyB64, { overlay: baseFile !== undefined }));\n if (baseFile !== undefined) {\n await fc.rootDrive(baseFile, true);\n await fc.overlayDrive(OVERLAY_REL);\n } else {\n await fc.rootDrive(m.disk, false);\n }\n await fc.machineConfig(spec.vcpu, spec.memMib);\n await fc.networkInterface(\"eth0\", tap, spec.mac);\n await fc.vsock(GUEST_CID, m.vsock);\n await fc.start();\n } finally {\n await fc.close();\n }\n return pid;\n } catch (err) {\n killQuietly(pid);\n throw err;\n }\n}\n\n/** A frozen VM on disk: a snapshot's files, or a hibernated box's own dump. `label` names it in errors. */\ninterface MemoryImage {\n vmstate: string;\n mem: string;\n label: string;\n}\n\n/**\n * Spawn Firecracker and restore the image into it, still paused, with this box's tap and vsock\n * in place of the source box's. Drive paths cannot be overridden at load: a vmstate written by this\n * server names the overlay relatively and already resolves to this box's copy, while one from an\n * older server names the source box's file (which must still exist for the load to succeed) and is\n * re-pointed afterwards. Returns the pid; the caller resumes and rolls back on throw.\n */\nasync function loadSnapshot(spec: LaunchSpec, image: MemoryImage, tap: string, cfg: Config, p: Paths): Promise<number> {\n const m = p.machine(spec.owner, spec.name);\n const pid = await spawnFirecracker(spec, cfg, p);\n try {\n const fc = new FirecrackerClient(m.sock);\n try {\n try {\n await fc.snapshotLoad({\n snapshotPath: image.vmstate,\n memFilePath: image.mem,\n tap: { ifaceId: \"eth0\", hostDevName: tap },\n vsockPath: m.vsock,\n trackDirtyPages: true,\n resume: false,\n });\n } catch (err) {\n // No vsock device in the vmstate: the source box predates kvbox-agent, so nothing inside could take the new identity.\n if (/Unknown Vsock Device/.test((err as Error).message)) throw new KvboxError(tooOldToRestore(image.label));\n throw err;\n }\n if (await namesOverlayAbsolutely(image.vmstate)) await fc.patchDrivePath(\"overlay\", m.overlay);\n } finally {\n await fc.close();\n }\n return pid;\n } catch (err) {\n killQuietly(pid);\n throw err;\n }\n}\n\nfunction tooOldToRestore(snapshot: string): string {\n return `snapshot ${snapshot} was taken from a box made before kvbox-agent existed (older base image) and cannot be restored: make a fresh box with this kvbox, set it up, and snapshot that one`;\n}\n\n/** The base image version `kvbox new` uses right now (what `assets/rootfs.ext4` points at). */\nexport async function currentBaseVersion(p: Paths = paths()): Promise<string> {\n return (await currentBase(await loadConfig(p), p)).version;\n}\n\n/** The vmstate stores drive paths as plain strings; one with a directory in front is the pre-relative layout. */\nasync function namesOverlayAbsolutely(vmstate: string): Promise<boolean> {\n return (await readFile(vmstate)).includes(`/${OVERLAY_REL}`);\n}\n\nasync function readPubkeyB64(p: Paths): Promise<string> {\n try {\n return Buffer.from((await readFile(`${p.sshKey}.pub`, \"utf8\")).trim()).toString(\"base64\");\n } catch {\n throw new KvboxError(`SSH key missing at ${p.sshKey}.pub; run install-server.sh`);\n }\n}\n\nfunction assertAssets(cfg: Config): void {\n for (const [what, file] of [[\"kernel\", cfg.kernel], [\"base image\", cfg.rootfs], [\"firecracker\", cfg.firecracker]] as const) {\n if (!existsSync(file)) throw new KvboxError(`${what} missing at ${file}; run install-server.sh`);\n }\n}\n\n/**\n * `owner` is who the box belongs to: the caller, as the route resolved it (the host owner over the\n * local socket). `req.owner` is not read here on purpose: a caller does not get to pick.\n */\nexport async function createMachine(req: CreateMachineRequest, owner: string, p: Paths = paths()): Promise<Machine> {\n const cfg = await loadConfig(p);\n if (req.from !== undefined) return restoreMachine(req.from, owner, req, cfg, p);\n const sizeName = req.size ?? cfg.defaultSize;\n if (!isSizeName(sizeName)) throw new KvboxError(`unknown size \"${sizeName}\"; use one of ${Object.keys(SIZES).join(\", \")}`);\n const size = SIZES[sizeName];\n assertAssets(cfg);\n await assertRoomFor(size.vcpu, size.memMib, req.force ?? false, p);\n const pubkeyB64 = await readPubkeyB64(p);\n\n const existing = await readAllMeta(p);\n // names are per owner; IPs and taps are per host\n const name = pickName(req.name, new Set(existing.filter((m) => m.owner === owner).map((m) => m.name)));\n const ip = nextFreeIp(cfg.subnet, [...existing.map((m) => m.ip), cfg.gateway]);\n const mac = macFor(ip);\n const m = p.machine(owner, name);\n\n const base = await currentBase(cfg, p);\n await assertOverlayCapable(base.file, base.version);\n\n await ensureHostNetwork(cfg);\n await mkdir(m.dir, { recursive: true, mode: 0o700 });\n let tapCreated = false;\n try {\n // The base image is shared read-only by every box; only the box's own writes land in its overlay.\n await createOverlay(m.overlay, size.diskGib);\n const tap = await createTap(name, cfg);\n tapCreated = true;\n const spec: LaunchSpec = { name, owner, ip, mac, vcpu: size.vcpu, memMib: size.memMib, base: base.version };\n const pid = await launch(spec, tap, cfg, pubkeyB64, p);\n const meta: MachineMeta = { ...spec, pid, createdAt: new Date().toISOString(), source: \"base\" };\n await writeMachineMeta(meta, p);\n recordState(meta, \"running\", \"new\", p, meta.createdAt);\n return toMachine(meta, p);\n } catch (err) {\n // leave nothing half-made behind\n if (tapCreated) await deleteTap(name, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n }\n}\n\n\nasync function readSnap(ref: BoxRef, p: Paths): Promise<SnapshotMeta> {\n try {\n return await readSnapshotMeta(ref, p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") throw new NotFoundError(`snapshot ${shown(ref)}`);\n throw err;\n }\n}\n\n/** a.b.c.d/len -> len */\nfunction prefixLenOf(subnet: string): number {\n return Number(subnet.split(\"/\")[1]);\n}\n\n/**\n * `kvbox new --from <snapshot>`: a warm box. The snapshot's memory and overlay come back exactly as\n * frozen, processes included, under a new name, IP and MAC. The guest itself still remembers the\n * source box's identity, so its tap stays off the bridge until kvbox-agent (reached over vsock, not\n * the network) has applied the new one and set the clock. Sub-second: the memory file is mapped,\n * not read, and the overlay copy is sparse.\n */\nasync function restoreMachine(fromText: string, owner: string, req: CreateMachineRequest, cfg: Config, p: Paths): Promise<Machine> {\n const from = parseRef(fromText, owner);\n const snap = await readSnap(from, p);\n if (req.size !== undefined) {\n throw new KvboxError(`--size cannot be combined with --from: a restored box has the snapshot's size (${shown(from)}: ${snap.vcpu} vCPU, ${snap.memMib} MiB)`);\n }\n assertAssets(cfg);\n if (!existsSync(p.baseImage(snap.base))) {\n throw new KvboxError(`snapshot ${shown(from)} stacks on base image ${snap.base}, which is gone from ${p.assets}`);\n }\n await assertRoomFor(snap.vcpu, snap.memMib, req.force ?? false, p);\n\n const existing = await readAllMeta(p);\n const name = pickName(req.name, new Set(existing.filter((m) => m.owner === owner).map((m) => m.name)));\n const ip = nextFreeIp(cfg.subnet, [...existing.map((m) => m.ip), cfg.gateway]);\n const mac = macFor(ip);\n const m = p.machine(owner, name);\n const s = p.snapshot(from.owner, from.name);\n\n await ensureHostNetwork(cfg);\n await mkdir(m.dir, { recursive: true, mode: 0o700 });\n let tapCreated = false;\n let pid: number | undefined;\n try {\n await run([\"cp\", \"--sparse=always\", \"--reflink=auto\", s.overlay, m.overlay]);\n // The box's memory lineage starts at the snapshot's image: its first snapshot is a diff merged onto it.\n await link(s.mem, m.memBase);\n const tap = await createTap(name, cfg, { detached: true });\n tapCreated = true;\n const spec: LaunchSpec = { name, owner, ip, mac, vcpu: snap.vcpu, memMib: snap.memMib, base: snap.base };\n pid = await loadSnapshot(spec, { vmstate: s.vmstate, mem: s.mem, label: shown(from) }, tap, cfg, p);\n await resumeVm(m.sock);\n await introduce(spec, m.vsock, cfg, {\n silent: `nothing answered on the restored box's control channel for 3 s; ${tooOldToRestore(shown(from))}`,\n noAnswer: \"the restored box was discarded. kvbox-agent inside it took the request but gave no answer; try again, and if it keeps happening look at the box's journal (kvbox exec <box> -- sudo journalctl -u kvbox-agent) on a box started from the same snapshot.\",\n });\n await attachTap(name, cfg);\n const meta: MachineMeta = { ...spec, pid, createdAt: new Date().toISOString(), source: `snapshot:${refKey(from)}`, memSnapshots: 1 };\n await writeMachineMeta(meta, p);\n recordState(meta, \"running\", \"new\", p, meta.createdAt);\n return toMachine(meta, p);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n if (tapCreated) await deleteTap(name, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n }\n}\n\n/**\n * Hand the restored guest its identity through kvbox-agent. The agent is already running (it was\n * in memory at the snapshot), but the vsock path to it comes up with the VM, so refused connections\n * are retried for a moment. Once it has accepted, it gets a generous wait: the guest's memory is\n * paged in from the snapshot file on first touch, which on a cold, busy disk can take seconds\n * (seen on the dev host right after install-server.sh had written a new base image).\n */\nconst AGENT_REPLY_MS = 20_000;\n\nasync function introduce(spec: LaunchSpec, vsock: string, cfg: Config, failure: { silent: string; noAnswer: string }): Promise<void> {\n const id = { name: spec.name, ip: spec.ip, prefixLen: prefixLenOf(cfg.subnet), gateway: cfg.gateway, mac: spec.mac, time: Math.floor(Date.now() / 1000) };\n const deadline = Date.now() + 3000;\n for (;;) {\n try {\n await setIdentity(vsock, id, AGENT_REPLY_MS);\n return;\n } catch (err) {\n const msg = (err as Error).message;\n const transient = /unreachable|refused|before the guest accepted/.test(msg);\n if (transient && Date.now() < deadline) {\n await sleep(100);\n continue;\n }\n if (transient) throw new KvboxError(`${msg}\\n ${failure.silent}`);\n throw new KvboxError(`${msg}\\n ${failure.noAnswer}`);\n }\n }\n}\n\nasync function resumeVm(sock: string): Promise<void> {\n const fc = new FirecrackerClient(sock);\n try {\n await fc.resume();\n } finally {\n await fc.close();\n }\n}\n\n/**\n * Clean guest shutdown (Ctrl+Alt+Del), SIGKILL after `graceMs`; tap removed; disk and meta kept.\n * A box in standby is unfrozen first, so the guest can actually act on the key.\n */\nasync function shutdown(meta: MachineMeta, cfg: Config, p: Paths, graceMs: number): Promise<void> {\n const pid = meta.pid;\n if (pidAlive(pid)) {\n const fc = new FirecrackerClient(p.machine(meta.owner, meta.name).sock);\n try {\n if (meta.paused) await fc.resume();\n await fc.sendCtrlAltDel();\n } catch {\n process.kill(pid!, \"SIGTERM\");\n } finally {\n await fc.close();\n }\n await waitDead(pid!, graceMs);\n }\n await cleanupProcess(meta, cfg, p);\n}\n\n/** Wait `graceMs` for the process to go, then SIGKILL it. */\nasync function waitDead(pid: number, graceMs: number): Promise<void> {\n if (!(await waitFor(() => !pidAlive(pid), graceMs, 100))) {\n killQuietly(pid);\n await waitFor(() => !pidAlive(pid), 1000, 50);\n }\n}\n\n/** After Firecracker is gone: the tap and the sockets it left behind. */\nasync function cleanupProcess(meta: MachineMeta, cfg: Config, p: Paths): Promise<void> {\n await deleteTap(meta.name, cfg);\n const m = p.machine(meta.owner, meta.name);\n await rm(m.sock, { force: true });\n await rm(m.vsock, { force: true });\n}\n\n/**\n * `kvbox stop`: clean shutdown, disk kept. A hibernated box has no process to shut down; its memory\n * dump is discarded instead, which for the guest is a power cut (files intact, what was in memory gone).\n */\nexport async function stopMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const m = p.machine(ref.owner, ref.name);\n if (!pidAlive(meta.pid) && !isHibernated(meta, p)) throw new KvboxError(`box ${shown(ref)} is already stopped`);\n await shutdown(meta, cfg, p, 10_000);\n await rm(m.hibernateDir, { recursive: true, force: true });\n // A stopped box boots from scratch next time, so its memory lineage (see state.ts memSnapshots) starts over.\n await rm(m.memBase, { force: true });\n const stopped: MachineMeta = { ...meta, pid: null, memSnapshots: undefined, paused: undefined };\n await writeMachineMeta(stopped, p);\n recordState(stopped, \"stopped\", \"stop\", p);\n return toMachine(stopped, p);\n}\n\nexport async function startMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n if (pidAlive(meta.pid)) throw new KvboxError(`box ${shown(ref)} is already ${meta.paused ? \"up, in standby (kvbox resume \" + shown(ref) + \")\" : \"running\"}`);\n if (isHibernated(meta, p)) {\n throw new KvboxError(`${stateMessage(ref, \"hibernated\")}: kvbox wake ${shown(ref)} continues where it left off; to boot fresh instead, kvbox stop ${shown(ref)} first (discards its memory)`);\n }\n assertAssets(cfg);\n const pubkeyB64 = await readPubkeyB64(p);\n await ensureHostNetwork(cfg);\n const tap = await createTap(ref.name, cfg);\n try {\n const pid = await launch(meta, tap, cfg, pubkeyB64, p);\n const started: MachineMeta = { ...meta, pid };\n await writeMachineMeta(started, p);\n recordState(started, \"running\", \"start\", p);\n return toMachine(started, p);\n } catch (err) {\n await deleteTap(ref.name, cfg).catch(() => undefined);\n throw err;\n }\n}\n\n/** `kvbox pause`: freeze the VM in place. Memory and processes stay, no CPU is used; `resume` is instant. */\nexport async function pauseMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const status = statusOf(meta, p);\n if (status === \"standby\") throw new KvboxError(`${stateMessage(ref, status)} already`);\n if (status === \"hibernated\") throw new KvboxError(`${stateMessage(ref, status)}; kvbox wake ${shown(ref)} brings it back`);\n if (status === \"stopped\") throw new KvboxError(`${stateMessage(ref, status)}; only a running box can be paused`);\n const fc = new FirecrackerClient(p.machine(ref.owner, ref.name).sock);\n try {\n await fc.pause();\n } finally {\n await fc.close();\n }\n const paused: MachineMeta = { ...meta, paused: true };\n await writeMachineMeta(paused, p);\n recordState(paused, \"standby\", \"pause\", p);\n return toMachine(paused, p);\n}\n\n/** `kvbox resume`: unfreeze a box in standby. */\nexport async function resumeMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const status = statusOf(meta, p);\n if (status === \"running\") throw new KvboxError(`${stateMessage(ref, status)} already`);\n if (status === \"hibernated\") throw new KvboxError(`${stateMessage(ref, status)}, not in standby; kvbox wake ${shown(ref)} brings it back`);\n if (status === \"stopped\") throw new KvboxError(`${stateMessage(ref, status)}, not in standby; kvbox start ${shown(ref)} boots it`);\n await resumeVm(p.machine(ref.owner, ref.name).sock);\n const running: MachineMeta = { ...meta, paused: undefined };\n await writeMachineMeta(running, p);\n recordState(running, \"running\", \"resume\", p);\n return toMachine(running, p);\n}\n\n/**\n * `kvbox hibernate`: write the VM's memory and state into the box's own dir, then end the Firecracker\n * process. The host gets the RAM back; `wake` loads the image into a new process and the guest carries\n * on from the same instant. A snapshot that is not named and not copied: the overlay stays where it is.\n * Works from running or standby. The dump is a full one (the box's diff lineage ends here; wake starts\n * a new one from this image), sparse once the untouched pages are punched out.\n */\nexport async function hibernateMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const status = statusOf(meta, p);\n if (status === \"hibernated\") throw new KvboxError(`${stateMessage(ref, status)} already`);\n if (status === \"stopped\") throw new KvboxError(`${stateMessage(ref, status)}; only a running box can be hibernated (there is no memory to keep)`);\n if (meta.base === undefined) throw new KvboxError(`box ${shown(ref)} was made before overlays and runs on its own disk copy; it cannot be hibernated`);\n const m = p.machine(ref.owner, ref.name);\n await rm(m.hibernateDir, { recursive: true, force: true });\n await mkdir(m.hibernateDir, { recursive: true, mode: 0o700 });\n const fc = new FirecrackerClient(m.sock);\n try {\n try {\n await fc.pause();\n await fc.snapshotCreate(m.hibernateVmstate, m.hibernateMem, \"Full\");\n } catch (err) {\n // Leave the box as it was: running, or in standby if it already was.\n await rm(m.hibernateDir, { recursive: true, force: true });\n if (!meta.paused) await fc.resume().catch(() => undefined);\n throw err;\n }\n } finally {\n await fc.close();\n }\n killQuietly(meta.pid!);\n await waitFor(() => !pidAlive(meta.pid), 5000, 50);\n await cleanupProcess(meta, cfg, p);\n // Pages the guest never touched are zeros in a full dump: punch them out so the image costs what was used.\n await run([\"fallocate\", \"--dig-holes\", m.hibernateMem]);\n await rm(m.memBase, { force: true });\n const hibernated: MachineMeta = { ...meta, pid: null, memSnapshots: undefined, paused: undefined };\n await writeMachineMeta(hibernated, p);\n recordState(hibernated, \"hibernated\", \"hibernate\", p);\n return toMachine(hibernated, p);\n}\n\n/**\n * `kvbox wake`: a hibernated box runs again from its memory image, same name, IP and MAC, so the guest\n * needs no new identity; kvbox-agent is still told, which is how its clock catches up on the time it\n * slept. The image becomes the box's memory lineage base (its next snapshot is a diff), like a box\n * restored from a snapshot. On failure the image is kept and the box stays hibernated.\n */\nexport async function wakeMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const status = statusOf(meta, p);\n if (status === \"running\" || status === \"standby\") throw new KvboxError(`${stateMessage(ref, status)}, not hibernated`);\n if (status === \"stopped\") throw new KvboxError(`${stateMessage(ref, status)}, not hibernated; kvbox start ${shown(ref)} boots it`);\n assertAssets(cfg);\n if (meta.base !== undefined && !existsSync(p.baseImage(meta.base))) {\n throw new KvboxError(`box ${shown(ref)} stacks on base image ${meta.base}, which is gone from ${p.assets}`);\n }\n const m = p.machine(ref.owner, ref.name);\n await ensureHostNetwork(cfg);\n const tap = await createTap(ref.name, cfg, { detached: true });\n let pid: number | undefined;\n try {\n const spec: LaunchSpec = { name: meta.name, owner: meta.owner, ip: meta.ip, mac: meta.mac, vcpu: meta.vcpu, memMib: meta.memMib, base: meta.base };\n pid = await loadSnapshot(spec, { vmstate: m.hibernateVmstate, mem: m.hibernateMem, label: `box ${shown(ref)}'s memory image` }, tap, cfg, p);\n await resumeVm(m.sock);\n await introduce(spec, m.vsock, cfg, {\n silent: `nothing answered on the box's control channel for 3 s; it stays hibernated, try kvbox wake ${shown(ref)} again`,\n noAnswer: `the box stays hibernated. kvbox-agent inside it took the request but gave no answer; try kvbox wake ${shown(ref)} again`,\n });\n await attachTap(ref.name, cfg);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n await deleteTap(ref.name, cfg).catch(() => undefined);\n throw err;\n }\n // The image is now the lineage base; the hibernate dir goes, the hard link keeps the data.\n await rm(m.memBase, { force: true });\n await link(m.hibernateMem, m.memBase);\n await rm(m.hibernateDir, { recursive: true, force: true });\n const running: MachineMeta = { ...meta, pid, memSnapshots: 1, paused: undefined };\n await writeMachineMeta(running, p);\n recordState(running, \"running\", \"wake\", p);\n return toMachine(running, p);\n}\n\n/**\n * Change a box's shape or base. Both only take effect at boot (Firecracker fixes vCPU and memory\n * when the VM starts, the base is stacked by overlay-init), so a running box is shut down and\n * started again; a stopped one just gets its meta updated. `whileStopped` runs in between, for\n * work that needs the disk unmounted. Returns the box, running again if it was.\n */\nasync function applyAtNextBoot(\n meta: MachineMeta,\n changes: Partial<MachineMeta>,\n by: \"rescale\" | \"update\",\n cfg: Config,\n p: Paths,\n whileStopped?: () => Promise<void>,\n): Promise<Machine> {\n const wasRunning = pidAlive(meta.pid);\n if (wasRunning) {\n await shutdown(meta, cfg, p, 10_000);\n await rm(p.machine(meta.owner, meta.name).memBase, { force: true });\n }\n const updated: MachineMeta = { ...meta, ...changes, pid: null, memSnapshots: undefined, paused: undefined };\n await writeMachineMeta(updated, p);\n if (whileStopped) await whileStopped();\n // The new shape is on this row (after the disk grew), so usage rates change from here on.\n recordState(updated, \"stopped\", by, p);\n return wasRunning ? startMachine(meta, p) : toMachine(updated, p);\n}\n\n/** A hibernated box's memory image fits its current shape and base; neither can change under it. */\nfunction assertNotHibernated(meta: MachineMeta, p: Paths): void {\n if (isHibernated(meta, p)) {\n throw new KvboxError(`${stateMessage(meta, \"hibernated\")}; its memory image was made with its current shape and base: kvbox wake ${shown(meta)} first`);\n }\n}\n\n/** `kvbox vm update <box>`: move the box onto the base image new boxes get. Its overlay (its own writes) stays. */\nexport async function updateMachine(ref: BoxRef, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n assertNotHibernated(meta, p);\n if (meta.base === undefined) {\n throw new KvboxError(`box ${shown(ref)} was made before overlays and runs on its own disk copy; it cannot be moved to another base image`);\n }\n assertAssets(cfg);\n const base = await currentBase(cfg, p);\n if (base.version === meta.base) return toMachine(meta, p);\n await assertOverlayCapable(base.file, base.version);\n return applyAtNextBoot(meta, { base: base.version }, \"update\", cfg, p);\n}\n\n/**\n * `kvbox vm rescale <box>`: new vCPU count, memory and/or disk. The disk can only grow: the overlay\n * file is extended and its ext4 resized while the box is down (e2fsck first, resize2fs refuses\n * a filesystem that was mounted since its last check).\n */\nexport async function rescaleMachine(ref: BoxRef, req: RescaleMachineRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n assertNotHibernated(meta, p);\n const disk = ownDisk(meta, p);\n const currentDiskGib = Math.round(statSync(disk).size / 1024 ** 3);\n const preset = req.size !== undefined && isSizeName(req.size) ? SIZES[req.size] : undefined;\n const target = {\n vcpu: req.vcpu ?? preset?.vcpu ?? meta.vcpu,\n memMib: req.memMib ?? preset?.memMib ?? meta.memMib,\n diskGib: req.diskGib ?? preset?.diskGib ?? currentDiskGib,\n };\n if (target.diskGib < currentDiskGib) {\n throw new KvboxError(`box ${shown(ref)} has a ${currentDiskGib} GB disk and a disk cannot shrink; ${target.diskGib} GB is smaller`);\n }\n const changes: Partial<MachineMeta> = {};\n if (target.vcpu !== meta.vcpu) changes.vcpu = target.vcpu;\n if (target.memMib !== meta.memMib) changes.memMib = target.memMib;\n const growTo = target.diskGib > currentDiskGib ? target.diskGib : undefined;\n if (Object.keys(changes).length === 0 && growTo === undefined) return toMachine(meta, p);\n return applyAtNextBoot(meta, changes, \"rescale\", cfg, p, growTo === undefined ? undefined : () => growDisk(disk, growTo));\n}\n\n/** Extend a box's (unmounted) ext4 disk file to `gib` GiB. */\nexport async function growDisk(file: string, gib: number): Promise<void> {\n await truncate(file, gib * 1024 ** 3);\n await run([\"e2fsck\", \"-f\", \"-p\", file], { okExitCodes: [1] });\n await run([\"resize2fs\", file]);\n}\n\nasync function readMeta(ref: BoxRef, p: Paths): Promise<MachineMeta> {\n try {\n return await readMachineMeta(ref, p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") throw new NotFoundError(`box ${shown(ref)}`);\n throw err;\n }\n}\n\nexport async function destroyMachine(ref: BoxRef, p: Paths = paths()): Promise<void> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n await shutdown(meta, cfg, p, 2000);\n // The ledger keeps the box's history after it is gone: a final row, while the disk is still there to measure.\n recordState(meta, \"stopped\", \"rm\", p);\n await rm(p.machine(ref.owner, ref.name).dir, { recursive: true, force: true });\n}\n","/**\n * Client for kvbox-agent, the small service every box runs (kvbox-images, /usr/local/sbin/kvbox-agent).\n * It listens on a vsock port, and Firecracker exposes that as a Unix socket next to the box's API\n * socket: connect, send `CONNECT <port>\\n`, get `OK <n>\\n` back once the guest accepted, then the\n * stream is the guest's. The agent speaks one JSON object per line, one request per connection.\n * Vsock does not touch the box's network, so this works whatever the box did to its own eth0.\n */\nimport { connect } from \"node:net\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\n/** The vsock port kvbox-agent listens on; fixed in the image. */\nexport const AGENT_PORT = 52;\n\nexport interface Identity {\n name: string;\n ip: string;\n prefixLen: number;\n gateway: string;\n mac: string;\n /** Unix seconds for the guest's clock, which stopped at the snapshot. */\n time: number;\n}\n\ntype AgentReply = { ok: true; [k: string]: unknown } | { ok: false; error: string };\n\n/** One request/reply exchange with the agent behind `udsPath`. Rejects on connection errors, timeout or `ok: false`. */\nexport async function agentCall(udsPath: string, req: Record<string, unknown>, timeoutMs = 5000): Promise<Record<string, unknown>> {\n const reply = await new Promise<string>((resolve, reject) => {\n const sock = connect(udsPath);\n let buf = \"\";\n let handshaken = false;\n const fail = (err: Error) => {\n sock.destroy();\n reject(err);\n };\n sock.setTimeout(timeoutMs, () => fail(new KvboxError(`kvbox-agent did not answer within ${timeoutMs} ms`)));\n sock.once(\"error\", (err) => fail(new KvboxError(`kvbox-agent unreachable: ${err.message}`)));\n sock.once(\"connect\", () => sock.write(`CONNECT ${AGENT_PORT}\\n`));\n sock.on(\"data\", (chunk) => {\n buf += chunk.toString(\"utf8\");\n let nl: number;\n while ((nl = buf.indexOf(\"\\n\")) !== -1) {\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + 1);\n if (!handshaken) {\n if (!line.startsWith(\"OK \")) return fail(new KvboxError(`vsock connect refused: ${line}`));\n handshaken = true;\n sock.write(JSON.stringify(req) + \"\\n\");\n } else {\n sock.end();\n return resolve(line);\n }\n }\n });\n sock.once(\"close\", () => {\n if (!handshaken) fail(new KvboxError(\"vsock connection closed before the guest accepted\"));\n else fail(new KvboxError(\"kvbox-agent closed the connection without a reply\"));\n });\n });\n let parsed: AgentReply;\n try {\n parsed = JSON.parse(reply) as AgentReply;\n } catch {\n throw new KvboxError(`kvbox-agent sent something that is not JSON: ${reply}`);\n }\n if (!parsed.ok) throw new KvboxError(`kvbox-agent: ${parsed.error}`);\n return parsed;\n}\n\nexport function ping(udsPath: string, timeoutMs?: number) {\n return agentCall(udsPath, { op: \"ping\" }, timeoutMs);\n}\n\n/** Tell a restored box who it is now; it renames itself, re-addresses eth0 and sets its clock. */\nexport function setIdentity(udsPath: string, id: Identity, timeoutMs?: number) {\n return agentCall(udsPath, { op: \"identity\", ...id }, timeoutMs);\n}\n","/**\n * The capacity guard. Firecracker reserves neither RAM nor cores on the host, so without a rule\n * of our own the kernel's OOM-killer is what ends an over-full host: a Firecracker process dies\n * and a box vanishes without a trace. Before a box is started, `kvbox new` adds it to what the\n * running boxes already reserve (their sizes, not what they touch right now) and refuses when\n * memory: reserved + new > host RAM - 2 GB (hard: the host needs room of its own), or\n * vCPU: reserved + new > 2 x host cores (soft: vCPUs time-slice fine, this stops the absurd).\n * `--force` skips both. Decision \"`zbox new` guards host capacity\".\n */\nimport { cpus, totalmem } from \"node:os\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { Capacity } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { listMachineRefs, pidAlive, readMachineMeta } from \"./state.js\";\n\nexport const MEM_HEADROOM_MIB = 2048;\nexport const VCPU_OVERSUBSCRIPTION = 2;\n\nexport interface Host {\n memMib: number;\n cores: number;\n}\nexport interface Reservation {\n name: string;\n vcpu: number;\n memMib: number;\n}\n\nexport function hostResources(): Host {\n return { memMib: Math.floor(totalmem() / 1024 ** 2), cores: cpus().length };\n}\n\n/** The sizes of every box whose Firecracker process is alive; a dead pid reserves nothing. */\nexport async function runningReservations(p: Paths = paths()): Promise<Reservation[]> {\n const out: Reservation[] = [];\n for (const ref of await listMachineRefs(p)) {\n try {\n const meta = await readMachineMeta(ref, p);\n if (pidAlive(meta.pid)) out.push({ name: meta.name, vcpu: meta.vcpu, memMib: meta.memMib });\n } catch {\n // unreadable meta: not a running box we can account for\n }\n }\n return out;\n}\n\nexport async function capacity(p: Paths = paths()): Promise<Capacity> {\n const host = hostResources();\n const running = await runningReservations(p);\n return {\n hostMemMib: host.memMib,\n hostCores: host.cores,\n reservedMemMib: running.reduce((n, r) => n + r.memMib, 0),\n reservedVcpu: running.reduce((n, r) => n + r.vcpu, 0),\n running: running.length,\n };\n}\n\nfunction gb(mib: number): string {\n const g = mib / 1024;\n return `${Number.isInteger(g) ? g : g.toFixed(1)} GB`;\n}\n\nfunction describeRunning(running: Reservation[]): string {\n if (running.length === 0) return \"no box is running\";\n const list = running.map((r) => `${r.name} ${r.vcpu} vCPU/${gb(r.memMib)}`).join(\", \");\n const vcpu = running.reduce((n, r) => n + r.vcpu, 0);\n const mem = running.reduce((n, r) => n + r.memMib, 0);\n return `${running.length} running ${running.length === 1 ? \"box reserves\" : \"boxes reserve\"} ${vcpu} vCPU and ${gb(mem)} (${list})`;\n}\n\n/**\n * Why a box of `want` cannot start on `host` next to `running`, or undefined when it can.\n * Pure, so the rule is testable without a host.\n */\nexport function roomFor(host: Host, running: Reservation[], want: { vcpu: number; memMib: number }): string | undefined {\n const reservedMem = running.reduce((n, r) => n + r.memMib, 0);\n const reservedVcpu = running.reduce((n, r) => n + r.vcpu, 0);\n const memLimit = host.memMib - MEM_HEADROOM_MIB;\n const vcpuLimit = host.cores * VCPU_OVERSUBSCRIPTION;\n const hint = \"stop or remove a box (kvbox stop, kvbox rm), pick a smaller --size, or pass --force to start it anyway\";\n if (reservedMem + want.memMib > memLimit) {\n return (\n `not enough memory for a ${gb(want.memMib)} box: ${describeRunning(running)}; ` +\n `this host has ${gb(host.memMib)} and keeps ${gb(MEM_HEADROOM_MIB)} for itself, so boxes may reserve ${gb(memLimit)} in total. ` +\n hint\n );\n }\n if (reservedVcpu + want.vcpu > vcpuLimit) {\n return (\n `too many vCPUs for a ${want.vcpu} vCPU box: ${describeRunning(running)}; ` +\n `this host has ${host.cores} cores and allows ${vcpuLimit} vCPUs in total (${VCPU_OVERSUBSCRIPTION}x). ` +\n hint\n );\n }\n return undefined;\n}\n\n/** Throws (HTTP 400, exit 1) when the host cannot take another box of this size; `force` skips the check. */\nexport async function assertRoomFor(vcpu: number, memMib: number, force: boolean, p: Paths = paths()): Promise<void> {\n if (force) return;\n const reason = roomFor(hostResources(), await runningReservations(p), { vcpu, memMib });\n if (reason !== undefined) throw new KvboxError(reason);\n}\n","/**\n * Client for one Firecracker process's API socket. Ten-odd endpoints, all\n * PUT/PATCH with JSON bodies, so a thin wrapper over undici beats an SDK.\n */\nimport { Agent, request } from \"undici\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nexport class FirecrackerClient {\n private readonly agent: Agent;\n\n constructor(readonly socketPath: string) {\n this.agent = new Agent({ connect: { socketPath } });\n }\n\n private async call(method: \"GET\" | \"PUT\" | \"PATCH\", path: string, body?: unknown): Promise<unknown> {\n const res = await request(`http://localhost${path}`, {\n dispatcher: this.agent,\n method,\n headers: body === undefined ? {} : { \"content-type\": \"application/json\" },\n body: body === undefined ? null : JSON.stringify(body),\n });\n const text = await res.body.text();\n if (res.statusCode >= 300) {\n throw new KvboxError(`firecracker ${method} ${path} -> ${res.statusCode}: ${text}`);\n }\n return text ? JSON.parse(text) : undefined;\n }\n\n bootSource(kernelImagePath: string, bootArgs: string) {\n return this.call(\"PUT\", \"/boot-source\", { kernel_image_path: kernelImagePath, boot_args: bootArgs });\n }\n\n /**\n * /dev/vda. Firecracker adds `root=/dev/vda` plus `ro` or `rw` to the boot args to match.\n * Read-only for the shared base image; read-write only for pre-overlay boxes with their own copy.\n */\n rootDrive(pathOnHost: string, readOnly: boolean) {\n return this.drive(\"rootfs\", pathOnHost, { root: true, readOnly });\n }\n\n /** The box's own writable disk, /dev/vdb: the guest stacks it on the base as an overlay. */\n overlayDrive(pathOnHost: string) {\n return this.drive(\"overlay\", pathOnHost, { root: false, readOnly: false });\n }\n\n private drive(id: string, pathOnHost: string, opts: { root: boolean; readOnly: boolean }) {\n return this.call(\"PUT\", `/drives/${id}`, {\n drive_id: id,\n path_on_host: pathOnHost,\n is_root_device: opts.root,\n is_read_only: opts.readOnly,\n // \"Unsafe\" (the default) acks guest flushes without doing anything, so the last journal\n // commit of a clean shutdown can be lost when the guest resets and Firecracker exits.\n // Writeback makes a guest flush a real fsync; a box's writes must survive `kvbox stop`.\n cache_type: \"Writeback\",\n });\n }\n\n /** Swap the file behind a drive while the VM runs or is paused; the guest is told the config changed. */\n patchDrivePath(id: string, pathOnHost: string) {\n return this.call(\"PATCH\", `/drives/${id}`, { drive_id: id, path_on_host: pathOnHost });\n }\n\n /**\n * The host's control channel into the box: Firecracker listens on `udsPath`, a connection there\n * followed by `CONNECT <port>\\n` reaches whatever listens on that vsock port in the guest (kvbox-agent).\n */\n vsock(guestCid: number, udsPath: string) {\n return this.call(\"PUT\", \"/vsock\", { guest_cid: guestCid, uds_path: udsPath });\n }\n\n machineConfig(vcpuCount: number, memSizeMib: number) {\n // Dirty page tracking lets a snapshot write only the pages the guest touched since the last one\n // (a \"Diff\" snapshot) instead of dumping all of guest memory: sub-second instead of ~10 s frozen.\n return this.call(\"PUT\", \"/machine-config\", { vcpu_count: vcpuCount, mem_size_mib: memSizeMib, track_dirty_pages: true });\n }\n\n networkInterface(ifaceId: string, hostDevName: string, guestMac: string) {\n return this.call(\"PUT\", `/network-interfaces/${ifaceId}`, {\n iface_id: ifaceId,\n host_dev_name: hostDevName,\n guest_mac: guestMac,\n });\n }\n\n start() {\n return this.call(\"PUT\", \"/actions\", { action_type: \"InstanceStart\" });\n }\n\n /** Ask the guest to shut down cleanly (systemd handles Ctrl+Alt+Del as poweroff on Firecracker). */\n sendCtrlAltDel() {\n return this.call(\"PUT\", \"/actions\", { action_type: \"SendCtrlAltDel\" });\n }\n\n pause() {\n return this.call(\"PATCH\", \"/vm\", { state: \"Paused\" });\n }\n\n resume() {\n return this.call(\"PATCH\", \"/vm\", { state: \"Resumed\" });\n }\n\n /** `track_dirty_pages` is what matters: a box from an older server runs without it. */\n async machineConfigInfo(): Promise<{ vcpu_count: number; mem_size_mib: number; track_dirty_pages: boolean }> {\n return (await this.call(\"GET\", \"/machine-config\")) as { vcpu_count: number; mem_size_mib: number; track_dirty_pages: boolean };\n }\n\n /**\n * Full: all of guest memory, dense (seconds for a 4 GB box). Diff: only pages dirtied since the last\n * snapshot (or since boot), written sparse; needs dirty page tracking and resets its bitmap.\n */\n snapshotCreate(snapshotPath: string, memFilePath: string, type: \"Full\" | \"Diff\" = \"Full\") {\n return this.call(\"PUT\", \"/snapshot/create\", {\n snapshot_type: type,\n snapshot_path: snapshotPath,\n mem_file_path: memFilePath,\n });\n }\n\n /**\n * Restore a snapshot into this (fresh) process. The memory file is mapped privately: the guest's\n * writes never reach the snapshot. The vmstate carries the source box's tap and vsock paths; the\n * overrides point them at this box's. Drive paths are not overridable here: see patchDrivePath.\n */\n snapshotLoad(opts: {\n snapshotPath: string;\n memFilePath: string;\n tap: { ifaceId: string; hostDevName: string };\n vsockPath: string;\n /** Required for diff snapshots later: the flag is not part of the vmstate. */\n trackDirtyPages: boolean;\n resume: boolean;\n }) {\n return this.call(\"PUT\", \"/snapshot/load\", {\n snapshot_path: opts.snapshotPath,\n mem_backend: { backend_type: \"File\", backend_path: opts.memFilePath },\n network_overrides: [{ iface_id: opts.tap.ifaceId, host_dev_name: opts.tap.hostDevName }],\n vsock_override: { uds_path: opts.vsockPath },\n track_dirty_pages: opts.trackDirtyPages,\n resume_vm: opts.resume,\n });\n }\n\n info() {\n return this.call(\"GET\", \"/\");\n }\n\n async close() {\n await this.agent.close();\n }\n}\n","/**\n * `kvbox vm usage <box>`: what the usage_events ledger (db.ts) adds up to over a window.\n * `computeUsage` is pure over the rows; `machineUsage` reads the box and the ledger around it.\n */\nimport type { MachineUsage } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { loadConfig, type Pricing } from \"./config.js\";\nimport { insertUsageEvent, usageEventsFor, type UsageEvent, type UsageState } from \"./db.js\";\nimport { getMachine, listMachines } from \"./machines.js\";\nimport { refKey, type BoxRef } from \"./refs.js\";\n\nexport type { UsageEvent, UsageState };\n\nexport interface UsageWindow {\n from: string;\n to: string;\n pricing?: Pricing | undefined;\n}\n\nexport type UsageTotals = Pick<MachineUsage, \"seconds\" | \"vcpuHours\" | \"ramGibHours\" | \"diskGibHours\" | \"cost\" | \"estimatedStops\" | \"historyFrom\">;\n\nconst HOUR_MS = 3_600_000;\nconst round = (n: number, places: number) => Math.round(n * 10 ** places) / 10 ** places;\n\n/**\n * Each event opens an interval that lasts until the next one (or `to`); intervals are clipped to the\n * window, so the event before `from` supplies the state the window starts in. Time before the first\n * event belongs to no state: it was never recorded. Running hours earn vCPU and RAM; standby hours\n * earn RAM (the memory is still held) but no vCPU; every hour the box exists earns disk (its overlay\n * is there while it is hibernated or stopped too). A repeated state continues it.\n */\nexport function computeUsage(events: readonly UsageEvent[], w: UsageWindow): UsageTotals {\n const sorted = [...events].sort((a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : 0));\n const from = Date.parse(w.from);\n const to = Date.parse(w.to);\n const ms: Record<UsageState, number> = { running: 0, standby: 0, hibernated: 0, stopped: 0 };\n let vcpuHours = 0;\n let ramGibHours = 0;\n let diskGibHours = 0;\n sorted.forEach((e, i) => {\n const start = Math.max(Date.parse(e.at), from);\n const next = sorted[i + 1];\n const end = Math.min(next === undefined ? to : Date.parse(next.at), to);\n if (end <= start) return;\n const h = (end - start) / HOUR_MS;\n ms[e.state] += end - start;\n if (e.state === \"running\") vcpuHours += h * e.vcpu;\n if (e.state === \"running\" || e.state === \"standby\") ramGibHours += (h * e.memMib) / 1024;\n diskGibHours += h * e.diskGib;\n });\n const totals: UsageTotals = {\n seconds: {\n running: Math.round(ms.running / 1000),\n standby: Math.round(ms.standby / 1000),\n hibernated: Math.round(ms.hibernated / 1000),\n stopped: Math.round(ms.stopped / 1000),\n },\n vcpuHours: round(vcpuHours, 3),\n ramGibHours: round(ramGibHours, 3),\n diskGibHours: round(diskGibHours, 3),\n estimatedStops: sorted.filter((e) => e.state === \"stopped\" && e.by === \"server\" && e.at >= w.from).length,\n historyFrom: sorted[0]?.at ?? null,\n };\n if (w.pricing !== undefined) {\n const amount = vcpuHours * w.pricing.vcpuHour + ramGibHours * w.pricing.ramGibHour + diskGibHours * w.pricing.diskGibHour;\n totals.cost = { amount: round(amount, 4), currency: w.pricing.currency };\n }\n return totals;\n}\n\nconst GIB = 1024 ** 3;\n\n/**\n * Usage of one box from its creation (or `since`, already an ISO string) until now. Reading the box\n * (getMachine) also closes the run of a box whose Firecracker died, so the ledger is current before\n * it is summed. A box with no rows since its creation predates the ledger: its history starts now,\n * in whatever state it is in, and `historyFrom` says so.\n */\nexport async function machineUsage(ref: BoxRef, since: string | undefined, p: Paths = paths()): Promise<MachineUsage> {\n const box = await getMachine(ref, p);\n const cfg = await loadConfig(p);\n const now = new Date().toISOString();\n const boxId = refKey(ref);\n let events = usageEventsFor(boxId, box.createdAt, p);\n if (events.length === 0) {\n insertUsageEvent(\n { boxId, owner: box.owner, name: box.name, at: now, state: box.status, by: \"upgrade\", vcpu: box.vcpu, memMib: box.memMib, diskGib: Math.round(box.diskBytes / GIB) },\n p,\n );\n events = usageEventsFor(boxId, box.createdAt, p);\n }\n const window = { from: since ?? box.createdAt, to: now };\n return { name: box.name, owner: box.owner, status: box.status, window, ...computeUsage(events, { ...window, pricing: cfg.pricing }) };\n}\n\n/**\n * Run at server start: every box the ledger has never heard of gets its first row now, in its current\n * state, so the history of boxes made before this server version begins at the upgrade rather than at\n * their first `usage` call. Returns how many were seeded.\n */\nexport async function seedUsageLedger(p: Paths = paths()): Promise<number> {\n let seeded = 0;\n for (const box of await listMachines(null, p)) {\n const boxId = `${box.owner}/${box.name}`;\n if (usageEventsFor(boxId, box.createdAt, p).length > 0) continue;\n insertUsageEvent(\n { boxId, owner: box.owner, name: box.name, at: new Date().toISOString(), state: box.status, by: \"upgrade\", vcpu: box.vcpu, memMib: box.memMib, diskGib: Math.round(box.diskBytes / GIB) },\n p,\n );\n seeded += 1;\n }\n return seeded;\n}\n","/**\n * The hono app behind `kvbox-server`. Served over `~/.kvbox/server.sock`\n * in M1; the same app goes behind HTTPS in M2.\n */\nimport { Hono } from \"hono\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport { VERSION } from \"./version.js\";\nimport { resolveCaller, type Env } from \"./caller.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { currentBaseVersion } from \"./core/machines.js\";\nimport { capacityRoutes } from \"./routes/capacity.js\";\nimport { machineRoutes } from \"./routes/machines.js\";\nimport { snapshotRoutes } from \"./routes/snapshots.js\";\n\nexport function createApp() {\n const app = new Hono<Env>();\n app.use(resolveCaller());\n\n app.get(\"/health\", async (c) =>\n c.json({\n ok: true as const,\n version: VERSION,\n pid: process.pid,\n base: await currentBaseVersion().catch(() => null),\n owner: (await loadConfig()).owner,\n }),\n );\n app.route(\"/machines\", machineRoutes());\n app.route(\"/snapshots\", snapshotRoutes());\n app.route(\"/capacity\", capacityRoutes());\n\n app.notFound((c) => c.json({ error: `no route: ${c.req.method} ${c.req.path}` }, 404));\n app.onError((err, c) => {\n if (err instanceof NotFoundError) return c.json({ error: err.message }, 404);\n if (err instanceof KvboxError) {\n return c.json({ error: err.message }, err.exitCode === 2 ? 501 : 400);\n }\n console.error(err);\n return c.json({ error: err.message }, 500);\n });\n\n return app;\n}\n\nexport type App = ReturnType<typeof createApp>;\n","/**\n * Each binary's version comes from its own package.json: tsup injects\n * `__KVBOX_VERSION__` at build time; the dev path (tsx) reads the file.\n * Usage in a package: `versionOf(import.meta.url)` from its `src/version.ts`.\n */\nimport { createRequire } from \"node:module\";\n\nexport function versionOf(srcFileUrl: string, injected?: string): string {\n if (typeof injected === \"string\") return injected;\n try {\n const require = createRequire(srcFileUrl);\n return (require(\"../package.json\") as { version: string }).version;\n } catch {\n return \"0.0.0-dev\";\n }\n}\n","import { versionOf } from \"@kvbox/shared/version\";\n\ndeclare const __KVBOX_VERSION__: string | undefined;\n\nexport const VERSION: string = versionOf(import.meta.url, typeof __KVBOX_VERSION__ === \"string\" ? __KVBOX_VERSION__ : undefined);\n","/**\n * Who is calling. Every request carries an `owner` the routes file boxes under and scope listings\n * to. Today there is one caller: the host owner over the local Unix socket, which is the server's\n * configured `owner` (the Unix user running it). The control plane (#18) adds the other branch:\n * an HTTPS caller whose owner is `<user>@<control plane>`, qualified here and nowhere else.\n */\nimport type { MiddlewareHandler } from \"hono\";\nimport { loadConfig } from \"./core/config.js\";\n\nexport type Env = { Variables: { owner: string } };\n\nexport function resolveCaller(): MiddlewareHandler<Env> {\n return async (c, next) => {\n const cfg = await loadConfig();\n c.set(\"owner\", cfg.owner);\n await next();\n };\n}\n","import { Hono } from \"hono\";\nimport { capacity } from \"../core/capacity.js\";\n\nexport function capacityRoutes() {\n const r = new Hono();\n r.get(\"/\", async (c) => c.json(await capacity()));\n return r;\n}\n","import { Hono } from \"hono\";\nimport { CreateMachineRequest, RescaleMachineRequest } from \"@kvbox/shared/api\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport {\n createMachine,\n destroyMachine,\n hibernateMachine,\n listMachines,\n pauseMachine,\n rescaleMachine,\n resumeMachine,\n startMachine,\n stopMachine,\n updateMachine,\n wakeMachine,\n} from \"../core/machines.js\";\nimport { parseRef } from \"../core/refs.js\";\nimport { machineUsage } from \"../core/usage.js\";\nimport type { Env } from \"../caller.js\";\n\nexport function machineRoutes() {\n const r = new Hono<Env>();\n r.get(\"/\", async (c) => c.json(await listMachines(c.get(\"owner\"))));\n r.post(\"/\", async (c) => {\n const body = CreateMachineRequest.parse(await c.req.json().catch(() => ({})));\n return c.json(await createMachine(body, c.get(\"owner\")), 201);\n });\n r.post(\"/:name/stop\", async (c) => c.json(await stopMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/start\", async (c) => c.json(await startMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/pause\", async (c) => c.json(await pauseMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/resume\", async (c) => c.json(await resumeMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/hibernate\", async (c) => c.json(await hibernateMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/wake\", async (c) => c.json(await wakeMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/update\", async (c) => c.json(await updateMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\n r.post(\"/:name/rescale\", async (c) => {\n const body = RescaleMachineRequest.parse(await c.req.json().catch(() => ({})));\n return c.json(await rescaleMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body));\n });\n r.get(\"/:name/usage\", async (c) => {\n const since = c.req.query(\"since\");\n let from: string | undefined;\n if (since !== undefined) {\n const t = Date.parse(since);\n if (Number.isNaN(t)) throw new KvboxError(`since: \"${since}\" is not a date; write it like 2026-10-19 or 2026-10-19T08:00:00Z`);\n from = new Date(t).toISOString();\n }\n return c.json(await machineUsage(parseRef(c.req.param(\"name\"), c.get(\"owner\")), from));\n });\n r.delete(\"/:name\", async (c) => {\n await destroyMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")));\n return c.body(null, 204);\n });\n return r;\n}\n","/**\n * Wire shapes of the kvbox HTTP API, shared by the client (src/cli) and the\n * server (src/server). Validated with zod on both sides because the client\n * may be talking to an older or newer server.\n */\nimport { z } from \"zod\";\nimport { SIZE_NAMES } from \"./sizes.js\";\n\nexport const SizeSchema = z.enum(SIZE_NAMES as [string, ...string[]]);\n\n/**\n * A box's state. `running`: Firecracker up, guest executing. `standby`: Firecracker up but frozen (kvbox\n * pause): memory and processes kept, no CPU. `hibernated`: no process; memory dumped to the box's dir\n * (kvbox hibernate), wake continues where it left off. `stopped`: no process, memory gone, next start boots.\n */\nexport const BoxStatusSchema = z.enum([\"running\", \"standby\", \"hibernated\", \"stopped\"]);\nexport type BoxStatus = z.infer<typeof BoxStatusSchema>;\n\nexport const MachineSchema = z.object({\n name: z.string(),\n /** Who the box belongs to; names are unique per owner. A bare name is local to the host, `user@control-plane` later. */\n owner: z.string(),\n ip: z.string(),\n mac: z.string(),\n pid: z.number().int().nullable(),\n vcpu: z.number().int(),\n memMib: z.number().int(),\n diskBytes: z.number().int(), // the box's own writable disk, as the guest sees it\n diskUsedBytes: z.number().int(), // what that sparse file really occupies on the host\n base: z.string().nullable(), // base image version the box runs on (null: pre-overlay box with its own copy)\n createdAt: z.string(),\n source: z.string(), // \"base\" or \"snapshot:<name>\"\n status: BoxStatusSchema,\n});\nexport type Machine = z.infer<typeof MachineSchema>;\n\nexport const CreateMachineRequest = z.object({\n name: z.string().optional(),\n /** Ignored over the local socket (the caller is the host owner); the control plane sets it over HTTPS. */\n owner: z.string().optional(),\n size: SizeSchema.optional(),\n from: z.string().optional(),\n force: z.boolean().optional(),\n});\nexport type CreateMachineRequest = z.infer<typeof CreateMachineRequest>;\n\n/** `kvbox vm rescale`: a preset and/or explicit values; explicit ones win. Anything omitted stays as it is. */\nexport const RescaleMachineRequest = z.object({\n size: SizeSchema.optional(),\n vcpu: z.number().int().min(1).max(64).optional(),\n memMib: z.number().int().min(256).optional(),\n diskGib: z.number().int().min(1).optional(),\n});\nexport type RescaleMachineRequest = z.infer<typeof RescaleMachineRequest>;\n\nexport const SnapshotSchema = z.object({\n name: z.string(),\n owner: z.string(),\n source: z.string(), // the box it was taken from, as owner/name\n base: z.string(), // base image version the overlay stacks on; a restore needs the same one\n vcpu: z.number().int(),\n memMib: z.number().int(),\n sizeBytes: z.number().int(), // what vmstate + mem + overlay really occupy on the host\n createdAt: z.string(),\n});\nexport type Snapshot = z.infer<typeof SnapshotSchema>;\n\nexport const CreateSnapshotRequest = z.object({\n box: z.string(),\n name: z.string(),\n});\nexport type CreateSnapshotRequest = z.infer<typeof CreateSnapshotRequest>;\n\nexport const CapacitySchema = z.object({\n hostMemMib: z.number().int(),\n hostCores: z.number().int(),\n reservedMemMib: z.number().int(),\n reservedVcpu: z.number().int(),\n running: z.number().int(),\n});\nexport type Capacity = z.infer<typeof CapacitySchema>;\n\nexport const HealthSchema = z.object({\n ok: z.literal(true),\n version: z.string(),\n pid: z.number().int(),\n /** Base image version new boxes get (null when the host has no usable base image yet); absent from older servers. */\n base: z.string().nullable().optional(),\n /** Owner that boxes made over the local socket get (the Unix user running the server); absent from older servers. */\n owner: z.string().optional(),\n});\nexport type Health = z.infer<typeof HealthSchema>;\n\n/**\n * `kvbox vm usage <box>`: how long the box spent in each state over a window and what that adds up\n * to. Hours are fractional; the CLI rounds. `cost` is present only when the host prices usage.\n * `historyFrom` is the first recorded moment: later than `window.from` for a box older than the\n * ledger, null when nothing is recorded (never for a box the server knows).\n */\nexport const MachineUsageSchema = z.object({\n name: z.string(),\n owner: z.string(),\n status: BoxStatusSchema,\n window: z.object({ from: z.string(), to: z.string() }),\n /** standby and hibernated default to 0 so a newer CLI reads an older server's answer. */\n seconds: z.object({\n running: z.number().int(),\n standby: z.number().int().default(0),\n hibernated: z.number().int().default(0),\n stopped: z.number().int(),\n }),\n vcpuHours: z.number(),\n ramGibHours: z.number(),\n diskGibHours: z.number(),\n cost: z.object({ amount: z.number(), currency: z.string() }).optional(),\n /** Stops the server did not witness (Firecracker died, host rebooted) and dated to when it noticed. */\n estimatedStops: z.number().int(),\n historyFrom: z.string().nullable(),\n});\nexport type MachineUsage = z.infer<typeof MachineUsageSchema>;\n\nexport const ApiErrorSchema = z.object({\n error: z.string(),\n});\n","import { Hono } from \"hono\";\nimport { CreateSnapshotRequest } from \"@kvbox/shared/api\";\nimport { deleteSnapshot, listSnapshots, saveSnapshot } from \"../core/snapshots.js\";\nimport { parseRef } from \"../core/refs.js\";\nimport type { Env } from \"../caller.js\";\n\nexport function snapshotRoutes() {\n const r = new Hono<Env>();\n r.get(\"/\", async (c) => c.json(await listSnapshots(c.get(\"owner\"))));\n r.post(\"/\", async (c) => {\n const body = CreateSnapshotRequest.parse(await c.req.json());\n return c.json(await saveSnapshot(body, c.get(\"owner\")), 201);\n });\n r.delete(\"/:name\", async (c) => {\n await deleteSnapshot(parseRef(c.req.param(\"name\"), c.get(\"owner\")));\n return c.body(null, 204);\n });\n return r;\n}\n","/**\n * Snapshots: a running box frozen into `snapshots/<name>/` as vmstate + mem (a complete memory image)\n * + a copy of the box's overlay. The base image is referenced by version, not copied, so a snapshot costs\n * what the guest touched (memory pages + overlay blocks), not the box's size.\n *\n * Memory is captured incrementally. Boxes run with dirty page tracking, so Firecracker can write only\n * the pages dirtied since the last snapshot (a \"Diff\": sub-second, sparse) instead of dumping all of\n * guest memory (~10 s frozen for 4 GB). A diff is only a complete image when merged onto the previous\n * one, so each box keeps `mem.base`, a hard link to its last snapshot's `mem`, and the merge happens\n * after the box is already running again. See state.ts `memSnapshots` for the bookkeeping.\n */\nimport { existsSync } from \"node:fs\";\nimport { link, mkdir, readdir, rename, rm, stat } from \"node:fs/promises\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport type { CreateSnapshotRequest, Snapshot } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { loadConfig } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { FirecrackerClient } from \"./firecracker.js\";\nimport { parseRef, refKey, shown, type BoxRef } from \"./refs.js\";\nimport {\n listSnapshotRefs,\n pidAlive,\n readMachineMeta,\n readSnapshotMeta,\n writeMachineMeta,\n writeSnapshotMeta,\n type MachineMeta,\n type SnapshotMeta,\n} from \"./state.js\";\n\n/** Snapshot names are directory names shown in tables: letters, digits, dots, dashes, underscores. */\nconst NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/;\n\nfunction toSnapshot(meta: SnapshotMeta): Snapshot {\n return {\n name: meta.name,\n owner: meta.owner,\n source: meta.source,\n base: meta.base,\n vcpu: meta.vcpu,\n memMib: meta.memMib,\n sizeBytes: meta.sizeBytes,\n createdAt: meta.createdAt,\n };\n}\n\n/** One owner's snapshots, or every snapshot on the host when `owner` is null. */\nexport async function listSnapshots(owner: string | null, p: Paths = paths()): Promise<Snapshot[]> {\n const out: Snapshot[] = [];\n for (const ref of await listSnapshotRefs(p)) {\n if (owner !== null && ref.owner !== owner) continue;\n try {\n out.push(toSnapshot(await readSnapshotMeta(ref, p)));\n } catch (err) {\n console.error(`warning: skipping snapshots/${refKey(ref)}: ${(err as Error).message}`);\n }\n }\n return out;\n}\n\n/** Bytes the snapshot really occupies: its files are sparse, so allocated blocks, not sizes. */\nasync function usedBytes(dir: string): Promise<number> {\n let total = 0;\n for (const entry of await readdir(dir)) {\n total += (await stat(`${dir}/${entry}`)).blocks * 512;\n }\n return total;\n}\n\nasync function readBox(ref: BoxRef, p: Paths): Promise<MachineMeta> {\n try {\n return await readMachineMeta(ref, p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") throw new NotFoundError(`box ${shown(ref)}`);\n throw err;\n }\n}\n\n/** The snapshot belongs to `owner` (the caller); `req.box` may name another owner's box as owner/name. */\nexport async function saveSnapshot(req: CreateSnapshotRequest, owner: string, p: Paths = paths()): Promise<Snapshot> {\n if (!NAME_RE.test(req.name)) {\n throw new KvboxError(`invalid snapshot name \"${req.name}\": 1-64 chars, lowercase letters, digits, '.', '_' and '-', starting with a letter or digit`);\n }\n const box = await readBox(parseRef(req.box, owner), p);\n if (box.base === undefined) {\n throw new KvboxError(`box ${req.box} was made before overlays and runs on its own disk copy; snapshots need a box made by this version of kvbox (kvbox new)`);\n }\n if (!pidAlive(box.pid)) {\n if (existsSync(p.machine(box.owner, box.name).hibernateVmstate)) {\n throw new KvboxError(`box ${req.box} is hibernated; a snapshot freezes a running box (kvbox wake ${req.box} first)`);\n }\n throw new KvboxError(`box ${req.box} is not running; a snapshot freezes a running box (kvbox start ${req.box} first)`);\n }\n const s = p.snapshot(owner, req.name);\n if (existsSync(s.dir)) throw new KvboxError(`snapshot ${req.name} already exists`);\n const cfg = await loadConfig(p);\n const m = p.machine(box.owner, box.name);\n\n await mkdir(s.dir, { recursive: true, mode: 0o700 });\n const fc = new FirecrackerClient(m.sock);\n let lineageTouched = false;\n try {\n const tracked = (await fc.machineConfigInfo()).track_dirty_pages;\n const since = box.memSnapshots ?? 0;\n // A diff is standalone right after boot, or once merged onto the previous image. Otherwise (a box\n // from an older server without tracking, or a lineage broken by an earlier failure) dump everything.\n const mode: \"Diff\" | \"Full\" = tracked && (since === 0 || existsSync(m.memBase)) ? \"Diff\" : \"Full\";\n\n // The guest is frozen for the whole capture so memory and overlay describe the same instant.\n // A box in standby (kvbox pause) is frozen already and stays that way afterwards.\n let failure: unknown;\n await fc.pause();\n try {\n await fc.snapshotCreate(s.vmstate, s.mem, mode);\n lineageTouched = tracked; // Firecracker reset its dirty bitmap: the box's next diff is relative to this image\n await run([\"cp\", \"--sparse=always\", \"--reflink=auto\", m.overlay, s.overlay]);\n } catch (err) {\n failure = err;\n } finally {\n if (!box.paused) await fc.resume();\n }\n if (lineageTouched) {\n // Recorded before anything else can fail: memSnapshots > 0 without mem.base reads as a broken\n // lineage, and the next snapshot falls back to a full dump instead of a diff missing pages.\n await writeMachineMeta({ ...box, memSnapshots: since + 1 }, p);\n }\n if (failure !== undefined) throw failure;\n\n if (mode === \"Full\") {\n // A full dump is dense; pages the guest never touched are zeros, so punch them out.\n await run([\"fallocate\", \"--dig-holes\", s.mem]);\n } else if (since > 0) {\n await mergeOntoPrevious(m.memBase, s.mem, cfg.snapshotEditor ?? p.snapshotEditor);\n }\n if (tracked) {\n await rm(m.memBase, { force: true });\n await link(s.mem, m.memBase);\n }\n\n const meta: SnapshotMeta = {\n name: req.name,\n owner,\n source: refKey(box),\n base: box.base,\n vcpu: box.vcpu,\n memMib: box.memMib,\n sizeBytes: await usedBytes(s.dir),\n createdAt: new Date().toISOString(),\n };\n await writeSnapshotMeta(meta, p);\n return toSnapshot(meta);\n } catch (err) {\n // The diff that was just discarded took pages with it: never let the next diff build on the old image.\n if (lineageTouched) await rm(m.memBase, { force: true }).catch(() => undefined);\n await rm(s.dir, { recursive: true, force: true });\n throw err;\n } finally {\n await fc.close();\n }\n}\n\n/**\n * Turn the diff at `diffFile` into a complete image: copy the previous image and apply the diff's pages\n * over it. Holes in the diff are untouched pages; a page dirtied to zeros is data and overwrites.\n */\nasync function mergeOntoPrevious(previous: string, diffFile: string, editor: string): Promise<void> {\n if (!existsSync(editor)) throw new KvboxError(`snapshot-editor missing at ${editor}; rerun install-server.sh`);\n const merged = `${diffFile}.merged`;\n await run([\"cp\", \"--sparse=always\", \"--reflink=auto\", previous, merged]);\n await run([editor, \"edit-memory\", \"rebase\", \"--memory-path\", merged, \"--diff-path\", diffFile]);\n await rename(merged, diffFile);\n}\n\nexport async function deleteSnapshot(ref: BoxRef, p: Paths = paths()): Promise<void> {\n const dir = p.snapshot(ref.owner, ref.name).dir;\n if (!existsSync(dir)) throw new NotFoundError(`snapshot ${shown(ref)}`);\n await rm(dir, { recursive: true, force: true });\n}\n"],"mappings":"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","names":["rm","writeFile","readFile","writeFile","z","z","readFile","writeFile","existsSync","mkdir","readdir","readFile","writeFile","join","join","existsSync","mkdir","readdir","readFile","writeFile","closeSync","existsSync","openSync","mkdir","readFile","writeFile","bootArgs","existsSync","writeFile","readFile","openSync","closeSync","m","mkdir","Hono","require","Hono","z","z","Hono","Hono","existsSync","link","mkdir","readdir","rename","rm","NAME_RE","readdir","existsSync","mkdir","rm","link","rename","Hono","Hono","rm","writeFile","shutdown"]}