@kvbox/server 0.5.14 → 0.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kvbox-server.js +67 -21
- package/dist/kvbox-server.js.map +1 -1
- package/package.json +1 -1
package/dist/kvbox-server.js.map
CHANGED
|
@@ -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","../../shared/src/usage.ts","../src/core/refs.ts","../src/core/controlPlane.ts","../../shared/src/api.ts","../../shared/src/ssh.ts","../src/core/exec.ts","../src/core/kvm.ts","../src/core/machines.ts","../src/core/agent.ts","../src/core/capacity.ts","../../shared/src/capacity.ts","../src/core/state.ts","../src/core/db.ts","../src/core/locks.ts","../src/core/firecracker.ts","../src/core/network.ts","../src/core/relay.ts","../../shared/src/relay.ts","../src/core/idle.ts","../src/core/relayWatch.ts","../src/listen.ts","../src/app.ts","../../shared/src/version.ts","../src/version.ts","../src/caller.ts","../../shared/src/names.ts","../src/routes/boxHttp.ts","../../shared/src/httpHead.ts","../src/routes/capacity.ts","../src/routes/machines.ts","../src/core/stats.ts","../src/core/usage.ts","../src/routes/snapshots.ts","../src/core/snapshots.ts","../src/routes/ssh.ts","../src/routes/usage.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. `join` / `leave` (M2) attach the host to a control plane,\n * after which `start` also answers that control plane over HTTPS.\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 { joinControlPlane, leaveControlPlane } from \"./core/controlPlane.js\";\nimport { requireKvm } from \"./core/kvm.js\";\nimport { bootRecovered, settleDeadBoxes } from \"./core/machines.js\";\nimport { ensureHostNetwork, netSetupScript } from \"./core/network.js\";\nimport { dropRelay, useRelay } from \"./core/relay.js\";\nimport { startIdleWatch } from \"./core/idle.js\";\nimport { startRelayWatch } from \"./core/relayWatch.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 await requireKvm(); // a daemon without /dev/kvm would only fail at the first kvbox new (#61)\n // Before listening: boxes whose Firecracker died with the host (#29), so a listing cannot get to them first.\n const settled = await settleDeadBoxes(paths());\n const { socketPath, https } = await listen(opts.socket ? { socketPath: opts.socket } : {});\n console.log(`kvbox-server ${VERSION} listening on ${socketPath} (pid ${process.pid})`);\n if (https) {\n const cfg = await loadConfig(paths());\n console.log(`control plane ${cfg.controlPlane?.name}: answering on ${https.url}`);\n }\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 // A relay tunnel that stops carrying traffic is redialed (#50); idle when the host has no relay.\n startRelayWatch();\n // Boxes with an idle timeout are hibernated once their network goes quiet (#47).\n startIdleWatch();\n const recovery = await bootRecovered(settled, paths());\n if (recovery) {\n for (const box of recovery.booted) console.log(`box ${box} was running when it went down; booted it again`);\n for (const box of recovery.leftStopped) console.log(`box ${box} was in standby when it went down; its memory is gone, left stopped`);\n for (const f of recovery.failed) console.error(`warning: box ${f.box} was running when it went down and did not come back: ${f.error}`);\n }\n });\n\nprogram\n .command(\"join <control-plane-url>\")\n .description(\"register this host with a control plane (needs a one-time token minted there); it answers the control plane from its next start\")\n .requiredOption(\"--token <token>\", \"one-time join token from the control plane\")\n .option(\"--advertise <host-or-ip>\", \"address the control plane reaches this host at (default: this host's default-route address)\")\n .option(\"--name <name>\", \"how the control plane lists this host (default: hostname)\")\n .action(async (url: string, opts: { token: string; advertise?: string; name?: string }) => {\n const joined = await joinControlPlane({ url, ...opts }, paths());\n console.log(`joined ${joined.controlPlane} as host ${joined.hostName}`);\n console.log(`it answers the control plane on ${joined.hostUrl} once its server restarts`);\n console.log(`make sure port ${new URL(joined.hostUrl).port} is reachable from the control plane`);\n });\n\nprogram\n .command(\"leave\")\n .description(\"forget the control plane this host joined; the HTTPS port closes at the next start\")\n .action(async () => {\n const left = await leaveControlPlane(paths());\n console.log(`left ${left.controlPlane}; the HTTPS port closes once its server restarts`);\n if (!left.told) console.log(`(the control plane could not be told; remove this host there)`);\n });\n\nprogram\n .command(\"relay <join-string>\")\n .description(\"reach the internet through a relay (paste what `kvbox-relay add` printed there); `off` takes the tunnel down\")\n .action(async (joinString: string) => {\n if (joinString === \"off\") {\n const relay = await dropRelay(paths());\n console.log(`tunnel to relay ${relay.name} is down; this host no longer answers at ${relay.publicIp}`);\n return;\n }\n const relay = await useRelay(joinString, paths());\n console.log(`tunnel to relay ${relay.name} (${relay.endpoint}) is up`);\n console.log(`this host is reachable at ${relay.publicIp}; kvbox server join advertises it by default`);\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/** The caller is known but the rule says no (an org member outside their role): HTTP 403, exit 1. */\nexport class ForbiddenError extends KvboxError {\n constructor(message: string) {\n super(message, 1);\n this.name = \"ForbiddenError\";\n }\n}\n\n/** A bare name that is in more than one of the caller's orgs (#68); the CLI and the control plane say it the same way. */\nexport class AmbiguousRefError extends KvboxError {\n constructor(kind: string, name: string, slugs: readonly string[]) {\n super(`${kind} ${name} exists in ${slugs.slice(0, -1).join(\", \")} and ${slugs.at(-1)}; say which with --org ${slugs[0]} or ${slugs[0]}/${name}`, 1);\n this.name = \"AmbiguousRefError\";\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, cli.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 /** The CLI's login to the control plane (`kvbox login`): url, bearer token, user. Mode 600. */\n cli: join(home, \"cli.json\"),\n ssh: join(home, \"ssh\"),\n sshKey: join(home, \"ssh\", \"id_ed25519\"),\n /** The device key signed by the control plane's CA (#51); ssh loads it by itself next to `-i id_ed25519`. */\n sshCert: join(home, \"ssh\", \"id_ed25519-cert.pub\"),\n /** Host keys of the cloud boxes this laptop connected to, one entry per box (`connect`, #21). */\n sshKnownHosts: join(home, \"ssh\", \"known_hosts\"),\n /** The host's self-signed TLS identity for the control plane (`kvbox-server join`): pinned there by fingerprint. */\n tls: join(home, \"tls\"),\n tlsKey: join(home, \"tls\", \"key.pem\"),\n tlsCert: join(home, \"tls\", \"cert.pem\"),\n /** The host's WireGuard tunnel to its relay (`kvbox server relay`, #50): the conf net-setup.sh installs for wg-quick. Mode 600. */\n relay: join(home, \"relay\"),\n relayConf: join(home, \"relay\", \"kvbox.conf\"),\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 /**\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 { chmod, readFile, rename, 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 { PricingSchema } from \"@kvbox/shared/usage\";\nimport { LOCAL_OWNER_RE, REALM_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 { PricingSchema, type Pricing } from \"@kvbox/shared/usage\";\n\n/** The control plane this host joined (`kvbox-server join`, #18): where it is, what it calls itself, and the secret it presents. */\nexport const ControlPlaneSchema = z.object({\n url: z.string().url(),\n /** The realm name: boxes the control plane creates are owned by `<user>@<name>`, a directory name on disk. */\n name: z.string().regex(REALM_RE),\n /** Minted at join; every HTTPS call from the control plane carries it as a bearer. */\n secret: z.string().min(1),\n /** The address the control plane reaches this host at. */\n advertise: z.string().min(1),\n port: z.number().int().positive().default(7777),\n});\nexport type ControlPlane = z.infer<typeof ControlPlaneSchema>;\n\n/**\n * The relay this host reaches the internet through (`kvbox-server relay`, #50): a public VM that owns\n * `publicIp` and forwards it down a WireGuard tunnel to `tunnelIp`. The tunnel's private key is not\n * here: it lives in the wg-quick conf under relay/. `join` advertises `publicIp` by default.\n */\nexport const RelaySchema = z.object({\n name: z.string().min(1),\n publicIp: z.string().min(1),\n tunnelIp: z.string().min(1),\n /** `<relay-ip>:<port>` the tunnel dials. */\n endpoint: z.string().min(1),\n});\nexport type Relay = z.infer<typeof RelaySchema>;\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 /** What a new box gets when `new` does not say (#47): seconds without network traffic before it is hibernated; 0: never. */\n autoHibernateSec: z.number().int().min(0).default(0),\n /** Absent until the host joins a control plane; then the server also listens on HTTPS. */\n controlPlane: ControlPlaneSchema.optional(),\n /** Absent unless the host sits behind a relay. */\n relay: RelaySchema.optional(),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/** Write config.json back, whole or not at all. Mode 600: once joined it holds the host's secret. */\nexport async function saveConfig(cfg: Config, p: Paths = paths()): Promise<void> {\n const parsed = ConfigSchema.parse(cfg);\n const tmp = `${p.config}.tmp`;\n await writeFile(tmp, JSON.stringify(parsed, null, 2) + \"\\n\", { mode: 0o600 });\n await chmod(tmp, 0o600); // writeFile's mode applies to a new file only\n await rename(tmp, p.config);\n}\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 * Summing a box's usage ledger: one pure function over its state-change rows, used by the host\n * (`kvbox vm usage`, `GET /usage`) and by the control plane over the rows it pulled (#42). A row\n * opens an interval that lasts until the next row; the sizes ride on every row so a rescale\n * changes the rate from that moment on. Pricing is per resource-hour (decision \"Usage is priced\n * per resource-hour\").\n */\nimport { z } from \"zod\";\nimport type { BoxStatus, BoxUsage } from \"./api.js\";\n\nexport type UsageState = \"running\" | \"standby\" | \"hibernated\" | \"stopped\";\n\n/** One state change of a box. */\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, server (a stop the server did not see). */\n by: string;\n}\n\n/** What an hour of each resource costs. */\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 interface UsageWindow {\n from: string;\n to: string;\n pricing?: Pricing | undefined;\n}\n\nexport interface UsageTotals {\n seconds: Record<UsageState, number>;\n vcpuHours: number;\n ramGibHours: number;\n diskGibHours: number;\n cost?: { amount: number; currency: string };\n /** Stops the server did not witness (Firecracker died, host rebooted) and dated to when it noticed. */\n estimatedStops: number;\n /** The first recorded moment, null when nothing is recorded. */\n historyFrom: string | null;\n}\n\nconst HOUR_MS = 3_600_000;\n\nexport const 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) totals.cost = { amount: round(costOf(totals, w.pricing), 4), currency: w.pricing.currency };\n return totals;\n}\n\n/** The price of a set of resource-hours; totals over several boxes are summed the same way. */\nexport function costOf(t: Pick<UsageTotals, \"vcpuHours\" | \"ramGibHours\" | \"diskGibHours\">, pricing: Pricing): number {\n return t.vcpuHours * pricing.vcpuHour + t.ramGibHours * pricing.ramGibHour + t.diskGibHours * pricing.diskGibHour;\n}\n\n/** Add up several boxes' totals (hours and seconds; the cost is recomputed from the hours when priced). */\nexport function sumUsage(items: readonly Pick<UsageTotals, \"seconds\" | \"vcpuHours\" | \"ramGibHours\" | \"diskGibHours\">[], pricing?: Pricing): Omit<UsageTotals, \"estimatedStops\" | \"historyFrom\"> {\n const sum: Omit<UsageTotals, \"estimatedStops\" | \"historyFrom\"> = {\n seconds: { running: 0, standby: 0, hibernated: 0, stopped: 0 },\n vcpuHours: 0,\n ramGibHours: 0,\n diskGibHours: 0,\n };\n for (const t of items) {\n for (const s of Object.keys(sum.seconds) as UsageState[]) sum.seconds[s] += t.seconds[s];\n sum.vcpuHours += t.vcpuHours;\n sum.ramGibHours += t.ramGibHours;\n sum.diskGibHours += t.diskGibHours;\n }\n sum.vcpuHours = round(sum.vcpuHours, 3);\n sum.ramGibHours = round(sum.ramGibHours, 3);\n sum.diskGibHours = round(sum.diskGibHours, 3);\n if (pricing !== undefined) sum.cost = { amount: round(costOf(sum, pricing), 4), currency: pricing.currency };\n return sum;\n}\n\n/**\n * The window a `GET /usage` call asks for: `since` and `until` as the user wrote them (any Date.parse\n * form), defaulting to the start of the current calendar month (UTC, what a bill covers) and now.\n */\nexport function usageWindow(since: string | undefined, until: string | undefined, now = new Date()): { from: string; to: string } {\n const parse = (name: string, value: string): string => {\n const t = Date.parse(value);\n if (Number.isNaN(t)) throw new Error(`${name}: \"${value}\" is not a date; write it like 2026-10-19 or 2026-10-19T08:00:00Z`);\n return new Date(t).toISOString();\n };\n const from = since === undefined ? new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)).toISOString() : parse(\"since\", since);\n const to = until === undefined ? now.toISOString() : parse(\"until\", until);\n return { from, to };\n}\n\n/** A ledger row as the host stores it: the event plus whose box it is. */\nexport interface LedgerRow extends UsageEvent {\n /** The host ledger the row came from, when rows of several hosts are mixed: box ids are only unique within one. */\n ledger?: string;\n boxId: string;\n owner: string;\n name: string;\n}\n\n/**\n * Rows of many boxes → one `BoxUsage` per box id, in owner/name order: the report both the host\n * (`GET /usage`) and the control plane build. A box's `rm` row ends its time: nothing accrues after\n * it, and a box gone before the window opened (or made after it closed) is left out. `live` says what\n * a box that still exists is doing now; one not in it reads its state off its last row, `removed`\n * when that row is the `rm`. A name removed and made again is two boxes (two ids); rows carrying a\n * `ledger` are grouped by ledger and box id, so two hosts' boxes never merge.\n */\nexport function groupUsage(\n rows: readonly LedgerRow[],\n window: { from: string; to: string },\n pricing: Pricing | undefined,\n live: ReadonlyMap<string, BoxStatus> = new Map(),\n): BoxUsage[] {\n const byBox = new Map<string, LedgerRow[]>();\n for (const r of rows) {\n const key = r.ledger === undefined ? r.boxId : `${r.ledger}:${r.boxId}`;\n const list = byBox.get(key);\n if (list === undefined) byBox.set(key, [r]);\n else list.push(r);\n }\n const out: BoxUsage[] = [];\n for (const events of byBox.values()) {\n events.sort((a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : 0));\n const first = events[0]!;\n const last = events[events.length - 1]!;\n const id = last.boxId;\n const removed = last.by === \"rm\" && !live.has(id);\n const to = removed && last.at < window.to ? last.at : window.to;\n if (first.at >= to || (removed && last.at <= window.from)) continue;\n const totals = computeUsage(events, { from: window.from, to, pricing });\n const status: BoxUsage[\"status\"] = live.get(id) ?? (removed ? \"removed\" : last.state);\n out.push({ id, name: last.name, owner: last.owner, status, ...totals });\n }\n return out.sort((a, b) => a.owner.localeCompare(b.owner) || a.name.localeCompare(b.name) || (a.historyFrom ?? \"\").localeCompare(b.historyFrom ?? \"\"));\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/** A realm: a control plane's name as hosts qualify owners with it (`kvbox.sh`). A path segment later, so nothing but a host name. */\nexport const REALM_RE = /^[A-Za-z0-9.-]{1,128}$/;\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/**\n * Who a listing is for: one owner, every owner of a realm (`{ realm }`: the control plane reconciling\n * its index, #20), or everyone (`null`: the host owner's own accounting).\n */\nexport type ListScope = string | { realm: string } | null;\n\nexport function inScope(owner: string, scope: ListScope): boolean {\n if (scope === null) return true;\n if (typeof scope === \"string\") return owner === scope;\n return realmOf(owner) === scope.realm;\n}\n\n/** The control plane an owner belongs to (`alice@kvbox.sh` → `kvbox.sh`); null for a local owner. */\nexport function realmOf(owner: string): string | null {\n const at = owner.indexOf(\"@\");\n return at === -1 ? null : owner.slice(at + 1);\n}\n\n/**\n * `lab1` → the caller's box; `user2/lab1` → that owner's. A caller from a control plane (`user@realm`)\n * can only name owners of that realm: the control plane never sees the host owner's local boxes or\n * another control plane's. The host owner over the socket is not restricted.\n */\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 const realm = realmOf(caller);\n if (realm !== null && realmOf(owner) !== realm) {\n throw new KvboxError(`invalid box reference \"${text}\": ${owner} is not in your realm`);\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 * The host's side of the control plane (#18, design in the brain's multi-host doc). A host joins\n * exactly one control plane with a one-time token an admin minted there; it gets back a secret the\n * control plane will present on every call, and from its next start it also serves the API over\n * HTTPS. The control plane trusts the host by the fingerprint of the self-signed certificate made\n * here (no CA), so the certificate is generated once and kept for the host's life.\n */\nimport { X509Certificate } from \"node:crypto\";\nimport { chmod, mkdir, readFile } from \"node:fs/promises\";\nimport { hostname as osHostname } from \"node:os\";\nimport { request } from \"undici\";\nimport { HostJoinResponseSchema, HostSshCaResponseSchema, type CloudCa, type HostJoinRequest } from \"@kvbox/shared/api\";\nimport { parseSshPublicKey, sshKeyFingerprint } from \"@kvbox/shared/ssh\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { loadConfig, saveConfig } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { REALM_RE } from \"./refs.js\";\n\nexport const DEFAULT_HTTPS_PORT = 7777;\n\n/** The certificate's sha256 fingerprint, `AA:BB:…`, the form the control plane pins. */\nexport interface TlsIdentity {\n fingerprint: string;\n}\n\n/** Generate `tls/key.pem` + `tls/cert.pem` on first use (openssl, EC P-256, 10 years); return the fingerprint either way. */\nexport async function ensureTlsCert(p: Paths = paths()): Promise<TlsIdentity> {\n const have = await readFile(p.tlsCert, \"utf8\").catch(() => null);\n const haveKey = await readFile(p.tlsKey).then(() => true, () => false);\n if (have === null || !haveKey) {\n await mkdir(p.tls, { recursive: true, mode: 0o700 });\n try {\n await run([\n \"openssl\", \"req\", \"-x509\", \"-newkey\", \"ec\", \"-pkeyopt\", \"ec_paramgen_curve:prime256v1\", \"-nodes\",\n \"-keyout\", p.tlsKey, \"-out\", p.tlsCert, \"-subj\", \"/CN=kvbox-host\", \"-days\", \"3650\",\n ]);\n } catch (err) {\n throw new KvboxError(`could not make the host's certificate (is openssl installed?): ${(err as Error).message}`);\n }\n await chmod(p.tlsKey, 0o600);\n }\n const pem = await readFile(p.tlsCert, \"utf8\");\n return { fingerprint: new X509Certificate(pem).fingerprint256 };\n}\n\nexport interface JoinOptions {\n /** The control plane, e.g. https://api.kvbox.sh. */\n url: string;\n /** One-time token an admin minted there. */\n token: string;\n /** Host or IP the control plane reaches this host at; default: the address of this host's default route. */\n advertise?: string;\n /** How the control plane lists this host; default: the hostname. */\n name?: string;\n port?: number;\n}\n\nexport interface Joined {\n hostName: string;\n controlPlane: string;\n /** Where the control plane will call this host: https://<advertise>:<port>. */\n hostUrl: string;\n}\n\n/** RFC 1918, loopback, link-local and carrier-grade NAT: addresses a control plane on the internet cannot reach. */\nexport function isPrivateAddress(ip: string): boolean {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$/.exec(ip);\n if (!m) return false;\n const [a, b] = [Number(m[1]), Number(m[2])];\n return a === 10 || a === 127 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 169 && b === 254) || (a === 100 && b >= 64 && b <= 127);\n}\n\n/** The IPv4 this host would use to reach the internet: the `src` of the default route. */\nexport async function defaultAdvertise(): Promise<string> {\n const { stdout } = await run([\"ip\", \"-4\", \"route\", \"get\", \"1.1.1.1\"]).catch((err: Error) => {\n throw new KvboxError(`cannot tell this host's address (${err.message}); pass --advertise <host-or-ip>`);\n });\n const m = /\\bsrc\\s+(\\S+)/.exec(stdout);\n if (!m) throw new KvboxError(\"cannot tell this host's address from its routes; pass --advertise <host-or-ip>\");\n return m[1]!;\n}\n\n/**\n * Register this host with a control plane: make sure it has a certificate, send the join, keep the\n * secret in config.json. The server picks the HTTPS listener up at its next start.\n */\nexport async function joinControlPlane(opts: JoinOptions, p: Paths = paths(), guessAddress: () => Promise<string> = defaultAdvertise): Promise<Joined> {\n const url = opts.url.replace(/\\/+$/, \"\");\n const port = opts.port ?? DEFAULT_HTTPS_PORT;\n const cfg = await loadConfig(p);\n if (cfg.controlPlane) throw new KvboxError(`this host has already joined ${cfg.controlPlane.name} (${cfg.controlPlane.url}); run kvbox server leave first`);\n let advertise = opts.advertise;\n if (advertise === undefined && cfg.relay) {\n // Behind a relay the host's own addresses are beside the point: the relay's public IP is where it is reached.\n advertise = cfg.relay.publicIp;\n } else if (advertise === undefined) {\n advertise = await guessAddress();\n if (isPrivateAddress(advertise)) {\n throw new KvboxError(\n `${advertise} is a private address: a control plane on the internet cannot reach this host there.\\n` +\n ` Pass --advertise <public host or ip>, or --advertise ${advertise} if the control plane is on the same network.`,\n );\n }\n }\n const name = opts.name ?? osHostname();\n const { fingerprint } = await ensureTlsCert(p);\n const hostUrl = `https://${advertise}:${port}`;\n const body: HostJoinRequest = { token: opts.token, name, url: hostUrl, fingerprint, publicAddress: advertise };\n\n const res = await request(`${url}/hosts/join`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n headersTimeout: 10_000,\n bodyTimeout: 10_000,\n }).catch((err: Error) => {\n throw new KvboxError(`cannot reach ${url} (${err.message})`);\n });\n const text = await res.body.text();\n if (res.statusCode < 200 || res.statusCode >= 300) {\n throw new KvboxError(errorIn(text) ?? `control plane answered ${res.statusCode}`);\n }\n const parsed = HostJoinResponseSchema.safeParse(jsonOrNull(text));\n if (!parsed.success) throw new KvboxError(`${url} did not answer like a kvbox control plane`);\n if (!REALM_RE.test(parsed.data.controlPlane.name)) {\n throw new KvboxError(`${url} calls itself \"${parsed.data.controlPlane.name}\", which cannot name a realm (letters, digits, '.', '-')`);\n }\n\n await saveConfig({ ...cfg, controlPlane: { url, name: parsed.data.controlPlane.name, secret: parsed.data.hostSecret, advertise, port } }, p);\n return { hostName: name, controlPlane: parsed.data.controlPlane.name, hostUrl };\n}\n\n/**\n * Ask the joined control plane which SSH CA boxes should trust (`GET /hosts/self/ssh-ca`, by the\n * host secret), with its fingerprint, for `kvbox server trust-ca --from-cloud` to show before\n * anything changes (#55).\n */\nexport async function fetchCloudCa(p: Paths = paths()): Promise<CloudCa> {\n const cfg = await loadConfig(p);\n const cp = cfg.controlPlane;\n if (!cp) throw new KvboxError(\"this host has not joined a control plane, so there is no CA to fetch; paste the key instead: kvbox server trust-ca <public-key>\");\n const res = await request(`${cp.url}/hosts/self/ssh-ca`, {\n headers: { authorization: `Bearer ${cp.secret}` },\n headersTimeout: 10_000,\n bodyTimeout: 10_000,\n }).catch((err: Error) => {\n throw new KvboxError(`cannot reach ${cp.url} (${err.message})`);\n });\n const text = await res.body.text();\n if (res.statusCode === 404) throw new KvboxError(`${cp.name} does not answer /hosts/self/ssh-ca: it is older than this host; paste the key instead`);\n if (res.statusCode < 200 || res.statusCode >= 300) throw new KvboxError(errorIn(text) ?? `${cp.name} answered ${res.statusCode}`);\n const parsed = HostSshCaResponseSchema.safeParse(jsonOrNull(text));\n if (!parsed.success) throw new KvboxError(`${cp.name} did not answer with a CA key`);\n const publicKey = parseSshPublicKey(parsed.data.publicKey);\n return { controlPlane: cp.name, publicKey, fingerprint: sshKeyFingerprint(publicKey) };\n}\n\nexport interface Left {\n controlPlane: string;\n /** Whether the control plane acknowledged; false means an admin has to remove the host there. */\n told: boolean;\n}\n\n/** Forget the control plane (the HTTPS listener stops at the next start) and tell it so, best effort. */\nexport async function leaveControlPlane(p: Paths = paths()): Promise<Left> {\n const cfg = await loadConfig(p);\n const cp = cfg.controlPlane;\n if (!cp) throw new KvboxError(\"this host has not joined a control plane\");\n const told = await request(`${cp.url}/hosts/self`, {\n method: \"DELETE\",\n headers: { authorization: `Bearer ${cp.secret}` },\n headersTimeout: 3000,\n bodyTimeout: 3000,\n })\n .then(async (res) => {\n await res.body.dump();\n return res.statusCode >= 200 && res.statusCode < 300;\n })\n .catch(() => false);\n const { controlPlane: _gone, ...rest } = cfg;\n await saveConfig(rest, p);\n return { controlPlane: cp.name, told };\n}\n\nfunction jsonOrNull(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return null;\n }\n}\n\n/** The `{ error }` of a kvbox JSON answer, if that is what the text is. */\nfunction errorIn(text: string): string | undefined {\n const v = jsonOrNull(text);\n if (v && typeof v === \"object\" && typeof (v as { error?: unknown }).error === \"string\") return (v as { error: string }).error;\n return undefined;\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/** The guest account every box has; `ssh` logs in as it. */\nexport const BOX_SSH_USER = \"kvbox\";\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 * `unknown`: only from the control plane, for a box whose host did not answer in time (#20).\n */\nexport const BoxStatusSchema = z.enum([\"running\", \"standby\", \"hibernated\", \"stopped\", \"unknown\"]);\nexport type BoxStatus = z.infer<typeof BoxStatusSchema>;\n\n/** A published box port's protocol (#30). */\nexport const PortProtoSchema = z.enum([\"tcp\", \"udp\"]);\nexport type PortProto = z.infer<typeof PortProtoSchema>;\n\n/** At most this many published ports per box (#30): room for a lab of services, not for draining the host's range. */\nexport const MAX_BOX_PORTS = 16;\n\n/**\n * A box port published on the host's public address (#30, `kvbox vm proxy`): `hostPort` on the\n * host reaches `guestPort` in the box. The host port is drawn at random and stays the box's.\n */\nexport const PortForwardSchema = z.object({\n guestPort: z.number().int().min(1).max(65535),\n hostPort: z.number().int(),\n proto: PortProtoSchema,\n /** The host's public address; only the control plane fills it in, as for `ssh`. */\n address: z.string().optional(),\n});\nexport type PortForward = z.infer<typeof PortForwardSchema>;\n\n/** `POST /machines/:name/ports` adds these, `DELETE` removes them; the answer is the box. */\nexport const PortsRequest = z.object({\n ports: z.array(z.object({ guestPort: z.number().int().min(1).max(65535), proto: PortProtoSchema.optional() })).min(1).max(MAX_BOX_PORTS),\n});\nexport type PortsRequest = z.infer<typeof PortsRequest>;\n\nconst BoxPortSchema = z.number().int().min(1).max(65535);\n\n/** `PUT /machines/:name/subdomain` (#31): claim `<name>.kvbox.app` for the box, serving `port`. */\nexport const ClaimSubdomainRequest = z.object({ name: z.string(), port: BoxPortSchema });\nexport type ClaimSubdomainRequest = z.infer<typeof ClaimSubdomainRequest>;\n\n/** `POST /machines/:name/subdomain/port`: the default port changes. */\nexport const SubdomainPortRequest = z.object({ port: BoxPortSchema });\nexport type SubdomainPortRequest = z.infer<typeof SubdomainPortRequest>;\n\n/** `POST /machines/:name/subdomain/routes`: `<name>.<sub>.kvbox.app` serves `port`. */\nexport const SubdomainRouteRequest = z.object({ name: z.string(), port: BoxPortSchema });\nexport type SubdomainRouteRequest = z.infer<typeof SubdomainRouteRequest>;\n\n/**\n * A box's HTTPS subdomain (#31): `url` serves the box's `port`, each route's `url` its own port.\n * `owner` is the box's slug (a user's or an org's), `box` its name.\n */\nexport const SubdomainSchema = z.object({\n owner: z.string(),\n box: z.string(),\n subdomain: z.string(),\n port: BoxPortSchema,\n url: z.string(),\n routes: z.array(z.object({ name: z.string(), port: BoxPortSchema, url: z.string() })),\n});\nexport type Subdomain = z.infer<typeof SubdomainSchema>;\n\nexport const MachineSchema = z.object({\n /** Host-unique short id (the tap is `kv-<id>`). Missing only on a box made before ids that has not restarted since. */\n id: z.string(),\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(), // base image version the box's overlay stacks on\n createdAt: z.string(),\n source: z.string(), // \"base\" or \"snapshot:<name>\"\n status: BoxStatusSchema,\n /**\n * Public TCP port on the host that reaches the box's SSH while it runs (#49). Only boxes made\n * through a control plane have one; the control plane adds the host's address for `connect` (#21).\n */\n sshPort: z.number().int().optional(),\n /**\n * Where `ssh` reaches the box from outside: the host's public address and that port (#21). Only\n * the control plane fills it in (a host does not know its own public address); absent for a box\n * whose host reported no port or did not answer.\n */\n ssh: z.object({ host: z.string(), port: z.number().int(), user: z.string() }).optional(),\n /** Box ports published on the host (#30). Absent: none. */\n ports: z.array(PortForwardSchema).optional(),\n /** Whether the owner slug is a user or an org. Only the control plane knows; it fills it in on `GET /machines`. */\n ownerKind: z.enum([\"user\", \"org\"]).optional(),\n /** Seconds without network traffic before the host hibernates the box (#47). Absent: never. */\n autoHibernateSec: z.number().int().positive().optional(),\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 /**\n * Extra authorized_keys lines for the box, on top of the host's own key: the control plane sends\n * its SSH CA as one `cert-authority …` line (#51). Written into the box's authorized_keys at every\n * boot (#49); a host older than that ignores them.\n */\n sshKeys: z.array(z.string()).optional(),\n /** Seconds without network traffic before the box is hibernated (#47); 0: never. Absent: the host's default. */\n autoHibernateSec: z.number().int().min(0).optional(),\n});\nexport type CreateMachineRequest = z.infer<typeof CreateMachineRequest>;\n\n/**\n * `POST /machines/:name/ssh-keys` on a host (orgs phase 4): replace the authorized_keys lines the box\n * gets on top of the host's own key. Takes effect at the box's next boot (kvbox-init rewrites the\n * file from the kernel command line); a running or hibernated box keeps its current file until then.\n */\nexport const SetSshKeysRequest = z.object({\n sshKeys: z.array(z.string()),\n});\nexport type SetSshKeysRequest = z.infer<typeof SetSshKeysRequest>;\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\n/** `kvbox vm set`: settings that change nothing in the running VM. Anything omitted stays as it is. */\nexport const SetMachineRequest = z.object({\n /** Seconds without network traffic before the box is hibernated (#47); 0: never. */\n autoHibernateSec: z.number().int().min(0).optional(),\n});\nexport type SetMachineRequest = z.infer<typeof SetMachineRequest>;\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\n/**\n * What the server did at its last start about boxes whose Firecracker had died (host reboot or crash,\n * #29). Boxes are `owner/name`. `leftStopped`: they were in standby, their memory went with the process.\n */\nexport const RecoveryReportSchema = z.object({\n at: z.string(),\n booted: z.array(z.string()),\n leftStopped: z.array(z.string()),\n failed: z.array(z.object({ box: z.string(), error: z.string() })),\n});\nexport type RecoveryReport = z.infer<typeof RecoveryReportSchema>;\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). */\n base: z.string().nullable(),\n /** Owner that boxes made over the local socket get (the Unix user running the server). */\n owner: z.string(),\n /** The control plane this host joined (null when none). */\n controlPlane: z\n .object({\n /** Realm name, e.g. kvbox.sh. */\n name: z.string(),\n url: z.string(),\n /** Where this host answers the control plane. */\n hostUrl: z.string(),\n })\n .nullable(),\n /** The relay this host reaches the internet through (#50); null when it has its own public address. Older servers omit it. */\n relay: z\n .object({\n name: z.string(),\n /** The public IP the relay owns for this host. */\n publicIp: z.string(),\n /** The relay's WireGuard endpoint the tunnel dials. */\n endpoint: z.string(),\n /** Times the server redialed the tunnel since it started, because the relay stopped answering. Older servers omit them. */\n restarts: z.number().int().optional(),\n lastRestartAt: z.string().nullable().optional(),\n })\n .nullable()\n .optional(),\n /** Boxes brought back at the server's last start; null when there were none or it is still at it. Older servers omit it. */\n recovery: RecoveryReportSchema.nullable().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, null when nothing is recorded yet.\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 seconds: z.object({\n running: z.number().int(),\n standby: z.number().int(),\n hibernated: z.number().int(),\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\n/** What a running box says about itself through kvbox-agent's `stats` (base v0.7.0 and later). */\nexport const GuestStatsSchema = z.object({\n /** Load average over 1, 5 and 15 minutes. */\n load: z.tuple([z.number(), z.number(), z.number()]),\n cpus: z.number().int(),\n memTotalMib: z.number().int(),\n /** Total minus available: page cache counts as free. */\n memUsedMib: z.number().int(),\n /** The box's root, which is its overlay disk: the box's own writes, not the shared base. */\n diskTotalBytes: z.number().int(),\n diskUsedBytes: z.number().int(),\n uptimeSec: z.number().int(),\n});\nexport type GuestStats = z.infer<typeof GuestStatsSchema>;\n\n/** `GET /machines/:name/stats` (#67): `stats` is null when the box's image predates the request. */\nexport const MachineStatsSchema = z.object({\n name: z.string(),\n owner: z.string(),\n stats: GuestStatsSchema.nullable(),\n});\nexport type MachineStats = z.infer<typeof MachineStatsSchema>;\n\n/** A box's state as the usage ledger tells it: a box status, or `removed` when its last row is the `rm`. */\nexport const UsageStatusSchema = z.enum([...BoxStatusSchema.options, \"removed\"]);\nexport type UsageStatus = z.infer<typeof UsageStatusSchema>;\n\n/** One box's share of a `GET /usage` report (#41, #42): the same figures as `MachineUsage`, over the report's window. */\nexport const BoxUsageSchema = MachineUsageSchema.omit({ window: true, status: true }).extend({\n /** The host's box id; a name removed and recreated appears twice, with two ids. */\n id: z.string(),\n status: UsageStatusSchema,\n /** Through a control plane: whether the owner slug is a user's or an org's (what `kvbox ls` shows). */\n ownerKind: z.enum([\"user\", \"org\"]).optional(),\n});\nexport type BoxUsage = z.infer<typeof BoxUsageSchema>;\n\n/**\n * `GET /usage?since=&until=`: every box of the caller over the window (removed ones included) and\n * the totals. On a host over its socket: the host owner's boxes; through a control plane: every slug\n * the user can read (`X-Kvbox-Org` narrows to one). `cost` is present when the answering side prices usage.\n */\nexport const UsageReportSchema = z.object({\n window: z.object({ from: z.string(), to: z.string() }),\n boxes: z.array(BoxUsageSchema),\n totals: z.object({\n seconds: MachineUsageSchema.shape.seconds,\n vcpuHours: z.number(),\n ramGibHours: z.number(),\n diskGibHours: z.number(),\n cost: z.object({ amount: z.number(), currency: z.string() }).optional(),\n }),\n});\nexport type UsageReport = z.infer<typeof UsageReportSchema>;\n\n/**\n * `GET /usage/events?after=<id>&limit=<n>` on a host (#42): the ledger rows after `after`, oldest\n * first, as the control plane pulls them. `next` is the last row's id (the cursor to store), equal\n * to `after` when there was nothing new. Over HTTPS only rows of the caller's realm come back.\n * `ledger` names the host's ledger: row ids are unique only within it, and a new one restarts at 1.\n */\nexport const UsageEventRowSchema = z.object({\n id: z.number().int(),\n boxId: z.string(),\n owner: z.string(),\n name: z.string(),\n at: z.string(),\n state: z.enum([\"running\", \"standby\", \"hibernated\", \"stopped\"]),\n vcpu: z.number().int(),\n memMib: z.number().int(),\n diskGib: z.number().int(),\n by: z.string(),\n});\nexport type UsageEventRow = z.infer<typeof UsageEventRowSchema>;\n\nexport const UsageEventsResponseSchema = z.object({\n ledger: z.string().min(1),\n events: z.array(UsageEventRowSchema),\n next: z.number().int(),\n});\nexport type UsageEventsResponse = z.infer<typeof UsageEventsResponseSchema>;\n\nexport const ApiErrorSchema = z.object({\n error: z.string(),\n});\n\n// ---- control plane (kvbox-cloud) ----\n\n/** Where `kvbox login` goes without a URL, and the control plane's own public URL by default. */\nexport const DEFAULT_CLOUD_URL = \"https://api.kvbox.sh\";\n\n/**\n * Who turned a slug (a user or an org) on: a card on file (`card`, #75) or an admin by hand\n * (`admin`, #74). Until one of them does, the account only logs in and looks: every other route\n * answers 402 (decision \"Signup is email + password… inactive until a card is on file\").\n */\nexport const ACTIVATED_BY = [\"card\", \"admin\"] as const;\nexport const ActivatedBySchema = z.enum(ACTIVATED_BY);\nexport type ActivatedBy = z.infer<typeof ActivatedBySchema>;\n\n/** A user account on the control plane; returned by `GET /me`, `GET /users` (#48). */\nexport const CloudUserSchema = z.object({\n /** The handle: what hosts file boxes under (`<username>@<control plane>`). Lowercase, no `@` or `/`. */\n username: z.string(),\n /** Display name, free text (\"Alexandru Ghiura\"). */\n name: z.string(),\n /** Login identity, unique. */\n email: z.string(),\n role: z.enum([\"admin\", \"user\"]),\n createdAt: z.string(),\n /**\n * False until a card is on file or an admin activates the account (#74): then only `/me` and\n * `/logout` answer. Admins are never gated. A control plane older than #74 does not send these and\n * gates nobody, hence the defaults: a newer CLI must still parse its answers.\n */\n active: z.boolean().default(true),\n activatedBy: ActivatedBySchema.nullable().default(null),\n});\nexport type CloudUser = z.infer<typeof CloudUserSchema>;\n\n// ---- orgs (plan \"Orgs, slugs and roles\") ----\n\nexport const ORG_ROLES = [\"owner\", \"admin\", \"member\"] as const;\nexport const OrgRoleSchema = z.enum(ORG_ROLES);\nexport type OrgRole = z.infer<typeof OrgRoleSchema>;\n\n/** An org as the API shows it; its slug owns boxes the way a username does. */\nexport const CloudOrgSchema = z.object({\n slug: z.string(),\n /** Display name; the slug never changes, this may. */\n name: z.string(),\n createdAt: z.string(),\n /** An org pays for itself (#74): off until it has a card or an admin activates it; its boxes are 402. Defaults as on CloudUser. */\n active: z.boolean().default(true),\n activatedBy: ActivatedBySchema.nullable().default(null),\n});\nexport type CloudOrg = z.infer<typeof CloudOrgSchema>;\n\n/** One of the caller's orgs with their role in it (`GET /orgs`, `GET /me`). */\nexport const OrgMembershipSchema = CloudOrgSchema.extend({ role: OrgRoleSchema });\nexport type OrgMembership = z.infer<typeof OrgMembershipSchema>;\n\nexport const OrgMemberSchema = z.object({\n username: z.string(),\n name: z.string(),\n role: OrgRoleSchema,\n addedAt: z.string(),\n});\nexport type OrgMember = z.infer<typeof OrgMemberSchema>;\n\n/** `GET /orgs/:slug`: the org and its members (members and up see it). */\nexport const OrgDetailSchema = CloudOrgSchema.extend({ members: z.array(OrgMemberSchema) });\nexport type OrgDetail = z.infer<typeof OrgDetailSchema>;\n\n/** `POST /orgs`: the caller becomes the org's owner. */\nexport const CreateOrgRequestSchema = z.object({\n slug: z.string().min(1),\n name: z.string().min(1),\n});\nexport type CreateOrgRequest = z.infer<typeof CreateOrgRequestSchema>;\n\n/** `PATCH /orgs/:slug` (owner): the display name. */\nexport const RenameOrgRequestSchema = z.object({ name: z.string().min(1) });\n\n/** `POST /orgs/:slug/members` (admin, owner): an existing user joins, as a member unless said otherwise. */\nexport const AddMemberRequestSchema = z.object({\n username: z.string().min(1),\n role: OrgRoleSchema.default(\"member\"),\n});\nexport type AddMemberRequest = z.infer<typeof AddMemberRequestSchema>;\n\n/** `PATCH /orgs/:slug/members/:username` (owner). */\nexport const SetRoleRequestSchema = z.object({ role: OrgRoleSchema });\n\n/** `GET /me`: the account plus the orgs it belongs to. */\nexport const MeResponseSchema = CloudUserSchema.extend({ orgs: z.array(OrgMembershipSchema) });\nexport type MeResponse = z.infer<typeof MeResponseSchema>;\n\n// ---- prepaid credit (#76) ----\n\n/**\n * `GET /billing/balance`: what a slug (the caller's own, or `X-Kvbox-Org`'s) has left. `balance` is\n * every top-up minus what the usage ledger says its boxes cost since `since`, the slug's first top-up\n * (null: it never had any); at or below zero the slug cannot start or create anything (402).\n * `topUps` and `spent` are the two sides of it.\n */\nexport const BalanceSchema = z.object({\n slug: z.string(),\n balance: z.number(),\n currency: z.string(),\n topUps: z.number(),\n spent: z.number(),\n /** The first moment usage counts from: the slug's first top-up; null when it has none. */\n since: z.string().nullable(),\n /** When the slug ran out and its boxes were hibernated (the `sweep-credit` job); null in good standing. Absent from a control plane older than this field. */\n suspendedAt: z.string().nullable().default(null),\n});\nexport type Balance = z.infer<typeof BalanceSchema>;\n\n/** `POST /admin/billing/top-ups` (platform admin): give a slug money by hand. */\nexport const TopUpRequestSchema = z.object({\n slug: z.string().min(1),\n /** In the control plane's currency; negative corrects a mistake. */\n amount: z.number().finite(),\n note: z.string().max(200).optional(),\n});\nexport type TopUpRequest = z.infer<typeof TopUpRequestSchema>;\n\n/** One top-up as recorded, answered by `POST /admin/billing/top-ups`. */\nexport const TopUpSchema = z.object({\n id: z.string(),\n slug: z.string(),\n amount: z.number(),\n currency: z.string(),\n source: z.enum([\"admin\", \"card\", \"trial\"]),\n note: z.string().nullable(),\n at: z.string(),\n});\nexport type TopUp = z.infer<typeof TopUpSchema>;\n\n/** `POST /login` body from `kvbox login` (#48); `publicKey` is the user's SSH key to inject into new boxes. */\nexport const LoginRequestSchema = z.object({\n email: z.string().min(1),\n password: z.string().min(1),\n publicKey: z.string().optional(),\n});\nexport type LoginRequest = z.infer<typeof LoginRequestSchema>;\n\n/** `POST /signup` body from the website: a new account with the `user` role; answers like `/login` (logged in at once). */\nexport const SignupRequestSchema = z.object({\n username: z.string().min(1),\n name: z.string().min(1),\n email: z.string().min(1),\n password: z.string().min(1),\n});\nexport type SignupRequest = z.infer<typeof SignupRequestSchema>;\n\n/**\n * `POST /login` answer: the bearer token the CLI stores (#48). With a `publicKey` in the request,\n * also that key signed by the control plane's SSH CA (#51): the `-cert.pub` text and when it expires (ISO).\n */\nexport const LoginResponseSchema = z.object({\n token: z.string(),\n user: CloudUserSchema,\n sshCert: z.string().optional(),\n sshCertExpires: z.string().optional(),\n /** Whose boxes the certificate opens: `<slug>@<realm>` for the user and each org they are in (orgs phase 4). */\n sshCertPrincipals: z.array(z.string()).optional(),\n});\nexport type LoginResponse = z.infer<typeof LoginResponseSchema>;\n\n/** `POST /ssh/cert` body: one of the caller's uploaded keys to sign again (#51). */\nexport const SshCertRequestSchema = z.object({\n publicKey: z.string().min(1),\n});\nexport type SshCertRequest = z.infer<typeof SshCertRequestSchema>;\n\n/** `POST /ssh/cert` answer: the certificate text, its expiry (ISO) and its principals. */\nexport const SshCertResponseSchema = z.object({\n cert: z.string(),\n expires: z.string(),\n principals: z.array(z.string()),\n});\nexport type SshCertResponse = z.infer<typeof SshCertResponseSchema>;\n\n/** `GET /ssh/ca` answer: the CA's public key, the line boxes trust after `cert-authority `. */\nexport const SshCaResponseSchema = z.object({\n publicKey: z.string(),\n /** CAs replaced by `ca rotate` (#55), newest first; a box still holding one of these has not had `kvbox server trust-ca` run on its host. */\n retired: z.array(z.object({ publicKey: z.string(), retiredAt: z.string() })).optional(),\n});\nexport type SshCaResponse = z.infer<typeof SshCaResponseSchema>;\n\n/** `GET /hosts/self/ssh-ca` on the control plane, by the host secret: the CA every box should trust (`kvbox server trust-ca --from-cloud`, #55). */\nexport const HostSshCaResponseSchema = z.object({\n publicKey: z.string(),\n});\n\n/** `GET /ssh/cloud-ca` on a host's socket: what its control plane says the CA is, with the fingerprint to confirm. */\nexport const CloudCaSchema = z.object({\n controlPlane: z.string(),\n publicKey: z.string(),\n fingerprint: z.string(),\n});\nexport type CloudCa = z.infer<typeof CloudCaSchema>;\n\n/** `POST /ssh/trust-ca` on a host's socket (#55): the CA public key (a pasted `cert-authority …` line is accepted too). */\nexport const TrustCaRequestSchema = z.object({\n publicKey: z.string().min(1),\n});\nexport type TrustCaRequest = z.infer<typeof TrustCaRequestSchema>;\n\n/**\n * When a box's new authorized_keys reach the guest: `now` (pushed through kvbox-agent), or at its\n * next `start` (stopped: kvbox-init writes the file at boot), `wake` (hibernated), `resume`\n * (standby), or `later` (running, but its agent could not take them: the next stop and start).\n */\nexport const SshKeysAppliedSchema = z.enum([\"now\", \"start\", \"wake\", \"resume\", \"later\"]);\nexport type SshKeysApplied = z.infer<typeof SshKeysAppliedSchema>;\n\n/** `POST /ssh/trust-ca` answer: every cloud box on the host, by what happened to it. Boxes are `owner/name`. */\nexport const TrustCaReportSchema = z.object({\n publicKey: z.string(),\n fingerprint: z.string(),\n /** The guest trusts the CA now. */\n updated: z.array(z.string()),\n /** meta.json has the line; the guest gets it at `when`. */\n pending: z.array(z.object({ box: z.string(), when: SshKeysAppliedSchema, why: z.string().optional() })),\n failed: z.array(z.object({ box: z.string(), error: z.string() })),\n /** Local boxes, untouched: they trust the host's key only. */\n local: z.number().int(),\n});\nexport type TrustCaReport = z.infer<typeof TrustCaReportSchema>;\n\n/** `POST /hosts/join` body from `kvbox-server join` (#18); `fingerprint` is the host's TLS cert sha256, colon-separated. */\nexport const HostJoinRequestSchema = z.object({\n token: z.string().min(1),\n name: z.string().min(1),\n url: z.string().url(),\n fingerprint: z.string().regex(/^([0-9A-F]{2}:){31}[0-9A-F]{2}$/),\n publicAddress: z.string().min(1),\n});\nexport type HostJoinRequest = z.infer<typeof HostJoinRequestSchema>;\n\n/** `POST /hosts/join` answer: the secret the control plane will present to the host from now on (#18). */\nexport const HostJoinResponseSchema = z.object({\n hostSecret: z.string(),\n controlPlane: z.object({ name: z.string() }),\n});\nexport type HostJoinResponse = z.infer<typeof HostJoinResponseSchema>;\n\n/** A host as the control plane knows it; returned by `GET /hosts` (admin). */\nexport const CloudHostSchema = z.object({\n name: z.string(),\n url: z.string(),\n publicAddress: z.string(),\n joinedAt: z.string(),\n lastSeenAt: z.string().nullable(),\n capacity: CapacitySchema.nullable(),\n});\nexport type CloudHost = z.infer<typeof CloudHostSchema>;\n","/**\n * SSH public keys as text, for the three places that handle the CA's: the control plane writes a\n * box's `cert-authority` line and prints a fingerprint after `ca rotate`, the host builds the same\n * line for every box at `kvbox server trust-ca`, the CLI shows the fingerprint before asking.\n */\nimport { createHash } from \"node:crypto\";\nimport { KvboxError } from \"./errors.js\";\n\n/** `<type> <base64>[ <comment>]`, one line; the types OpenSSH signs certificates with. */\nexport const SSH_PUBLIC_KEY_RE =\n /^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp(?:256|384|521)|sk-ssh-ed25519@openssh\\.com|sk-ecdsa-sha2-nistp256@openssh\\.com) ([A-Za-z0-9+/]+=*)(?: [^\\r\\n]*)?$/;\n\n/** The key, trimmed, with a leading `cert-authority ` (a pasted authorized_keys line) allowed and dropped. */\nexport function parseSshPublicKey(text: string): string {\n const key = text.trim().replace(/^cert-authority\\s+/, \"\");\n if (!SSH_PUBLIC_KEY_RE.test(key)) {\n throw new KvboxError(\"that is not an SSH public key; expected one line like: ssh-ed25519 AAAA… kvbox-ca@kvbox.sh\");\n }\n return key;\n}\n\n/** `SHA256:<base64, no padding>` of the key blob, what `ssh-keygen -l` prints. */\nexport function sshKeyFingerprint(publicKey: string): string {\n const m = SSH_PUBLIC_KEY_RE.exec(publicKey.trim());\n if (!m) throw new KvboxError(\"cannot fingerprint: not an SSH public key\");\n return `SHA256:${createHash(\"sha256\").update(Buffer.from(m[2]!, \"base64\")).digest(\"base64\").replace(/=+$/, \"\")}`;\n}\n\n/**\n * A box's authorized_keys line for a CA: trust it, but only for certificates naming `principal`\n * (the box's owner, `<slug>@<realm>`); sshd then ignores the login name and matches `principals=`.\n */\nexport function caLineFor(principal: string, caPublicKey: string): string {\n return `cert-authority,principals=\"${principal}\" ${caPublicKey}`;\n}\n\n/** Whether an authorized_keys line is a CA line (any options, the keyword first). */\nexport const isCaLine = (line: string): boolean => /^cert-authority(,|\\s)/.test(line.trim());\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","/**\n * Firecracker needs /dev/kvm. A daemon that cannot open it starts fine and only fails at the first\n * `kvbox new`, with an opaque firecracker 400 (#61): the usual cause is a shell that logged in\n * before the user was added to the kvm group, so the daemon it spawned runs without that group.\n * Checked once at `kvbox-server start`, before the socket is bound, and told in plain words.\n */\nimport { access, constants, readFile, stat } from \"node:fs/promises\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nexport const KVM_DEVICE = \"/dev/kvm\";\n\n/** The group's name for a gid from /etc/group, `kvm` when the file does not say. */\nexport async function groupName(gid: number, groupFile = \"/etc/group\"): Promise<string> {\n const text = await readFile(groupFile, \"utf8\").catch(() => \"\");\n for (const line of text.split(\"\\n\")) {\n const [name, , id] = line.split(\":\");\n if (id !== undefined && Number.parseInt(id, 10) === gid && name) return name;\n }\n return \"kvm\";\n}\n\n/** Resolves when this process can open the device for reading and writing; a KvboxError saying what to do otherwise. */\nexport async function requireKvm(device = KVM_DEVICE, groupFile = \"/etc/group\"): Promise<void> {\n try {\n await access(device, constants.R_OK | constants.W_OK);\n return;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw new KvboxError(`${device} is missing: this machine has no KVM, so boxes cannot run here (enable virtualization in the BIOS, then install-server.sh checks the rest)`);\n }\n if (code !== \"EACCES\" && code !== \"EPERM\") throw new KvboxError(`cannot open ${device}: ${(err as Error).message}`);\n }\n const owner = await stat(device).then((s) => groupName(s.gid, groupFile), () => \"kvm\");\n throw new KvboxError(\n `cannot start: this process is not allowed to open ${device}, so no box could run. ` +\n `It was started from a shell without the ${owner} group (a login from before you were added to it). ` +\n `Log out and back in, or start it from a shell that has the group: sg ${owner} -c \"kvbox server start\"`,\n );\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 { MAX_BOX_PORTS, type BoxStatus, type CreateMachineRequest, type Machine, type PortsRequest, type RecoveryReport, type RescaleMachineRequest, type SetMachineRequest, type SshKeysApplied, type TrustCaReport } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { SIZES, isSizeName } from \"@kvbox/shared/sizes\";\nimport { caLineFor, isCaLine, parseSshPublicKey, sshKeyFingerprint } from \"@kvbox/shared/ssh\";\nimport { isUnknownOp, setAuthorizedKeys, setIdentity } from \"./agent.js\";\nimport { assertRoomFor } from \"./capacity.js\";\nimport { closeOpenRun, closeRunCutByBoot, insertUsageEvent, type UsageState } from \"./db.js\";\nimport { inScope, parseRef, realmOf, refKey, shown, type BoxRef, type ListScope } from \"./refs.js\";\nimport { loadConfig, type Config } from \"./config.js\";\nimport { locked, withBoxLock, withHostLock } from \"./locks.js\";\nimport { run } from \"./exec.js\";\nimport { FirecrackerClient } from \"./firecracker.js\";\nimport { attachTap, closeProxy, createTap, deleteTap, ensureHostNetwork, listeningPorts, macFor, nextFreeIp, openProxy, pickSshPort, type Proxy } from \"./network.js\";\nimport {\n listMachineRefs,\n newBoxId,\n currentBootId,\n hostBootTime,\n pidAlive,\n readMachineMeta,\n readSnapshotMeta,\n vmAlive,\n writeMachineMeta,\n type MachineMeta,\n type SnapshotMeta,\n} from \"./state.js\";\n\n/** Box names double as guest hostnames; short and plain on purpose. */\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\n/** Every id in use on the host, so a new draw can avoid them. */\nconst idsInUse = (metas: MachineMeta[]) => new Set(metas.map((m) => m.id));\n/** Every public port a box on the host holds, running or not (its SSH port and the ones it published): a port stays the box's for its life. */\nconst publicPortsInUse = (metas: MachineMeta[]) => metas.flatMap((m) => [...(m.sshPort === undefined ? [] : [m.sshPort]), ...(m.ports ?? []).map((f) => f.hostPort)]);\n\n/**\n * A box made through a control plane (its owner is `user@realm`) is reached from the internet:\n * it gets the control plane's authorized_keys lines and a public SSH port on the host (#49).\n * A box the host owner makes over the socket keeps the host key only and no public port.\n */\nconst isCloudBox = (owner: string) => realmOf(owner) !== null;\n\ntype Forwarded = Pick<MachineMeta, \"id\" | \"ip\" | \"sshPort\" | \"ports\">;\n\n/** Every forward the box has on the host: its public SSH port (#49) and the ports it published (#30). */\nfunction boxProxies(meta: Forwarded): Proxy[] {\n const ssh: Proxy[] = meta.sshPort === undefined ? [] : [{ box: meta.id, boxIp: meta.ip, hostPort: meta.sshPort, guestPort: 22 }];\n return [...ssh, ...(meta.ports ?? []).map((f) => ({ box: meta.id, boxIp: meta.ip, hostPort: f.hostPort, guestPort: f.guestPort, proto: f.proto }))];\n}\n\n/** Open the box's public ports (after Firecracker is up), always with its current IP; nothing to do for a box without any. */\nasync function openPorts(meta: Forwarded, cfg: Config): Promise<void> {\n for (const proxy of boxProxies(meta)) await openProxy(proxy, cfg);\n}\n\n/** Close them (the box is going down); a failure here is logged, the box's own state change goes on. */\nasync function closePorts(meta: Forwarded, cfg: Config): Promise<void> {\n for (const proxy of boxProxies(meta)) {\n await closeProxy(proxy, cfg).catch((err: Error) => console.error(`warning: could not close port ${proxy.hostPort}: ${err.message}`));\n }\n}\n\n/** Public ports drawn but not in any meta.json yet: the next draw must see them too. */\nconst reservedPorts = new Set<number>();\n\n/**\n * `count` fresh public ports: random, never 22, not another box's, not something the host listens\n * on (#49, #30). Drawn under the host's `ports` lock and held in `reservedPorts` until the caller has\n * written them to meta.json and calls `release`, so two boxes drawing at once never get the same one.\n */\nasync function drawPorts(count: number, p: Paths): Promise<{ ports: number[]; release: () => void }> {\n return withHostLock(\"ports\", async () => {\n // Reservations first: one released while the metas are read was written before its release, but\n // that write may be the half-written meta.json the read skipped.\n const reserved = [...reservedPorts];\n const taken = new Set([...reserved, ...publicPortsInUse(await readAllMeta(p)), ...(await listeningPorts())]);\n const ports: number[] = [];\n for (let i = 0; i < count; i++) {\n const port = pickSshPort(taken);\n taken.add(port);\n ports.push(port);\n }\n for (const port of ports) reservedPorts.add(port);\n return { ports, release: () => ports.forEach((port) => reservedPorts.delete(port)) };\n });\n}\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/** Whole GiB of the box's overlay (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(p.machine(meta.owner, meta.name).overlay).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: meta.id, 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 !vmAlive(meta) && existsSync(p.machine(meta.owner, meta.name).hibernateVmstate);\n}\n\nexport function statusOf(meta: MachineMeta, p: Paths = paths()): BoxStatus {\n if (vmAlive(meta)) 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. */\nexport function 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 = vmAlive(meta);\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(meta.id, new Date().toISOString(), p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n }\n return {\n id: meta.id,\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(p.machine(meta.owner, meta.name).overlay),\n base: meta.base,\n createdAt: meta.createdAt,\n source: meta.source,\n status: statusOf(meta, p),\n ...(meta.sshPort === undefined ? {} : { sshPort: meta.sshPort }),\n ...(meta.ports?.length ? { ports: meta.ports.map((f) => ({ ...f })) } : {}),\n ...(meta.autoHibernateSec ? { autoHibernateSec: meta.autoHibernateSec } : {}),\n };\n}\n\n/** The idle timeout a new box gets (#47): the request's, else the host's default; 0 is stored as absent. */\nfunction autoHibernateFor(req: CreateMachineRequest, cfg: Config): number | undefined {\n return (req.autoHibernateSec ?? cfg.autoHibernateSec) || undefined;\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(scope: ListScope, p: Paths = paths()): Promise<Machine[]> {\n return (await readAllMeta(p)).filter((m) => inScope(m.owner, scope)).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\n/** Lines a box's authorized_keys may hold: the host's key plus what the control plane sends. */\nexport const MAX_SSH_KEY_LINES = 8;\n/** The kernel command line is 2 KB on x86; the rest of ours is ~200 bytes, so the key blob gets this much. */\nconst MAX_SSH_KEYS_B64 = 1500;\n\n/** The authorized_keys lines a box holds: the host's own key first, then what the control plane gave it. Checked, never written unchecked. */\nexport function authorizedKeysLines(hostKey: string, extra: readonly string[]): string[] {\n const lines = [hostKey.trim(), ...extra.map((l) => l.trim())];\n if (lines.some((l) => l === \"\" || /[\\r\\n]/.test(l))) throw new KvboxError(\"sshKeys: every entry must be one non-empty authorized_keys line\");\n if (lines.length > MAX_SSH_KEY_LINES) {\n throw new KvboxError(`a box takes at most ${MAX_SSH_KEY_LINES - 1} SSH keys on top of the host's own; ${extra.length} were given`);\n }\n return lines;\n}\n\n/**\n * The `kvbox.sshkey=` value: the host's own public key and every extra authorized_keys line, as\n * base64 of the whole file (one line each, trailing newline). kvbox-init in the image decodes it\n * verbatim into the kvbox user's authorized_keys at every boot, so `cert-authority …` lines work\n * without an image change. Checked before Firecracker starts.\n */\nexport function authorizedKeysB64(hostKey: string, extra: readonly string[]): string {\n const lines = authorizedKeysLines(hostKey, extra);\n const b64 = Buffer.from(lines.join(\"\\n\") + \"\\n\").toString(\"base64\");\n if (b64.length > MAX_SSH_KEYS_B64) {\n throw new KvboxError(`the SSH keys for this box do not fit the kernel command line (${b64.length} bytes encoded, ${MAX_SSH_KEYS_B64} at most); use fewer or shorter keys`);\n }\n return b64;\n}\n\nexport function bootArgs(name: string, ip: string, cfg: Config, pubkeyB64: string): string {\n // Firecracker appends `pci=off root=/dev/vda ro` itself. ip= is read by the guest kernel,\n // kvbox.name= / kvbox.sshkey= by kvbox-init on first boot (the kvbox-images contract).\n // /sbin/overlay-init in the image stacks the box's disk (/dev/vdb) on the read-only base before\n // systemd starts.\n const args = `console=ttyS0 reboot=k panic=1 init=/sbin/overlay-init kvbox.overlay=/dev/vdb 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 not an installed base image. */\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. */\nfunction baseFileFor(meta: Pick<MachineMeta, \"name\" | \"base\">, p: Paths): string {\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 without /sbin/overlay-init (not built by kvbox-images) 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 not a kvbox base image (no /sbin/overlay-init); rerun install-server.sh`);\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 id: string;\n name: string;\n owner: string;\n ip: string;\n mac: string;\n vcpu: number;\n memMib: number;\n base: string;\n /** See MachineMetaSchema (#49). */\n sshKeys?: string[] | undefined;\n sshPort?: number | 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));\n await fc.rootDrive(baseFile);\n await fc.overlayDrive(OVERLAY_REL);\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, and need not be: the\n * vmstate names the overlay relative to the box dir, so it already resolves to this box's copy.\n * 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 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 } finally {\n await fc.close();\n }\n return pid;\n } catch (err) {\n killQuietly(pid);\n throw err;\n }\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 host's own public key line: every box on the host trusts it (that is how local `connect` works). */\nasync function readHostPubkey(p: Paths): Promise<string> {\n try {\n return (await readFile(`${p.sshKey}.pub`, \"utf8\")).trim();\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 cloud = isCloudBox(owner);\n const sshKeys = cloud && req.sshKeys !== undefined && req.sshKeys.length > 0 ? req.sshKeys : undefined;\n const keysB64 = authorizedKeysB64(await readHostPubkey(p), sshKeys ?? []);\n\n const existing = await readAllMeta(p);\n // names are per owner; IPs, taps and public ports are per host\n const name = pickName(req.name, new Set(existing.filter((m) => m.owner === owner).map((m) => m.name)));\n const id = newBoxId(idsInUse(existing));\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 let pid: number | undefined;\n let sshPort: number | undefined;\n let drawn: Awaited<ReturnType<typeof drawPorts>> | undefined;\n try {\n drawn = cloud ? await drawPorts(1, p) : undefined;\n sshPort = drawn?.ports[0];\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(id, cfg);\n tapCreated = true;\n const spec: LaunchSpec = { id, name, owner, ip, mac, vcpu: size.vcpu, memMib: size.memMib, base: base.version, sshKeys, sshPort };\n pid = await launch(spec, tap, cfg, keysB64, p);\n await openPorts(spec, cfg);\n const meta: MachineMeta = { ...spec, pid, bootId: currentBootId(), createdAt: new Date().toISOString(), source: \"base\", autoHibernateSec: autoHibernateFor(req, cfg) };\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 (pid !== undefined) killQuietly(pid);\n await closePorts({ id, ip, sshPort }, cfg);\n if (tapCreated) await deleteTap(id, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n } finally {\n drawn?.release();\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 // The restored guest keeps the authorized_keys it was frozen with (kvbox-init does not run again);\n // the lines are kept so a later cold boot (`stop`, `start`) writes them like a fresh box.\n const cloud = isCloudBox(owner);\n const sshKeys = cloud && req.sshKeys !== undefined && req.sshKeys.length > 0 ? req.sshKeys : undefined;\n authorizedKeysB64(await readHostPubkey(p), sshKeys ?? []);\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 // A restored box is a new box: its own id, never the source box's (a snapshot carries none).\n const id = newBoxId(idsInUse(existing));\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 let sshPort: number | undefined;\n let drawn: Awaited<ReturnType<typeof drawPorts>> | undefined;\n try {\n drawn = cloud ? await drawPorts(1, p) : undefined;\n sshPort = drawn?.ports[0];\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(id, cfg, { detached: true });\n tapCreated = true;\n const spec: LaunchSpec = { id, name, owner, ip, mac, vcpu: snap.vcpu, memMib: snap.memMib, base: snap.base, sshKeys, sshPort };\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; the restored box was discarded, try again`,\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 // The guest woke up with the authorized_keys the snapshot froze; give it the current ones (#63).\n const stale = await pushAuthorizedKeys({ owner, name, sshKeys }, m.vsock, p);\n await attachTap(id, cfg);\n await openPorts(spec, cfg);\n const meta: MachineMeta = { ...spec, pid, bootId: currentBootId(), createdAt: new Date().toISOString(), source: `snapshot:${refKey(from)}`, memSnapshots: 1, sshKeysStale: stale ? true : undefined, autoHibernateSec: autoHibernateFor(req, cfg) };\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 await closePorts({ id, ip, sshPort }, cfg);\n if (tapCreated) await deleteTap(id, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n } finally {\n drawn?.release();\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\n/**\n * Hand a live guest its current authorized_keys through kvbox-agent (base v0.6.0 and later): a\n * restored or woken box has the file it was frozen with, which may predate a CA change (#63, #55).\n * Never fails the caller. The reason is returned (and logged) when the guest keeps its old file: an\n * image whose agent does not know the request, or one that did not answer; a boot fixes both.\n */\nasync function pushAuthorizedKeys(box: Pick<MachineMeta, \"owner\" | \"name\" | \"sshKeys\">, vsock: string, p: Paths): Promise<string | undefined> {\n try {\n await setAuthorizedKeys(vsock, authorizedKeysLines(await readHostPubkey(p), box.sshKeys ?? []), AGENT_REPLY_MS);\n return undefined;\n } catch (err) {\n const why = isUnknownOp(err)\n ? `its image predates base v0.6.0, whose kvbox-agent can replace authorized_keys (kvbox vm update ${shown(box)} moves it onto the current base)`\n : (err as Error).message;\n console.error(`warning: box ${shown(box)} keeps the authorized_keys it was frozen with: ${why}`);\n return why;\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 (vmAlive(meta)) {\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 public port, the tap and the sockets it left behind. */\nasync function cleanupProcess(meta: MachineMeta, cfg: Config, p: Paths): Promise<void> {\n await closePorts(meta, cfg);\n await deleteTap(meta.id, 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 const stopMachine = locked(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 (!vmAlive(meta) && !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 const startMachine = locked(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 (vmAlive(meta)) 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 keysB64 = authorizedKeysB64(await readHostPubkey(p), meta.sshKeys ?? []);\n await ensureHostNetwork(cfg);\n const tap = await createTap(meta.id, cfg);\n let pid: number | undefined;\n try {\n pid = await launch(meta, tap, cfg, keysB64, p);\n await openPorts(meta, cfg);\n const started: MachineMeta = { ...meta, pid, bootId: currentBootId(), sshKeysStale: undefined }; // kvbox-init writes the file from the command line\n await writeMachineMeta(started, p);\n recordState(started, \"running\", \"start\", p);\n return toMachine(started, p);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n await closePorts(meta, cfg);\n await deleteTap(meta.id, cfg).catch(() => undefined);\n throw err;\n }\n});\n\n/**\n * Replace the authorized_keys lines the box gets on top of the host's key (the control plane's\n * `rewrite-boxes`: a new CA line for the box's owner). Checked like at `new`, before anything is\n * written. A running box gets them through kvbox-agent right away; any other state gets them when\n * it next runs (`applied` says when).\n */\nexport const setSshKeys = locked(async function setSshKeys(ref: BoxRef, sshKeys: readonly string[], p: Paths = paths()): Promise<{ machine: Machine; applied: SshKeysApplied }> {\n const meta = await readMeta(ref, p);\n // Like `new`: a local box trusts this host's key and nothing else; only a cloud box carries lines.\n if (!isCloudBox(meta.owner)) throw new KvboxError(`box ${shown(ref)} is local: it trusts this host's key, there are no authorized_keys lines to replace`);\n // A cloud box with the host's key alone would be open to nobody who logs in: one bad call must not do that fleet-wide.\n if (sshKeys.length === 0) throw new KvboxError(\"sshKeys: at least one authorized_keys line (the box would keep only the host's own key)\");\n authorizedKeysB64(await readHostPubkey(p), sshKeys);\n const { meta: updated, applied } = await applySshKeys(meta, sshKeys, p);\n return { machine: toMachine(updated, p), applied };\n});\n\n/**\n * Write new `sshKeys` into meta.json and get them to the guest: through kvbox-agent when the box\n * runs, else at its next start (kvbox-init), wake or resume (the `sshKeysStale` flag makes those\n * push). A running box whose agent could not take them is `later`: its next stop and start.\n */\nasync function applySshKeys(meta: MachineMeta, sshKeys: readonly string[], p: Paths): Promise<{ meta: MachineMeta; applied: SshKeysApplied; why?: string }> {\n const status = statusOf(meta, p);\n let updated: MachineMeta = { ...meta, sshKeys: [...sshKeys], sshKeysStale: status === \"stopped\" ? undefined : true };\n let applied: SshKeysApplied = status === \"stopped\" ? \"start\" : status === \"standby\" ? \"resume\" : status === \"hibernated\" ? \"wake\" : \"later\";\n let why: string | undefined;\n if (status === \"running\") {\n why = await pushAuthorizedKeys(updated, p.machine(meta.owner, meta.name).vsock, p);\n if (why === undefined) {\n updated = { ...updated, sshKeysStale: undefined };\n applied = \"now\";\n }\n }\n await writeMachineMeta(updated, p);\n return why === undefined ? { meta: updated, applied } : { meta: updated, applied, why };\n}\n\n/**\n * `kvbox server trust-ca` (#55): every cloud box on this host trusts `publicKey` as the CA for its\n * owner, in place of the CA line it had (one CA per box, as at `new`; the old CA is out, which is\n * the point after a leak, and a laptop renews its certificate at the next refused connect). Local\n * boxes are untouched. A box that is not running gets the line when it next runs.\n */\nexport async function trustCa(publicKeyText: string, p: Paths = paths()): Promise<TrustCaReport> {\n const publicKey = parseSshPublicKey(publicKeyText);\n const report: TrustCaReport = { publicKey, fingerprint: sshKeyFingerprint(publicKey), updated: [], pending: [], failed: [], local: 0 };\n const hostKey = await readHostPubkey(p);\n for (const listed of await readAllMeta(p)) {\n if (!isCloudBox(listed.owner)) {\n report.local++;\n continue;\n }\n const box = refKey(listed);\n try {\n await withBoxLock(listed, async () => {\n const meta = await readMeta(listed, p); // again, under the lock: the listing may be stale by now\n const sshKeys = [...(meta.sshKeys ?? []).filter((l) => !isCaLine(l)), caLineFor(meta.owner, publicKey)];\n authorizedKeysLines(hostKey, sshKeys);\n const { applied, why } = await applySshKeys(meta, sshKeys, p);\n if (applied === \"now\") report.updated.push(box);\n else report.pending.push(why === undefined ? { box, when: applied } : { box, when: applied, why });\n });\n } catch (err) {\n report.failed.push({ box, error: (err as Error).message });\n }\n }\n return report;\n}\n\n/** `kvbox pause`: freeze the VM in place. Memory and processes stay, no CPU is used; `resume` is instant. */\nexport const pauseMachine = locked(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 const resumeMachine = locked(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 const m = p.machine(ref.owner, ref.name);\n await resumeVm(m.sock);\n // Keys changed while it was frozen (#55): the agent can take them now.\n const stale = meta.sshKeysStale ? await pushAuthorizedKeys(meta, m.vsock, p) : undefined;\n const running: MachineMeta = { ...meta, paused: undefined, sshKeysStale: stale ? true : 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 * `by` names who asked in the ledger: `hibernate` for a caller, `auto-hibernate` for core/idle.ts.\n */\nexport const hibernateMachine = locked(async function hibernateMachine(ref: BoxRef, p: Paths = paths(), by: string = \"hibernate\"): 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 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\", by, 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 const wakeMachine = locked(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 (!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(meta.id, cfg, { detached: true });\n let pid: number | undefined;\n let stale: string | undefined;\n try {\n const spec: LaunchSpec = { id: meta.id, 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 // The guest's authorized_keys are the ones it slept with; the CA may have changed meanwhile (#55).\n stale = await pushAuthorizedKeys(meta, m.vsock, p);\n await attachTap(meta.id, cfg);\n await openPorts(meta, cfg);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n await closePorts(meta, cfg);\n await deleteTap(meta.id, 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, bootId: currentBootId(), memSnapshots: 1, paused: undefined, sshKeysStale: stale ? true : 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 = vmAlive(meta);\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 const updateMachine = locked(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 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 const rescaleMachine = locked(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 = p.machine(ref.owner, ref.name).overlay;\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/** `kvbox vm set <box>`: settings the VM itself never sees, so they apply in any state and at once. */\nexport const setMachine = locked(async function setMachine(ref: BoxRef, req: SetMachineRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const next: MachineMeta = { ...meta };\n if (req.autoHibernateSec !== undefined) next.autoHibernateSec = req.autoHibernateSec || undefined;\n await writeMachineMeta(next, p);\n return toMachine(next, p);\n});\n\ntype PortKey = { guestPort: number; proto: \"tcp\" | \"udp\" };\nconst portKeys = (req: PortsRequest): PortKey[] => {\n const keys = req.ports.map((x) => ({ guestPort: x.guestPort, proto: x.proto ?? \"tcp\" }));\n return keys.filter((k, i) => keys.findIndex((o) => o.guestPort === k.guestPort && o.proto === k.proto) === i);\n};\nconst samePort = (a: PortKey) => (b: PortKey) => a.guestPort === b.guestPort && a.proto === b.proto;\n\n/**\n * `kvbox vm proxy add` (#30): publish box ports on the host's public address, each on a host port\n * drawn at random. All or nothing: if one forward cannot be opened, the ones this call opened are\n * closed and nothing is stored. A box that is not running keeps them in meta.json; they open when\n * it next runs, like its SSH port.\n */\nexport const addPorts = locked(async function addPorts(ref: BoxRef, req: PortsRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const current = meta.ports ?? [];\n const wanted = portKeys(req);\n const already = wanted.find((w) => current.some(samePort(w)));\n if (already) throw new KvboxError(`box ${shown(ref)} already publishes port ${already.guestPort} (${already.proto})`);\n // The box's SSH forward already accepts 22/tcp into it; a second forward to 22 would share that\n // FORWARD rule, and closing it would cut the box's SSH.\n if (meta.sshPort !== undefined && wanted.some(samePort({ guestPort: 22, proto: \"tcp\" }))) {\n throw new KvboxError(`box ${shown(ref)} already reaches port 22 from outside on port ${meta.sshPort} (kvbox connect)`);\n }\n if (current.length + wanted.length > MAX_BOX_PORTS) {\n throw new KvboxError(`a box publishes at most ${MAX_BOX_PORTS} ports; box ${shown(ref)} has ${current.length}`);\n }\n const drawn = await drawPorts(wanted.length, p);\n const opened: Proxy[] = [];\n try {\n const added = wanted.map((w, i) => ({ ...w, hostPort: drawn.ports[i]! }));\n if (vmAlive(meta)) {\n for (const proxy of boxProxies({ id: meta.id, ip: meta.ip, ports: added })) {\n await openProxy(proxy, cfg);\n opened.push(proxy);\n }\n }\n const next: MachineMeta = { ...meta, ports: [...current, ...added] };\n await writeMachineMeta(next, p);\n return toMachine(next, p);\n } catch (err) {\n // Nothing stored, so nothing may stay open: a rule meta.json does not name could never be removed.\n for (const proxy of opened) await closeProxy(proxy, cfg).catch(() => undefined);\n throw err;\n } finally {\n drawn.release();\n }\n});\n\n/** `kvbox vm proxy rm` (#30): stop publishing box ports. Their host ports go back to the pool. */\nexport const removePorts = locked(async function removePorts(ref: BoxRef, req: PortsRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const current = meta.ports ?? [];\n const gone = portKeys(req);\n const missing = gone.find((g) => !current.some(samePort(g)));\n if (missing) throw new KvboxError(`box ${shown(ref)} does not publish port ${missing.guestPort} (${missing.proto})`);\n const removed = current.filter((f) => gone.some(samePort(f)));\n // Closed first: a rule that would not go keeps the port in meta.json, so trying again finds it.\n // Closed whether or not the box runs: one whose Firecracker died never ran cleanupProcess, and its\n // rules would outlive the port's return to the pool. Closing what is not there is fine.\n for (const proxy of boxProxies({ id: meta.id, ip: meta.ip, ports: removed })) await closeProxy(proxy, cfg);\n const kept = current.filter((f) => !gone.some(samePort(f)));\n const next: MachineMeta = { ...meta, ports: kept.length > 0 ? kept : undefined };\n await writeMachineMeta(next, p);\n return toMachine(next, p);\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 const destroyMachine = locked(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// ── after the host was down (#29) ─────────────────────────────────────────────\n/** Boxes booted at once when the server brings them back: each boot is a burst of disk and CPU. */\nconst RECOVERY_CONCURRENCY = 2;\n\n/**\n * At server start, the boxes whose Firecracker died with an earlier boot of the host: meta.json still\n * names a pid, but from another boot. Each one's open run in the ledger is closed (at the host's boot\n * when it predates it) and its memory image goes: the next boot is fresh. A box that was in standby\n * lost its memory with the process, so it is left stopped; the others keep the old pid and boot id,\n * which mark them as not brought back yet, and are returned to be booted (`bootRecovered`). A box\n * whose Firecracker died earlier in this boot (a crash) is not touched: it reads as stopped, as it has\n * since. Done before the server listens, so a listing cannot close those runs at \"now\" first.\n */\nexport async function settleDeadBoxes(p: Paths = paths()): Promise<{ boot: BoxRef[]; leftStopped: string[] }> {\n const now = new Date().toISOString();\n const bootAt = hostBootTime()?.toISOString() ?? now;\n const boot: BoxRef[] = [];\n const leftStopped: string[] = [];\n for (const meta of await readAllMeta(p)) {\n if (!cutByReboot(meta) || vmAlive(meta)) continue;\n try {\n closeRunCutByBoot(meta.id, bootAt, now, p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n await rm(p.machine(meta.owner, meta.name).memBase, { force: true });\n if (meta.paused) {\n await writeMachineMeta({ ...meta, pid: null, bootId: undefined, memSnapshots: undefined, paused: undefined }, p);\n leftStopped.push(refKey(meta));\n } else {\n await writeMachineMeta({ ...meta, memSnapshots: undefined }, p);\n boot.push({ owner: meta.owner, name: meta.name });\n }\n }\n return { boot, leftStopped };\n}\n\n/** A pid launched in another boot of the host (or before #29, with no boot id): the reboot ended it. */\nfunction cutByReboot(meta: MachineMeta): boolean {\n return meta.pid !== null && meta.bootId !== currentBootId();\n}\n\nlet recovery: RecoveryReport | null = null;\nlet recoveryStopping = false;\nlet recoveryRun: Promise<unknown> = Promise.resolve();\n\n/** What `bootRecovered` did at this server's start (`/health`); null when nothing needed it. */\nexport function lastRecovery(): RecoveryReport | null {\n return recovery;\n}\n\n/**\n * For the server's shutdown: boot no further box, and resolve once the boots under way have written\n * their pid to meta.json (exiting halfway would leave a Firecracker no meta.json names). The boxes\n * not reached keep their old boot id, so the next server start brings them back.\n */\nexport async function stopRecovery(): Promise<void> {\n recoveryStopping = true;\n await recoveryRun;\n}\n\n/**\n * Boot the boxes `settleDeadBoxes` found, a few at a time, like `kvbox start` (fresh boot, current\n * SSH lines). A box someone started while it waited its turn now has this boot's id and is skipped.\n * One that does not come up is reported, never fatal: the server keeps serving.\n */\nexport async function bootRecovered(settled: { boot: readonly BoxRef[]; leftStopped: readonly string[] }, p: Paths = paths()): Promise<RecoveryReport | null> {\n const refs = settled.boot;\n if (refs.length === 0 && settled.leftStopped.length === 0) return null;\n const booted: string[] = [];\n const failed: RecoveryReport[\"failed\"] = [];\n const queue = [...refs];\n const worker = async () => {\n for (let ref = queue.shift(); ref !== undefined && !recoveryStopping; ref = queue.shift()) {\n try {\n if (!cutByReboot(await readMeta(ref, p))) continue;\n await startMachine(ref, p);\n booted.push(refKey(ref));\n } catch (err) {\n failed.push({ box: refKey(ref), error: (err as Error).message });\n }\n }\n };\n const run = Promise.all(Array.from({ length: Math.min(RECOVERY_CONCURRENCY, refs.length) }, worker));\n recoveryRun = run;\n await run;\n recovery = { at: new Date().toISOString(), booted, leftStopped: [...settled.leftStopped], failed };\n return recovery;\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 { GuestStatsSchema, type GuestStats } from \"@kvbox/shared/api\";\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/**\n * Replace the kvbox user's authorized_keys with exactly these lines (base v0.6.0 and later): a\n * restored or woken box has the file it was frozen with, the host has the current one (#63, #55).\n */\nexport function setAuthorizedKeys(udsPath: string, lines: readonly string[], timeoutMs?: number) {\n return agentCall(udsPath, { op: \"authorizedKeys\", lines: [...lines] }, timeoutMs);\n}\n\n/** The box's own load, memory, disk and uptime (base v0.7.0 and later). */\nexport async function stats(udsPath: string, timeoutMs?: number): Promise<GuestStats> {\n const reply = GuestStatsSchema.safeParse(await agentCall(udsPath, { op: \"stats\" }, timeoutMs));\n if (!reply.success) throw new KvboxError(`kvbox-agent sent stats kvbox does not understand: ${reply.error.issues[0]?.message ?? \"invalid\"}`);\n return reply.data;\n}\n\n/** An agent from an image older than the request it was sent. */\nexport const isUnknownOp = (err: unknown): boolean => /unknown op/.test((err as Error).message ?? \"\");\n\n/**\n * Nothing in the guest took the connection: an image older than kvbox-agent itself (before base\n * v0.5.0), so no vsock listener, or a box booted without the vsock socket.\n */\nexport const isNoAgent = (err: unknown): boolean =>\n /vsock connect refused|vsock connection closed before the guest accepted|kvbox-agent unreachable: connect (ENOENT|ECONNREFUSED)/.test((err as Error).message ?? \"\");\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. The constants live in shared/capacity.ts: the control plane applies the same\n * rule to each host's totals to place a box (#20). 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 { MEM_HEADROOM_MIB, VCPU_OVERSUBSCRIPTION } from \"@kvbox/shared/capacity\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { listMachineRefs, readMachineMeta, vmAlive } from \"./state.js\";\n\nexport { MEM_HEADROOM_MIB, VCPU_OVERSUBSCRIPTION };\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 (vmAlive(meta)) 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 * The capacity rule both sides apply. Firecracker reserves neither RAM nor cores, so a host counts\n * what its running boxes are sized at and refuses a box that would push the total past\n * memory: host RAM minus 2 GB the host keeps for itself (hard), or\n * vCPU: 2 x host cores (soft: vCPUs time-slice fine, this stops the absurd).\n * The host applies it box by box at `new` (server core/capacity.ts, with the names of the running\n * boxes in the refusal); the control plane applies it to each host's reported totals to choose\n * where a box lands (#20). Decision \"`zbox new` guards host capacity\".\n */\nimport type { Capacity } from \"./api.js\";\n\nexport const MEM_HEADROOM_MIB = 2048;\nexport const VCPU_OVERSUBSCRIPTION = 2;\n\nexport interface Want {\n vcpu: number;\n memMib: number;\n}\n\n/** What a host can still take: memory after the headroom and what is reserved, vCPUs under the cap. Never negative. */\nexport function freeOf(c: Capacity): { memMib: number; vcpu: number } {\n return {\n memMib: Math.max(0, c.hostMemMib - MEM_HEADROOM_MIB - c.reservedMemMib),\n vcpu: Math.max(0, c.hostCores * VCPU_OVERSUBSCRIPTION - c.reservedVcpu),\n };\n}\n\nexport function hasRoom(c: Capacity, want: Want): boolean {\n const free = freeOf(c);\n return want.memMib <= free.memMib && want.vcpu <= free.vcpu;\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 { randomBytes } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\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 /** Host-unique, minted at `kvbox new` (fresh or restored) and kept for the box's life; the tap is `kv-<id>`. */\n id: z.string(),\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 /**\n * The host boot `pid` belongs to (/proc/sys/kernel/random/boot_id at launch, #29). After a reboot\n * the number can name some other process; a pid from another boot is dead whatever `kill -0` says.\n * Absent (boxes launched before #29): the pid alone decides.\n */\n bootId: z.string().optional(),\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's overlay stacks on. */\n base: z.string(),\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 /**\n * authorized_keys lines the box gets on top of the host's own key, as the control plane sent them\n * at `new` (#49). kvbox-init rewrites authorized_keys from the kernel cmdline at every boot, so\n * `start` has to send the same lines again. Absent: host key only.\n */\n sshKeys: z.array(z.string()).optional(),\n /**\n * The guest's authorized_keys may not match `sshKeys`: they changed while the box was not running,\n * or its agent could not take them (#55, #63). Cleared by a push through kvbox-agent or a boot.\n */\n sshKeysStale: z.boolean().optional(),\n /** Public port on the host DNATed to the box's SSH while it runs (#49); fixed for the box's life. Absent: none. */\n sshPort: z.number().int().optional(),\n /**\n * Box ports published on the host (#30, `kvbox vm proxy`): unique per guest port and protocol,\n * each host port the box's for its life. DNATed while the box runs, rebuilt from here with its\n * current IP every time it comes up. Absent: none.\n */\n ports: z.array(z.object({ guestPort: z.number().int(), hostPort: z.number().int(), proto: z.enum([\"tcp\", \"udp\"]) })).optional(),\n /** Seconds without traffic on the box's tap before the server hibernates it (#47, core/idle.ts). Absent: never. */\n autoHibernateSec: z.number().int().positive().optional(),\n});\nexport type MachineMeta = z.infer<typeof MachineMetaSchema>;\n\n/** 6 lowercase hex chars: 16M values per host, 9 chars as a tap name, well inside Linux's 15-char limit. */\nexport const BOX_ID_RE = /^[0-9a-f]{6}$/;\n\n/** A fresh id no box on the host has (`taken`: every id in use, so a draw can be retried). */\nexport function newBoxId(taken: ReadonlySet<string>): string {\n for (;;) {\n const id = randomBytes(3).toString(\"hex\");\n if (!taken.has(id)) return id;\n }\n}\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>. */\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\nlet bootId: { id: string | undefined } | undefined;\n\n/** This boot's id (undefined where the kernel does not expose one). Read once: it cannot change under a running process. */\nexport function currentBootId(): string | undefined {\n if (bootId === undefined) {\n try {\n bootId = { id: readFileSync(\"/proc/sys/kernel/random/boot_id\", \"utf8\").trim() };\n } catch {\n bootId = { id: undefined };\n }\n }\n return bootId.id;\n}\n\n/** True when the box's Firecracker is still there: its pid is alive and was launched in this boot. */\nexport function vmAlive(meta: Pick<MachineMeta, \"pid\" | \"bootId\">): boolean {\n if (meta.bootId !== undefined && meta.bootId !== currentBootId()) return false;\n return pidAlive(meta.pid);\n}\n\n/** When the host booted, from /proc/stat's btime (null where there is none). */\nexport function hostBootTime(): Date | null {\n try {\n const m = /^btime (\\d+)$/m.exec(readFileSync(\"/proc/stat\", \"utf8\"));\n return m ? new Date(Number(m[1]) * 1000) : null;\n } catch {\n return null;\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\";\nimport type { UsageEvent, UsageState } from \"@kvbox/shared/usage\";\nimport { inScope, type ListScope } from \"./refs.js\";\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 // The ledger's identity (#42): a control plane keys pulled rows by it, so a re-join is recognised\n // and a fresh ledger (KVBOX_HOME wiped) restarts its cursor instead of waiting for ids it already saw.\n `create table ledger (id text not null);\n insert into ledger (id) values (lower(hex(randomblob(16))));\n create index usage_events_at on usage_events (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 { UsageEvent, UsageState };\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\nexport interface UsageEventRow extends UsageEvent {\n /** The box's id. Owner and name ride along so the ledger reads alone after a box is gone. */\n boxId: string;\n owner: string;\n name: string;\n}\n\ninterface Raw {\n id: number;\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/**\n * The run a host shutdown cut (#29): a run that began before the host booted cannot have outlived the\n * boot, so it ends at `bootAt`; one that began after it (Firecracker crashed since) ends `now`.\n */\nexport function closeRunCutByBoot(boxId: string, bootAt: string, now: string, p: Paths = paths()): boolean {\n const last = lastEvent(boxId, openDb(p));\n return closeOpenRun(boxId, last !== undefined && last.at < bootAt ? bootAt : now, p);\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/** A ledger row with its id: the cursor a control plane pulls by (#42). */\nexport type UsageEventWithId = UsageEventRow & { id: number };\n\nconst withId = (r: Raw): UsageEventWithId => ({ ...fromRaw(r), id: r.id });\n\n/** This home's ledger id, made with the database; it changes only when the database is recreated. */\nexport function ledgerId(p: Paths = paths()): string {\n return (openDb(p).prepare(\"select id from ledger\").get() as { id: string }).id;\n}\n\n/**\n * Rows after `after` by id (the order they were written in, so a puller never misses one), at\n * most `limit`, of the owners in `scope`. The id is monotonic: a pull is resumable and a repeat\n * is a no-op on the other side.\n */\nexport function usageEventsAfter(after: number, limit: number, scope: ListScope, p: Paths = paths()): UsageEventWithId[] {\n const db = openDb(p);\n const rows = (scope === null\n ? db.prepare(\"select * from usage_events where id > ? order by id limit ?\").all(after, limit)\n : typeof scope === \"string\"\n ? db.prepare(\"select * from usage_events where id > ? and owner = ? order by id limit ?\").all(after, scope, limit)\n : db.prepare(\"select * from usage_events where id > ? and substr(owner, -length(?)) = ? order by id limit ?\").all(after, `@${scope.realm}`, `@${scope.realm}`, limit)) as unknown as Raw[];\n return rows.map(withId);\n}\n\n/**\n * The rows of the owners in `scope` that a report over the window needs, in time order: those inside\n * it plus each box's last row before it (the state the window opens in). The host-wide report (#41).\n */\nexport function usageEventsInScope(scope: ListScope, window: { from: string; to: string }, p: Paths = paths()): UsageEventWithId[] {\n const rows = openDb(p)\n .prepare(\n `select * from usage_events where at < ? and (at >= ? or id in (select max(id) from usage_events where at < ? group by box_id))\n order by at, id`,\n )\n .all(window.to, window.from, window.from) as unknown as Raw[];\n return rows.filter((r) => inScope(r.owner, scope)).map(withId);\n}\n\n","/**\n * One operation on a box at a time (#64). Every change to a box (its meta.json, its Firecracker process,\n * its memory image) runs under the box's lock, so a background job such as core/idle.ts cannot step into\n * a caller's snapshot, and two read-modify-writes of meta.json cannot lose each other's change.\n * In-process only: the server is the only writer. Reentrant, so an operation that calls another one on\n * the same box (rescale -> start) does not wait on itself.\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { refKey, type BoxRef } from \"./refs.js\";\n\n/** box -> the promise the next caller waits on (resolved when the current holder and every earlier waiter are done). */\nconst tails = new Map<string, Promise<void>>();\n/** The boxes the current async call chain already holds. */\nconst held = new AsyncLocalStorage<ReadonlySet<string>>();\n\nexport function withBoxLock<T>(ref: BoxRef, fn: () => Promise<T>): Promise<T> {\n return withLock(refKey(ref), fn);\n}\n\n/**\n * A lock for something the whole host shares rather than one box: `ports` guards drawing public\n * ports (#30), which reads every box's meta.json. The key has no '/', so it never meets a box's.\n * Take it inside a box lock, never the other way round.\n */\nexport function withHostLock<T>(name: \"ports\", fn: () => Promise<T>): Promise<T> {\n return withLock(`host:${name}`, fn);\n}\n\nasync function withLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const mine = held.getStore();\n if (mine?.has(key)) return fn();\n const previous = tails.get(key);\n let release!: () => void;\n const tail = new Promise<void>((resolve) => (release = resolve));\n tails.set(key, tail);\n try {\n await previous;\n return await held.run(new Set([...(mine ?? []), key]), fn);\n } finally {\n release();\n if (tails.get(key) === tail) tails.delete(key);\n }\n}\n\n/** Whether something holds or waits for the box's lock right now. */\nexport function boxBusy(ref: BoxRef): boolean {\n return tails.has(refKey(ref));\n}\n\n/** `fn` with the lock of the box named by its first argument taken around every call. */\nexport function locked<A extends [BoxRef, ...unknown[]], R>(fn: (...args: A) => Promise<R>): (...args: A) => Promise<R> {\n return (...args) => withBoxLock(args[0], () => fn(...args));\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 /** /dev/vda: the shared base image, read-only. Firecracker adds `root=/dev/vda ro` to the boot args to match. */\n rootDrive(pathOnHost: string) {\n return this.drive(\"rootfs\", pathOnHost, { root: true, readOnly: true });\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 /**\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 /**\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: the vmstate names the overlay relative to the box dir (spawnFirecracker).\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 * Host networking: bridge `kvbox0`, one tap `kv-<box id>` 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 { randomInt } from \"node:crypto\";\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/** The host's end of a relay tunnel (core/relay.ts, #50): `relay up <conf> | down`, root via the script. */\nexport async function netSetup(cfg: NetConfig, args: string[]): Promise<void> {\n await netRun(cfg, args);\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// ── public ports (#49) ────────────────────────────────────────────────────────\n/** Where a box's public SSH port is drawn from: high, random, and never 22 (which every bot scans). */\nexport const SSH_PORT_MIN = 20000;\nexport const SSH_PORT_MAX = 60000;\n\n/**\n * A random port in [SSH_PORT_MIN, SSH_PORT_MAX] that is not in `taken` (other boxes' ports and\n * whatever listens on the host). Random so two boxes never get adjacent, guessable ports; after\n * a few unlucky draws it walks the range from a random start so a crowded host still gets one.\n */\nexport function pickSshPort(taken: ReadonlySet<number>): number {\n const span = SSH_PORT_MAX - SSH_PORT_MIN + 1;\n for (let i = 0; i < 32; i++) {\n const port = SSH_PORT_MIN + randomInt(span);\n if (!taken.has(port)) return port;\n }\n const start = randomInt(span);\n for (let i = 0; i < span; i++) {\n const port = SSH_PORT_MIN + ((start + i) % span);\n if (!taken.has(port)) return port;\n }\n throw new KvboxError(`no free port left between ${SSH_PORT_MIN} and ${SSH_PORT_MAX} on this host`);\n}\n\n/** Local ports out of `ss -ltnH` / `ss -lunH` output (one socket per line, the address in the 4th column). */\nexport function parseListeningPorts(ssOutput: string): Set<number> {\n const ports = new Set<number>();\n for (const line of ssOutput.split(\"\\n\")) {\n const cols = line.trim().split(/\\s+/);\n const local = cols[3];\n if (!local) continue;\n const port = Number(local.slice(local.lastIndexOf(\":\") + 1));\n if (Number.isInteger(port) && port > 0) ports.add(port);\n }\n return ports;\n}\n\n/**\n * TCP and UDP ports something on the host listens on right now, so a box's public port never\n * shadows one: a UDP forward drawn onto, say, WireGuard's random port would swallow the relay tunnel.\n * One set for both protocols: a port either one uses is not drawn.\n */\nexport async function listeningPorts(): Promise<Set<number>> {\n const ports = new Set<number>();\n for (const flags of [\"-ltnH\", \"-lunH\"]) {\n try {\n for (const port of parseListeningPorts((await run([\"ss\", flags])).stdout)) ports.add(port);\n } catch {\n // no ss: the draw still avoids other boxes' ports\n }\n }\n return ports;\n}\n\nexport interface Proxy {\n /** Box id; the rules are tagged `kvbox:<id>` so `status` and `down` find them. */\n box: string;\n boxIp: string;\n hostPort: number;\n guestPort: number;\n /** tcp unless said otherwise (#30 publishes UDP too). */\n proto?: \"tcp\" | \"udp\";\n}\n\nconst proxyArgs = (p: Proxy) => [p.box, p.boxIp, String(p.hostPort), String(p.guestPort), p.proto ?? \"tcp\"];\n\n/** DNAT `hostPort` on every non-bridge interface of the host to `boxIp:guestPort`. Idempotent. */\nexport async function openProxy(proxy: Proxy, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"proxy\", \"add\", ...proxyArgs(proxy)]);\n}\n\n/** Remove what `openProxy` added; nothing to remove is fine. */\nexport async function closeProxy(proxy: Proxy, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"proxy\", \"rm\", ...proxyArgs(proxy)]);\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 host's side of a relay (#50). A home host behind a router has no public address of its own;\n * a relay (a small public VM, set up with install-relay.sh) owns one for it and forwards it down a\n * WireGuard tunnel the host dials out. `kvbox-relay add` on the relay prints a join string; here it\n * becomes a wg-quick conf under relay/, which net-setup.sh installs as /etc/wireguard/kvbox.conf\n * and enables (root). config.json keeps what the rest of the server needs: the public IP `join`\n * advertises by default, the tunnel address, the endpoint. The private key stays in the conf.\n */\nimport { chmod, mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { decodeRelayJoin, RELAY_TUNNEL_GATEWAY, type RelayJoin } from \"@kvbox/shared/relay\";\nimport { loadConfig, saveConfig, type Relay } from \"./config.js\";\nimport { DEFAULT_HTTPS_PORT } from \"./controlPlane.js\";\nimport { netSetup } from \"./network.js\";\n\n/** The wg-quick conf for the host's end of the tunnel. */\nexport function relayConf(join: RelayJoin): string {\n return [\n \"# kvbox relay tunnel: made by `kvbox server relay`, installed by net-setup.sh. Do not edit.\",\n \"[Interface]\",\n `PrivateKey = ${join.privateKey}`,\n `Address = ${join.tunnelIp}/32`,\n \"\",\n \"[Peer]\",\n `PublicKey = ${join.relayKey}`,\n `Endpoint = ${join.relay}`,\n // Only the relay's own tunnel address goes through the tunnel: the host keeps its normal internet\n // route, and the relay SNATs forwarded connections so their replies come back this way.\n `AllowedIPs = ${RELAY_TUNNEL_GATEWAY}/32`,\n // The router forgets an idle outbound mapping; a packet every 25 s keeps the relay able to reach us.\n \"PersistentKeepalive = 25\",\n \"\",\n ].join(\"\\n\");\n}\n\n/** Decode the join string, write the conf, bring the tunnel up (root via net-setup.sh), remember the relay. */\nexport async function useRelay(joinString: string, p: Paths = paths()): Promise<Relay> {\n const join = decodeRelayJoin(joinString);\n if (!join) throw new KvboxError(\"that is not a relay join string; copy the whole line `kvbox-relay add` printed on the relay\");\n const cfg = await loadConfig(p);\n if (cfg.relay && cfg.relay.name !== join.name) {\n throw new KvboxError(`this host already goes through relay ${cfg.relay.name} (${cfg.relay.publicIp}); run kvbox server relay off first`);\n }\n // A re-issued string may carry another public IP; the control plane would keep calling the old one.\n if (cfg.relay && cfg.relay.publicIp !== join.publicIp && cfg.controlPlane?.advertise === cfg.relay.publicIp) {\n throw new KvboxError(\n `${cfg.controlPlane.name} reaches this host at ${cfg.relay.publicIp}, not ${join.publicIp}; run kvbox server leave first, then join again`,\n );\n }\n await mkdir(p.relay, { recursive: true, mode: 0o700 });\n await writeFile(p.relayConf, relayConf(join), { mode: 0o600 });\n await chmod(p.relayConf, 0o600);\n // The root helper also lets the control plane's port in on the tunnel interface (a host firewall would drop it).\n await netSetup(cfg, [\"relay\", \"up\", p.relayConf, String(cfg.controlPlane?.port ?? DEFAULT_HTTPS_PORT)]);\n const relay: Relay = { name: join.name, publicIp: join.publicIp, tunnelIp: join.tunnelIp, endpoint: join.relay };\n await saveConfig({ ...cfg, relay }, p);\n return relay;\n}\n\n/** Take the tunnel down and forget the relay. Refused while a control plane still reaches this host through it. */\nexport async function dropRelay(p: Paths = paths()): Promise<Relay> {\n const cfg = await loadConfig(p);\n const relay = cfg.relay;\n if (!relay) throw new KvboxError(\"this host does not go through a relay\");\n if (cfg.controlPlane?.advertise === relay.publicIp) {\n throw new KvboxError(`${cfg.controlPlane.name} reaches this host through the relay (${relay.publicIp}); run kvbox server leave first`);\n }\n await netSetup(cfg, [\"relay\", \"down\"]);\n await rm(p.relayConf, { force: true });\n const { relay: _gone, ...rest } = cfg;\n await saveConfig(rest, p);\n return relay;\n}\n","/**\n * The relay join string (#50). A home host behind a router gets a public address through a relay:\n * a small public VM with one extra IPv4 per host and a WireGuard tunnel the host dials out. The\n * relay's `kvbox-relay add <name> --ip <public-ip>` (kvbox-relay.sh at the repo root, bash: it builds\n * the same base64url token) makes the host's keypair and prints this string once; the host's\n * `kvbox server relay <string>` turns it into its tunnel. It carries the host's\n * private key, so it is a secret. The control plane never sees any of it: the host just advertises\n * the public IP.\n */\nimport { z } from \"zod\";\n\n/** Where WireGuard listens on the relay's primary address. */\nexport const RELAY_WG_PORT = 51820;\n/** The tunnel network: the relay is .1, hosts are .2 onwards. */\nexport const RELAY_TUNNEL_SUBNET = \"10.77.0.0/24\";\nexport const RELAY_TUNNEL_GATEWAY = \"10.77.0.1\";\n\nconst IPV4_RE = /^(\\d{1,3})(\\.\\d{1,3}){3}$/;\nconst WG_KEY_RE = /^[A-Za-z0-9+/]{43}=$/;\n\nexport const RelayJoinSchema = z.object({\n v: z.literal(1),\n /** How the relay lists this host. */\n name: z.string().regex(/^[a-z0-9][a-z0-9-]{0,30}$/),\n /** `<relay-primary-ip>:<port>`, the WireGuard endpoint the host dials. */\n relay: z.string().regex(/^(\\d{1,3})(\\.\\d{1,3}){3}:\\d{1,5}$/),\n /** The relay's WireGuard public key. */\n relayKey: z.string().regex(WG_KEY_RE),\n /** This host's address inside the tunnel. */\n tunnelIp: z.string().regex(IPV4_RE),\n /** This host's WireGuard private key, generated on the relay, kept nowhere else. */\n privateKey: z.string().regex(WG_KEY_RE),\n /** The extra public IPv4 the relay owns for this host; what the host advertises to the control plane. */\n publicIp: z.string().regex(IPV4_RE),\n});\nexport type RelayJoin = z.infer<typeof RelayJoinSchema>;\n\n/** The string the relay prints: base64url of the JSON, one token the owner can paste. */\nexport function encodeRelayJoin(join: RelayJoin): string {\n return Buffer.from(JSON.stringify(RelayJoinSchema.parse(join)), \"utf8\").toString(\"base64url\");\n}\n\n/** The string back into its fields, or null when it is not a relay join string. */\nexport function decodeRelayJoin(text: string): RelayJoin | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.from(text.trim(), \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n const res = RelayJoinSchema.safeParse(parsed);\n return res.success ? res.data : null;\n}\n","/**\n * Auto-hibernate (#47): a box with `autoHibernateSec` whose tap has carried no traffic, either way, for\n * that long is hibernated, so the host gets its RAM back and the meter moves to the cheaper state.\n * `connect` and `exec` already wake a hibernated box, and their ssh sends a keepalive every minute, so a\n * quiet open session counts as traffic. Any byte counts as activity; CPU-only work with nobody connected\n * looks idle (the guest's own view comes with #67). Only running boxes are watched: one in standby was\n * paused on purpose, for an instant resume. When a box was last active is kept in memory only, so a\n * server restart gives every box its full timeout again.\n */\nimport { readFile } from \"node:fs/promises\";\nimport type { Machine } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { boxBusy, withBoxLock } from \"./locks.js\";\nimport { getMachine, hibernateMachine, listMachines } from \"./machines.js\";\nimport { tapName } from \"./network.js\";\n\n/** Hibernations at once: each one dumps a box's whole memory to disk. */\nconst HIBERNATE_CONCURRENCY = 2;\n\nexport interface IdleWatchOptions {\n intervalMs?: number;\n /** Every box on the host. */\n list?: () => Promise<Machine[]>;\n /** rx + tx bytes of a box's tap; null when it cannot be read (no tap). */\n traffic?: (id: string) => Promise<number | null>;\n /** Hibernate the box if it still runs; false when it no longer did. */\n hibernate?: (box: Machine) => Promise<boolean>;\n /** Whether a caller's operation holds the box right now. */\n busy?: (box: Machine) => boolean;\n now?: () => number;\n log?: (line: string) => void;\n p?: Paths;\n}\n\n/** Bytes the box's tap has moved in both directions since it was created. */\nexport async function tapTraffic(id: string): Promise<number | null> {\n const dir = `/sys/class/net/${tapName(id)}/statistics`;\n try {\n const [rx, tx] = await Promise.all([readFile(`${dir}/rx_bytes`, \"utf8\"), readFile(`${dir}/tx_bytes`, \"utf8\")]);\n return Number(rx) + Number(tx);\n } catch {\n return null;\n }\n}\n\n/** Under the box's lock: hibernate it unless something paused, stopped or hibernated it since the listing. */\nasync function hibernateIfRunning(box: Machine, p: Paths): Promise<boolean> {\n const ref = { owner: box.owner, name: box.name };\n return withBoxLock(ref, async () => {\n if ((await getMachine(ref, p)).status !== \"running\") return false;\n await hibernateMachine(ref, p, \"auto-hibernate\");\n return true;\n });\n}\n\n/**\n * Start watching; returns a stop function. Also returns `round` so tests can drive it without timers:\n * one check plus the hibernations it started. The timer runs only the check, so a long dump does not\n * hold back the next minute's check of every other box.\n */\nexport function startIdleWatch(opts: IdleWatchOptions = {}): { stop: () => void; round: () => Promise<void> } {\n const intervalMs = opts.intervalMs ?? 60_000;\n const p = opts.p ?? paths();\n const list = opts.list ?? (() => listMachines(null, p));\n const traffic = opts.traffic ?? tapTraffic;\n const hibernate = opts.hibernate ?? ((box: Machine) => hibernateIfRunning(box, p));\n const busy = opts.busy ?? ((box: Machine) => boxBusy(box));\n const now = opts.now ?? Date.now;\n const log = opts.log ?? ((line: string) => console.log(line));\n // box id -> the tap's byte count when it last changed, and when that was\n const seen = new Map<string, { bytes: number; since: number }>();\n let timer: NodeJS.Timeout | undefined;\n let stopped = false;\n\n // boxes being hibernated right now\n const inflight = new Set<string>();\n\n const hibernateOne = async (box: Machine, quiet: number, bytes: number, t: number) => {\n inflight.add(box.id);\n try {\n if (await hibernate(box)) log(`box ${box.owner}/${box.name}: no network traffic for ${quiet} min; hibernated it (kvbox connect wakes it)`);\n seen.delete(box.id);\n } catch (err) {\n // Try again after another full timeout rather than every round.\n log(`warning: box ${box.owner}/${box.name}: could not hibernate it after ${quiet} min without traffic: ${(err as Error).message}`);\n seen.set(box.id, { bytes, since: t });\n } finally {\n inflight.delete(box.id);\n }\n };\n\n const check = async (): Promise<Promise<void>[]> => {\n const started: Promise<void>[] = [];\n const watched = new Set<string>();\n for (const box of await list()) {\n if (!box.autoHibernateSec || box.status !== \"running\") continue;\n if (inflight.has(box.id)) {\n watched.add(box.id);\n continue;\n }\n const bytes = await traffic(box.id);\n if (bytes === null) continue;\n watched.add(box.id);\n const t = now();\n const last = seen.get(box.id);\n // A caller working on the box (a snapshot, a resize) is activity too.\n if (!last || last.bytes !== bytes || busy(box)) {\n seen.set(box.id, { bytes, since: t });\n continue;\n }\n if (t - last.since < box.autoHibernateSec * 1000) continue;\n if (inflight.size >= HIBERNATE_CONCURRENCY) continue; // next round: it stays due\n started.push(hibernateOne(box, Math.round((t - last.since) / 60_000), bytes, t));\n }\n // A box that slept, stopped or lost its timeout starts over when it is watched again.\n for (const id of seen.keys()) if (!watched.has(id)) seen.delete(id);\n return started;\n };\n\n const round = async () => {\n await Promise.all(await check());\n };\n\n const schedule = () => {\n if (stopped) return;\n timer = setTimeout(() => void check().catch((err: Error) => log(`warning: idle watch: ${err.message}`)).finally(schedule), intervalMs);\n timer.unref();\n };\n schedule();\n return {\n stop: () => {\n stopped = true;\n clearTimeout(timer);\n },\n round,\n };\n}\n","/**\n * Keeps a relay tunnel (#50) carrying traffic. After the relay VM reboots, the home router can keep a\n * stale mapping for the tunnel's UDP flow: the relay still gets our handshakes, but nothing it sends\n * reaches us, and wg-quick never notices (seen 2026-10-26, every box went `unknown`). Restarting the\n * tunnel makes WireGuard dial from a new port, which the router maps afresh. So while the host uses\n * a relay, the server pings the relay's tunnel address and restarts the tunnel after a few misses.\n */\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { RELAY_TUNNEL_GATEWAY } from \"@kvbox/shared/relay\";\nimport { loadConfig } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { netSetup } from \"./network.js\";\n\n/** What `/health` reports: restarts since this server started. */\nexport interface RelayWatchReport {\n restarts: number;\n lastRestartAt: string | null;\n}\n\nexport interface RelayWatchOptions {\n intervalMs?: number;\n /** Misses in a row before a restart. */\n misses?: number;\n /** Does the relay answer through the tunnel? */\n probe?: () => Promise<boolean>;\n restart?: () => Promise<void>;\n log?: (line: string) => void;\n p?: Paths;\n}\n\nlet report: RelayWatchReport = { restarts: 0, lastRestartAt: null };\n\nexport function relayWatchReport(): RelayWatchReport {\n return report;\n}\n\n/** One ICMP echo to the relay's end of the tunnel. */\nexport async function pingRelay(): Promise<boolean> {\n try {\n await run([\"ping\", \"-c\", \"1\", \"-W\", \"3\", RELAY_TUNNEL_GATEWAY], { timeoutMs: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Start watching; returns a stop function. The config is read on every round, so `kvbox server relay`\n * (no daemon restart) starts or ends the watching without telling us. While the relay itself is down\n * the tunnel is restarted every `misses` rounds; that costs nothing and only the first is logged.\n */\nexport function startRelayWatch(opts: RelayWatchOptions = {}): () => void {\n const intervalMs = opts.intervalMs ?? 30_000;\n const misses = opts.misses ?? 3;\n const probe = opts.probe ?? pingRelay;\n const p = opts.p ?? paths();\n const log = opts.log ?? ((line: string) => console.log(line));\n const restart = opts.restart ?? (async () => netSetup(await loadConfig(p), [\"relay\", \"restart\"]));\n report = { restarts: 0, lastRestartAt: null };\n let missed = 0;\n let stuck = false; // restarted, and the relay has not answered since\n let timer: NodeJS.Timeout | undefined;\n let stopped = false;\n\n const round = async () => {\n const cfg = await loadConfig(p).catch(() => null);\n if (!cfg?.relay) {\n missed = 0;\n return;\n }\n if (await probe()) {\n if (stuck) log(`relay ${cfg.relay.name}: the tunnel carries traffic again`);\n missed = 0;\n stuck = false;\n return;\n }\n if (++missed < misses) return;\n missed = 0;\n if (!stuck) log(`relay ${cfg.relay.name}: no answer through the tunnel for ${(misses * intervalMs) / 1000} s; restarting it`);\n try {\n await restart();\n report = { restarts: report.restarts + 1, lastRestartAt: new Date().toISOString() };\n } catch (err) {\n if (!stuck) console.error(`warning: relay ${cfg.relay.name}: could not restart the tunnel: ${(err as Error).message}`);\n }\n stuck = true;\n };\n\n const schedule = () => {\n if (stopped) return;\n timer = setTimeout(() => void round().catch((err: Error) => console.error(`warning: relay watch: ${err.message}`)).finally(schedule), intervalMs);\n timer.unref();\n };\n schedule();\n return () => {\n stopped = true;\n clearTimeout(timer);\n };\n}\n","/**\n * Bind the app to the local Unix socket and write the pid file. A host that joined a control plane\n * (`kvbox-server join`) also serves a second instance of the app over HTTPS with its own\n * certificate; that instance demands the host secret on every call (caller.ts).\n */\nimport { readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo } from \"node:net\";\nimport { createAdaptorServer, type ServerType } from \"@hono/node-server\";\nimport { ensureLayout } from \"./core/state.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { stopRecovery } from \"./core/machines.js\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths } from \"@kvbox/shared/paths\";\nimport { createApp } from \"./app.js\";\nimport { boxUpgradeHandler } from \"./routes/boxHttp.js\";\n\nexport interface ListenOptions {\n socketPath?: string;\n /** Overrides the joined control plane's port (tests: 0 picks a free one). */\n httpsPort?: number;\n}\n\nexport interface Listening {\n socketPath: string;\n server: ServerType;\n /** Present when the host has joined a control plane. */\n https?: { port: number; url: string };\n close: () => Promise<void>;\n}\n\nexport async function listen(opts: ListenOptions = {}): Promise<Listening> {\n const p = await ensureLayout(paths());\n const cfg = await loadConfig(p);\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 let https: Listening[\"https\"];\n let httpsServer: ServerType | undefined;\n const cp = cfg.controlPlane;\n if (cp) {\n const [key, cert] = await Promise.all([readFile(p.tlsKey), readFile(p.tlsCert)]).catch((err: Error) => {\n throw new KvboxError(`joined ${cp.name} but the host's certificate is missing (${err.message}); run kvbox-server leave, then join again`);\n });\n httpsServer = createAdaptorServer({\n fetch: createApp({ controlPlane: { name: cp.name, secret: cp.secret } }).fetch,\n createServer: createHttpsServer,\n serverOptions: { key, cert },\n });\n // WebSockets to a box's web server (#31) never reach the app: the server hands them over raw.\n httpsServer.on(\"upgrade\", boxUpgradeHandler({ name: cp.name, secret: cp.secret }));\n const port = opts.httpsPort ?? cp.port;\n await new Promise<void>((resolve, reject) => {\n httpsServer!.once(\"error\", reject);\n httpsServer!.listen(port, \"0.0.0.0\", () => resolve());\n }).catch(async (err: Error) => {\n server.close();\n await rm(socketPath, { force: true });\n await rm(p.serverPid, { force: true });\n throw new KvboxError(`cannot listen on port ${port} for ${cp.name} (${err.message})`);\n });\n const bound = (httpsServer.address() as AddressInfo).port;\n https = { port: bound, url: `https://${cp.advertise}:${bound}` };\n }\n\n /** Tests: wait for both listeners to let go. */\n const close = async () => {\n await Promise.all([\n new Promise<void>((resolve) => server.close(() => resolve())),\n httpsServer ? new Promise<void>((resolve) => httpsServer!.close(() => resolve())) : undefined,\n ]);\n await rm(socketPath, { force: true });\n await rm(p.serverPid, { force: true });\n };\n // A signal must end the process even mid-request (a box creation can take a while and\n // `kvbox server stop` sends one SIGTERM): stop accepting, drop the files, exit. Only boxes being\n // brought back after a reboot are waited for, so none is left running unrecorded (#29).\n const shutdown = async () => {\n server.close();\n httpsServer?.close();\n await stopRecovery();\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 https ? { socketPath, server, https, close } : { socketPath, server, close };\n}\n","/**\n * The hono app behind `kvbox-server`. Served over `~/.kvbox/server.sock` to the host owner, and,\n * once the host joined a control plane, a second instance over HTTPS that demands the host secret\n * (see caller.ts).\n */\nimport { Hono } from \"hono\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport { VERSION } from \"./version.js\";\nimport { resolveCaller, type CallerOptions, type Env } from \"./caller.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { currentBaseVersion, lastRecovery } from \"./core/machines.js\";\nimport { relayWatchReport } from \"./core/relayWatch.js\";\nimport { boxHttpRoutes } from \"./routes/boxHttp.js\";\nimport { capacityRoutes } from \"./routes/capacity.js\";\nimport { machineRoutes } from \"./routes/machines.js\";\nimport { snapshotRoutes } from \"./routes/snapshots.js\";\nimport { sshRoutes } from \"./routes/ssh.js\";\nimport { usageRoutes } from \"./routes/usage.js\";\n\nexport function createApp(opts: CallerOptions = {}) {\n const app = new Hono<Env>();\n app.use(resolveCaller(opts));\n\n app.get(\"/health\", async (c) => {\n const cfg = await loadConfig();\n const cp = cfg.controlPlane;\n return c.json({\n ok: true as const,\n version: VERSION,\n pid: process.pid,\n base: await currentBaseVersion().catch(() => null),\n owner: cfg.owner,\n controlPlane: cp ? { name: cp.name, url: cp.url, hostUrl: `https://${cp.advertise}:${cp.port}` } : null,\n relay: cfg.relay ? { name: cfg.relay.name, publicIp: cfg.relay.publicIp, endpoint: cfg.relay.endpoint, ...relayWatchReport() } : null,\n recovery: lastRecovery(),\n });\n });\n // A box's web servers for the edge (#31): only what came from the control plane's side.\n if (opts.controlPlane) app.route(\"/machines\", boxHttpRoutes());\n app.route(\"/machines\", machineRoutes());\n app.route(\"/snapshots\", snapshotRoutes());\n app.route(\"/capacity\", capacityRoutes());\n app.route(\"/ssh\", sshRoutes(opts));\n app.route(\"/usage\", usageRoutes(opts));\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. Two callers exist:\n * - the host owner over the local Unix socket: no credential (the socket's permissions are the\n * auth), owner = the server's configured `owner` (the Unix user running it);\n * - the control plane this host joined (#18), over HTTPS: it presents the host secret from `join`\n * as a bearer on every call and names the user it acts for in `X-Kvbox-Owner`, qualified here\n * and nowhere else to `<user>@<control plane name>` (decision \"Owner realms\"). `/health` and\n * `/capacity` need no owner; box and snapshot routes do, except the two listings: without the\n * header `GET /machines` and `GET /snapshots` cover every owner of the realm (the control\n * plane reconciling its index, #20). The host owner's local boxes are never in that answer.\n * The edge (#31) presents `edgeCredential(secret)` instead, which opens a box's port\n * (`BOX_HTTP_PATH_RE`) and nothing else.\n */\nimport { createHash, timingSafeEqual } from \"node:crypto\";\nimport type { MiddlewareHandler } from \"hono\";\nimport { BOX_HTTP_PATH_RE, edgeCredential } from \"@kvbox/shared/names\";\nimport { loadConfig } from \"./core/config.js\";\nimport { LOCAL_OWNER_RE, type ListScope } from \"./core/refs.js\";\n\nexport type Env = { Variables: { owner: string; listScope: ListScope } };\n\nexport interface ControlPlaneCaller {\n /** The realm name owners are qualified with. */\n name: string;\n /** The host secret minted at join. */\n secret: string;\n}\n\nexport interface CallerOptions {\n /** Set on the HTTPS app only; the socket app trusts its caller. */\n controlPlane?: ControlPlaneCaller;\n}\n\nexport const OWNER_HEADER = \"x-kvbox-owner\";\n\nexport function resolveCaller(opts: CallerOptions = {}): MiddlewareHandler<Env> {\n const cp = opts.controlPlane;\n if (!cp) {\n return async (c, next) => {\n const cfg = await loadConfig();\n c.set(\"owner\", cfg.owner);\n c.set(\"listScope\", cfg.owner);\n await next();\n };\n }\n const authorized = secretCheck(cp);\n const edge = edgeCheck(cp);\n return async (c, next) => {\n const auth = c.req.header(\"authorization\");\n if (!authorized(auth) && !(edge(auth) && BOX_HTTP_PATH_RE.test(c.req.path))) return c.json({ error: \"not authorized\" }, 401);\n const user = c.req.header(OWNER_HEADER);\n if (user === undefined) {\n const path = c.req.path.replace(/\\/$/, \"\");\n const realmListing = c.req.method === \"GET\" && (path === \"/machines\" || path === \"/snapshots\");\n if (!realmListing && /^\\/(machines|snapshots)(\\/|$)/.test(c.req.path)) {\n return c.json({ error: \"X-Kvbox-Owner header required\" }, 400);\n }\n c.set(\"owner\", \"\");\n c.set(\"listScope\", { realm: cp.name });\n } else {\n if (!LOCAL_OWNER_RE.test(user)) return c.json({ error: \"X-Kvbox-Owner: letters, digits, '.', '_', '-'\" }, 400);\n const owner = `${user}@${cp.name}`;\n c.set(\"owner\", owner);\n c.set(\"listScope\", owner);\n }\n await next();\n };\n}\n\n/** Whether an `Authorization` header carries the host secret (constant time). */\nexport function secretCheck(cp: ControlPlaneCaller): (authorization: string | undefined) => boolean {\n return bearerCheck(cp.secret);\n}\n\n/** Whether it carries the edge's credential, good for a box's port only. */\nexport function edgeCheck(cp: ControlPlaneCaller): (authorization: string | undefined) => boolean {\n return bearerCheck(edgeCredential(cp.secret));\n}\n\nfunction bearerCheck(token: string): (authorization: string | undefined) => boolean {\n const expected = digest(token);\n return (authorization) => {\n const m = /^Bearer\\s+(\\S+)$/i.exec(authorization ?? \"\");\n return m !== null && timingSafeEqual(digest(m[1]!), expected);\n };\n}\n\n/** Fixed-length form of a secret so the compare is constant time whatever the caller sent. */\nfunction digest(secret: string): Buffer {\n return createHash(\"sha256\").update(secret).digest();\n}\n","/**\n * HTTPS names for boxes (#31, decision \"A box claims one subdomain\"): a box claims one subdomain\n * `<sub>.kvbox.app` with a default port, and named ports nest under it as `<name>.<sub>.kvbox.app`.\n * Both are single DNS labels. The CLI checks them before calling; the control plane checks again.\n */\nimport { createHmac } from \"node:crypto\";\nimport { KvboxError } from \"./errors.js\";\n\n/** Where box URLs live (decision d2cb4d88's domain); the control plane and the edge can be told otherwise. */\nexport const DEFAULT_PROXY_DOMAIN = \"kvbox.app\";\n\n/** A domain box names may live under (`kvbox.app`): the control plane's and the edge's must match. */\nexport function assertProxyDomain(text: string, key: string): string {\n if (!/^[a-z0-9-]+(\\.[a-z0-9-]+)+$/.test(text)) throw new KvboxError(`${key} must be a domain like ${DEFAULT_PROXY_DOMAIN}: ${text}`);\n return text;\n}\n\n/** One DNS label: lowercase letters, digits and `-`, never at either end. */\nconst LABEL_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/** Subdomains nobody may claim: the platform's own names, and ones that would read as ours. */\nexport const RESERVED_SUBDOMAINS: ReadonlySet<string> = new Set([\n \"admin\",\n \"api\",\n \"app\",\n \"assets\",\n \"auth\",\n \"billing\",\n \"blog\",\n \"cdn\",\n \"dashboard\",\n \"dev\",\n \"docs\",\n \"edge\",\n \"help\",\n \"install\",\n \"kvbox\",\n \"login\",\n \"mail\",\n \"relay\",\n \"root\",\n \"smtp\",\n \"static\",\n \"status\",\n \"support\",\n \"www\",\n]);\n\n/** Why `text` cannot be a claimed subdomain, or null when it can. */\nexport function subdomainProblem(text: string): string | null {\n if (text.length < 3 || text.length > 63) return `\"${text}\" must be 3 to 63 characters`;\n if (!LABEL_RE.test(text)) return `\"${text}\" may hold only lowercase letters, digits and '-', not at either end`;\n if (RESERVED_SUBDOMAINS.has(text)) return `\"${text}\" is reserved; pick another name`;\n return null;\n}\n\n/** Why `text` cannot be a name under a subdomain (`<name>.<sub>`), or null when it can. */\nexport function routeNameProblem(text: string): string | null {\n if (text.length < 1 || text.length > 63) return `\"${text}\" must be 1 to 63 characters`;\n if (!LABEL_RE.test(text)) return `\"${text}\" may hold only lowercase letters, digits and '-', not at either end`;\n return null;\n}\n\nexport function assertSubdomain(text: string): string {\n const problem = subdomainProblem(text);\n if (problem) throw new KvboxError(`subdomain ${problem}`);\n return text;\n}\n\nexport function assertRouteName(text: string): string {\n const problem = routeNameProblem(text);\n if (problem) throw new KvboxError(`name ${problem}`);\n return text;\n}\n\n/** `https://<sub>.<domain>`, or `https://<name>.<sub>.<domain>` for a named port. */\nexport function subdomainUrl(domain: string, sub: string, name?: string): string {\n return `https://${name === undefined ? \"\" : `${name}.`}${sub}.${domain}`;\n}\n\n/**\n * What a request's `Host` names under `domain`: the subdomain and, for `<name>.<sub>`, the name.\n * Null for anything else (the bare domain, deeper names, another domain).\n */\nexport function parseProxyHost(host: string, domain: string): { sub: string; name?: string } | null {\n const bare = host.toLowerCase().replace(/:\\d+$/, \"\").replace(/\\.$/, \"\");\n const suffix = `.${domain}`;\n if (!bare.endsWith(suffix)) return null;\n const labels = bare.slice(0, -suffix.length).split(\".\");\n if (labels.some((l) => !LABEL_RE.test(l))) return null;\n if (labels.length === 1) return { sub: labels[0]! };\n if (labels.length === 2) return { sub: labels[1]!, name: labels[0]! };\n return null;\n}\n\n/**\n * How the edge and a host carry a visitor's request to a box (#31). The host's answers of its own\n * (no such box, box not running, nothing listening) carry `PROXY_ERROR_HEADER`, and the box's carry\n * `PROXIED_HEADER`, so the edge can tell the box's own 404 or 401 from the host's and show its page\n * for the latter. The edge strips every `x-kvbox-*` header before a visitor sees the answer.\n */\nexport const PROXY_ERROR_HEADER = \"x-kvbox-proxy-error\";\nexport type ProxyError = \"not-found\" | \"not-running\" | \"unreachable\" | \"timeout\";\n/** Set by the host on every answer that came from the box: anything without it is the host's own (a refusal, a host too old for #31). */\nexport const PROXIED_HEADER = \"x-kvbox-proxied\";\n/**\n * The visitor's path and query. It never goes into the URL the edge calls on the host: a URL resolves\n * `..`, and `/machines/<box>/http/<port>/../../..` would reach any route on the host with the host\n * secret. The host URL is always exactly `/machines/<box>/http/<port>`.\n */\nexport const VISITOR_PATH_HEADER = \"x-kvbox-path\";\n/** The visitor's own `Authorization`, carried past the host secret that takes its place between edge and host. */\nexport const VISITOR_AUTH_HEADER = \"x-kvbox-authorization\";\n\n/**\n * Request headers neither hop passes on although they are not hop-by-hop: undici refuses to send\n * `expect` at all, so `Expect: 100-continue` (curl on a large upload) would fail every forward.\n * Node's server already answers the `100 Continue` itself.\n */\nexport const NOT_FORWARDED: ReadonlySet<string> = new Set([\"expect\"]);\n\n/** Headers that describe one connection, never passed along by a proxy (RFC 9110 §7.6.1). */\nexport const HOP_BY_HOP: ReadonlySet<string> = new Set([\"connection\", \"keep-alive\", \"proxy-authenticate\", \"proxy-authorization\", \"proxy-connection\", \"te\", \"trailer\", \"transfer-encoding\", \"upgrade\"]);\n\n/** The one host path the edge calls: a box's port, `/machines/<box>/http/<port>`. */\nexport const BOX_HTTP_PATH_RE = /^\\/machines\\/([^/]+)\\/http\\/(\\d{1,5})\\/?$/;\n\n/**\n * The edge's bearer for a host, derived from the host secret so neither side stores anything new.\n * A host takes it on `BOX_HTTP_PATH_RE` alone, so the internet-facing edge never holds a key to the\n * rest of a host's API; the control plane keeps it in `hosts.edge_secret` for the edge to read.\n */\nexport function edgeCredential(hostSecret: string): string {\n return createHmac(\"sha256\", hostSecret).update(\"kvbox-edge-v1\").digest(\"base64url\");\n}\n","/**\n * A box's web servers for the edge (#31): `ANY /machines/:name/http/:port` on the HTTPS app only\n * (never the socket) is passed to `<box ip>:<port><x-kvbox-path>` with its body streamed both ways,\n * and the same call as a WebSocket upgrade (listen.ts) is piped. The visitor's path comes in a\n * header, never in the URL (see VISITOR_PATH_HEADER). The control plane already decided\n * the name is the box's; this only forwards to a box of the caller's realm that is running.\n *\n * The edge sends the visitor's `Authorization` as `x-kvbox-authorization` (the host secret holds the\n * real header between edge and host) and the visitor's host name as `x-forwarded-host`; the box\n * gets them back as `authorization` and `host`, and never sees the secret or `x-kvbox-owner`.\n * Answers the host gives itself carry `x-kvbox-proxy-error`; the box's carry `x-kvbox-proxied`,\n * and any `x-kvbox-*` the box sent itself is dropped, so a box cannot pass for the host.\n * The caller is the control plane (host secret) or the edge (its credential, caller.ts).\n */\nimport type { IncomingHttpHeaders, IncomingMessage } from \"node:http\";\nimport { connect, type Socket } from \"node:net\";\nimport { Readable } from \"node:stream\";\nimport { Hono } from \"hono\";\nimport { request } from \"undici\";\nimport { NotFoundError } from \"@kvbox/shared/errors\";\nimport { HeadTimeoutError, readHead, rewriteHead } from \"@kvbox/shared/httpHead\";\nimport {\n BOX_HTTP_PATH_RE,\n HOP_BY_HOP,\n NOT_FORWARDED,\n PROXIED_HEADER,\n PROXY_ERROR_HEADER,\n VISITOR_AUTH_HEADER,\n VISITOR_PATH_HEADER,\n type ProxyError,\n} from \"@kvbox/shared/names\";\nimport { edgeCheck, OWNER_HEADER, secretCheck, type ControlPlaneCaller, type Env } from \"../caller.js\";\nimport { getMachine } from \"../core/machines.js\";\nimport { LOCAL_OWNER_RE, parseRef } from \"../core/refs.js\";\n\n/**\n * How long the box may take to start answering; a stream (SSE, a long download) then has no limit.\n * Shorter than the edge's wait for the host (edge proxy.ts), so the host's `timeout` answer gets there first.\n */\nconst HEADERS_TIMEOUT_MS = 55_000;\n/** The most a box's answer to a WebSocket handshake may hold before its blank line. */\nconst MAX_HANDSHAKE_BYTES = 16 * 1024;\n/** Connecting to the box: it is on the host's own bridge, so anything slower means nothing is there. */\nconst CONNECT_TIMEOUT_MS = 5_000;\n/** Headers that never reach the box: the edge-to-host credentials and what the forward rewrites. */\nconst DROPPED = new Set([...HOP_BY_HOP, ...NOT_FORWARDED, \"host\", \"authorization\", OWNER_HEADER, VISITOR_AUTH_HEADER, VISITOR_PATH_HEADER]);\n\nclass ProxyFailure extends Error {\n constructor(\n readonly status: number,\n readonly code: ProxyError,\n message: string,\n ) {\n super(message);\n }\n}\n\ninterface Target {\n ip: string;\n port: number;\n /** The path and query on the box. */\n path: string;\n}\n\n/** The path on the box: the edge's header, a plain origin-form path; anything else is the box's `/`. */\nfunction visitorPath(value: string | string[] | null | undefined): string {\n const path = Array.isArray(value) ? value[0] : value;\n return path !== undefined && path !== null && path.startsWith(\"/\") && !/[\\s]/.test(path) ? path : \"/\";\n}\n\n/** The running box a forward path names, or a ProxyFailure saying why not. */\nasync function targetOf(url: URL, owner: string, path: string): Promise<Target> {\n const m = BOX_HTTP_PATH_RE.exec(url.pathname);\n const port = Number(m?.[2]);\n if (!m || port < 1 || port > 65535) throw new ProxyFailure(404, \"not-found\", `no route: ${url.pathname}`);\n const name = decodeURIComponent(m[1]!);\n let box;\n try {\n box = await getMachine(parseRef(name, owner));\n } catch (err) {\n if (err instanceof NotFoundError) throw new ProxyFailure(404, \"not-found\", err.message);\n throw err;\n }\n if (box.status !== \"running\") throw new ProxyFailure(409, \"not-running\", `box ${name} is ${box.status}`);\n return { ip: box.ip, port, path };\n}\n\n/** The request headers as the box gets them. `upgrade` keeps the two headers a WebSocket handshake needs. */\nfunction boxHeaders(incoming: Iterable<[string, string]>, target: Target, upgrade = false): [string, string][] {\n const out: [string, string][] = [];\n let host = `${target.ip}:${target.port}`;\n for (const [name, value] of incoming) {\n const key = name.toLowerCase();\n if (key === \"x-forwarded-host\") host = value;\n if (key === VISITOR_AUTH_HEADER) out.push([\"authorization\", value]);\n if (upgrade && (key === \"upgrade\" || key === \"connection\")) out.push([name, value]);\n else if (!DROPPED.has(key)) out.push([name, value]);\n }\n out.push([\"host\", host]);\n return out;\n}\n\nconst failure = (err: ProxyFailure) => new Response(JSON.stringify({ error: err.message }), { status: err.status, headers: { \"content-type\": \"application/json\", [PROXY_ERROR_HEADER]: err.code } });\n\nexport function boxHttpRoutes() {\n const r = new Hono<Env>();\n r.all(\"/:name/http/:port\", forward);\n return r;\n}\n\nasync function forward(c: import(\"hono\").Context<Env>): Promise<Response> {\n let target: Target;\n try {\n target = await targetOf(new URL(c.req.url), c.get(\"owner\"), visitorPath(c.req.header(VISITOR_PATH_HEADER)));\n } catch (err) {\n if (err instanceof ProxyFailure) return failure(err);\n throw err;\n }\n const raw = c.req.raw;\n const pairs: [string, string][] = [];\n raw.headers.forEach((value, name) => pairs.push([name, value]));\n let res;\n try {\n res = await request(`http://${target.ip}:${target.port}${target.path}`, {\n method: raw.method as \"GET\",\n headers: boxHeaders(pairs, target).flat(),\n body: raw.body === null ? null : Readable.fromWeb(raw.body as import(\"node:stream/web\").ReadableStream),\n headersTimeout: HEADERS_TIMEOUT_MS,\n bodyTimeout: 0,\n signal: raw.signal,\n });\n } catch (err) {\n const e = err as Error & { code?: string };\n if (e.code === \"UND_ERR_HEADERS_TIMEOUT\") return failure(new ProxyFailure(504, \"timeout\", `box took over ${HEADERS_TIMEOUT_MS / 1000} s to answer on port ${target.port}`));\n return failure(new ProxyFailure(502, \"unreachable\", `box answered nothing on port ${target.port} (${e.code ?? e.message})`));\n }\n const headers = new Headers();\n for (const [name, value] of Object.entries(res.headers)) {\n if (value === undefined || HOP_BY_HOP.has(name) || name.startsWith(\"x-kvbox-\")) continue;\n for (const v of Array.isArray(value) ? value : [value]) headers.append(name, v);\n }\n headers.set(PROXIED_HEADER, \"1\");\n const empty = res.statusCode === 204 || res.statusCode === 304 || raw.method === \"HEAD\";\n if (empty) res.body.resume();\n return new Response(empty ? null : (Readable.toWeb(res.body) as ReadableStream), { status: res.statusCode, headers });\n}\n\n/**\n * An answer written straight on a socket, for an upgrade that cannot go ahead. It always carries\n * PROXY_ERROR_HEADER (`refused` when no box reason applies) and never PROXIED_HEADER, which only a\n * box's own answer gets.\n */\nfunction refuse(socket: Socket, status: number, text: string, code: ProxyError | \"refused\" = \"refused\"): void {\n const body = JSON.stringify({ error: text });\n socket.end(`HTTP/1.1 ${status} ${status === 401 ? \"Unauthorized\" : \"Error\"}\\r\\ncontent-type: application/json\\r\\ncontent-length: ${Buffer.byteLength(body)}\\r\\n${PROXY_ERROR_HEADER}: ${code}\\r\\nconnection: close\\r\\n\\r\\n${body}`);\n}\n\nfunction headerPairs(raw: readonly string[]): [string, string][] {\n const out: [string, string][] = [];\n for (let i = 0; i + 1 < raw.length; i += 2) out.push([raw[i]!, raw[i + 1]!]);\n return out;\n}\n\n/**\n * The HTTPS server's `upgrade` handler: a WebSocket to a box. Checked like any call from the control\n * plane's side (host secret or the edge's credential, owner), then the handshake is written to the\n * box as it came, rewritten the same way as a plain forward. The box's answer is read up to its\n * blank line (a box that says nothing in `headersTimeoutMs` is our `timeout`), stamped like a plain\n * forward's, and from then on the two sockets are piped.\n */\nexport function boxUpgradeHandler(cp: ControlPlaneCaller, headersTimeoutMs = HEADERS_TIMEOUT_MS) {\n const full = secretCheck(cp);\n const edge = edgeCheck(cp);\n const authorized = (auth: string | undefined) => full(auth) || edge(auth);\n return (req: IncomingMessage, socket: Socket, head: Buffer): void => {\n // Node drops its own error listener on an upgraded socket: without this one, a visitor resetting\n // the connection while we look the box up (or write a refusal) would crash the daemon.\n socket.on(\"error\", () => socket.destroy());\n void (async () => {\n const headers: IncomingHttpHeaders = req.headers;\n if (!authorized(headers.authorization)) return refuse(socket, 401, \"not authorized\");\n const user = headers[OWNER_HEADER];\n if (typeof user !== \"string\" || !LOCAL_OWNER_RE.test(user)) return refuse(socket, 400, \"X-Kvbox-Owner header required\");\n let target: Target;\n try {\n target = await targetOf(new URL(req.url ?? \"/\", \"https://host\"), `${user}@${cp.name}`, visitorPath(headers[VISITOR_PATH_HEADER]));\n } catch (err) {\n if (err instanceof ProxyFailure) return refuse(socket, err.status, err.message, err.code);\n return refuse(socket, 500, (err as Error).message);\n }\n // the visitor may have left while we looked: then there is nobody to open the box for\n if (socket.destroyed) return;\n const box = connect({ host: target.ip, port: target.port, timeout: CONNECT_TIMEOUT_MS });\n let connected = false;\n let piped = false;\n box.once(\"timeout\", () => box.destroy(new Error(\"timed out\")));\n box.once(\"error\", (err: Error & { code?: string }) => {\n if (!connected && !socket.destroyed) refuse(socket, 502, `box answered nothing on port ${target.port} (${err.code ?? err.message})`, \"unreachable\");\n else if (piped) socket.destroy();\n });\n socket.once(\"close\", () => box.destroy());\n box.once(\"close\", () => {\n if (piped) socket.destroy();\n });\n box.once(\"connect\", () => {\n connected = true;\n box.setTimeout(0);\n const lines = boxHeaders(headerPairs(req.rawHeaders), target, true).map(([k, v]) => `${k}: ${v}\\r\\n`);\n box.write(`${req.method ?? \"GET\"} ${target.path} HTTP/1.1\\r\\n${lines.join(\"\")}\\r\\n`);\n if (head.length > 0) box.write(head);\n readHead(box, { maxBytes: MAX_HANDSHAKE_BYTES, timeoutMs: headersTimeoutMs }).then(\n (answer) => {\n if (socket.destroyed) return void box.destroy();\n socket.write(rewriteHead(answer.head, (name) => name.startsWith(\"x-kvbox-\"), { [PROXIED_HEADER]: \"1\" }));\n if (answer.rest.length > 0) socket.write(answer.rest);\n piped = true;\n box.pipe(socket);\n socket.pipe(box);\n },\n (err: Error) => {\n box.destroy();\n if (socket.destroyed) return;\n if (err instanceof HeadTimeoutError) refuse(socket, 504, `box took over ${headersTimeoutMs / 1000} s to answer on port ${target.port}`, \"timeout\");\n else refuse(socket, 502, `box gave no answer on port ${target.port} (${err.message})`, \"unreachable\");\n },\n );\n });\n })();\n };\n}\n","/**\n * The head of an HTTP/1.1 answer read off a raw socket (#31). A WebSocket goes edge → host → box as\n * piped bytes, so both hops read the answer to the handshake themselves: the host to stamp the box's\n * answer as the box's and drop any `x-kvbox-*` it sent, the edge to tell that from the host's refusal.\n */\nimport type { Duplex } from \"node:stream\";\n\nconst END = \"\\r\\n\\r\\n\";\n\n/** Nothing came before `timeoutMs`: the box (or host) took the connection and said nothing. */\nexport class HeadTimeoutError extends Error {}\n\n/**\n * What `socket` answers, up to its blank line: the head (status line and headers, no blank line) and\n * whatever came after it in the same reads. The socket is left paused with nothing more consumed.\n */\nexport function readHead(socket: Duplex, opts: { maxBytes: number; timeoutMs: number }): Promise<{ head: string; rest: Buffer }> {\n return new Promise((resolve, reject) => {\n let bytes = Buffer.alloc(0);\n const done = (err?: Error) => {\n clearTimeout(timer);\n socket.off(\"data\", onData);\n socket.off(\"close\", onClose);\n socket.pause();\n if (err) return reject(err);\n const end = bytes.indexOf(END);\n resolve({ head: bytes.subarray(0, end).toString(\"latin1\"), rest: bytes.subarray(end + END.length) });\n };\n const onData = (chunk: Buffer) => {\n bytes = Buffer.concat([bytes, chunk]);\n if (bytes.includes(END)) done();\n else if (bytes.length > opts.maxBytes) done(new Error(\"answer head too large\"));\n };\n const onClose = () => done(new Error(\"closed before answering\"));\n const timer = setTimeout(() => done(new HeadTimeoutError(`no answer within ${opts.timeoutMs / 1000} s`)), opts.timeoutMs);\n socket.on(\"data\", onData);\n socket.once(\"close\", onClose);\n });\n}\n\n/** The value of header `name` (lowercase) in a head, or undefined. */\nexport function headHeader(head: string, name: string): string | undefined {\n const line = head.split(\"\\r\\n\").slice(1).find((l) => l.slice(0, l.indexOf(\":\")).trim().toLowerCase() === name);\n return line?.slice(line.indexOf(\":\") + 1).trim();\n}\n\n/** The head again with the headers `drop` names left out and `add` appended, blank line included. */\nexport function rewriteHead(head: string, drop: (name: string) => boolean, add: Record<string, string> = {}): Buffer {\n const [status, ...lines] = head.split(\"\\r\\n\");\n const kept = lines.filter((l) => !drop(l.slice(0, l.indexOf(\":\")).trim().toLowerCase()));\n const extra = Object.entries(add).map(([k, v]) => `${k}: ${v}`);\n return Buffer.from(`${[status, ...kept, ...extra].join(\"\\r\\n\")}${END}`, \"latin1\");\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, PortsRequest, RescaleMachineRequest, SetMachineRequest, SetSshKeysRequest } from \"@kvbox/shared/api\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport {\n addPorts,\n createMachine,\n destroyMachine,\n hibernateMachine,\n listMachines,\n pauseMachine,\n removePorts,\n rescaleMachine,\n resumeMachine,\n setMachine,\n setSshKeys,\n startMachine,\n stopMachine,\n updateMachine,\n wakeMachine,\n} from \"../core/machines.js\";\nimport { parseRef } from \"../core/refs.js\";\nimport { machineStats } from \"../core/stats.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(\"listScope\"))));\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.post(\"/:name/set\", async (c) => {\n const body = SetMachineRequest.parse(await c.req.json().catch(() => ({})));\n return c.json(await setMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body));\n });\n r.post(\"/:name/ssh-keys\", async (c) => {\n const body = SetSshKeysRequest.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"sshKeys: expected a list of authorized_keys lines\");\n const { machine, applied } = await setSshKeys(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body.data.sshKeys);\n return c.json({ ...machine, sshKeysApplied: applied });\n });\n // Published box ports (#30): both answer with the box, its `ports` as they are now.\n r.post(\"/:name/ports\", async (c) => {\n const body = PortsRequest.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"ports: expected a list of box ports\");\n return c.json(await addPorts(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body.data), 201);\n });\n r.delete(\"/:name/ports\", async (c) => {\n const body = PortsRequest.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"ports: expected a list of box ports\");\n return c.json(await removePorts(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body.data));\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.get(\"/:name/stats\", async (c) => c.json(await machineStats(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\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 * `kvbox vm top` (#67): a running box's own load, memory and disk, asked of kvbox-agent over vsock,\n * so it answers whatever the box did to its network. Read-only and unlocked: a box that stops\n * mid-question just fails this one answer.\n */\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { MachineStats } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { isNoAgent, isUnknownOp, stats } from \"./agent.js\";\nimport { getMachine, stateMessage } from \"./machines.js\";\nimport type { BoxRef } from \"./refs.js\";\n\n/** The guest is asked live; a busy one gets this long before the caller hears it did not answer. */\nconst STATS_REPLY_MS = 3_000;\n\nexport async function machineStats(ref: BoxRef, p: Paths = paths()): Promise<MachineStats> {\n const m = await getMachine(ref, p);\n if (m.status !== \"running\") throw new KvboxError(`${stateMessage(ref, m.status)}; only a running box can say how it is doing`);\n try {\n return { name: m.name, owner: m.owner, stats: await stats(p.machine(m.owner, m.name).vsock, STATS_REPLY_MS) };\n } catch (err) {\n // An image older than base v0.7.0 (an agent without \"stats\", or no agent at all): no numbers, not an error.\n if (isUnknownOp(err) || isNoAgent(err)) return { name: m.name, owner: m.owner, stats: null };\n throw err;\n }\n}\n","/**\n * What the usage_events ledger (db.ts) adds up to: one box (`kvbox vm usage <box>`) or every box of\n * an owner (`kvbox usage`, #41). The arithmetic is `computeUsage` in @kvbox/shared/usage, shared with\n * the control plane, which sums the same rows after pulling them (#42).\n */\nimport type { MachineUsage, UsageReport } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { computeUsage, groupUsage, sumUsage } from \"@kvbox/shared/usage\";\nimport { loadConfig } from \"./config.js\";\nimport { usageEventsFor, usageEventsInScope } from \"./db.js\";\nimport { getMachine, listMachines } from \"./machines.js\";\nimport type { BoxRef, ListScope } from \"./refs.js\";\n\nexport { computeUsage, type UsageEvent, type UsageState, type UsageTotals, type UsageWindow } from \"@kvbox/shared/usage\";\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.\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 events = usageEventsFor(box.id, box.createdAt, p);\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 * Every box of the owners in `scope` over the window, removed ones included: the ledger keeps their\n * rows, and a name removed and made again is two boxes (two ids). Listing the live boxes first closes\n * any run whose Firecracker died, so the ledger is current. A box with no row inside the window is\n * left out: it did not exist then.\n */\nexport async function usageReport(scope: ListScope, window: { from: string; to: string }, p: Paths = paths()): Promise<UsageReport> {\n const cfg = await loadConfig(p);\n const live = new Map((await listMachines(scope, p)).map((m) => [m.id, m.status]));\n const boxes = groupUsage(usageEventsInScope(scope, window, p), window, cfg.pricing, live);\n return { window, boxes, totals: sumUsage(boxes, cfg.pricing) };\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(\"listScope\"))));\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 { withBoxLock } from \"./locks.js\";\nimport { inScope, parseRef, refKey, shown, type BoxRef, type ListScope } from \"./refs.js\";\nimport {\n listSnapshotRefs,\n readMachineMeta,\n readSnapshotMeta,\n vmAlive,\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(scope: ListScope, p: Paths = paths()): Promise<Snapshot[]> {\n const out: Snapshot[] = [];\n for (const ref of await listSnapshotRefs(p)) {\n if (!inScope(ref.owner, scope)) 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 ref = parseRef(req.box, owner);\n return withBoxLock(ref, () => snapshotBox(ref, req, owner, p));\n}\n\nasync function snapshotBox(ref: BoxRef, req: CreateSnapshotRequest, owner: string, p: Paths): Promise<Snapshot> {\n const box = await readBox(ref, p);\n if (!vmAlive(box)) {\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 since = box.memSnapshots ?? 0;\n // A diff is standalone right after boot, or once merged onto the previous image. Otherwise (a\n // lineage broken by an earlier failure) dump everything.\n const mode: \"Diff\" | \"Full\" = 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 = true; // 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 await rm(m.memBase, { force: true });\n await link(s.mem, m.memBase);\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","/**\n * The SSH CA on a host (#55). `POST /ssh/trust-ca` makes every cloud box trust a new CA, `GET\n * /ssh/cloud-ca` asks the joined control plane which CA that should be. Both exist on the Unix\n * socket only: adding a trusted CA to every box is the most powerful thing a host can do, so it\n * takes someone on the host itself, never the control plane (or whoever holds its token).\n */\nimport { Hono } from \"hono\";\nimport { TrustCaRequestSchema } from \"@kvbox/shared/api\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { CallerOptions, Env } from \"../caller.js\";\nimport { fetchCloudCa } from \"../core/controlPlane.js\";\nimport { trustCa } from \"../core/machines.js\";\n\nexport function sshRoutes(opts: CallerOptions = {}) {\n const r = new Hono<Env>();\n if (opts.controlPlane) {\n r.all(\"/*\", (c) => c.json({ error: \"trusting a CA is done on the host itself (kvbox server trust-ca there); the control plane cannot ask a host to\" }, 403));\n return r;\n }\n r.get(\"/cloud-ca\", async (c) => c.json(await fetchCloudCa()));\n r.post(\"/trust-ca\", async (c) => {\n const body = TrustCaRequestSchema.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"trust-ca: expected the CA public key as publicKey\");\n return c.json(await trustCa(body.data.publicKey));\n });\n return r;\n}\n","/**\n * The usage ledger over HTTP. `GET /usage?since=&until=` is the host-wide report (#41) for the\n * caller's boxes. `GET /usage/events?after=&limit=` hands out raw ledger rows by id for a control\n * plane to pull (#42): over HTTPS only the caller's realm (or, with `X-Kvbox-Owner`, that one\n * owner) comes back, so the host owner's local boxes never leave the host; over the socket the\n * host owner gets every row.\n */\nimport { Hono } from \"hono\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { usageWindow } from \"@kvbox/shared/usage\";\nimport type { CallerOptions, Env } from \"../caller.js\";\nimport { ledgerId, usageEventsAfter } from \"../core/db.js\";\nimport { usageReport } from \"../core/usage.js\";\n\n/** Rows per pull; the control plane keeps pulling while a page comes back full. */\nexport const PULL_LIMIT = 1000;\n\nexport function usageRoutes(opts: CallerOptions = {}) {\n const r = new Hono<Env>();\n r.get(\"/\", async (c) => {\n let window;\n try {\n window = usageWindow(c.req.query(\"since\"), c.req.query(\"until\"));\n } catch (err) {\n throw new KvboxError((err as Error).message);\n }\n return c.json(await usageReport(c.get(\"listScope\"), window));\n });\n r.get(\"/events\", async (c) => {\n const after = whole(c.req.query(\"after\") ?? \"0\", \"after\");\n const limit = Math.min(whole(c.req.query(\"limit\") ?? String(PULL_LIMIT), \"limit\") || PULL_LIMIT, PULL_LIMIT);\n // The socket app trusts its caller: the whole ledger. The HTTPS app's scope is its realm or the named owner.\n const scope = opts.controlPlane === undefined ? null : c.get(\"listScope\");\n const events = usageEventsAfter(after, limit, scope);\n return c.json({ ledger: ledgerId(), events, next: events.length === 0 ? after : events[events.length - 1]!.id });\n });\n return r;\n}\n\nfunction whole(value: string, name: string): number {\n const n = Number(value);\n if (!Number.isInteger(n) || n < 0) throw new KvboxError(`${name}: expected a whole number, got \"${value}\"`);\n return n;\n}\n"],"mappings":"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","names":["z","z","chmod","readFile","z","z","z","z","readFile","chmod","readFile","readFile","closeSync","existsSync","openSync","mkdir","readFile","writeFile","mkdir","readFile","writeFile","z","z","z","mkdir","readFile","writeFile","request","request","bootArgs","existsSync","writeFile","readFile","openSync","closeSync","m","mkdir","failure","stopMachine","startMachine","setSshKeys","report","pauseMachine","resumeMachine","hibernateMachine","wakeMachine","updateMachine","rescaleMachine","setMachine","addPorts","removePorts","destroyMachine","run","chmod","mkdir","rm","writeFile","z","z","join","mkdir","writeFile","chmod","rm","readFile","readFile","round","round","readFile","rm","writeFile","Hono","require","createHash","createHash","connect","request","request","connect","Hono","Hono","Hono","Hono","Hono","existsSync","link","mkdir","readdir","rename","rm","stat","NAME_RE","readdir","stat","existsSync","mkdir","failure","rm","link","rename","Hono","Hono","Hono","Hono","Hono","Hono","rm","writeFile","readFile","shutdown","recovery","relay"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../shared/src/errors.ts","../../shared/src/paths.ts","../src/core/config.ts","../../shared/src/sizes.ts","../../shared/src/usage.ts","../src/core/refs.ts","../src/core/controlPlane.ts","../../shared/src/api.ts","../../shared/src/ssh.ts","../src/core/exec.ts","../src/core/kvm.ts","../src/core/machines.ts","../src/core/agent.ts","../src/core/capacity.ts","../../shared/src/capacity.ts","../src/core/state.ts","../src/core/db.ts","../src/core/locks.ts","../src/core/firecracker.ts","../src/core/network.ts","../src/core/relay.ts","../../shared/src/relay.ts","../src/core/idle.ts","../src/core/relayWatch.ts","../src/listen.ts","../src/app.ts","../../shared/src/version.ts","../src/version.ts","../src/caller.ts","../../shared/src/names.ts","../src/routes/boxHttp.ts","../../shared/src/httpHead.ts","../src/routes/capacity.ts","../src/routes/machines.ts","../src/core/stats.ts","../src/core/usage.ts","../src/routes/snapshots.ts","../src/core/snapshots.ts","../src/routes/ssh.ts","../src/routes/usage.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. `join` / `leave` (M2) attach the host to a control plane,\n * after which `start` also answers that control plane over HTTPS.\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 { joinControlPlane, leaveControlPlane } from \"./core/controlPlane.js\";\nimport { requireKvm } from \"./core/kvm.js\";\nimport { bootRecovered, settleDeadBoxes } from \"./core/machines.js\";\nimport { ensureHostNetwork, netSetupScript } from \"./core/network.js\";\nimport { dropRelay, useRelay } from \"./core/relay.js\";\nimport { startIdleWatch } from \"./core/idle.js\";\nimport { startRelayWatch } from \"./core/relayWatch.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 await requireKvm(); // a daemon without /dev/kvm would only fail at the first kvbox new (#61)\n // Before listening: boxes whose Firecracker died with the host (#29), so a listing cannot get to them first.\n const settled = await settleDeadBoxes(paths());\n const { socketPath, https } = await listen(opts.socket ? { socketPath: opts.socket } : {});\n console.log(`kvbox-server ${VERSION} listening on ${socketPath} (pid ${process.pid})`);\n if (https) {\n const cfg = await loadConfig(paths());\n console.log(`control plane ${cfg.controlPlane?.name}: answering on ${https.url}`);\n }\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 // A relay tunnel that stops carrying traffic is redialed (#50); idle when the host has no relay.\n startRelayWatch();\n // Boxes with an idle timeout are hibernated once their network goes quiet (#47).\n startIdleWatch();\n const recovery = await bootRecovered(settled, paths());\n if (recovery) {\n for (const box of recovery.booted) console.log(`box ${box} was running when it went down; booted it again`);\n for (const box of recovery.leftStopped) console.log(`box ${box} was in standby when it went down; its memory is gone, left stopped`);\n for (const f of recovery.failed) console.error(`warning: box ${f.box} was running when it went down and did not come back: ${f.error}`);\n }\n });\n\nprogram\n .command(\"join <control-plane-url>\")\n .description(\"register this host with a control plane (needs a one-time token minted there); it answers the control plane from its next start\")\n .requiredOption(\"--token <token>\", \"one-time join token from the control plane\")\n .option(\"--advertise <host-or-ip>\", \"address the control plane reaches this host at (default: this host's default-route address)\")\n .option(\"--name <name>\", \"how the control plane lists this host (default: hostname)\")\n .action(async (url: string, opts: { token: string; advertise?: string; name?: string }) => {\n const joined = await joinControlPlane({ url, ...opts }, paths());\n console.log(`joined ${joined.controlPlane} as host ${joined.hostName}`);\n console.log(`it answers the control plane on ${joined.hostUrl} once its server restarts`);\n console.log(`make sure port ${new URL(joined.hostUrl).port} is reachable from the control plane`);\n });\n\nprogram\n .command(\"leave\")\n .description(\"forget the control plane this host joined; the HTTPS port closes at the next start\")\n .action(async () => {\n const left = await leaveControlPlane(paths());\n console.log(`left ${left.controlPlane}; the HTTPS port closes once its server restarts`);\n if (!left.told) console.log(`(the control plane could not be told; remove this host there)`);\n });\n\nprogram\n .command(\"relay <join-string>\")\n .description(\"reach the internet through a relay (paste what `kvbox-relay add` printed there); `off` takes the tunnel down\")\n .action(async (joinString: string) => {\n if (joinString === \"off\") {\n const relay = await dropRelay(paths());\n console.log(`tunnel to relay ${relay.name} is down; this host no longer answers at ${relay.publicIp}`);\n return;\n }\n const relay = await useRelay(joinString, paths());\n console.log(`tunnel to relay ${relay.name} (${relay.endpoint}) is up`);\n console.log(`this host is reachable at ${relay.publicIp}; kvbox server join advertises it by default`);\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/** The caller is known but the rule says no (an org member outside their role): HTTP 403, exit 1. */\nexport class ForbiddenError extends KvboxError {\n constructor(message: string) {\n super(message, 1);\n this.name = \"ForbiddenError\";\n }\n}\n\n/** A bare name that is in more than one of the caller's orgs (#68); the CLI and the control plane say it the same way. */\nexport class AmbiguousRefError extends KvboxError {\n constructor(kind: string, name: string, slugs: readonly string[]) {\n super(`${kind} ${name} exists in ${slugs.slice(0, -1).join(\", \")} and ${slugs.at(-1)}; say which with --org ${slugs[0]} or ${slugs[0]}/${name}`, 1);\n this.name = \"AmbiguousRefError\";\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, cli.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 /** The CLI's login to the control plane (`kvbox login`): url, bearer token, user. Mode 600. */\n cli: join(home, \"cli.json\"),\n ssh: join(home, \"ssh\"),\n sshKey: join(home, \"ssh\", \"id_ed25519\"),\n /** The device key signed by the control plane's CA (#51); ssh loads it by itself next to `-i id_ed25519`. */\n sshCert: join(home, \"ssh\", \"id_ed25519-cert.pub\"),\n /** Host keys of the cloud boxes this laptop connected to, one entry per box (`connect`, #21). */\n sshKnownHosts: join(home, \"ssh\", \"known_hosts\"),\n /** The host's self-signed TLS identity for the control plane (`kvbox-server join`): pinned there by fingerprint. */\n tls: join(home, \"tls\"),\n tlsKey: join(home, \"tls\", \"key.pem\"),\n tlsCert: join(home, \"tls\", \"cert.pem\"),\n /** The host's WireGuard tunnel to its relay (`kvbox server relay`, #50): the conf net-setup.sh installs for wg-quick. Mode 600. */\n relay: join(home, \"relay\"),\n relayConf: join(home, \"relay\", \"kvbox.conf\"),\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 /**\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 { chmod, readFile, rename, 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 { PricingSchema } from \"@kvbox/shared/usage\";\nimport { LOCAL_OWNER_RE, REALM_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 { PricingSchema, type Pricing } from \"@kvbox/shared/usage\";\n\n/** The control plane this host joined (`kvbox-server join`, #18): where it is, what it calls itself, and the secret it presents. */\nexport const ControlPlaneSchema = z.object({\n url: z.string().url(),\n /** The realm name: boxes the control plane creates are owned by `<user>@<name>`, a directory name on disk. */\n name: z.string().regex(REALM_RE),\n /** Minted at join; every HTTPS call from the control plane carries it as a bearer. */\n secret: z.string().min(1),\n /** The address the control plane reaches this host at. */\n advertise: z.string().min(1),\n port: z.number().int().positive().default(7777),\n});\nexport type ControlPlane = z.infer<typeof ControlPlaneSchema>;\n\n/**\n * The relay this host reaches the internet through (`kvbox-server relay`, #50): a public VM that owns\n * `publicIp` and forwards it down a WireGuard tunnel to `tunnelIp`. The tunnel's private key is not\n * here: it lives in the wg-quick conf under relay/. `join` advertises `publicIp` by default.\n */\nexport const RelaySchema = z.object({\n name: z.string().min(1),\n publicIp: z.string().min(1),\n tunnelIp: z.string().min(1),\n /** `<relay-ip>:<port>` the tunnel dials. */\n endpoint: z.string().min(1),\n});\nexport type Relay = z.infer<typeof RelaySchema>;\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 /** What a new box gets when `new` does not say (#47): seconds without network traffic before it is hibernated; 0: never. */\n autoHibernateSec: z.number().int().min(0).default(0),\n /** Absent until the host joins a control plane; then the server also listens on HTTPS. */\n controlPlane: ControlPlaneSchema.optional(),\n /** Absent unless the host sits behind a relay. */\n relay: RelaySchema.optional(),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/** Write config.json back, whole or not at all. Mode 600: once joined it holds the host's secret. */\nexport async function saveConfig(cfg: Config, p: Paths = paths()): Promise<void> {\n const parsed = ConfigSchema.parse(cfg);\n const tmp = `${p.config}.tmp`;\n await writeFile(tmp, JSON.stringify(parsed, null, 2) + \"\\n\", { mode: 0o600 });\n await chmod(tmp, 0o600); // writeFile's mode applies to a new file only\n await rename(tmp, p.config);\n}\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 * Summing a box's usage ledger: one pure function over its state-change rows, used by the host\n * (`kvbox vm usage`, `GET /usage`) and by the control plane over the rows it pulled (#42). A row\n * opens an interval that lasts until the next row; the sizes ride on every row so a rescale\n * changes the rate from that moment on. Pricing is per resource-hour (decision \"Usage is priced\n * per resource-hour\").\n */\nimport { z } from \"zod\";\nimport type { BoxStatus, BoxUsage } from \"./api.js\";\n\nexport type UsageState = \"running\" | \"standby\" | \"hibernated\" | \"stopped\";\n\n/** One state change of a box. */\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, server (a stop the server did not see). */\n by: string;\n}\n\n/** What an hour of each resource costs. */\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 interface UsageWindow {\n from: string;\n to: string;\n pricing?: Pricing | undefined;\n}\n\nexport interface UsageTotals {\n seconds: Record<UsageState, number>;\n vcpuHours: number;\n ramGibHours: number;\n diskGibHours: number;\n cost?: { amount: number; currency: string };\n /** Stops the server did not witness (Firecracker died, host rebooted) and dated to when it noticed. */\n estimatedStops: number;\n /** The first recorded moment, null when nothing is recorded. */\n historyFrom: string | null;\n}\n\nconst HOUR_MS = 3_600_000;\n\nexport const 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) totals.cost = { amount: round(costOf(totals, w.pricing), 4), currency: w.pricing.currency };\n return totals;\n}\n\n/** The price of a set of resource-hours; totals over several boxes are summed the same way. */\nexport function costOf(t: Pick<UsageTotals, \"vcpuHours\" | \"ramGibHours\" | \"diskGibHours\">, pricing: Pricing): number {\n return t.vcpuHours * pricing.vcpuHour + t.ramGibHours * pricing.ramGibHour + t.diskGibHours * pricing.diskGibHour;\n}\n\n/** Add up several boxes' totals (hours and seconds; the cost is recomputed from the hours when priced). */\nexport function sumUsage(items: readonly Pick<UsageTotals, \"seconds\" | \"vcpuHours\" | \"ramGibHours\" | \"diskGibHours\">[], pricing?: Pricing): Omit<UsageTotals, \"estimatedStops\" | \"historyFrom\"> {\n const sum: Omit<UsageTotals, \"estimatedStops\" | \"historyFrom\"> = {\n seconds: { running: 0, standby: 0, hibernated: 0, stopped: 0 },\n vcpuHours: 0,\n ramGibHours: 0,\n diskGibHours: 0,\n };\n for (const t of items) {\n for (const s of Object.keys(sum.seconds) as UsageState[]) sum.seconds[s] += t.seconds[s];\n sum.vcpuHours += t.vcpuHours;\n sum.ramGibHours += t.ramGibHours;\n sum.diskGibHours += t.diskGibHours;\n }\n sum.vcpuHours = round(sum.vcpuHours, 3);\n sum.ramGibHours = round(sum.ramGibHours, 3);\n sum.diskGibHours = round(sum.diskGibHours, 3);\n if (pricing !== undefined) sum.cost = { amount: round(costOf(sum, pricing), 4), currency: pricing.currency };\n return sum;\n}\n\n/**\n * The window a `GET /usage` call asks for: `since` and `until` as the user wrote them (any Date.parse\n * form), defaulting to the start of the current calendar month (UTC, what a bill covers) and now.\n */\nexport function usageWindow(since: string | undefined, until: string | undefined, now = new Date()): { from: string; to: string } {\n const parse = (name: string, value: string): string => {\n const t = Date.parse(value);\n if (Number.isNaN(t)) throw new Error(`${name}: \"${value}\" is not a date; write it like 2026-10-19 or 2026-10-19T08:00:00Z`);\n return new Date(t).toISOString();\n };\n const from = since === undefined ? new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)).toISOString() : parse(\"since\", since);\n const to = until === undefined ? now.toISOString() : parse(\"until\", until);\n return { from, to };\n}\n\n/** A ledger row as the host stores it: the event plus whose box it is. */\nexport interface LedgerRow extends UsageEvent {\n /** The host ledger the row came from, when rows of several hosts are mixed: box ids are only unique within one. */\n ledger?: string;\n boxId: string;\n owner: string;\n name: string;\n}\n\n/**\n * Rows of many boxes → one `BoxUsage` per box id, in owner/name order: the report both the host\n * (`GET /usage`) and the control plane build. A box's `rm` row ends its time: nothing accrues after\n * it, and a box gone before the window opened (or made after it closed) is left out. `live` says what\n * a box that still exists is doing now; one not in it reads its state off its last row, `removed`\n * when that row is the `rm`. A name removed and made again is two boxes (two ids); rows carrying a\n * `ledger` are grouped by ledger and box id, so two hosts' boxes never merge.\n */\nexport function groupUsage(\n rows: readonly LedgerRow[],\n window: { from: string; to: string },\n pricing: Pricing | undefined,\n live: ReadonlyMap<string, BoxStatus> = new Map(),\n): BoxUsage[] {\n const byBox = new Map<string, LedgerRow[]>();\n for (const r of rows) {\n const key = r.ledger === undefined ? r.boxId : `${r.ledger}:${r.boxId}`;\n const list = byBox.get(key);\n if (list === undefined) byBox.set(key, [r]);\n else list.push(r);\n }\n const out: BoxUsage[] = [];\n for (const events of byBox.values()) {\n events.sort((a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : 0));\n const first = events[0]!;\n const last = events[events.length - 1]!;\n const id = last.boxId;\n const removed = last.by === \"rm\" && !live.has(id);\n const to = removed && last.at < window.to ? last.at : window.to;\n if (first.at >= to || (removed && last.at <= window.from)) continue;\n const totals = computeUsage(events, { from: window.from, to, pricing });\n const status: BoxUsage[\"status\"] = live.get(id) ?? (removed ? \"removed\" : last.state);\n out.push({ id, name: last.name, owner: last.owner, status, ...totals });\n }\n return out.sort((a, b) => a.owner.localeCompare(b.owner) || a.name.localeCompare(b.name) || (a.historyFrom ?? \"\").localeCompare(b.historyFrom ?? \"\"));\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/** A realm: a control plane's name as hosts qualify owners with it (`kvbox.sh`). A path segment later, so nothing but a host name. */\nexport const REALM_RE = /^[A-Za-z0-9.-]{1,128}$/;\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/**\n * Who a listing is for: one owner, every owner of a realm (`{ realm }`: the control plane reconciling\n * its index, #20), or everyone (`null`: the host owner's own accounting).\n */\nexport type ListScope = string | { realm: string } | null;\n\nexport function inScope(owner: string, scope: ListScope): boolean {\n if (scope === null) return true;\n if (typeof scope === \"string\") return owner === scope;\n return realmOf(owner) === scope.realm;\n}\n\n/** The control plane an owner belongs to (`alice@kvbox.sh` → `kvbox.sh`); null for a local owner. */\nexport function realmOf(owner: string): string | null {\n const at = owner.indexOf(\"@\");\n return at === -1 ? null : owner.slice(at + 1);\n}\n\n/**\n * `lab1` → the caller's box; `user2/lab1` → that owner's. A caller from a control plane (`user@realm`)\n * can only name owners of that realm: the control plane never sees the host owner's local boxes or\n * another control plane's. The host owner over the socket is not restricted.\n */\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 const realm = realmOf(caller);\n if (realm !== null && realmOf(owner) !== realm) {\n throw new KvboxError(`invalid box reference \"${text}\": ${owner} is not in your realm`);\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 * The host's side of the control plane (#18, design in the brain's multi-host doc). A host joins\n * exactly one control plane with a one-time token an admin minted there; it gets back a secret the\n * control plane will present on every call, and from its next start it also serves the API over\n * HTTPS. The control plane trusts the host by the fingerprint of the self-signed certificate made\n * here (no CA), so the certificate is generated once and kept for the host's life.\n */\nimport { X509Certificate } from \"node:crypto\";\nimport { chmod, mkdir, readFile } from \"node:fs/promises\";\nimport { hostname as osHostname } from \"node:os\";\nimport { request } from \"undici\";\nimport { HostJoinResponseSchema, HostSshCaResponseSchema, type CloudCa, type HostJoinRequest } from \"@kvbox/shared/api\";\nimport { parseSshPublicKey, sshKeyFingerprint } from \"@kvbox/shared/ssh\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { loadConfig, saveConfig } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { REALM_RE } from \"./refs.js\";\n\nexport const DEFAULT_HTTPS_PORT = 7777;\n\n/** The certificate's sha256 fingerprint, `AA:BB:…`, the form the control plane pins. */\nexport interface TlsIdentity {\n fingerprint: string;\n}\n\n/** Generate `tls/key.pem` + `tls/cert.pem` on first use (openssl, EC P-256, 10 years); return the fingerprint either way. */\nexport async function ensureTlsCert(p: Paths = paths()): Promise<TlsIdentity> {\n const have = await readFile(p.tlsCert, \"utf8\").catch(() => null);\n const haveKey = await readFile(p.tlsKey).then(() => true, () => false);\n if (have === null || !haveKey) {\n await mkdir(p.tls, { recursive: true, mode: 0o700 });\n try {\n await run([\n \"openssl\", \"req\", \"-x509\", \"-newkey\", \"ec\", \"-pkeyopt\", \"ec_paramgen_curve:prime256v1\", \"-nodes\",\n \"-keyout\", p.tlsKey, \"-out\", p.tlsCert, \"-subj\", \"/CN=kvbox-host\", \"-days\", \"3650\",\n ]);\n } catch (err) {\n throw new KvboxError(`could not make the host's certificate (is openssl installed?): ${(err as Error).message}`);\n }\n await chmod(p.tlsKey, 0o600);\n }\n const pem = await readFile(p.tlsCert, \"utf8\");\n return { fingerprint: new X509Certificate(pem).fingerprint256 };\n}\n\nexport interface JoinOptions {\n /** The control plane, e.g. https://api.kvbox.sh. */\n url: string;\n /** One-time token an admin minted there. */\n token: string;\n /** Host or IP the control plane reaches this host at; default: the address of this host's default route. */\n advertise?: string;\n /** How the control plane lists this host; default: the hostname. */\n name?: string;\n port?: number;\n}\n\nexport interface Joined {\n hostName: string;\n controlPlane: string;\n /** Where the control plane will call this host: https://<advertise>:<port>. */\n hostUrl: string;\n}\n\n/** RFC 1918, loopback, link-local and carrier-grade NAT: addresses a control plane on the internet cannot reach. */\nexport function isPrivateAddress(ip: string): boolean {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$/.exec(ip);\n if (!m) return false;\n const [a, b] = [Number(m[1]), Number(m[2])];\n return a === 10 || a === 127 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 169 && b === 254) || (a === 100 && b >= 64 && b <= 127);\n}\n\n/** The IPv4 this host would use to reach the internet: the `src` of the default route. */\nexport async function defaultAdvertise(): Promise<string> {\n const { stdout } = await run([\"ip\", \"-4\", \"route\", \"get\", \"1.1.1.1\"]).catch((err: Error) => {\n throw new KvboxError(`cannot tell this host's address (${err.message}); pass --advertise <host-or-ip>`);\n });\n const m = /\\bsrc\\s+(\\S+)/.exec(stdout);\n if (!m) throw new KvboxError(\"cannot tell this host's address from its routes; pass --advertise <host-or-ip>\");\n return m[1]!;\n}\n\n/**\n * Register this host with a control plane: make sure it has a certificate, send the join, keep the\n * secret in config.json. The server picks the HTTPS listener up at its next start.\n */\nexport async function joinControlPlane(opts: JoinOptions, p: Paths = paths(), guessAddress: () => Promise<string> = defaultAdvertise): Promise<Joined> {\n const url = opts.url.replace(/\\/+$/, \"\");\n const port = opts.port ?? DEFAULT_HTTPS_PORT;\n const cfg = await loadConfig(p);\n if (cfg.controlPlane) throw new KvboxError(`this host has already joined ${cfg.controlPlane.name} (${cfg.controlPlane.url}); run kvbox server leave first`);\n let advertise = opts.advertise;\n if (advertise === undefined && cfg.relay) {\n // Behind a relay the host's own addresses are beside the point: the relay's public IP is where it is reached.\n advertise = cfg.relay.publicIp;\n } else if (advertise === undefined) {\n advertise = await guessAddress();\n if (isPrivateAddress(advertise)) {\n throw new KvboxError(\n `${advertise} is a private address: a control plane on the internet cannot reach this host there.\\n` +\n ` Pass --advertise <public host or ip>, or --advertise ${advertise} if the control plane is on the same network.`,\n );\n }\n }\n const name = opts.name ?? osHostname();\n const { fingerprint } = await ensureTlsCert(p);\n const hostUrl = `https://${advertise}:${port}`;\n const body: HostJoinRequest = { token: opts.token, name, url: hostUrl, fingerprint, publicAddress: advertise };\n\n const res = await request(`${url}/hosts/join`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n headersTimeout: 10_000,\n bodyTimeout: 10_000,\n }).catch((err: Error) => {\n throw new KvboxError(`cannot reach ${url} (${err.message})`);\n });\n const text = await res.body.text();\n if (res.statusCode < 200 || res.statusCode >= 300) {\n throw new KvboxError(errorIn(text) ?? `control plane answered ${res.statusCode}`);\n }\n const parsed = HostJoinResponseSchema.safeParse(jsonOrNull(text));\n if (!parsed.success) throw new KvboxError(`${url} did not answer like a kvbox control plane`);\n if (!REALM_RE.test(parsed.data.controlPlane.name)) {\n throw new KvboxError(`${url} calls itself \"${parsed.data.controlPlane.name}\", which cannot name a realm (letters, digits, '.', '-')`);\n }\n\n await saveConfig({ ...cfg, controlPlane: { url, name: parsed.data.controlPlane.name, secret: parsed.data.hostSecret, advertise, port } }, p);\n return { hostName: name, controlPlane: parsed.data.controlPlane.name, hostUrl };\n}\n\n/**\n * Ask the joined control plane which SSH CA boxes should trust (`GET /hosts/self/ssh-ca`, by the\n * host secret), with its fingerprint, for `kvbox server trust-ca --from-cloud` to show before\n * anything changes (#55).\n */\nexport async function fetchCloudCa(p: Paths = paths()): Promise<CloudCa> {\n const cfg = await loadConfig(p);\n const cp = cfg.controlPlane;\n if (!cp) throw new KvboxError(\"this host has not joined a control plane, so there is no CA to fetch; paste the key instead: kvbox server trust-ca <public-key>\");\n const res = await request(`${cp.url}/hosts/self/ssh-ca`, {\n headers: { authorization: `Bearer ${cp.secret}` },\n headersTimeout: 10_000,\n bodyTimeout: 10_000,\n }).catch((err: Error) => {\n throw new KvboxError(`cannot reach ${cp.url} (${err.message})`);\n });\n const text = await res.body.text();\n if (res.statusCode === 404) throw new KvboxError(`${cp.name} does not answer /hosts/self/ssh-ca: it is older than this host; paste the key instead`);\n if (res.statusCode < 200 || res.statusCode >= 300) throw new KvboxError(errorIn(text) ?? `${cp.name} answered ${res.statusCode}`);\n const parsed = HostSshCaResponseSchema.safeParse(jsonOrNull(text));\n if (!parsed.success) throw new KvboxError(`${cp.name} did not answer with a CA key`);\n const publicKey = parseSshPublicKey(parsed.data.publicKey);\n return { controlPlane: cp.name, publicKey, fingerprint: sshKeyFingerprint(publicKey) };\n}\n\nexport interface Left {\n controlPlane: string;\n /** Whether the control plane acknowledged; false means an admin has to remove the host there. */\n told: boolean;\n}\n\n/** Forget the control plane (the HTTPS listener stops at the next start) and tell it so, best effort. */\nexport async function leaveControlPlane(p: Paths = paths()): Promise<Left> {\n const cfg = await loadConfig(p);\n const cp = cfg.controlPlane;\n if (!cp) throw new KvboxError(\"this host has not joined a control plane\");\n const told = await request(`${cp.url}/hosts/self`, {\n method: \"DELETE\",\n headers: { authorization: `Bearer ${cp.secret}` },\n headersTimeout: 3000,\n bodyTimeout: 3000,\n })\n .then(async (res) => {\n await res.body.dump();\n return res.statusCode >= 200 && res.statusCode < 300;\n })\n .catch(() => false);\n const { controlPlane: _gone, ...rest } = cfg;\n await saveConfig(rest, p);\n return { controlPlane: cp.name, told };\n}\n\nfunction jsonOrNull(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return null;\n }\n}\n\n/** The `{ error }` of a kvbox JSON answer, if that is what the text is. */\nfunction errorIn(text: string): string | undefined {\n const v = jsonOrNull(text);\n if (v && typeof v === \"object\" && typeof (v as { error?: unknown }).error === \"string\") return (v as { error: string }).error;\n return undefined;\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/** The guest account every box has; `ssh` logs in as it. */\nexport const BOX_SSH_USER = \"kvbox\";\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 * `unknown`: only from the control plane, for a box whose host did not answer in time (#20).\n */\nexport const BoxStatusSchema = z.enum([\"running\", \"standby\", \"hibernated\", \"stopped\", \"unknown\"]);\nexport type BoxStatus = z.infer<typeof BoxStatusSchema>;\n\n/** A published box port's protocol (#30). */\nexport const PortProtoSchema = z.enum([\"tcp\", \"udp\"]);\nexport type PortProto = z.infer<typeof PortProtoSchema>;\n\n/** At most this many published ports per box (#30): room for a lab of services, not for draining the host's range. */\nexport const MAX_BOX_PORTS = 16;\n\n/**\n * A box port published on the host's public address (#30, `kvbox vm proxy`): `hostPort` on the\n * host reaches `guestPort` in the box. The host port is drawn at random and stays the box's.\n */\nexport const PortForwardSchema = z.object({\n guestPort: z.number().int().min(1).max(65535),\n hostPort: z.number().int(),\n proto: PortProtoSchema,\n /** The host's public address; only the control plane fills it in, as for `ssh`. */\n address: z.string().optional(),\n});\nexport type PortForward = z.infer<typeof PortForwardSchema>;\n\n/** `POST /machines/:name/ports` adds these, `DELETE` removes them; the answer is the box. */\nexport const PortsRequest = z.object({\n ports: z.array(z.object({ guestPort: z.number().int().min(1).max(65535), proto: PortProtoSchema.optional() })).min(1).max(MAX_BOX_PORTS),\n});\nexport type PortsRequest = z.infer<typeof PortsRequest>;\n\nconst BoxPortSchema = z.number().int().min(1).max(65535);\n\n/** `PUT /machines/:name/subdomain` (#31): claim `<name>.kvbox.app` for the box, serving `port`. */\nexport const ClaimSubdomainRequest = z.object({ name: z.string(), port: BoxPortSchema });\nexport type ClaimSubdomainRequest = z.infer<typeof ClaimSubdomainRequest>;\n\n/** `POST /machines/:name/subdomain/port`: the default port changes. */\nexport const SubdomainPortRequest = z.object({ port: BoxPortSchema });\nexport type SubdomainPortRequest = z.infer<typeof SubdomainPortRequest>;\n\n/** `POST /machines/:name/subdomain/routes`: `<name>.<sub>.kvbox.app` serves `port`. */\nexport const SubdomainRouteRequest = z.object({ name: z.string(), port: BoxPortSchema });\nexport type SubdomainRouteRequest = z.infer<typeof SubdomainRouteRequest>;\n\n/**\n * A box's HTTPS subdomain (#31): `url` serves the box's `port`, each route's `url` its own port.\n * `owner` is the box's slug (a user's or an org's), `box` its name.\n */\nexport const SubdomainSchema = z.object({\n owner: z.string(),\n box: z.string(),\n subdomain: z.string(),\n port: BoxPortSchema,\n url: z.string(),\n routes: z.array(z.object({ name: z.string(), port: BoxPortSchema, url: z.string() })),\n});\nexport type Subdomain = z.infer<typeof SubdomainSchema>;\n\nexport const MachineSchema = z.object({\n /** Host-unique short id (the tap is `kv-<id>`). Missing only on a box made before ids that has not restarted since. */\n id: z.string(),\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(), // base image version the box's overlay stacks on\n createdAt: z.string(),\n source: z.string(), // \"base\" or \"snapshot:<name>\"\n status: BoxStatusSchema,\n /**\n * Public TCP port on the host that reaches the box's SSH while it runs (#49). Only boxes made\n * through a control plane have one; the control plane adds the host's address for `connect` (#21).\n */\n sshPort: z.number().int().optional(),\n /**\n * Where `ssh` reaches the box from outside: the host's public address and that port (#21). Only\n * the control plane fills it in (a host does not know its own public address); absent for a box\n * whose host reported no port or did not answer.\n */\n ssh: z.object({ host: z.string(), port: z.number().int(), user: z.string() }).optional(),\n /** Box ports published on the host (#30). Absent: none. */\n ports: z.array(PortForwardSchema).optional(),\n /** Whether the owner slug is a user or an org. Only the control plane knows; it fills it in on `GET /machines`. */\n ownerKind: z.enum([\"user\", \"org\"]).optional(),\n /** Seconds without network traffic before the host hibernates the box (#47). Absent: never. */\n autoHibernateSec: z.number().int().positive().optional(),\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 /**\n * Extra authorized_keys lines for the box, on top of the host's own key: the control plane sends\n * its SSH CA as one `cert-authority …` line (#51). Written into the box's authorized_keys at every\n * boot (#49); a host older than that ignores them.\n */\n sshKeys: z.array(z.string()).optional(),\n /** Seconds without network traffic before the box is hibernated (#47); 0: never. Absent: the host's default. */\n autoHibernateSec: z.number().int().min(0).optional(),\n});\nexport type CreateMachineRequest = z.infer<typeof CreateMachineRequest>;\n\n/**\n * `POST /machines/:name/ssh-keys` on a host (orgs phase 4): replace the authorized_keys lines the box\n * gets on top of the host's own key. Takes effect at the box's next boot (kvbox-init rewrites the\n * file from the kernel command line); a running or hibernated box keeps its current file until then.\n */\nexport const SetSshKeysRequest = z.object({\n sshKeys: z.array(z.string()),\n});\nexport type SetSshKeysRequest = z.infer<typeof SetSshKeysRequest>;\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\n/** `kvbox vm set`: settings that change nothing in the running VM. Anything omitted stays as it is. */\nexport const SetMachineRequest = z.object({\n /** Seconds without network traffic before the box is hibernated (#47); 0: never. */\n autoHibernateSec: z.number().int().min(0).optional(),\n});\nexport type SetMachineRequest = z.infer<typeof SetMachineRequest>;\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\n/**\n * What the server did at its last start about boxes whose Firecracker had died (host reboot or crash,\n * #29). Boxes are `owner/name`. `leftStopped`: they were in standby, their memory went with the process.\n */\nexport const RecoveryReportSchema = z.object({\n at: z.string(),\n booted: z.array(z.string()),\n leftStopped: z.array(z.string()),\n failed: z.array(z.object({ box: z.string(), error: z.string() })),\n});\nexport type RecoveryReport = z.infer<typeof RecoveryReportSchema>;\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). */\n base: z.string().nullable(),\n /** Owner that boxes made over the local socket get (the Unix user running the server). */\n owner: z.string(),\n /** The control plane this host joined (null when none). */\n controlPlane: z\n .object({\n /** Realm name, e.g. kvbox.sh. */\n name: z.string(),\n url: z.string(),\n /** Where this host answers the control plane. */\n hostUrl: z.string(),\n })\n .nullable(),\n /** The relay this host reaches the internet through (#50); null when it has its own public address. Older servers omit it. */\n relay: z\n .object({\n name: z.string(),\n /** The public IP the relay owns for this host. */\n publicIp: z.string(),\n /** The relay's WireGuard endpoint the tunnel dials. */\n endpoint: z.string(),\n /** Times the server redialed the tunnel since it started, because the relay stopped answering. Older servers omit them. */\n restarts: z.number().int().optional(),\n lastRestartAt: z.string().nullable().optional(),\n })\n .nullable()\n .optional(),\n /** Boxes brought back at the server's last start; null when there were none or it is still at it. Older servers omit it. */\n recovery: RecoveryReportSchema.nullable().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, null when nothing is recorded yet.\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 seconds: z.object({\n running: z.number().int(),\n standby: z.number().int(),\n hibernated: z.number().int(),\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\n/** What a running box says about itself through kvbox-agent's `stats` (base v0.7.0 and later). */\nexport const GuestStatsSchema = z.object({\n /** Load average over 1, 5 and 15 minutes. */\n load: z.tuple([z.number(), z.number(), z.number()]),\n cpus: z.number().int(),\n memTotalMib: z.number().int(),\n /** Total minus available: page cache counts as free. */\n memUsedMib: z.number().int(),\n /** The box's root, which is its overlay disk: the box's own writes, not the shared base. */\n diskTotalBytes: z.number().int(),\n diskUsedBytes: z.number().int(),\n uptimeSec: z.number().int(),\n});\nexport type GuestStats = z.infer<typeof GuestStatsSchema>;\n\n/** `GET /machines/:name/stats` (#67): `stats` is null when the box's image predates the request. */\nexport const MachineStatsSchema = z.object({\n name: z.string(),\n owner: z.string(),\n stats: GuestStatsSchema.nullable(),\n});\nexport type MachineStats = z.infer<typeof MachineStatsSchema>;\n\n/** A box's state as the usage ledger tells it: a box status, or `removed` when its last row is the `rm`. */\nexport const UsageStatusSchema = z.enum([...BoxStatusSchema.options, \"removed\"]);\nexport type UsageStatus = z.infer<typeof UsageStatusSchema>;\n\n/** One box's share of a `GET /usage` report (#41, #42): the same figures as `MachineUsage`, over the report's window. */\nexport const BoxUsageSchema = MachineUsageSchema.omit({ window: true, status: true }).extend({\n /** The host's box id; a name removed and recreated appears twice, with two ids. */\n id: z.string(),\n status: UsageStatusSchema,\n /** Through a control plane: whether the owner slug is a user's or an org's (what `kvbox ls` shows). */\n ownerKind: z.enum([\"user\", \"org\"]).optional(),\n});\nexport type BoxUsage = z.infer<typeof BoxUsageSchema>;\n\n/**\n * `GET /usage?since=&until=`: every box of the caller over the window (removed ones included) and\n * the totals. On a host over its socket: the host owner's boxes; through a control plane: every slug\n * the user can read (`X-Kvbox-Org` narrows to one). `cost` is present when the answering side prices usage.\n */\nexport const UsageReportSchema = z.object({\n window: z.object({ from: z.string(), to: z.string() }),\n boxes: z.array(BoxUsageSchema),\n totals: z.object({\n seconds: MachineUsageSchema.shape.seconds,\n vcpuHours: z.number(),\n ramGibHours: z.number(),\n diskGibHours: z.number(),\n cost: z.object({ amount: z.number(), currency: z.string() }).optional(),\n }),\n});\nexport type UsageReport = z.infer<typeof UsageReportSchema>;\n\n/**\n * `GET /usage/events?after=<id>&limit=<n>` on a host (#42): the ledger rows after `after`, oldest\n * first, as the control plane pulls them. `next` is the last row's id (the cursor to store), equal\n * to `after` when there was nothing new. Over HTTPS only rows of the caller's realm come back.\n * `ledger` names the host's ledger: row ids are unique only within it, and a new one restarts at 1.\n */\nexport const UsageEventRowSchema = z.object({\n id: z.number().int(),\n boxId: z.string(),\n owner: z.string(),\n name: z.string(),\n at: z.string(),\n state: z.enum([\"running\", \"standby\", \"hibernated\", \"stopped\"]),\n vcpu: z.number().int(),\n memMib: z.number().int(),\n diskGib: z.number().int(),\n by: z.string(),\n});\nexport type UsageEventRow = z.infer<typeof UsageEventRowSchema>;\n\nexport const UsageEventsResponseSchema = z.object({\n ledger: z.string().min(1),\n events: z.array(UsageEventRowSchema),\n next: z.number().int(),\n});\nexport type UsageEventsResponse = z.infer<typeof UsageEventsResponseSchema>;\n\nexport const ApiErrorSchema = z.object({\n error: z.string(),\n});\n\n// ---- control plane (kvbox-cloud) ----\n\n/** Where `kvbox login` goes without a URL, and the control plane's own public URL by default. */\nexport const DEFAULT_CLOUD_URL = \"https://api.kvbox.sh\";\n\n/**\n * Who turned a slug (a user or an org) on: a card on file (`card`, #75) or an admin by hand\n * (`admin`, #74). Until one of them does, the account only logs in and looks: every other route\n * answers 402 (decision \"Signup is email + password… inactive until a card is on file\").\n */\nexport const ACTIVATED_BY = [\"card\", \"admin\"] as const;\nexport const ActivatedBySchema = z.enum(ACTIVATED_BY);\nexport type ActivatedBy = z.infer<typeof ActivatedBySchema>;\n\n/** A user account on the control plane; returned by `GET /me`, `GET /users` (#48). */\nexport const CloudUserSchema = z.object({\n /** The handle: what hosts file boxes under (`<username>@<control plane>`). Lowercase, no `@` or `/`. */\n username: z.string(),\n /** Display name, free text (\"Alexandru Ghiura\"). */\n name: z.string(),\n /** Login identity, unique. */\n email: z.string(),\n role: z.enum([\"admin\", \"user\"]),\n createdAt: z.string(),\n /**\n * False until a card is on file or an admin activates the account (#74): then only `/me` and\n * `/logout` answer. Admins are never gated. A control plane older than #74 does not send these and\n * gates nobody, hence the defaults: a newer CLI must still parse its answers.\n */\n active: z.boolean().default(true),\n activatedBy: ActivatedBySchema.nullable().default(null),\n});\nexport type CloudUser = z.infer<typeof CloudUserSchema>;\n\n// ---- orgs (plan \"Orgs, slugs and roles\") ----\n\nexport const ORG_ROLES = [\"owner\", \"admin\", \"member\"] as const;\nexport const OrgRoleSchema = z.enum(ORG_ROLES);\nexport type OrgRole = z.infer<typeof OrgRoleSchema>;\n\n/** An org as the API shows it; its slug owns boxes the way a username does. */\nexport const CloudOrgSchema = z.object({\n slug: z.string(),\n /** Display name; the slug never changes, this may. */\n name: z.string(),\n createdAt: z.string(),\n /** An org pays for itself (#74): off until it has a card or an admin activates it; its boxes are 402. Defaults as on CloudUser. */\n active: z.boolean().default(true),\n activatedBy: ActivatedBySchema.nullable().default(null),\n});\nexport type CloudOrg = z.infer<typeof CloudOrgSchema>;\n\n/** One of the caller's orgs with their role in it (`GET /orgs`, `GET /me`). */\nexport const OrgMembershipSchema = CloudOrgSchema.extend({ role: OrgRoleSchema });\nexport type OrgMembership = z.infer<typeof OrgMembershipSchema>;\n\nexport const OrgMemberSchema = z.object({\n username: z.string(),\n name: z.string(),\n role: OrgRoleSchema,\n addedAt: z.string(),\n});\nexport type OrgMember = z.infer<typeof OrgMemberSchema>;\n\n/** `GET /orgs/:slug`: the org and its members (members and up see it). */\nexport const OrgDetailSchema = CloudOrgSchema.extend({ members: z.array(OrgMemberSchema) });\nexport type OrgDetail = z.infer<typeof OrgDetailSchema>;\n\n/** `POST /orgs`: the caller becomes the org's owner. */\nexport const CreateOrgRequestSchema = z.object({\n slug: z.string().min(1),\n name: z.string().min(1),\n});\nexport type CreateOrgRequest = z.infer<typeof CreateOrgRequestSchema>;\n\n/** `PATCH /orgs/:slug` (owner): the display name. */\nexport const RenameOrgRequestSchema = z.object({ name: z.string().min(1) });\n\n/** `POST /orgs/:slug/members` (admin, owner): an existing user joins, as a member unless said otherwise. */\nexport const AddMemberRequestSchema = z.object({\n username: z.string().min(1),\n role: OrgRoleSchema.default(\"member\"),\n});\nexport type AddMemberRequest = z.infer<typeof AddMemberRequestSchema>;\n\n/** `PATCH /orgs/:slug/members/:username` (owner). */\nexport const SetRoleRequestSchema = z.object({ role: OrgRoleSchema });\n\n/** `GET /me`: the account plus the orgs it belongs to. */\nexport const MeResponseSchema = CloudUserSchema.extend({ orgs: z.array(OrgMembershipSchema) });\nexport type MeResponse = z.infer<typeof MeResponseSchema>;\n\n// ---- prepaid credit (#76) ----\n\n/**\n * `GET /billing/balance`: what a slug (the caller's own, or `X-Kvbox-Org`'s) has left. `balance` is\n * every top-up minus what the usage ledger says its boxes cost since `since`, the slug's first top-up\n * (null: it never had any); at or below zero the slug cannot start or create anything (402).\n * `topUps` and `spent` are the two sides of it.\n */\nexport const BalanceSchema = z.object({\n slug: z.string(),\n balance: z.number(),\n currency: z.string(),\n topUps: z.number(),\n spent: z.number(),\n /** The first moment usage counts from: the slug's first top-up; null when it has none. */\n since: z.string().nullable(),\n /** When the slug ran out and its boxes were hibernated (the `sweep-credit` job); null in good standing. Absent from a control plane older than this field. */\n suspendedAt: z.string().nullable().default(null),\n});\nexport type Balance = z.infer<typeof BalanceSchema>;\n\n/** `POST /admin/billing/top-ups` (platform admin): give a slug money by hand. */\nexport const TopUpRequestSchema = z.object({\n slug: z.string().min(1),\n /** In the control plane's currency; negative corrects a mistake. */\n amount: z.number().finite(),\n note: z.string().max(200).optional(),\n});\nexport type TopUpRequest = z.infer<typeof TopUpRequestSchema>;\n\n/** One top-up as recorded, answered by `POST /admin/billing/top-ups`. */\nexport const TopUpSchema = z.object({\n id: z.string(),\n slug: z.string(),\n amount: z.number(),\n currency: z.string(),\n source: z.enum([\"admin\", \"card\", \"trial\"]),\n note: z.string().nullable(),\n at: z.string(),\n});\nexport type TopUp = z.infer<typeof TopUpSchema>;\n\n/** `POST /login` body from `kvbox login` (#48); `publicKey` is the user's SSH key to inject into new boxes. */\nexport const LoginRequestSchema = z.object({\n email: z.string().min(1),\n password: z.string().min(1),\n publicKey: z.string().optional(),\n});\nexport type LoginRequest = z.infer<typeof LoginRequestSchema>;\n\n/** `POST /signup` body from the website: a new account with the `user` role; answers like `/login` (logged in at once). */\nexport const SignupRequestSchema = z.object({\n username: z.string().min(1),\n name: z.string().min(1),\n email: z.string().min(1),\n password: z.string().min(1),\n});\nexport type SignupRequest = z.infer<typeof SignupRequestSchema>;\n\n/**\n * `POST /login` answer: the bearer token the CLI stores (#48). With a `publicKey` in the request,\n * also that key signed by the control plane's SSH CA (#51): the `-cert.pub` text and when it expires (ISO).\n */\nexport const LoginResponseSchema = z.object({\n token: z.string(),\n user: CloudUserSchema,\n sshCert: z.string().optional(),\n sshCertExpires: z.string().optional(),\n /** Whose boxes the certificate opens: `<slug>@<realm>` for the user and each org they are in (orgs phase 4). */\n sshCertPrincipals: z.array(z.string()).optional(),\n});\nexport type LoginResponse = z.infer<typeof LoginResponseSchema>;\n\n/** `POST /ssh/cert` body: one of the caller's uploaded keys to sign again (#51). */\nexport const SshCertRequestSchema = z.object({\n publicKey: z.string().min(1),\n});\nexport type SshCertRequest = z.infer<typeof SshCertRequestSchema>;\n\n/** `POST /ssh/cert` answer: the certificate text, its expiry (ISO) and its principals. */\nexport const SshCertResponseSchema = z.object({\n cert: z.string(),\n expires: z.string(),\n principals: z.array(z.string()),\n});\nexport type SshCertResponse = z.infer<typeof SshCertResponseSchema>;\n\n/** `GET /ssh/ca` answer: the CA's public key, the line boxes trust after `cert-authority `. */\nexport const SshCaResponseSchema = z.object({\n publicKey: z.string(),\n /** CAs replaced by `ca rotate` (#55), newest first; a box still holding one of these has not had `kvbox server trust-ca` run on its host. */\n retired: z.array(z.object({ publicKey: z.string(), retiredAt: z.string() })).optional(),\n});\nexport type SshCaResponse = z.infer<typeof SshCaResponseSchema>;\n\n/** `GET /hosts/self/ssh-ca` on the control plane, by the host secret: the CA every box should trust (`kvbox server trust-ca --from-cloud`, #55). */\nexport const HostSshCaResponseSchema = z.object({\n publicKey: z.string(),\n});\n\n/** `GET /ssh/cloud-ca` on a host's socket: what its control plane says the CA is, with the fingerprint to confirm. */\nexport const CloudCaSchema = z.object({\n controlPlane: z.string(),\n publicKey: z.string(),\n fingerprint: z.string(),\n});\nexport type CloudCa = z.infer<typeof CloudCaSchema>;\n\n/** `POST /ssh/trust-ca` on a host's socket (#55): the CA public key (a pasted `cert-authority …` line is accepted too). */\nexport const TrustCaRequestSchema = z.object({\n publicKey: z.string().min(1),\n});\nexport type TrustCaRequest = z.infer<typeof TrustCaRequestSchema>;\n\n/**\n * When a box's new authorized_keys reach the guest: `now` (pushed through kvbox-agent), or at its\n * next `start` (stopped: kvbox-init writes the file at boot), `wake` (hibernated), `resume`\n * (standby), or `later` (running, but its agent could not take them: the next stop and start).\n */\nexport const SshKeysAppliedSchema = z.enum([\"now\", \"start\", \"wake\", \"resume\", \"later\"]);\nexport type SshKeysApplied = z.infer<typeof SshKeysAppliedSchema>;\n\n/** `POST /ssh/trust-ca` answer: every cloud box on the host, by what happened to it. Boxes are `owner/name`. */\nexport const TrustCaReportSchema = z.object({\n publicKey: z.string(),\n fingerprint: z.string(),\n /** The guest trusts the CA now. */\n updated: z.array(z.string()),\n /** meta.json has the line; the guest gets it at `when`. */\n pending: z.array(z.object({ box: z.string(), when: SshKeysAppliedSchema, why: z.string().optional() })),\n failed: z.array(z.object({ box: z.string(), error: z.string() })),\n /** Local boxes, untouched: they trust the host's key only. */\n local: z.number().int(),\n});\nexport type TrustCaReport = z.infer<typeof TrustCaReportSchema>;\n\n/** `POST /hosts/join` body from `kvbox-server join` (#18); `fingerprint` is the host's TLS cert sha256, colon-separated. */\nexport const HostJoinRequestSchema = z.object({\n token: z.string().min(1),\n name: z.string().min(1),\n url: z.string().url(),\n fingerprint: z.string().regex(/^([0-9A-F]{2}:){31}[0-9A-F]{2}$/),\n publicAddress: z.string().min(1),\n});\nexport type HostJoinRequest = z.infer<typeof HostJoinRequestSchema>;\n\n/** `POST /hosts/join` answer: the secret the control plane will present to the host from now on (#18). */\nexport const HostJoinResponseSchema = z.object({\n hostSecret: z.string(),\n controlPlane: z.object({ name: z.string() }),\n});\nexport type HostJoinResponse = z.infer<typeof HostJoinResponseSchema>;\n\n/** A host as the control plane knows it; returned by `GET /hosts` (admin). */\nexport const CloudHostSchema = z.object({\n name: z.string(),\n url: z.string(),\n publicAddress: z.string(),\n joinedAt: z.string(),\n lastSeenAt: z.string().nullable(),\n capacity: CapacitySchema.nullable(),\n});\nexport type CloudHost = z.infer<typeof CloudHostSchema>;\n","/**\n * SSH public keys as text, for the three places that handle the CA's: the control plane writes a\n * box's `cert-authority` line and prints a fingerprint after `ca rotate`, the host builds the same\n * line for every box at `kvbox server trust-ca`, the CLI shows the fingerprint before asking.\n */\nimport { createHash } from \"node:crypto\";\nimport { KvboxError } from \"./errors.js\";\n\n/** `<type> <base64>[ <comment>]`, one line; the types OpenSSH signs certificates with. */\nexport const SSH_PUBLIC_KEY_RE =\n /^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp(?:256|384|521)|sk-ssh-ed25519@openssh\\.com|sk-ecdsa-sha2-nistp256@openssh\\.com) ([A-Za-z0-9+/]+=*)(?: [^\\r\\n]*)?$/;\n\n/** The key, trimmed, with a leading `cert-authority ` (a pasted authorized_keys line) allowed and dropped. */\nexport function parseSshPublicKey(text: string): string {\n const key = text.trim().replace(/^cert-authority\\s+/, \"\");\n if (!SSH_PUBLIC_KEY_RE.test(key)) {\n throw new KvboxError(\"that is not an SSH public key; expected one line like: ssh-ed25519 AAAA… kvbox-ca@kvbox.sh\");\n }\n return key;\n}\n\n/** `SHA256:<base64, no padding>` of the key blob, what `ssh-keygen -l` prints. */\nexport function sshKeyFingerprint(publicKey: string): string {\n const m = SSH_PUBLIC_KEY_RE.exec(publicKey.trim());\n if (!m) throw new KvboxError(\"cannot fingerprint: not an SSH public key\");\n return `SHA256:${createHash(\"sha256\").update(Buffer.from(m[2]!, \"base64\")).digest(\"base64\").replace(/=+$/, \"\")}`;\n}\n\n/**\n * A box's authorized_keys line for a CA: trust it, but only for certificates naming `principal`\n * (the box's owner, `<slug>@<realm>`); sshd then ignores the login name and matches `principals=`.\n */\nexport function caLineFor(principal: string, caPublicKey: string): string {\n return `cert-authority,principals=\"${principal}\" ${caPublicKey}`;\n}\n\n/** Whether an authorized_keys line is a CA line (any options, the keyword first). */\nexport const isCaLine = (line: string): boolean => /^cert-authority(,|\\s)/.test(line.trim());\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","/**\n * Firecracker needs /dev/kvm. A daemon that cannot open it starts fine and only fails at the first\n * `kvbox new`, with an opaque firecracker 400 (#61): the usual cause is a shell that logged in\n * before the user was added to the kvm group, so the daemon it spawned runs without that group.\n * Checked once at `kvbox-server start`, before the socket is bound, and told in plain words.\n */\nimport { access, constants, readFile, stat } from \"node:fs/promises\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\n\nexport const KVM_DEVICE = \"/dev/kvm\";\n\n/** The group's name for a gid from /etc/group, `kvm` when the file does not say. */\nexport async function groupName(gid: number, groupFile = \"/etc/group\"): Promise<string> {\n const text = await readFile(groupFile, \"utf8\").catch(() => \"\");\n for (const line of text.split(\"\\n\")) {\n const [name, , id] = line.split(\":\");\n if (id !== undefined && Number.parseInt(id, 10) === gid && name) return name;\n }\n return \"kvm\";\n}\n\n/** Resolves when this process can open the device for reading and writing; a KvboxError saying what to do otherwise. */\nexport async function requireKvm(device = KVM_DEVICE, groupFile = \"/etc/group\"): Promise<void> {\n try {\n await access(device, constants.R_OK | constants.W_OK);\n return;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n throw new KvboxError(`${device} is missing: this machine has no KVM, so boxes cannot run here (enable virtualization in the BIOS, then install-server.sh checks the rest)`);\n }\n if (code !== \"EACCES\" && code !== \"EPERM\") throw new KvboxError(`cannot open ${device}: ${(err as Error).message}`);\n }\n const owner = await stat(device).then((s) => groupName(s.gid, groupFile), () => \"kvm\");\n throw new KvboxError(\n `cannot start: this process is not allowed to open ${device}, so no box could run. ` +\n `It was started from a shell without the ${owner} group (a login from before you were added to it). ` +\n `Log out and back in, or start it from a shell that has the group: sg ${owner} -c \"kvbox server start\"`,\n );\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 { MAX_BOX_PORTS, type BoxStatus, type CreateMachineRequest, type Machine, type PortsRequest, type RecoveryReport, type RescaleMachineRequest, type SetMachineRequest, type SshKeysApplied, type TrustCaReport } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { SIZES, isSizeName } from \"@kvbox/shared/sizes\";\nimport { caLineFor, isCaLine, parseSshPublicKey, sshKeyFingerprint } from \"@kvbox/shared/ssh\";\nimport { isUnknownOp, setAuthorizedKeys, setIdentity } from \"./agent.js\";\nimport { assertRoomFor } from \"./capacity.js\";\nimport { closeOpenRun, closeRunCutByBoot, insertUsageEvent, type UsageState } from \"./db.js\";\nimport { inScope, parseRef, realmOf, refKey, shown, type BoxRef, type ListScope } from \"./refs.js\";\nimport { loadConfig, type Config } from \"./config.js\";\nimport { locked, withBoxLock, withHostLock } from \"./locks.js\";\nimport { run } from \"./exec.js\";\nimport { FirecrackerClient } from \"./firecracker.js\";\nimport { attachTap, closeProxy, createTap, deleteTap, ensureHostNetwork, listeningPorts, macFor, nextFreeIp, openProxy, pickSshPort, type Proxy } from \"./network.js\";\nimport {\n listMachineRefs,\n newBoxId,\n currentBootId,\n hostBootTime,\n pidAlive,\n readMachineMeta,\n readSnapshotMeta,\n vmAlive,\n writeMachineMeta,\n type MachineMeta,\n type SnapshotMeta,\n} from \"./state.js\";\n\n/** Box names double as guest hostnames; short and plain on purpose. */\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\n/** Every id in use on the host, so a new draw can avoid them. */\nconst idsInUse = (metas: MachineMeta[]) => new Set(metas.map((m) => m.id));\n/** Every public port a box on the host holds, running or not (its SSH port and the ones it published): a port stays the box's for its life. */\nconst publicPortsInUse = (metas: MachineMeta[]) => metas.flatMap((m) => [...(m.sshPort === undefined ? [] : [m.sshPort]), ...(m.ports ?? []).map((f) => f.hostPort)]);\n\n/**\n * A box made through a control plane (its owner is `user@realm`) is reached from the internet:\n * it gets the control plane's authorized_keys lines and a public SSH port on the host (#49).\n * A box the host owner makes over the socket keeps the host key only and no public port.\n */\nconst isCloudBox = (owner: string) => realmOf(owner) !== null;\n\ntype Forwarded = Pick<MachineMeta, \"id\" | \"ip\" | \"sshPort\" | \"ports\">;\n\n/** Every forward the box has on the host: its public SSH port (#49) and the ports it published (#30). */\nfunction boxProxies(meta: Forwarded): Proxy[] {\n const ssh: Proxy[] = meta.sshPort === undefined ? [] : [{ box: meta.id, boxIp: meta.ip, hostPort: meta.sshPort, guestPort: 22 }];\n return [...ssh, ...(meta.ports ?? []).map((f) => ({ box: meta.id, boxIp: meta.ip, hostPort: f.hostPort, guestPort: f.guestPort, proto: f.proto }))];\n}\n\n/** Open the box's public ports (after Firecracker is up), always with its current IP; nothing to do for a box without any. */\nasync function openPorts(meta: Forwarded, cfg: Config): Promise<void> {\n for (const proxy of boxProxies(meta)) await openProxy(proxy, cfg);\n}\n\n/** Close them (the box is going down); a failure here is logged, the box's own state change goes on. */\nasync function closePorts(meta: Forwarded, cfg: Config): Promise<void> {\n for (const proxy of boxProxies(meta)) {\n await closeProxy(proxy, cfg).catch((err: Error) => console.error(`warning: could not close port ${proxy.hostPort}: ${err.message}`));\n }\n}\n\n/** Public ports drawn but not in any meta.json yet: the next draw must see them too. */\nconst reservedPorts = new Set<number>();\n\n/**\n * `count` fresh public ports: random, never 22, not another box's, not something the host listens\n * on (#49, #30). Drawn under the host's `ports` lock and held in `reservedPorts` until the caller has\n * written them to meta.json and calls `release`, so two boxes drawing at once never get the same one.\n */\nasync function drawPorts(count: number, p: Paths): Promise<{ ports: number[]; release: () => void }> {\n return withHostLock(\"ports\", async () => {\n // Reservations first: one released while the metas are read was written before its release, but\n // that write may be the half-written meta.json the read skipped.\n const reserved = [...reservedPorts];\n const taken = new Set([...reserved, ...publicPortsInUse(await readAllMeta(p)), ...(await listeningPorts())]);\n const ports: number[] = [];\n for (let i = 0; i < count; i++) {\n const port = pickSshPort(taken);\n taken.add(port);\n ports.push(port);\n }\n for (const port of ports) reservedPorts.add(port);\n return { ports, release: () => ports.forEach((port) => reservedPorts.delete(port)) };\n });\n}\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/** Whole GiB of the box's overlay (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(p.machine(meta.owner, meta.name).overlay).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: meta.id, 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 !vmAlive(meta) && existsSync(p.machine(meta.owner, meta.name).hibernateVmstate);\n}\n\nexport function statusOf(meta: MachineMeta, p: Paths = paths()): BoxStatus {\n if (vmAlive(meta)) 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. */\nexport function 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 = vmAlive(meta);\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(meta.id, new Date().toISOString(), p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n }\n return {\n id: meta.id,\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(p.machine(meta.owner, meta.name).overlay),\n base: meta.base,\n createdAt: meta.createdAt,\n source: meta.source,\n status: statusOf(meta, p),\n ...(meta.sshPort === undefined ? {} : { sshPort: meta.sshPort }),\n ...(meta.ports?.length ? { ports: meta.ports.map((f) => ({ ...f })) } : {}),\n ...(meta.autoHibernateSec ? { autoHibernateSec: meta.autoHibernateSec } : {}),\n };\n}\n\n/** The idle timeout a new box gets (#47): the request's, else the host's default; 0 is stored as absent. */\nfunction autoHibernateFor(req: CreateMachineRequest, cfg: Config): number | undefined {\n return (req.autoHibernateSec ?? cfg.autoHibernateSec) || undefined;\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(scope: ListScope, p: Paths = paths()): Promise<Machine[]> {\n return (await readAllMeta(p)).filter((m) => inScope(m.owner, scope)).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\n/** Lines a box's authorized_keys may hold: the host's key plus what the control plane sends. */\nexport const MAX_SSH_KEY_LINES = 8;\n/** The kernel command line is 2 KB on x86; the rest of ours is ~200 bytes, so the key blob gets this much. */\nconst MAX_SSH_KEYS_B64 = 1500;\n\n/** The authorized_keys lines a box holds: the host's own key first, then what the control plane gave it. Checked, never written unchecked. */\nexport function authorizedKeysLines(hostKey: string, extra: readonly string[]): string[] {\n const lines = [hostKey.trim(), ...extra.map((l) => l.trim())];\n if (lines.some((l) => l === \"\" || /[\\r\\n]/.test(l))) throw new KvboxError(\"sshKeys: every entry must be one non-empty authorized_keys line\");\n if (lines.length > MAX_SSH_KEY_LINES) {\n throw new KvboxError(`a box takes at most ${MAX_SSH_KEY_LINES - 1} SSH keys on top of the host's own; ${extra.length} were given`);\n }\n return lines;\n}\n\n/**\n * The `kvbox.sshkey=` value: the host's own public key and every extra authorized_keys line, as\n * base64 of the whole file (one line each, trailing newline). kvbox-init in the image decodes it\n * verbatim into the kvbox user's authorized_keys at every boot, so `cert-authority …` lines work\n * without an image change. Checked before Firecracker starts.\n */\nexport function authorizedKeysB64(hostKey: string, extra: readonly string[]): string {\n const lines = authorizedKeysLines(hostKey, extra);\n const b64 = Buffer.from(lines.join(\"\\n\") + \"\\n\").toString(\"base64\");\n if (b64.length > MAX_SSH_KEYS_B64) {\n throw new KvboxError(`the SSH keys for this box do not fit the kernel command line (${b64.length} bytes encoded, ${MAX_SSH_KEYS_B64} at most); use fewer or shorter keys`);\n }\n return b64;\n}\n\nexport function bootArgs(name: string, ip: string, cfg: Config, pubkeyB64: string): string {\n // Firecracker appends `pci=off root=/dev/vda ro` itself. ip= is read by the guest kernel,\n // kvbox.name= / kvbox.sshkey= by kvbox-init on first boot (the kvbox-images contract).\n // /sbin/overlay-init in the image stacks the box's disk (/dev/vdb) on the read-only base before\n // systemd starts.\n const args = `console=ttyS0 reboot=k panic=1 init=/sbin/overlay-init kvbox.overlay=/dev/vdb 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 not an installed base image. */\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. */\nfunction baseFileFor(meta: Pick<MachineMeta, \"name\" | \"base\">, p: Paths): string {\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 without /sbin/overlay-init (not built by kvbox-images) 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 not a kvbox base image (no /sbin/overlay-init); rerun install-server.sh`);\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 id: string;\n name: string;\n owner: string;\n ip: string;\n mac: string;\n vcpu: number;\n memMib: number;\n base: string;\n /** See MachineMetaSchema (#49). */\n sshKeys?: string[] | undefined;\n sshPort?: number | 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));\n await fc.rootDrive(baseFile);\n await fc.overlayDrive(OVERLAY_REL);\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, and need not be: the\n * vmstate names the overlay relative to the box dir, so it already resolves to this box's copy.\n * 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 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 } finally {\n await fc.close();\n }\n return pid;\n } catch (err) {\n killQuietly(pid);\n throw err;\n }\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 host's own public key line: every box on the host trusts it (that is how local `connect` works). */\nasync function readHostPubkey(p: Paths): Promise<string> {\n try {\n return (await readFile(`${p.sshKey}.pub`, \"utf8\")).trim();\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 cloud = isCloudBox(owner);\n const sshKeys = cloud && req.sshKeys !== undefined && req.sshKeys.length > 0 ? req.sshKeys : undefined;\n const keysB64 = authorizedKeysB64(await readHostPubkey(p), sshKeys ?? []);\n\n const existing = await readAllMeta(p);\n // names are per owner; IPs, taps and public ports are per host\n const name = pickName(req.name, new Set(existing.filter((m) => m.owner === owner).map((m) => m.name)));\n const id = newBoxId(idsInUse(existing));\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 let pid: number | undefined;\n let sshPort: number | undefined;\n let drawn: Awaited<ReturnType<typeof drawPorts>> | undefined;\n try {\n drawn = cloud ? await drawPorts(1, p) : undefined;\n sshPort = drawn?.ports[0];\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(id, cfg);\n tapCreated = true;\n const spec: LaunchSpec = { id, name, owner, ip, mac, vcpu: size.vcpu, memMib: size.memMib, base: base.version, sshKeys, sshPort };\n pid = await launch(spec, tap, cfg, keysB64, p);\n await openPorts(spec, cfg);\n const meta: MachineMeta = { ...spec, pid, bootId: currentBootId(), createdAt: new Date().toISOString(), source: \"base\", autoHibernateSec: autoHibernateFor(req, cfg) };\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 (pid !== undefined) killQuietly(pid);\n await closePorts({ id, ip, sshPort }, cfg);\n if (tapCreated) await deleteTap(id, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n } finally {\n drawn?.release();\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 // The restored guest keeps the authorized_keys it was frozen with (kvbox-init does not run again);\n // the lines are kept so a later cold boot (`stop`, `start`) writes them like a fresh box.\n const cloud = isCloudBox(owner);\n const sshKeys = cloud && req.sshKeys !== undefined && req.sshKeys.length > 0 ? req.sshKeys : undefined;\n authorizedKeysB64(await readHostPubkey(p), sshKeys ?? []);\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 // A restored box is a new box: its own id, never the source box's (a snapshot carries none).\n const id = newBoxId(idsInUse(existing));\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 let sshPort: number | undefined;\n let drawn: Awaited<ReturnType<typeof drawPorts>> | undefined;\n try {\n drawn = cloud ? await drawPorts(1, p) : undefined;\n sshPort = drawn?.ports[0];\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(id, cfg, { detached: true });\n tapCreated = true;\n const spec: LaunchSpec = { id, name, owner, ip, mac, vcpu: snap.vcpu, memMib: snap.memMib, base: snap.base, sshKeys, sshPort };\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; the restored box was discarded, try again`,\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 // The guest woke up with the authorized_keys the snapshot froze; give it the current ones (#63).\n const stale = await pushAuthorizedKeys({ owner, name, sshKeys }, m.vsock, p);\n await attachTap(id, cfg);\n await openPorts(spec, cfg);\n const meta: MachineMeta = { ...spec, pid, bootId: currentBootId(), createdAt: new Date().toISOString(), source: `snapshot:${refKey(from)}`, memSnapshots: 1, sshKeysStale: stale ? true : undefined, autoHibernateSec: autoHibernateFor(req, cfg) };\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 await closePorts({ id, ip, sshPort }, cfg);\n if (tapCreated) await deleteTap(id, cfg).catch(() => undefined);\n await rm(m.dir, { recursive: true, force: true });\n throw err;\n } finally {\n drawn?.release();\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\n/**\n * Hand a live guest its current authorized_keys through kvbox-agent (base v0.6.0 and later): a\n * restored or woken box has the file it was frozen with, which may predate a CA change (#63, #55).\n * Never fails the caller. The reason is returned (and logged) when the guest keeps its old file: an\n * image whose agent does not know the request, or one that did not answer; a boot fixes both.\n */\nasync function pushAuthorizedKeys(box: Pick<MachineMeta, \"owner\" | \"name\" | \"sshKeys\">, vsock: string, p: Paths): Promise<string | undefined> {\n try {\n await setAuthorizedKeys(vsock, authorizedKeysLines(await readHostPubkey(p), box.sshKeys ?? []), AGENT_REPLY_MS);\n return undefined;\n } catch (err) {\n const why = isUnknownOp(err)\n ? `its image predates base v0.6.0, whose kvbox-agent can replace authorized_keys (kvbox vm update ${shown(box)} moves it onto the current base)`\n : (err as Error).message;\n console.error(`warning: box ${shown(box)} keeps the authorized_keys it was frozen with: ${why}`);\n return why;\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 (vmAlive(meta)) {\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 public port, the tap and the sockets it left behind. */\nasync function cleanupProcess(meta: MachineMeta, cfg: Config, p: Paths): Promise<void> {\n await closePorts(meta, cfg);\n await deleteTap(meta.id, 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 const stopMachine = locked(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 (!vmAlive(meta) && !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 const startMachine = locked(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 (vmAlive(meta)) 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 keysB64 = authorizedKeysB64(await readHostPubkey(p), meta.sshKeys ?? []);\n await ensureHostNetwork(cfg);\n const tap = await createTap(meta.id, cfg);\n let pid: number | undefined;\n try {\n pid = await launch(meta, tap, cfg, keysB64, p);\n await openPorts(meta, cfg);\n const started: MachineMeta = { ...meta, pid, bootId: currentBootId(), sshKeysStale: undefined }; // kvbox-init writes the file from the command line\n await writeMachineMeta(started, p);\n recordState(started, \"running\", \"start\", p);\n return toMachine(started, p);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n await closePorts(meta, cfg);\n await deleteTap(meta.id, cfg).catch(() => undefined);\n throw err;\n }\n});\n\n/**\n * Replace the authorized_keys lines the box gets on top of the host's key (the control plane's\n * `rewrite-boxes`: a new CA line for the box's owner). Checked like at `new`, before anything is\n * written. A running box gets them through kvbox-agent right away; any other state gets them when\n * it next runs (`applied` says when).\n */\nexport const setSshKeys = locked(async function setSshKeys(ref: BoxRef, sshKeys: readonly string[], p: Paths = paths()): Promise<{ machine: Machine; applied: SshKeysApplied }> {\n const meta = await readMeta(ref, p);\n // Like `new`: a local box trusts this host's key and nothing else; only a cloud box carries lines.\n if (!isCloudBox(meta.owner)) throw new KvboxError(`box ${shown(ref)} is local: it trusts this host's key, there are no authorized_keys lines to replace`);\n // A cloud box with the host's key alone would be open to nobody who logs in: one bad call must not do that fleet-wide.\n if (sshKeys.length === 0) throw new KvboxError(\"sshKeys: at least one authorized_keys line (the box would keep only the host's own key)\");\n authorizedKeysB64(await readHostPubkey(p), sshKeys);\n const { meta: updated, applied } = await applySshKeys(meta, sshKeys, p);\n return { machine: toMachine(updated, p), applied };\n});\n\n/**\n * Write new `sshKeys` into meta.json and get them to the guest: through kvbox-agent when the box\n * runs, else at its next start (kvbox-init), wake or resume (the `sshKeysStale` flag makes those\n * push). A running box whose agent could not take them is `later`: its next stop and start.\n */\nasync function applySshKeys(meta: MachineMeta, sshKeys: readonly string[], p: Paths): Promise<{ meta: MachineMeta; applied: SshKeysApplied; why?: string }> {\n const status = statusOf(meta, p);\n let updated: MachineMeta = { ...meta, sshKeys: [...sshKeys], sshKeysStale: status === \"stopped\" ? undefined : true };\n let applied: SshKeysApplied = status === \"stopped\" ? \"start\" : status === \"standby\" ? \"resume\" : status === \"hibernated\" ? \"wake\" : \"later\";\n let why: string | undefined;\n if (status === \"running\") {\n why = await pushAuthorizedKeys(updated, p.machine(meta.owner, meta.name).vsock, p);\n if (why === undefined) {\n updated = { ...updated, sshKeysStale: undefined };\n applied = \"now\";\n }\n }\n await writeMachineMeta(updated, p);\n return why === undefined ? { meta: updated, applied } : { meta: updated, applied, why };\n}\n\n/**\n * `kvbox server trust-ca` (#55): every cloud box on this host trusts `publicKey` as the CA for its\n * owner, in place of the CA line it had (one CA per box, as at `new`; the old CA is out, which is\n * the point after a leak, and a laptop renews its certificate at the next refused connect). Local\n * boxes are untouched. A box that is not running gets the line when it next runs.\n */\nexport async function trustCa(publicKeyText: string, p: Paths = paths()): Promise<TrustCaReport> {\n const publicKey = parseSshPublicKey(publicKeyText);\n const report: TrustCaReport = { publicKey, fingerprint: sshKeyFingerprint(publicKey), updated: [], pending: [], failed: [], local: 0 };\n const hostKey = await readHostPubkey(p);\n for (const listed of await readAllMeta(p)) {\n if (!isCloudBox(listed.owner)) {\n report.local++;\n continue;\n }\n const box = refKey(listed);\n try {\n await withBoxLock(listed, async () => {\n const meta = await readMeta(listed, p); // again, under the lock: the listing may be stale by now\n const sshKeys = [...(meta.sshKeys ?? []).filter((l) => !isCaLine(l)), caLineFor(meta.owner, publicKey)];\n authorizedKeysLines(hostKey, sshKeys);\n const { applied, why } = await applySshKeys(meta, sshKeys, p);\n if (applied === \"now\") report.updated.push(box);\n else report.pending.push(why === undefined ? { box, when: applied } : { box, when: applied, why });\n });\n } catch (err) {\n report.failed.push({ box, error: (err as Error).message });\n }\n }\n return report;\n}\n\n/** `kvbox pause`: freeze the VM in place. Memory and processes stay, no CPU is used; `resume` is instant. */\nexport const pauseMachine = locked(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 const resumeMachine = locked(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 const m = p.machine(ref.owner, ref.name);\n await resumeVm(m.sock);\n // Keys changed while it was frozen (#55): the agent can take them now.\n const stale = meta.sshKeysStale ? await pushAuthorizedKeys(meta, m.vsock, p) : undefined;\n const running: MachineMeta = { ...meta, paused: undefined, sshKeysStale: stale ? true : 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 * `by` names who asked in the ledger: `hibernate` for a caller, `auto-hibernate` for core/idle.ts.\n */\nexport const hibernateMachine = locked(async function hibernateMachine(ref: BoxRef, p: Paths = paths(), by: string = \"hibernate\"): 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 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\", by, 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 const wakeMachine = locked(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 (!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(meta.id, cfg, { detached: true });\n let pid: number | undefined;\n let stale: string | undefined;\n try {\n const spec: LaunchSpec = { id: meta.id, 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 // The guest's authorized_keys are the ones it slept with; the CA may have changed meanwhile (#55).\n stale = await pushAuthorizedKeys(meta, m.vsock, p);\n await attachTap(meta.id, cfg);\n await openPorts(meta, cfg);\n } catch (err) {\n if (pid !== undefined) killQuietly(pid);\n await closePorts(meta, cfg);\n await deleteTap(meta.id, 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, bootId: currentBootId(), memSnapshots: 1, paused: undefined, sshKeysStale: stale ? true : 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 = vmAlive(meta);\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 const updateMachine = locked(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 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 const rescaleMachine = locked(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 = p.machine(ref.owner, ref.name).overlay;\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/** `kvbox vm set <box>`: settings the VM itself never sees, so they apply in any state and at once. */\nexport const setMachine = locked(async function setMachine(ref: BoxRef, req: SetMachineRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const next: MachineMeta = { ...meta };\n if (req.autoHibernateSec !== undefined) next.autoHibernateSec = req.autoHibernateSec || undefined;\n await writeMachineMeta(next, p);\n return toMachine(next, p);\n});\n\ntype PortKey = { guestPort: number; proto: \"tcp\" | \"udp\" };\nconst portKeys = (req: PortsRequest): PortKey[] => {\n const keys = req.ports.map((x) => ({ guestPort: x.guestPort, proto: x.proto ?? \"tcp\" }));\n return keys.filter((k, i) => keys.findIndex((o) => o.guestPort === k.guestPort && o.proto === k.proto) === i);\n};\nconst samePort = (a: PortKey) => (b: PortKey) => a.guestPort === b.guestPort && a.proto === b.proto;\n\n/**\n * `kvbox vm proxy add` (#30): publish box ports on the host's public address, each on a host port\n * drawn at random. All or nothing: if one forward cannot be opened, the ones this call opened are\n * closed and nothing is stored. A box that is not running keeps them in meta.json; they open when\n * it next runs, like its SSH port.\n */\nexport const addPorts = locked(async function addPorts(ref: BoxRef, req: PortsRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const current = meta.ports ?? [];\n const wanted = portKeys(req);\n const already = wanted.find((w) => current.some(samePort(w)));\n if (already) throw new KvboxError(`box ${shown(ref)} already publishes port ${already.guestPort} (${already.proto})`);\n // The box's SSH forward already accepts 22/tcp into it; a second forward to 22 would share that\n // FORWARD rule, and closing it would cut the box's SSH.\n if (meta.sshPort !== undefined && wanted.some(samePort({ guestPort: 22, proto: \"tcp\" }))) {\n throw new KvboxError(`box ${shown(ref)} already reaches port 22 from outside on port ${meta.sshPort} (kvbox connect)`);\n }\n if (current.length + wanted.length > MAX_BOX_PORTS) {\n throw new KvboxError(`a box publishes at most ${MAX_BOX_PORTS} ports; box ${shown(ref)} has ${current.length}`);\n }\n const drawn = await drawPorts(wanted.length, p);\n const opened: Proxy[] = [];\n try {\n const added = wanted.map((w, i) => ({ ...w, hostPort: drawn.ports[i]! }));\n if (vmAlive(meta)) {\n for (const proxy of boxProxies({ id: meta.id, ip: meta.ip, ports: added })) {\n await openProxy(proxy, cfg);\n opened.push(proxy);\n }\n }\n const next: MachineMeta = { ...meta, ports: [...current, ...added] };\n await writeMachineMeta(next, p);\n return toMachine(next, p);\n } catch (err) {\n // Nothing stored, so nothing may stay open: a rule meta.json does not name could never be removed.\n for (const proxy of opened) await closeProxy(proxy, cfg).catch(() => undefined);\n throw err;\n } finally {\n drawn.release();\n }\n});\n\n/** `kvbox vm proxy rm` (#30): stop publishing box ports. Their host ports go back to the pool. */\nexport const removePorts = locked(async function removePorts(ref: BoxRef, req: PortsRequest, p: Paths = paths()): Promise<Machine> {\n const meta = await readMeta(ref, p);\n const cfg = await loadConfig(p);\n const current = meta.ports ?? [];\n const gone = portKeys(req);\n const missing = gone.find((g) => !current.some(samePort(g)));\n if (missing) throw new KvboxError(`box ${shown(ref)} does not publish port ${missing.guestPort} (${missing.proto})`);\n const removed = current.filter((f) => gone.some(samePort(f)));\n // Closed first: a rule that would not go keeps the port in meta.json, so trying again finds it.\n // Closed whether or not the box runs: one whose Firecracker died never ran cleanupProcess, and its\n // rules would outlive the port's return to the pool. Closing what is not there is fine.\n for (const proxy of boxProxies({ id: meta.id, ip: meta.ip, ports: removed })) await closeProxy(proxy, cfg);\n const kept = current.filter((f) => !gone.some(samePort(f)));\n const next: MachineMeta = { ...meta, ports: kept.length > 0 ? kept : undefined };\n await writeMachineMeta(next, p);\n return toMachine(next, p);\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 const destroyMachine = locked(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// ── after the host was down (#29) ─────────────────────────────────────────────\n/** Boxes booted at once when the server brings them back: each boot is a burst of disk and CPU. */\nconst RECOVERY_CONCURRENCY = 2;\n\n/**\n * At server start, the boxes whose Firecracker died with an earlier boot of the host: meta.json still\n * names a pid, but from another boot. Each one's open run in the ledger is closed (at the host's boot\n * when it predates it) and its memory image goes: the next boot is fresh. A box that was in standby\n * lost its memory with the process, so it is left stopped; the others keep the old pid and boot id,\n * which mark them as not brought back yet, and are returned to be booted (`bootRecovered`). A box\n * whose Firecracker died earlier in this boot (a crash) is not touched: it reads as stopped, as it has\n * since. Done before the server listens, so a listing cannot close those runs at \"now\" first.\n */\nexport async function settleDeadBoxes(p: Paths = paths()): Promise<{ boot: BoxRef[]; leftStopped: string[] }> {\n const now = new Date().toISOString();\n const bootAt = hostBootTime()?.toISOString() ?? now;\n const boot: BoxRef[] = [];\n const leftStopped: string[] = [];\n for (const meta of await readAllMeta(p)) {\n if (!cutByReboot(meta) || vmAlive(meta)) continue;\n try {\n closeRunCutByBoot(meta.id, bootAt, now, p);\n } catch (err) {\n console.error(`warning: usage ledger: ${(err as Error).message}`);\n }\n await rm(p.machine(meta.owner, meta.name).memBase, { force: true });\n if (meta.paused) {\n await writeMachineMeta({ ...meta, pid: null, bootId: undefined, memSnapshots: undefined, paused: undefined }, p);\n leftStopped.push(refKey(meta));\n } else {\n await writeMachineMeta({ ...meta, memSnapshots: undefined }, p);\n boot.push({ owner: meta.owner, name: meta.name });\n }\n }\n return { boot, leftStopped };\n}\n\n/** A pid launched in another boot of the host (or before #29, with no boot id): the reboot ended it. */\nfunction cutByReboot(meta: MachineMeta): boolean {\n return meta.pid !== null && meta.bootId !== currentBootId();\n}\n\nlet recovery: RecoveryReport | null = null;\nlet recoveryStopping = false;\nlet recoveryRun: Promise<unknown> = Promise.resolve();\n\n/** What `bootRecovered` did at this server's start (`/health`); null when nothing needed it. */\nexport function lastRecovery(): RecoveryReport | null {\n return recovery;\n}\n\n/**\n * For the server's shutdown: boot no further box, and resolve once the boots under way have written\n * their pid to meta.json (exiting halfway would leave a Firecracker no meta.json names). The boxes\n * not reached keep their old boot id, so the next server start brings them back.\n */\nexport async function stopRecovery(): Promise<void> {\n recoveryStopping = true;\n await recoveryRun;\n}\n\n/**\n * Boot the boxes `settleDeadBoxes` found, a few at a time, like `kvbox start` (fresh boot, current\n * SSH lines). A box someone started while it waited its turn now has this boot's id and is skipped.\n * One that does not come up is reported, never fatal: the server keeps serving.\n */\nexport async function bootRecovered(settled: { boot: readonly BoxRef[]; leftStopped: readonly string[] }, p: Paths = paths()): Promise<RecoveryReport | null> {\n const refs = settled.boot;\n if (refs.length === 0 && settled.leftStopped.length === 0) return null;\n const booted: string[] = [];\n const failed: RecoveryReport[\"failed\"] = [];\n const queue = [...refs];\n const worker = async () => {\n for (let ref = queue.shift(); ref !== undefined && !recoveryStopping; ref = queue.shift()) {\n try {\n if (!cutByReboot(await readMeta(ref, p))) continue;\n await startMachine(ref, p);\n booted.push(refKey(ref));\n } catch (err) {\n failed.push({ box: refKey(ref), error: (err as Error).message });\n }\n }\n };\n const run = Promise.all(Array.from({ length: Math.min(RECOVERY_CONCURRENCY, refs.length) }, worker));\n recoveryRun = run;\n await run;\n recovery = { at: new Date().toISOString(), booted, leftStopped: [...settled.leftStopped], failed };\n return recovery;\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 { GuestStatsSchema, type GuestStats } from \"@kvbox/shared/api\";\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/**\n * Replace the kvbox user's authorized_keys with exactly these lines (base v0.6.0 and later): a\n * restored or woken box has the file it was frozen with, the host has the current one (#63, #55).\n */\nexport function setAuthorizedKeys(udsPath: string, lines: readonly string[], timeoutMs?: number) {\n return agentCall(udsPath, { op: \"authorizedKeys\", lines: [...lines] }, timeoutMs);\n}\n\n/** The box's own load, memory, disk and uptime (base v0.7.0 and later). */\nexport async function stats(udsPath: string, timeoutMs?: number): Promise<GuestStats> {\n const reply = GuestStatsSchema.safeParse(await agentCall(udsPath, { op: \"stats\" }, timeoutMs));\n if (!reply.success) throw new KvboxError(`kvbox-agent sent stats kvbox does not understand: ${reply.error.issues[0]?.message ?? \"invalid\"}`);\n return reply.data;\n}\n\n/** An agent from an image older than the request it was sent. */\nexport const isUnknownOp = (err: unknown): boolean => /unknown op/.test((err as Error).message ?? \"\");\n\n/**\n * Nothing in the guest took the connection: an image older than kvbox-agent itself (before base\n * v0.5.0), so no vsock listener, or a box booted without the vsock socket.\n */\nexport const isNoAgent = (err: unknown): boolean =>\n /vsock connect refused|vsock connection closed before the guest accepted|kvbox-agent unreachable: connect (ENOENT|ECONNREFUSED)/.test((err as Error).message ?? \"\");\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. The constants live in shared/capacity.ts: the control plane applies the same\n * rule to each host's totals to place a box (#20). 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 { MEM_HEADROOM_MIB, VCPU_OVERSUBSCRIPTION } from \"@kvbox/shared/capacity\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { listMachineRefs, readMachineMeta, vmAlive } from \"./state.js\";\n\nexport { MEM_HEADROOM_MIB, VCPU_OVERSUBSCRIPTION };\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 (vmAlive(meta)) 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 * The capacity rule both sides apply. Firecracker reserves neither RAM nor cores, so a host counts\n * what its running boxes are sized at and refuses a box that would push the total past\n * memory: host RAM minus 2 GB the host keeps for itself (hard), or\n * vCPU: 2 x host cores (soft: vCPUs time-slice fine, this stops the absurd).\n * The host applies it box by box at `new` (server core/capacity.ts, with the names of the running\n * boxes in the refusal); the control plane applies it to each host's reported totals to choose\n * where a box lands (#20). Decision \"`zbox new` guards host capacity\".\n */\nimport type { Capacity } from \"./api.js\";\n\nexport const MEM_HEADROOM_MIB = 2048;\nexport const VCPU_OVERSUBSCRIPTION = 2;\n\nexport interface Want {\n vcpu: number;\n memMib: number;\n}\n\n/** What a host can still take: memory after the headroom and what is reserved, vCPUs under the cap. Never negative. */\nexport function freeOf(c: Capacity): { memMib: number; vcpu: number } {\n return {\n memMib: Math.max(0, c.hostMemMib - MEM_HEADROOM_MIB - c.reservedMemMib),\n vcpu: Math.max(0, c.hostCores * VCPU_OVERSUBSCRIPTION - c.reservedVcpu),\n };\n}\n\nexport function hasRoom(c: Capacity, want: Want): boolean {\n const free = freeOf(c);\n return want.memMib <= free.memMib && want.vcpu <= free.vcpu;\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 { randomBytes } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\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 /** Host-unique, minted at `kvbox new` (fresh or restored) and kept for the box's life; the tap is `kv-<id>`. */\n id: z.string(),\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 /**\n * The host boot `pid` belongs to (/proc/sys/kernel/random/boot_id at launch, #29). After a reboot\n * the number can name some other process; a pid from another boot is dead whatever `kill -0` says.\n * Absent (boxes launched before #29): the pid alone decides.\n */\n bootId: z.string().optional(),\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's overlay stacks on. */\n base: z.string(),\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 /**\n * authorized_keys lines the box gets on top of the host's own key, as the control plane sent them\n * at `new` (#49). kvbox-init rewrites authorized_keys from the kernel cmdline at every boot, so\n * `start` has to send the same lines again. Absent: host key only.\n */\n sshKeys: z.array(z.string()).optional(),\n /**\n * The guest's authorized_keys may not match `sshKeys`: they changed while the box was not running,\n * or its agent could not take them (#55, #63). Cleared by a push through kvbox-agent or a boot.\n */\n sshKeysStale: z.boolean().optional(),\n /** Public port on the host DNATed to the box's SSH while it runs (#49); fixed for the box's life. Absent: none. */\n sshPort: z.number().int().optional(),\n /**\n * Box ports published on the host (#30, `kvbox vm proxy`): unique per guest port and protocol,\n * each host port the box's for its life. DNATed while the box runs, rebuilt from here with its\n * current IP every time it comes up. Absent: none.\n */\n ports: z.array(z.object({ guestPort: z.number().int(), hostPort: z.number().int(), proto: z.enum([\"tcp\", \"udp\"]) })).optional(),\n /** Seconds without traffic on the box's tap before the server hibernates it (#47, core/idle.ts). Absent: never. */\n autoHibernateSec: z.number().int().positive().optional(),\n});\nexport type MachineMeta = z.infer<typeof MachineMetaSchema>;\n\n/** 6 lowercase hex chars: 16M values per host, 9 chars as a tap name, well inside Linux's 15-char limit. */\nexport const BOX_ID_RE = /^[0-9a-f]{6}$/;\n\n/** A fresh id no box on the host has (`taken`: every id in use, so a draw can be retried). */\nexport function newBoxId(taken: ReadonlySet<string>): string {\n for (;;) {\n const id = randomBytes(3).toString(\"hex\");\n if (!taken.has(id)) return id;\n }\n}\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>. */\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\nlet bootId: { id: string | undefined } | undefined;\n\n/** This boot's id (undefined where the kernel does not expose one). Read once: it cannot change under a running process. */\nexport function currentBootId(): string | undefined {\n if (bootId === undefined) {\n try {\n bootId = { id: readFileSync(\"/proc/sys/kernel/random/boot_id\", \"utf8\").trim() };\n } catch {\n bootId = { id: undefined };\n }\n }\n return bootId.id;\n}\n\n/** True when the box's Firecracker is still there: its pid is alive and was launched in this boot. */\nexport function vmAlive(meta: Pick<MachineMeta, \"pid\" | \"bootId\">): boolean {\n if (meta.bootId !== undefined && meta.bootId !== currentBootId()) return false;\n return pidAlive(meta.pid);\n}\n\n/** When the host booted, from /proc/stat's btime (null where there is none). */\nexport function hostBootTime(): Date | null {\n try {\n const m = /^btime (\\d+)$/m.exec(readFileSync(\"/proc/stat\", \"utf8\"));\n return m ? new Date(Number(m[1]) * 1000) : null;\n } catch {\n return null;\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\";\nimport type { UsageEvent, UsageState } from \"@kvbox/shared/usage\";\nimport { inScope, type ListScope } from \"./refs.js\";\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 // The ledger's identity (#42): a control plane keys pulled rows by it, so a re-join is recognised\n // and a fresh ledger (KVBOX_HOME wiped) restarts its cursor instead of waiting for ids it already saw.\n `create table ledger (id text not null);\n insert into ledger (id) values (lower(hex(randomblob(16))));\n create index usage_events_at on usage_events (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 { UsageEvent, UsageState };\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\nexport interface UsageEventRow extends UsageEvent {\n /** The box's id. Owner and name ride along so the ledger reads alone after a box is gone. */\n boxId: string;\n owner: string;\n name: string;\n}\n\ninterface Raw {\n id: number;\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/**\n * The run a host shutdown cut (#29): a run that began before the host booted cannot have outlived the\n * boot, so it ends at `bootAt`; one that began after it (Firecracker crashed since) ends `now`.\n */\nexport function closeRunCutByBoot(boxId: string, bootAt: string, now: string, p: Paths = paths()): boolean {\n const last = lastEvent(boxId, openDb(p));\n return closeOpenRun(boxId, last !== undefined && last.at < bootAt ? bootAt : now, p);\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/** A ledger row with its id: the cursor a control plane pulls by (#42). */\nexport type UsageEventWithId = UsageEventRow & { id: number };\n\nconst withId = (r: Raw): UsageEventWithId => ({ ...fromRaw(r), id: r.id });\n\n/** This home's ledger id, made with the database; it changes only when the database is recreated. */\nexport function ledgerId(p: Paths = paths()): string {\n return (openDb(p).prepare(\"select id from ledger\").get() as { id: string }).id;\n}\n\n/**\n * Rows after `after` by id (the order they were written in, so a puller never misses one), at\n * most `limit`, of the owners in `scope`. The id is monotonic: a pull is resumable and a repeat\n * is a no-op on the other side.\n */\nexport function usageEventsAfter(after: number, limit: number, scope: ListScope, p: Paths = paths()): UsageEventWithId[] {\n const db = openDb(p);\n const rows = (scope === null\n ? db.prepare(\"select * from usage_events where id > ? order by id limit ?\").all(after, limit)\n : typeof scope === \"string\"\n ? db.prepare(\"select * from usage_events where id > ? and owner = ? order by id limit ?\").all(after, scope, limit)\n : db.prepare(\"select * from usage_events where id > ? and substr(owner, -length(?)) = ? order by id limit ?\").all(after, `@${scope.realm}`, `@${scope.realm}`, limit)) as unknown as Raw[];\n return rows.map(withId);\n}\n\n/**\n * The rows of the owners in `scope` that a report over the window needs, in time order: those inside\n * it plus each box's last row before it (the state the window opens in). The host-wide report (#41).\n */\nexport function usageEventsInScope(scope: ListScope, window: { from: string; to: string }, p: Paths = paths()): UsageEventWithId[] {\n const rows = openDb(p)\n .prepare(\n `select * from usage_events where at < ? and (at >= ? or id in (select max(id) from usage_events where at < ? group by box_id))\n order by at, id`,\n )\n .all(window.to, window.from, window.from) as unknown as Raw[];\n return rows.filter((r) => inScope(r.owner, scope)).map(withId);\n}\n\n","/**\n * One operation on a box at a time (#64). Every change to a box (its meta.json, its Firecracker process,\n * its memory image) runs under the box's lock, so a background job such as core/idle.ts cannot step into\n * a caller's snapshot, and two read-modify-writes of meta.json cannot lose each other's change.\n * In-process only: the server is the only writer. Reentrant, so an operation that calls another one on\n * the same box (rescale -> start) does not wait on itself.\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { refKey, type BoxRef } from \"./refs.js\";\n\n/** box -> the promise the next caller waits on (resolved when the current holder and every earlier waiter are done). */\nconst tails = new Map<string, Promise<void>>();\n/** The boxes the current async call chain already holds. */\nconst held = new AsyncLocalStorage<ReadonlySet<string>>();\n\nexport function withBoxLock<T>(ref: BoxRef, fn: () => Promise<T>): Promise<T> {\n return withLock(refKey(ref), fn);\n}\n\n/**\n * A lock for something the whole host shares rather than one box: `ports` guards drawing public\n * ports (#30), which reads every box's meta.json. The key has no '/', so it never meets a box's.\n * Take it inside a box lock, never the other way round.\n */\nexport function withHostLock<T>(name: \"ports\", fn: () => Promise<T>): Promise<T> {\n return withLock(`host:${name}`, fn);\n}\n\nasync function withLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const mine = held.getStore();\n if (mine?.has(key)) return fn();\n const previous = tails.get(key);\n let release!: () => void;\n const tail = new Promise<void>((resolve) => (release = resolve));\n tails.set(key, tail);\n try {\n await previous;\n return await held.run(new Set([...(mine ?? []), key]), fn);\n } finally {\n release();\n if (tails.get(key) === tail) tails.delete(key);\n }\n}\n\n/** Whether something holds or waits for the box's lock right now. */\nexport function boxBusy(ref: BoxRef): boolean {\n return tails.has(refKey(ref));\n}\n\n/** `fn` with the lock of the box named by its first argument taken around every call. */\nexport function locked<A extends [BoxRef, ...unknown[]], R>(fn: (...args: A) => Promise<R>): (...args: A) => Promise<R> {\n return (...args) => withBoxLock(args[0], () => fn(...args));\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 /** /dev/vda: the shared base image, read-only. Firecracker adds `root=/dev/vda ro` to the boot args to match. */\n rootDrive(pathOnHost: string) {\n return this.drive(\"rootfs\", pathOnHost, { root: true, readOnly: true });\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 /**\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 /**\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: the vmstate names the overlay relative to the box dir (spawnFirecracker).\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 * Host networking: bridge `kvbox0`, one tap `kv-<box id>` 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 { randomInt } from \"node:crypto\";\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/** The host's end of a relay tunnel (core/relay.ts, #50): `relay up <conf> | down`, root via the script. */\nexport async function netSetup(cfg: NetConfig, args: string[]): Promise<void> {\n await netRun(cfg, args);\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// ── public ports (#49) ────────────────────────────────────────────────────────\n/** Where a box's public SSH port is drawn from: high, random, and never 22 (which every bot scans). */\nexport const SSH_PORT_MIN = 20000;\nexport const SSH_PORT_MAX = 60000;\n\n/**\n * A random port in [SSH_PORT_MIN, SSH_PORT_MAX] that is not in `taken` (other boxes' ports and\n * whatever listens on the host). Random so two boxes never get adjacent, guessable ports; after\n * a few unlucky draws it walks the range from a random start so a crowded host still gets one.\n */\nexport function pickSshPort(taken: ReadonlySet<number>): number {\n const span = SSH_PORT_MAX - SSH_PORT_MIN + 1;\n for (let i = 0; i < 32; i++) {\n const port = SSH_PORT_MIN + randomInt(span);\n if (!taken.has(port)) return port;\n }\n const start = randomInt(span);\n for (let i = 0; i < span; i++) {\n const port = SSH_PORT_MIN + ((start + i) % span);\n if (!taken.has(port)) return port;\n }\n throw new KvboxError(`no free port left between ${SSH_PORT_MIN} and ${SSH_PORT_MAX} on this host`);\n}\n\n/** Local ports out of `ss -ltnH` / `ss -lunH` output (one socket per line, the address in the 4th column). */\nexport function parseListeningPorts(ssOutput: string): Set<number> {\n const ports = new Set<number>();\n for (const line of ssOutput.split(\"\\n\")) {\n const cols = line.trim().split(/\\s+/);\n const local = cols[3];\n if (!local) continue;\n const port = Number(local.slice(local.lastIndexOf(\":\") + 1));\n if (Number.isInteger(port) && port > 0) ports.add(port);\n }\n return ports;\n}\n\n/**\n * TCP and UDP ports something on the host listens on right now, so a box's public port never\n * shadows one: a UDP forward drawn onto, say, WireGuard's random port would swallow the relay tunnel.\n * One set for both protocols: a port either one uses is not drawn.\n */\nexport async function listeningPorts(): Promise<Set<number>> {\n const ports = new Set<number>();\n for (const flags of [\"-ltnH\", \"-lunH\"]) {\n try {\n for (const port of parseListeningPorts((await run([\"ss\", flags])).stdout)) ports.add(port);\n } catch {\n // no ss: the draw still avoids other boxes' ports\n }\n }\n return ports;\n}\n\nexport interface Proxy {\n /** Box id; the rules are tagged `kvbox:<id>` so `status` and `down` find them. */\n box: string;\n boxIp: string;\n hostPort: number;\n guestPort: number;\n /** tcp unless said otherwise (#30 publishes UDP too). */\n proto?: \"tcp\" | \"udp\";\n}\n\nconst proxyArgs = (p: Proxy) => [p.box, p.boxIp, String(p.hostPort), String(p.guestPort), p.proto ?? \"tcp\"];\n\n/** DNAT `hostPort` on every non-bridge interface of the host to `boxIp:guestPort`. Idempotent. */\nexport async function openProxy(proxy: Proxy, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"proxy\", \"add\", ...proxyArgs(proxy)]);\n}\n\n/** Remove what `openProxy` added; nothing to remove is fine. */\nexport async function closeProxy(proxy: Proxy, cfg: NetConfig): Promise<void> {\n await netRun(cfg, [\"proxy\", \"rm\", ...proxyArgs(proxy)]);\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 host's side of a relay (#50). A home host behind a router has no public address of its own;\n * a relay (a small public VM, set up with install-relay.sh) owns one for it and forwards it down a\n * WireGuard tunnel the host dials out. `kvbox-relay add` on the relay prints a join string; here it\n * becomes a wg-quick conf under relay/, which net-setup.sh installs as /etc/wireguard/kvbox.conf\n * and enables (root). config.json keeps what the rest of the server needs: the public IP `join`\n * advertises by default, the tunnel address, the endpoint. The private key stays in the conf.\n */\nimport { chmod, mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { decodeRelayJoin, RELAY_TUNNEL_GATEWAY, type RelayJoin } from \"@kvbox/shared/relay\";\nimport { loadConfig, saveConfig, type Relay } from \"./config.js\";\nimport { DEFAULT_HTTPS_PORT } from \"./controlPlane.js\";\nimport { netSetup } from \"./network.js\";\n\n/** The wg-quick conf for the host's end of the tunnel. */\nexport function relayConf(join: RelayJoin): string {\n return [\n \"# kvbox relay tunnel: made by `kvbox server relay`, installed by net-setup.sh. Do not edit.\",\n \"[Interface]\",\n `PrivateKey = ${join.privateKey}`,\n `Address = ${join.tunnelIp}/32`,\n \"\",\n \"[Peer]\",\n `PublicKey = ${join.relayKey}`,\n `Endpoint = ${join.relay}`,\n // Only the relay's own tunnel address goes through the tunnel: the host keeps its normal internet\n // route, and the relay SNATs forwarded connections so their replies come back this way.\n `AllowedIPs = ${RELAY_TUNNEL_GATEWAY}/32`,\n // The router forgets an idle outbound mapping; a packet every 25 s keeps the relay able to reach us.\n \"PersistentKeepalive = 25\",\n \"\",\n ].join(\"\\n\");\n}\n\n/** Decode the join string, write the conf, bring the tunnel up (root via net-setup.sh), remember the relay. */\nexport async function useRelay(joinString: string, p: Paths = paths()): Promise<Relay> {\n const join = decodeRelayJoin(joinString);\n if (!join) throw new KvboxError(\"that is not a relay join string; copy the whole line `kvbox-relay add` printed on the relay\");\n const cfg = await loadConfig(p);\n if (cfg.relay && cfg.relay.name !== join.name) {\n throw new KvboxError(`this host already goes through relay ${cfg.relay.name} (${cfg.relay.publicIp}); run kvbox server relay off first`);\n }\n // A re-issued string may carry another public IP; the control plane would keep calling the old one.\n if (cfg.relay && cfg.relay.publicIp !== join.publicIp && cfg.controlPlane?.advertise === cfg.relay.publicIp) {\n throw new KvboxError(\n `${cfg.controlPlane.name} reaches this host at ${cfg.relay.publicIp}, not ${join.publicIp}; run kvbox server leave first, then join again`,\n );\n }\n await mkdir(p.relay, { recursive: true, mode: 0o700 });\n await writeFile(p.relayConf, relayConf(join), { mode: 0o600 });\n await chmod(p.relayConf, 0o600);\n // The root helper also lets the control plane's port in on the tunnel interface (a host firewall would drop it).\n await netSetup(cfg, [\"relay\", \"up\", p.relayConf, String(cfg.controlPlane?.port ?? DEFAULT_HTTPS_PORT)]);\n const relay: Relay = { name: join.name, publicIp: join.publicIp, tunnelIp: join.tunnelIp, endpoint: join.relay };\n await saveConfig({ ...cfg, relay }, p);\n return relay;\n}\n\n/** Take the tunnel down and forget the relay. Refused while a control plane still reaches this host through it. */\nexport async function dropRelay(p: Paths = paths()): Promise<Relay> {\n const cfg = await loadConfig(p);\n const relay = cfg.relay;\n if (!relay) throw new KvboxError(\"this host does not go through a relay\");\n if (cfg.controlPlane?.advertise === relay.publicIp) {\n throw new KvboxError(`${cfg.controlPlane.name} reaches this host through the relay (${relay.publicIp}); run kvbox server leave first`);\n }\n await netSetup(cfg, [\"relay\", \"down\"]);\n await rm(p.relayConf, { force: true });\n const { relay: _gone, ...rest } = cfg;\n await saveConfig(rest, p);\n return relay;\n}\n","/**\n * The relay join string (#50). A home host behind a router gets a public address through a relay:\n * a small public VM with one extra IPv4 per host and a WireGuard tunnel the host dials out. The\n * relay's `kvbox-relay add <name> --ip <public-ip>` (kvbox-relay.sh at the repo root, bash: it builds\n * the same base64url token) makes the host's keypair and prints this string once; the host's\n * `kvbox server relay <string>` turns it into its tunnel. It carries the host's\n * private key, so it is a secret. The control plane never sees any of it: the host just advertises\n * the public IP.\n */\nimport { z } from \"zod\";\n\n/** Where WireGuard listens on the relay's primary address. */\nexport const RELAY_WG_PORT = 51820;\n/** The tunnel network: the relay is .1, hosts are .2 onwards. */\nexport const RELAY_TUNNEL_SUBNET = \"10.77.0.0/24\";\nexport const RELAY_TUNNEL_GATEWAY = \"10.77.0.1\";\n\nconst IPV4_RE = /^(\\d{1,3})(\\.\\d{1,3}){3}$/;\nconst WG_KEY_RE = /^[A-Za-z0-9+/]{43}=$/;\n\nexport const RelayJoinSchema = z.object({\n v: z.literal(1),\n /** How the relay lists this host. */\n name: z.string().regex(/^[a-z0-9][a-z0-9-]{0,30}$/),\n /** `<relay-primary-ip>:<port>`, the WireGuard endpoint the host dials. */\n relay: z.string().regex(/^(\\d{1,3})(\\.\\d{1,3}){3}:\\d{1,5}$/),\n /** The relay's WireGuard public key. */\n relayKey: z.string().regex(WG_KEY_RE),\n /** This host's address inside the tunnel. */\n tunnelIp: z.string().regex(IPV4_RE),\n /** This host's WireGuard private key, generated on the relay, kept nowhere else. */\n privateKey: z.string().regex(WG_KEY_RE),\n /** The extra public IPv4 the relay owns for this host; what the host advertises to the control plane. */\n publicIp: z.string().regex(IPV4_RE),\n});\nexport type RelayJoin = z.infer<typeof RelayJoinSchema>;\n\n/** The string the relay prints: base64url of the JSON, one token the owner can paste. */\nexport function encodeRelayJoin(join: RelayJoin): string {\n return Buffer.from(JSON.stringify(RelayJoinSchema.parse(join)), \"utf8\").toString(\"base64url\");\n}\n\n/** The string back into its fields, or null when it is not a relay join string. */\nexport function decodeRelayJoin(text: string): RelayJoin | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(Buffer.from(text.trim(), \"base64url\").toString(\"utf8\"));\n } catch {\n return null;\n }\n const res = RelayJoinSchema.safeParse(parsed);\n return res.success ? res.data : null;\n}\n","/**\n * Auto-hibernate (#47): a box with `autoHibernateSec` whose tap has carried no traffic, either way, for\n * that long is hibernated, so the host gets its RAM back and the meter moves to the cheaper state.\n * `connect` and `exec` already wake a hibernated box, and their ssh sends a keepalive every minute, so a\n * quiet open session counts as traffic. Any byte counts as activity; CPU-only work with nobody connected\n * looks idle (the guest's own view comes with #67). Only running boxes are watched: one in standby was\n * paused on purpose, for an instant resume. When a box was last active is kept in memory only, so a\n * server restart gives every box its full timeout again.\n */\nimport { readFile } from \"node:fs/promises\";\nimport type { Machine } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { boxBusy, withBoxLock } from \"./locks.js\";\nimport { getMachine, hibernateMachine, listMachines } from \"./machines.js\";\nimport { tapName } from \"./network.js\";\n\n/** Hibernations at once: each one dumps a box's whole memory to disk. */\nconst HIBERNATE_CONCURRENCY = 2;\n\nexport interface IdleWatchOptions {\n intervalMs?: number;\n /** Every box on the host. */\n list?: () => Promise<Machine[]>;\n /** rx + tx bytes of a box's tap; null when it cannot be read (no tap). */\n traffic?: (id: string) => Promise<number | null>;\n /** Hibernate the box if it still runs; false when it no longer did. */\n hibernate?: (box: Machine) => Promise<boolean>;\n /** Whether a caller's operation holds the box right now. */\n busy?: (box: Machine) => boolean;\n now?: () => number;\n log?: (line: string) => void;\n p?: Paths;\n}\n\n/** Bytes the box's tap has moved in both directions since it was created. */\nexport async function tapTraffic(id: string): Promise<number | null> {\n const dir = `/sys/class/net/${tapName(id)}/statistics`;\n try {\n const [rx, tx] = await Promise.all([readFile(`${dir}/rx_bytes`, \"utf8\"), readFile(`${dir}/tx_bytes`, \"utf8\")]);\n return Number(rx) + Number(tx);\n } catch {\n return null;\n }\n}\n\n/** Under the box's lock: hibernate it unless something paused, stopped or hibernated it since the listing. */\nasync function hibernateIfRunning(box: Machine, p: Paths): Promise<boolean> {\n const ref = { owner: box.owner, name: box.name };\n return withBoxLock(ref, async () => {\n if ((await getMachine(ref, p)).status !== \"running\") return false;\n await hibernateMachine(ref, p, \"auto-hibernate\");\n return true;\n });\n}\n\n/**\n * Start watching; returns a stop function. Also returns `round` so tests can drive it without timers:\n * one check plus the hibernations it started. The timer runs only the check, so a long dump does not\n * hold back the next minute's check of every other box.\n */\nexport function startIdleWatch(opts: IdleWatchOptions = {}): { stop: () => void; round: () => Promise<void> } {\n const intervalMs = opts.intervalMs ?? 60_000;\n const p = opts.p ?? paths();\n const list = opts.list ?? (() => listMachines(null, p));\n const traffic = opts.traffic ?? tapTraffic;\n const hibernate = opts.hibernate ?? ((box: Machine) => hibernateIfRunning(box, p));\n const busy = opts.busy ?? ((box: Machine) => boxBusy(box));\n const now = opts.now ?? Date.now;\n const log = opts.log ?? ((line: string) => console.log(line));\n // box id -> the tap's byte count when it last changed, and when that was\n const seen = new Map<string, { bytes: number; since: number }>();\n let timer: NodeJS.Timeout | undefined;\n let stopped = false;\n\n // boxes being hibernated right now\n const inflight = new Set<string>();\n\n const hibernateOne = async (box: Machine, quiet: number, bytes: number, t: number) => {\n inflight.add(box.id);\n try {\n if (await hibernate(box)) log(`box ${box.owner}/${box.name}: no network traffic for ${quiet} min; hibernated it (kvbox connect wakes it)`);\n seen.delete(box.id);\n } catch (err) {\n // Try again after another full timeout rather than every round.\n log(`warning: box ${box.owner}/${box.name}: could not hibernate it after ${quiet} min without traffic: ${(err as Error).message}`);\n seen.set(box.id, { bytes, since: t });\n } finally {\n inflight.delete(box.id);\n }\n };\n\n const check = async (): Promise<Promise<void>[]> => {\n const started: Promise<void>[] = [];\n const watched = new Set<string>();\n for (const box of await list()) {\n if (!box.autoHibernateSec || box.status !== \"running\") continue;\n if (inflight.has(box.id)) {\n watched.add(box.id);\n continue;\n }\n const bytes = await traffic(box.id);\n if (bytes === null) continue;\n watched.add(box.id);\n const t = now();\n const last = seen.get(box.id);\n // A caller working on the box (a snapshot, a resize) is activity too.\n if (!last || last.bytes !== bytes || busy(box)) {\n seen.set(box.id, { bytes, since: t });\n continue;\n }\n if (t - last.since < box.autoHibernateSec * 1000) continue;\n if (inflight.size >= HIBERNATE_CONCURRENCY) continue; // next round: it stays due\n started.push(hibernateOne(box, Math.round((t - last.since) / 60_000), bytes, t));\n }\n // A box that slept, stopped or lost its timeout starts over when it is watched again.\n for (const id of seen.keys()) if (!watched.has(id)) seen.delete(id);\n return started;\n };\n\n const round = async () => {\n await Promise.all(await check());\n };\n\n const schedule = () => {\n if (stopped) return;\n timer = setTimeout(() => void check().catch((err: Error) => log(`warning: idle watch: ${err.message}`)).finally(schedule), intervalMs);\n timer.unref();\n };\n schedule();\n return {\n stop: () => {\n stopped = true;\n clearTimeout(timer);\n },\n round,\n };\n}\n","/**\n * Keeps a relay tunnel (#50) carrying traffic. After the relay VM reboots, the home router can keep a\n * stale mapping for the tunnel's UDP flow: the relay still gets our handshakes, but nothing it sends\n * reaches us, and wg-quick never notices (seen 2026-10-26, every box went `unknown`). Restarting the\n * tunnel makes WireGuard dial from a new port, which the router maps afresh. So while the host uses\n * a relay, the server pings the relay's tunnel address and restarts the tunnel after a few misses.\n */\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { RELAY_TUNNEL_GATEWAY } from \"@kvbox/shared/relay\";\nimport { loadConfig } from \"./config.js\";\nimport { run } from \"./exec.js\";\nimport { netSetup } from \"./network.js\";\n\n/** What `/health` reports: restarts since this server started. */\nexport interface RelayWatchReport {\n restarts: number;\n lastRestartAt: string | null;\n}\n\nexport interface RelayWatchOptions {\n intervalMs?: number;\n /** Misses in a row before a restart. */\n misses?: number;\n /** Does the relay answer through the tunnel? */\n probe?: () => Promise<boolean>;\n restart?: () => Promise<void>;\n log?: (line: string) => void;\n p?: Paths;\n}\n\nlet report: RelayWatchReport = { restarts: 0, lastRestartAt: null };\n\nexport function relayWatchReport(): RelayWatchReport {\n return report;\n}\n\n/** One ICMP echo to the relay's end of the tunnel. */\nexport async function pingRelay(): Promise<boolean> {\n try {\n await run([\"ping\", \"-c\", \"1\", \"-W\", \"3\", RELAY_TUNNEL_GATEWAY], { timeoutMs: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Start watching; returns a stop function. The config is read on every round, so `kvbox server relay`\n * (no daemon restart) starts or ends the watching without telling us. While the relay itself is down\n * the tunnel is restarted every `misses` rounds; that costs nothing and only the first is logged.\n */\nexport function startRelayWatch(opts: RelayWatchOptions = {}): () => void {\n const intervalMs = opts.intervalMs ?? 30_000;\n const misses = opts.misses ?? 3;\n const probe = opts.probe ?? pingRelay;\n const p = opts.p ?? paths();\n const log = opts.log ?? ((line: string) => console.log(line));\n const restart = opts.restart ?? (async () => netSetup(await loadConfig(p), [\"relay\", \"restart\"]));\n report = { restarts: 0, lastRestartAt: null };\n let missed = 0;\n let stuck = false; // restarted, and the relay has not answered since\n let timer: NodeJS.Timeout | undefined;\n let stopped = false;\n\n const round = async () => {\n const cfg = await loadConfig(p).catch(() => null);\n if (!cfg?.relay) {\n missed = 0;\n return;\n }\n if (await probe()) {\n if (stuck) log(`relay ${cfg.relay.name}: the tunnel carries traffic again`);\n missed = 0;\n stuck = false;\n return;\n }\n if (++missed < misses) return;\n missed = 0;\n if (!stuck) log(`relay ${cfg.relay.name}: no answer through the tunnel for ${(misses * intervalMs) / 1000} s; restarting it`);\n try {\n await restart();\n report = { restarts: report.restarts + 1, lastRestartAt: new Date().toISOString() };\n } catch (err) {\n if (!stuck) console.error(`warning: relay ${cfg.relay.name}: could not restart the tunnel: ${(err as Error).message}`);\n }\n stuck = true;\n };\n\n const schedule = () => {\n if (stopped) return;\n timer = setTimeout(() => void round().catch((err: Error) => console.error(`warning: relay watch: ${err.message}`)).finally(schedule), intervalMs);\n timer.unref();\n };\n schedule();\n return () => {\n stopped = true;\n clearTimeout(timer);\n };\n}\n","/**\n * Bind the app to the local Unix socket and write the pid file. A host that joined a control plane\n * (`kvbox-server join`) also serves a second instance of the app over HTTPS with its own\n * certificate; that instance demands the host secret on every call (caller.ts).\n */\nimport { readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo } from \"node:net\";\nimport { createAdaptorServer, type ServerType } from \"@hono/node-server\";\nimport { ensureLayout } from \"./core/state.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { stopRecovery } from \"./core/machines.js\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { paths } from \"@kvbox/shared/paths\";\nimport { createApp } from \"./app.js\";\nimport { boxUpgradeHandler } from \"./routes/boxHttp.js\";\n\nexport interface ListenOptions {\n socketPath?: string;\n /** Overrides the joined control plane's port (tests: 0 picks a free one). */\n httpsPort?: number;\n}\n\nexport interface Listening {\n socketPath: string;\n server: ServerType;\n /** Present when the host has joined a control plane. */\n https?: { port: number; url: string };\n close: () => Promise<void>;\n}\n\nexport async function listen(opts: ListenOptions = {}): Promise<Listening> {\n const p = await ensureLayout(paths());\n const cfg = await loadConfig(p);\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 let https: Listening[\"https\"];\n let httpsServer: ServerType | undefined;\n const cp = cfg.controlPlane;\n if (cp) {\n const [key, cert] = await Promise.all([readFile(p.tlsKey), readFile(p.tlsCert)]).catch((err: Error) => {\n throw new KvboxError(`joined ${cp.name} but the host's certificate is missing (${err.message}); run kvbox-server leave, then join again`);\n });\n httpsServer = createAdaptorServer({\n fetch: createApp({ controlPlane: { name: cp.name, secret: cp.secret } }).fetch,\n createServer: createHttpsServer,\n serverOptions: { key, cert },\n });\n // WebSockets to a box's web server (#31) never reach the app: the server hands them over raw.\n httpsServer.on(\"upgrade\", boxUpgradeHandler({ name: cp.name, secret: cp.secret }));\n const port = opts.httpsPort ?? cp.port;\n await new Promise<void>((resolve, reject) => {\n httpsServer!.once(\"error\", reject);\n httpsServer!.listen(port, \"0.0.0.0\", () => resolve());\n }).catch(async (err: Error) => {\n server.close();\n await rm(socketPath, { force: true });\n await rm(p.serverPid, { force: true });\n throw new KvboxError(`cannot listen on port ${port} for ${cp.name} (${err.message})`);\n });\n const bound = (httpsServer.address() as AddressInfo).port;\n https = { port: bound, url: `https://${cp.advertise}:${bound}` };\n }\n\n /** Tests: wait for both listeners to let go. */\n const close = async () => {\n await Promise.all([\n new Promise<void>((resolve) => server.close(() => resolve())),\n httpsServer ? new Promise<void>((resolve) => httpsServer!.close(() => resolve())) : undefined,\n ]);\n await rm(socketPath, { force: true });\n await rm(p.serverPid, { force: true });\n };\n // A signal must end the process even mid-request (a box creation can take a while and\n // `kvbox server stop` sends one SIGTERM): stop accepting, drop the files, exit. Only boxes being\n // brought back after a reboot are waited for, so none is left running unrecorded (#29).\n const shutdown = async () => {\n server.close();\n httpsServer?.close();\n await stopRecovery();\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 https ? { socketPath, server, https, close } : { socketPath, server, close };\n}\n","/**\n * The hono app behind `kvbox-server`. Served over `~/.kvbox/server.sock` to the host owner, and,\n * once the host joined a control plane, a second instance over HTTPS that demands the host secret\n * (see caller.ts).\n */\nimport { Hono } from \"hono\";\nimport { KvboxError, NotFoundError } from \"@kvbox/shared/errors\";\nimport { VERSION } from \"./version.js\";\nimport { resolveCaller, type CallerOptions, type Env } from \"./caller.js\";\nimport { loadConfig } from \"./core/config.js\";\nimport { currentBaseVersion, lastRecovery } from \"./core/machines.js\";\nimport { relayWatchReport } from \"./core/relayWatch.js\";\nimport { boxHttpRoutes } from \"./routes/boxHttp.js\";\nimport { capacityRoutes } from \"./routes/capacity.js\";\nimport { machineRoutes } from \"./routes/machines.js\";\nimport { snapshotRoutes } from \"./routes/snapshots.js\";\nimport { sshRoutes } from \"./routes/ssh.js\";\nimport { usageRoutes } from \"./routes/usage.js\";\n\nexport function createApp(opts: CallerOptions = {}) {\n const app = new Hono<Env>();\n app.use(resolveCaller(opts));\n\n app.get(\"/health\", async (c) => {\n const cfg = await loadConfig();\n const cp = cfg.controlPlane;\n return c.json({\n ok: true as const,\n version: VERSION,\n pid: process.pid,\n base: await currentBaseVersion().catch(() => null),\n owner: cfg.owner,\n controlPlane: cp ? { name: cp.name, url: cp.url, hostUrl: `https://${cp.advertise}:${cp.port}` } : null,\n relay: cfg.relay ? { name: cfg.relay.name, publicIp: cfg.relay.publicIp, endpoint: cfg.relay.endpoint, ...relayWatchReport() } : null,\n recovery: lastRecovery(),\n });\n });\n // A box's web servers for the edge (#31): only what came from the control plane's side.\n if (opts.controlPlane) app.route(\"/machines\", boxHttpRoutes());\n app.route(\"/machines\", machineRoutes());\n app.route(\"/snapshots\", snapshotRoutes());\n app.route(\"/capacity\", capacityRoutes());\n app.route(\"/ssh\", sshRoutes(opts));\n app.route(\"/usage\", usageRoutes(opts));\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. Two callers exist:\n * - the host owner over the local Unix socket: no credential (the socket's permissions are the\n * auth), owner = the server's configured `owner` (the Unix user running it);\n * - the control plane this host joined (#18), over HTTPS: it presents the host secret from `join`\n * as a bearer on every call and names the user it acts for in `X-Kvbox-Owner`, qualified here\n * and nowhere else to `<user>@<control plane name>` (decision \"Owner realms\"). `/health` and\n * `/capacity` need no owner; box and snapshot routes do, except the two listings: without the\n * header `GET /machines` and `GET /snapshots` cover every owner of the realm (the control\n * plane reconciling its index, #20). The host owner's local boxes are never in that answer.\n * The edge (#31) presents `edgeCredential(secret)` instead, which opens a box's port\n * (`BOX_HTTP_PATH_RE`) and nothing else.\n */\nimport { createHash, timingSafeEqual } from \"node:crypto\";\nimport type { MiddlewareHandler } from \"hono\";\nimport { BOX_HTTP_PATH_RE, edgeCredential } from \"@kvbox/shared/names\";\nimport { loadConfig } from \"./core/config.js\";\nimport { LOCAL_OWNER_RE, type ListScope } from \"./core/refs.js\";\n\nexport type Env = { Variables: { owner: string; listScope: ListScope } };\n\nexport interface ControlPlaneCaller {\n /** The realm name owners are qualified with. */\n name: string;\n /** The host secret minted at join. */\n secret: string;\n}\n\nexport interface CallerOptions {\n /** Set on the HTTPS app only; the socket app trusts its caller. */\n controlPlane?: ControlPlaneCaller;\n}\n\nexport const OWNER_HEADER = \"x-kvbox-owner\";\n\nexport function resolveCaller(opts: CallerOptions = {}): MiddlewareHandler<Env> {\n const cp = opts.controlPlane;\n if (!cp) {\n return async (c, next) => {\n const cfg = await loadConfig();\n c.set(\"owner\", cfg.owner);\n c.set(\"listScope\", cfg.owner);\n await next();\n };\n }\n const authorized = secretCheck(cp);\n const edge = edgeCheck(cp);\n return async (c, next) => {\n const auth = c.req.header(\"authorization\");\n if (!authorized(auth) && !(edge(auth) && BOX_HTTP_PATH_RE.test(c.req.path))) return c.json({ error: \"not authorized\" }, 401);\n const user = c.req.header(OWNER_HEADER);\n if (user === undefined) {\n const path = c.req.path.replace(/\\/$/, \"\");\n const realmListing = c.req.method === \"GET\" && (path === \"/machines\" || path === \"/snapshots\");\n if (!realmListing && /^\\/(machines|snapshots)(\\/|$)/.test(c.req.path)) {\n return c.json({ error: \"X-Kvbox-Owner header required\" }, 400);\n }\n c.set(\"owner\", \"\");\n c.set(\"listScope\", { realm: cp.name });\n } else {\n if (!LOCAL_OWNER_RE.test(user)) return c.json({ error: \"X-Kvbox-Owner: letters, digits, '.', '_', '-'\" }, 400);\n const owner = `${user}@${cp.name}`;\n c.set(\"owner\", owner);\n c.set(\"listScope\", owner);\n }\n await next();\n };\n}\n\n/** Whether an `Authorization` header carries the host secret (constant time). */\nexport function secretCheck(cp: ControlPlaneCaller): (authorization: string | undefined) => boolean {\n return bearerCheck(cp.secret);\n}\n\n/** Whether it carries the edge's credential, good for a box's port only. */\nexport function edgeCheck(cp: ControlPlaneCaller): (authorization: string | undefined) => boolean {\n return bearerCheck(edgeCredential(cp.secret));\n}\n\nfunction bearerCheck(token: string): (authorization: string | undefined) => boolean {\n const expected = digest(token);\n return (authorization) => {\n const m = /^Bearer\\s+(\\S+)$/i.exec(authorization ?? \"\");\n return m !== null && timingSafeEqual(digest(m[1]!), expected);\n };\n}\n\n/** Fixed-length form of a secret so the compare is constant time whatever the caller sent. */\nfunction digest(secret: string): Buffer {\n return createHash(\"sha256\").update(secret).digest();\n}\n","/**\n * HTTPS names for boxes (#31, decision \"A box claims one subdomain\"): a box claims one subdomain\n * `<sub>.kvbox.app` with a default port, and named ports nest under it as `<name>.<sub>.kvbox.app`.\n * Both are single DNS labels. The CLI checks them before calling; the control plane checks again.\n */\nimport { createHmac } from \"node:crypto\";\nimport { KvboxError } from \"./errors.js\";\n\n/** Where box URLs live (decision d2cb4d88's domain); the control plane and the edge can be told otherwise. */\nexport const DEFAULT_PROXY_DOMAIN = \"kvbox.app\";\n\n/** A domain box names may live under (`kvbox.app`): the control plane's and the edge's must match. */\nexport function assertProxyDomain(text: string, key: string): string {\n if (!/^[a-z0-9-]+(\\.[a-z0-9-]+)+$/.test(text)) throw new KvboxError(`${key} must be a domain like ${DEFAULT_PROXY_DOMAIN}: ${text}`);\n return text;\n}\n\n/** One DNS label: lowercase letters, digits and `-`, never at either end. */\nconst LABEL_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/** Subdomains nobody may claim: the platform's own names, and ones that would read as ours. */\nexport const RESERVED_SUBDOMAINS: ReadonlySet<string> = new Set([\n \"admin\",\n \"api\",\n \"app\",\n \"assets\",\n \"auth\",\n \"billing\",\n \"blog\",\n \"cdn\",\n \"dashboard\",\n \"dev\",\n \"docs\",\n \"edge\",\n \"help\",\n \"install\",\n \"kvbox\",\n \"login\",\n \"mail\",\n \"relay\",\n \"root\",\n \"smtp\",\n \"static\",\n \"status\",\n \"support\",\n \"www\",\n]);\n\n/** Why `text` cannot be a claimed subdomain, or null when it can. */\nexport function subdomainProblem(text: string): string | null {\n if (text.length < 3 || text.length > 63) return `\"${text}\" must be 3 to 63 characters`;\n if (!LABEL_RE.test(text)) return `\"${text}\" may hold only lowercase letters, digits and '-', not at either end`;\n if (RESERVED_SUBDOMAINS.has(text)) return `\"${text}\" is reserved; pick another name`;\n return null;\n}\n\n/** Why `text` cannot be a name under a subdomain (`<name>.<sub>`), or null when it can. */\nexport function routeNameProblem(text: string): string | null {\n if (text.length < 1 || text.length > 63) return `\"${text}\" must be 1 to 63 characters`;\n if (!LABEL_RE.test(text)) return `\"${text}\" may hold only lowercase letters, digits and '-', not at either end`;\n return null;\n}\n\nexport function assertSubdomain(text: string): string {\n const problem = subdomainProblem(text);\n if (problem) throw new KvboxError(`subdomain ${problem}`);\n return text;\n}\n\nexport function assertRouteName(text: string): string {\n const problem = routeNameProblem(text);\n if (problem) throw new KvboxError(`name ${problem}`);\n return text;\n}\n\n/** `https://<sub>.<domain>`, or `https://<name>.<sub>.<domain>` for a named port. */\nexport function subdomainUrl(domain: string, sub: string, name?: string): string {\n return `https://${name === undefined ? \"\" : `${name}.`}${sub}.${domain}`;\n}\n\n/**\n * What a request's `Host` names under `domain`: the subdomain and, for `<name>.<sub>`, the name.\n * Null for anything else (the bare domain, deeper names, another domain).\n */\nexport function parseProxyHost(host: string, domain: string): { sub: string; name?: string } | null {\n const bare = host.toLowerCase().replace(/:\\d+$/, \"\").replace(/\\.$/, \"\");\n const suffix = `.${domain}`;\n if (!bare.endsWith(suffix)) return null;\n const labels = bare.slice(0, -suffix.length).split(\".\");\n if (labels.some((l) => !LABEL_RE.test(l))) return null;\n if (labels.length === 1) return { sub: labels[0]! };\n if (labels.length === 2) return { sub: labels[1]!, name: labels[0]! };\n return null;\n}\n\n/**\n * How the edge and a host carry a visitor's request to a box (#31). The host's answers of its own\n * (no such box, box not running, nothing listening) carry `PROXY_ERROR_HEADER`, and the box's carry\n * `PROXIED_HEADER`, so the edge can tell the box's own 404 or 401 from the host's and show its page\n * for the latter. The edge strips every `x-kvbox-*` header before a visitor sees the answer.\n */\nexport const PROXY_ERROR_HEADER = \"x-kvbox-proxy-error\";\n/**\n * `hibernated`, `standby` and `stopped` say why a box is not running (#80): the edge may ask for the\n * first two to be woken, never the last. `waking`: a wake asked for is still under way. `wake-failed`:\n * it did not work. `not-running` is what a host from before #80 says for all three.\n */\nexport type ProxyError = \"not-found\" | \"hibernated\" | \"standby\" | \"stopped\" | \"not-running\" | \"waking\" | \"wake-failed\" | \"unreachable\" | \"timeout\";\n/** Set by the host on every answer that came from the box: anything without it is the host's own (a refusal, a host too old for #31). */\nexport const PROXIED_HEADER = \"x-kvbox-proxied\";\n/**\n * The visitor's path and query. It never goes into the URL the edge calls on the host: a URL resolves\n * `..`, and `/machines/<box>/http/<port>/../../..` would reach any route on the host with the host\n * secret. The host URL is always exactly `/machines/<box>/http/<port>`.\n */\nexport const VISITOR_PATH_HEADER = \"x-kvbox-path\";\n/**\n * Sent by the edge when the box may be woken for this request (#80): its slug is not suspended and\n * the edge has not had it woken in the last minute. A host then wakes a hibernated box (resumes one in\n * standby) before forwarding, and stamps its answer with WOKE_HEADER when it did.\n */\nexport const WAKE_HEADER = \"x-kvbox-wake\";\n/**\n * The longest a host holds a request on a wake before answering `waking` (the wake itself goes on).\n * The edge adds it to its own wait for the host's answer when it sends WAKE_HEADER.\n */\nexport const WAKE_WAIT_MS = 30_000;\n/**\n * On a host's answer: this request woke the box, so the edge counts it against the box's wake limit.\n * Also on the host's own `unreachable` or `timeout` after a wake: the box was woken all the same.\n */\nexport const WOKE_HEADER = \"x-kvbox-woke\";\n/** The visitor's own `Authorization`, carried past the host secret that takes its place between edge and host. */\nexport const VISITOR_AUTH_HEADER = \"x-kvbox-authorization\";\n\n/**\n * Request headers neither hop passes on although they are not hop-by-hop: undici refuses to send\n * `expect` at all, so `Expect: 100-continue` (curl on a large upload) would fail every forward.\n * Node's server already answers the `100 Continue` itself.\n */\nexport const NOT_FORWARDED: ReadonlySet<string> = new Set([\"expect\"]);\n\n/** Headers that describe one connection, never passed along by a proxy (RFC 9110 §7.6.1). */\nexport const HOP_BY_HOP: ReadonlySet<string> = new Set([\"connection\", \"keep-alive\", \"proxy-authenticate\", \"proxy-authorization\", \"proxy-connection\", \"te\", \"trailer\", \"transfer-encoding\", \"upgrade\"]);\n\n/** The one host path the edge calls: a box's port, `/machines/<box>/http/<port>`. */\nexport const BOX_HTTP_PATH_RE = /^\\/machines\\/([^/]+)\\/http\\/(\\d{1,5})\\/?$/;\n\n/**\n * The edge's bearer for a host, derived from the host secret so neither side stores anything new.\n * A host takes it on `BOX_HTTP_PATH_RE` alone, so the internet-facing edge never holds a key to the\n * rest of a host's API; the control plane keeps it in `hosts.edge_secret` for the edge to read.\n */\nexport function edgeCredential(hostSecret: string): string {\n return createHmac(\"sha256\", hostSecret).update(\"kvbox-edge-v1\").digest(\"base64url\");\n}\n","/**\n * A box's web servers for the edge (#31): `ANY /machines/:name/http/:port` on the HTTPS app only\n * (never the socket) is passed to `<box ip>:<port><x-kvbox-path>` with its body streamed both ways,\n * and the same call as a WebSocket upgrade (listen.ts) is piped. The visitor's path comes in a\n * header, never in the URL (see VISITOR_PATH_HEADER). The control plane already decided\n * the name is the box's; this only forwards to a box of the caller's realm that is running.\n *\n * The edge sends the visitor's `Authorization` as `x-kvbox-authorization` (the host secret holds the\n * real header between edge and host) and the visitor's host name as `x-forwarded-host`; the box\n * gets them back as `authorization` and `host`, and never sees the secret or `x-kvbox-owner`.\n * Answers the host gives itself carry `x-kvbox-proxy-error`; the box's carry `x-kvbox-proxied`,\n * and any `x-kvbox-*` the box sent itself is dropped, so a box cannot pass for the host.\n * The caller is the control plane (host secret) or the edge (its credential, caller.ts).\n *\n * Wake on request (#80): with WAKE_HEADER, a hibernated box is woken (one in standby resumed) before\n * the forward, one wake per box however many requests wait on it; the edge decides whether a box\n * may be woken (credit, its rate limit), the host only how. A stopped box is never started.\n */\nimport type { IncomingHttpHeaders, IncomingMessage } from \"node:http\";\nimport { connect, type Socket } from \"node:net\";\nimport { Readable } from \"node:stream\";\nimport { Hono } from \"hono\";\nimport { request } from \"undici\";\nimport type { BoxStatus } from \"@kvbox/shared/api\";\nimport { NotFoundError } from \"@kvbox/shared/errors\";\nimport { HeadTimeoutError, readHead, rewriteHead } from \"@kvbox/shared/httpHead\";\nimport {\n BOX_HTTP_PATH_RE,\n HOP_BY_HOP,\n NOT_FORWARDED,\n PROXIED_HEADER,\n PROXY_ERROR_HEADER,\n VISITOR_AUTH_HEADER,\n VISITOR_PATH_HEADER,\n WAKE_HEADER,\n WAKE_WAIT_MS,\n WOKE_HEADER,\n type ProxyError,\n} from \"@kvbox/shared/names\";\nimport { edgeCheck, OWNER_HEADER, secretCheck, type ControlPlaneCaller, type Env } from \"../caller.js\";\nimport { getMachine, resumeMachine, wakeMachine } from \"../core/machines.js\";\nimport { LOCAL_OWNER_RE, parseRef, type BoxRef } from \"../core/refs.js\";\n\n/**\n * How long the box may take to start answering; a stream (SSE, a long download) then has no limit.\n * Shorter than the edge's wait for the host (edge proxy.ts), so the host's `timeout` answer gets there first.\n */\nconst HEADERS_TIMEOUT_MS = 55_000;\n/** The most a box's answer to a WebSocket handshake may hold before its blank line. */\nconst MAX_HANDSHAKE_BYTES = 16 * 1024;\n/** Connecting to the box: it is on the host's own bridge, so anything slower means nothing is there. */\nconst CONNECT_TIMEOUT_MS = 5_000;\n/** Headers that never reach the box: the edge-to-host credentials and what the forward rewrites. */\nconst DROPPED = new Set([...HOP_BY_HOP, ...NOT_FORWARDED, \"host\", \"authorization\", OWNER_HEADER, VISITOR_AUTH_HEADER, VISITOR_PATH_HEADER, WAKE_HEADER]);\n\nclass ProxyFailure extends Error {\n constructor(\n readonly status: number,\n readonly code: ProxyError,\n message: string,\n ) {\n super(message);\n }\n}\n\ninterface Target {\n ip: string;\n port: number;\n /** The path and query on the box. */\n path: string;\n /** This request woke the box (WOKE_HEADER on the answer). */\n woke: boolean;\n}\n\n/** Brings a hibernated or standby box back. Resolves once it runs; tests pass their own. */\nexport type Waker = (ref: BoxRef, status: \"hibernated\" | \"standby\") => Promise<void>;\n\n/**\n * A Waker that runs one wake per box at a time, the requests that arrive meanwhile waiting on the\n * same one, and gives up waiting (not waking) after `capMs` with a `waking` failure.\n */\nexport function sharedWaker(bring: Waker = defaultBring, capMs = WAKE_WAIT_MS): Waker {\n const inFlight = new Map<string, Promise<void>>();\n return async (ref, status) => {\n const key = `${ref.owner}/${ref.name}`;\n let wake = inFlight.get(key);\n if (!wake) {\n wake = bring(ref, status).finally(() => inFlight.delete(key));\n inFlight.set(key, wake);\n // a wake nobody waits on any more (they all hit the cap) must not be an unhandled rejection\n wake.catch(() => {});\n }\n let timer: NodeJS.Timeout | undefined;\n const cap = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new ProxyFailure(503, \"waking\", `box ${ref.name} is waking up`)), capMs);\n });\n try {\n await Promise.race([wake, cap]);\n } finally {\n clearTimeout(timer);\n }\n };\n}\n\nconst defaultBring: Waker = async (ref, status) => {\n await (status === \"hibernated\" ? wakeMachine(ref) : resumeMachine(ref));\n};\n\n/** Shared by the plain route and the upgrade handler, so a page and its WebSocket wake the box once. */\nconst wakeBox = sharedWaker();\n\n/** The answer code for a box that is not running. */\nconst notRunning = (status: BoxStatus): ProxyError => (status === \"hibernated\" || status === \"standby\" ? status : \"stopped\");\n\n/** The path on the box: the edge's header, a plain origin-form path; anything else is the box's `/`. */\nfunction visitorPath(value: string | string[] | null | undefined): string {\n const path = Array.isArray(value) ? value[0] : value;\n return path !== undefined && path !== null && path.startsWith(\"/\") && !/[\\s]/.test(path) ? path : \"/\";\n}\n\n/**\n * The running box a forward path names, or a ProxyFailure saying why not. With `wake`, a hibernated\n * or standby box is brought back first.\n */\nasync function targetOf(url: URL, owner: string, path: string, wake?: Waker): Promise<Target> {\n const m = BOX_HTTP_PATH_RE.exec(url.pathname);\n const port = Number(m?.[2]);\n if (!m || port < 1 || port > 65535) throw new ProxyFailure(404, \"not-found\", `no route: ${url.pathname}`);\n const name = decodeURIComponent(m[1]!);\n const ref = parseRef(name, owner);\n let box;\n try {\n box = await getMachine(ref);\n } catch (err) {\n if (err instanceof NotFoundError) throw new ProxyFailure(404, \"not-found\", err.message);\n throw err;\n }\n let woke = false;\n if (box.status !== \"running\" && wake && (box.status === \"hibernated\" || box.status === \"standby\")) {\n try {\n await wake(ref, box.status);\n woke = true;\n } catch (err) {\n if (err instanceof ProxyFailure) throw err;\n // another wake may have finished between our look and our call: then the box is up all the same\n box = await getMachine(ref);\n if (box.status !== \"running\") throw new ProxyFailure(502, \"wake-failed\", `box ${name} did not wake: ${(err as Error).message}`);\n }\n if (woke) box = await getMachine(ref);\n }\n if (box.status !== \"running\") throw new ProxyFailure(409, notRunning(box.status), `box ${name} is ${box.status}`);\n return { ip: box.ip, port, path, woke };\n}\n\n/** The request headers as the box gets them. `upgrade` keeps the two headers a WebSocket handshake needs. */\nfunction boxHeaders(incoming: Iterable<[string, string]>, target: Target, upgrade = false): [string, string][] {\n const out: [string, string][] = [];\n let host = `${target.ip}:${target.port}`;\n for (const [name, value] of incoming) {\n const key = name.toLowerCase();\n if (key === \"x-forwarded-host\") host = value;\n if (key === VISITOR_AUTH_HEADER) out.push([\"authorization\", value]);\n if (upgrade && (key === \"upgrade\" || key === \"connection\")) out.push([name, value]);\n else if (!DROPPED.has(key)) out.push([name, value]);\n }\n out.push([\"host\", host]);\n return out;\n}\n\n/** `woke`: this request woke the box before failing, so the edge still counts the wake (WOKE_HEADER). */\nconst failure = (err: ProxyFailure, woke = false) =>\n new Response(JSON.stringify({ error: err.message }), { status: err.status, headers: { \"content-type\": \"application/json\", [PROXY_ERROR_HEADER]: err.code, ...(woke ? { [WOKE_HEADER]: \"1\" } : {}) } });\n\n/** Whether the caller asked for the box to be woken (WAKE_HEADER). */\nconst wants = (value: string | string[] | null | undefined) => value === \"1\";\n\nexport function boxHttpRoutes(wake: Waker = wakeBox) {\n const r = new Hono<Env>();\n r.all(\"/:name/http/:port\", (c) => forward(c, wake));\n return r;\n}\n\nasync function forward(c: import(\"hono\").Context<Env>, wake: Waker): Promise<Response> {\n let target: Target;\n try {\n target = await targetOf(new URL(c.req.url), c.get(\"owner\"), visitorPath(c.req.header(VISITOR_PATH_HEADER)), wants(c.req.header(WAKE_HEADER)) ? wake : undefined);\n } catch (err) {\n if (err instanceof ProxyFailure) return failure(err);\n throw err;\n }\n const raw = c.req.raw;\n const pairs: [string, string][] = [];\n raw.headers.forEach((value, name) => pairs.push([name, value]));\n let res;\n try {\n res = await request(`http://${target.ip}:${target.port}${target.path}`, {\n method: raw.method as \"GET\",\n headers: boxHeaders(pairs, target).flat(),\n body: raw.body === null ? null : Readable.fromWeb(raw.body as import(\"node:stream/web\").ReadableStream),\n headersTimeout: HEADERS_TIMEOUT_MS,\n bodyTimeout: 0,\n signal: raw.signal,\n });\n } catch (err) {\n const e = err as Error & { code?: string };\n if (e.code === \"UND_ERR_HEADERS_TIMEOUT\") return failure(new ProxyFailure(504, \"timeout\", `box took over ${HEADERS_TIMEOUT_MS / 1000} s to answer on port ${target.port}`), target.woke);\n return failure(new ProxyFailure(502, \"unreachable\", `box answered nothing on port ${target.port} (${e.code ?? e.message})`), target.woke);\n }\n const headers = new Headers();\n for (const [name, value] of Object.entries(res.headers)) {\n if (value === undefined || HOP_BY_HOP.has(name) || name.startsWith(\"x-kvbox-\")) continue;\n for (const v of Array.isArray(value) ? value : [value]) headers.append(name, v);\n }\n headers.set(PROXIED_HEADER, \"1\");\n if (target.woke) headers.set(WOKE_HEADER, \"1\");\n const empty = res.statusCode === 204 || res.statusCode === 304 || raw.method === \"HEAD\";\n if (empty) res.body.resume();\n return new Response(empty ? null : (Readable.toWeb(res.body) as ReadableStream), { status: res.statusCode, headers });\n}\n\n/**\n * An answer written straight on a socket, for an upgrade that cannot go ahead. It always carries\n * PROXY_ERROR_HEADER (`refused` when no box reason applies) and never PROXIED_HEADER, which only a\n * box's own answer gets.\n */\nfunction refuse(socket: Socket, status: number, text: string, code: ProxyError | \"refused\" = \"refused\", woke = false): void {\n const body = JSON.stringify({ error: text });\n socket.end(`HTTP/1.1 ${status} ${status === 401 ? \"Unauthorized\" : \"Error\"}\\r\\ncontent-type: application/json\\r\\ncontent-length: ${Buffer.byteLength(body)}\\r\\n${PROXY_ERROR_HEADER}: ${code}\\r\\n${woke ? `${WOKE_HEADER}: 1\\r\\n` : \"\"}connection: close\\r\\n\\r\\n${body}`);\n}\n\nfunction headerPairs(raw: readonly string[]): [string, string][] {\n const out: [string, string][] = [];\n for (let i = 0; i + 1 < raw.length; i += 2) out.push([raw[i]!, raw[i + 1]!]);\n return out;\n}\n\n/**\n * The HTTPS server's `upgrade` handler: a WebSocket to a box. Checked like any call from the control\n * plane's side (host secret or the edge's credential, owner), then the handshake is written to the\n * box as it came, rewritten the same way as a plain forward. The box's answer is read up to its\n * blank line (a box that says nothing in `headersTimeoutMs` is our `timeout`), stamped like a plain\n * forward's, and from then on the two sockets are piped.\n */\nexport function boxUpgradeHandler(cp: ControlPlaneCaller, headersTimeoutMs = HEADERS_TIMEOUT_MS, wake: Waker = wakeBox) {\n const full = secretCheck(cp);\n const edge = edgeCheck(cp);\n const authorized = (auth: string | undefined) => full(auth) || edge(auth);\n return (req: IncomingMessage, socket: Socket, head: Buffer): void => {\n // Node drops its own error listener on an upgraded socket: without this one, a visitor resetting\n // the connection while we look the box up (or write a refusal) would crash the daemon.\n socket.on(\"error\", () => socket.destroy());\n void (async () => {\n const headers: IncomingHttpHeaders = req.headers;\n if (!authorized(headers.authorization)) return refuse(socket, 401, \"not authorized\");\n const user = headers[OWNER_HEADER];\n if (typeof user !== \"string\" || !LOCAL_OWNER_RE.test(user)) return refuse(socket, 400, \"X-Kvbox-Owner header required\");\n let target: Target;\n try {\n target = await targetOf(new URL(req.url ?? \"/\", \"https://host\"), `${user}@${cp.name}`, visitorPath(headers[VISITOR_PATH_HEADER]), wants(headers[WAKE_HEADER]) ? wake : undefined);\n } catch (err) {\n if (err instanceof ProxyFailure) return refuse(socket, err.status, err.message, err.code);\n return refuse(socket, 500, (err as Error).message);\n }\n // the visitor may have left while we looked: then there is nobody to open the box for\n if (socket.destroyed) return;\n const box = connect({ host: target.ip, port: target.port, timeout: CONNECT_TIMEOUT_MS });\n let connected = false;\n let piped = false;\n box.once(\"timeout\", () => box.destroy(new Error(\"timed out\")));\n box.once(\"error\", (err: Error & { code?: string }) => {\n if (!connected && !socket.destroyed) refuse(socket, 502, `box answered nothing on port ${target.port} (${err.code ?? err.message})`, \"unreachable\", target.woke);\n else if (piped) socket.destroy();\n });\n socket.once(\"close\", () => box.destroy());\n box.once(\"close\", () => {\n if (piped) socket.destroy();\n });\n box.once(\"connect\", () => {\n connected = true;\n box.setTimeout(0);\n const lines = boxHeaders(headerPairs(req.rawHeaders), target, true).map(([k, v]) => `${k}: ${v}\\r\\n`);\n box.write(`${req.method ?? \"GET\"} ${target.path} HTTP/1.1\\r\\n${lines.join(\"\")}\\r\\n`);\n if (head.length > 0) box.write(head);\n readHead(box, { maxBytes: MAX_HANDSHAKE_BYTES, timeoutMs: headersTimeoutMs }).then(\n (answer) => {\n if (socket.destroyed) return void box.destroy();\n socket.write(rewriteHead(answer.head, (name) => name.startsWith(\"x-kvbox-\"), { [PROXIED_HEADER]: \"1\", ...(target.woke ? { [WOKE_HEADER]: \"1\" } : {}) }));\n if (answer.rest.length > 0) socket.write(answer.rest);\n piped = true;\n box.pipe(socket);\n socket.pipe(box);\n },\n (err: Error) => {\n box.destroy();\n if (socket.destroyed) return;\n if (err instanceof HeadTimeoutError) refuse(socket, 504, `box took over ${headersTimeoutMs / 1000} s to answer on port ${target.port}`, \"timeout\", target.woke);\n else refuse(socket, 502, `box gave no answer on port ${target.port} (${err.message})`, \"unreachable\", target.woke);\n },\n );\n });\n })();\n };\n}\n","/**\n * The head of an HTTP/1.1 answer read off a raw socket (#31). A WebSocket goes edge → host → box as\n * piped bytes, so both hops read the answer to the handshake themselves: the host to stamp the box's\n * answer as the box's and drop any `x-kvbox-*` it sent, the edge to tell that from the host's refusal.\n */\nimport type { Duplex } from \"node:stream\";\n\nconst END = \"\\r\\n\\r\\n\";\n\n/** Nothing came before `timeoutMs`: the box (or host) took the connection and said nothing. */\nexport class HeadTimeoutError extends Error {}\n\n/**\n * What `socket` answers, up to its blank line: the head (status line and headers, no blank line) and\n * whatever came after it in the same reads. The socket is left paused with nothing more consumed.\n */\nexport function readHead(socket: Duplex, opts: { maxBytes: number; timeoutMs: number }): Promise<{ head: string; rest: Buffer }> {\n return new Promise((resolve, reject) => {\n let bytes = Buffer.alloc(0);\n const done = (err?: Error) => {\n clearTimeout(timer);\n socket.off(\"data\", onData);\n socket.off(\"close\", onClose);\n socket.pause();\n if (err) return reject(err);\n const end = bytes.indexOf(END);\n resolve({ head: bytes.subarray(0, end).toString(\"latin1\"), rest: bytes.subarray(end + END.length) });\n };\n const onData = (chunk: Buffer) => {\n bytes = Buffer.concat([bytes, chunk]);\n if (bytes.includes(END)) done();\n else if (bytes.length > opts.maxBytes) done(new Error(\"answer head too large\"));\n };\n const onClose = () => done(new Error(\"closed before answering\"));\n const timer = setTimeout(() => done(new HeadTimeoutError(`no answer within ${opts.timeoutMs / 1000} s`)), opts.timeoutMs);\n socket.on(\"data\", onData);\n socket.once(\"close\", onClose);\n });\n}\n\n/** The value of header `name` (lowercase) in a head, or undefined. */\nexport function headHeader(head: string, name: string): string | undefined {\n const line = head.split(\"\\r\\n\").slice(1).find((l) => l.slice(0, l.indexOf(\":\")).trim().toLowerCase() === name);\n return line?.slice(line.indexOf(\":\") + 1).trim();\n}\n\n/** The head again with the headers `drop` names left out and `add` appended, blank line included. */\nexport function rewriteHead(head: string, drop: (name: string) => boolean, add: Record<string, string> = {}): Buffer {\n const [status, ...lines] = head.split(\"\\r\\n\");\n const kept = lines.filter((l) => !drop(l.slice(0, l.indexOf(\":\")).trim().toLowerCase()));\n const extra = Object.entries(add).map(([k, v]) => `${k}: ${v}`);\n return Buffer.from(`${[status, ...kept, ...extra].join(\"\\r\\n\")}${END}`, \"latin1\");\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, PortsRequest, RescaleMachineRequest, SetMachineRequest, SetSshKeysRequest } from \"@kvbox/shared/api\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport {\n addPorts,\n createMachine,\n destroyMachine,\n hibernateMachine,\n listMachines,\n pauseMachine,\n removePorts,\n rescaleMachine,\n resumeMachine,\n setMachine,\n setSshKeys,\n startMachine,\n stopMachine,\n updateMachine,\n wakeMachine,\n} from \"../core/machines.js\";\nimport { parseRef } from \"../core/refs.js\";\nimport { machineStats } from \"../core/stats.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(\"listScope\"))));\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.post(\"/:name/set\", async (c) => {\n const body = SetMachineRequest.parse(await c.req.json().catch(() => ({})));\n return c.json(await setMachine(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body));\n });\n r.post(\"/:name/ssh-keys\", async (c) => {\n const body = SetSshKeysRequest.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"sshKeys: expected a list of authorized_keys lines\");\n const { machine, applied } = await setSshKeys(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body.data.sshKeys);\n return c.json({ ...machine, sshKeysApplied: applied });\n });\n // Published box ports (#30): both answer with the box, its `ports` as they are now.\n r.post(\"/:name/ports\", async (c) => {\n const body = PortsRequest.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"ports: expected a list of box ports\");\n return c.json(await addPorts(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body.data), 201);\n });\n r.delete(\"/:name/ports\", async (c) => {\n const body = PortsRequest.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"ports: expected a list of box ports\");\n return c.json(await removePorts(parseRef(c.req.param(\"name\"), c.get(\"owner\")), body.data));\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.get(\"/:name/stats\", async (c) => c.json(await machineStats(parseRef(c.req.param(\"name\"), c.get(\"owner\")))));\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 * `kvbox vm top` (#67): a running box's own load, memory and disk, asked of kvbox-agent over vsock,\n * so it answers whatever the box did to its network. Read-only and unlocked: a box that stops\n * mid-question just fails this one answer.\n */\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { MachineStats } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { isNoAgent, isUnknownOp, stats } from \"./agent.js\";\nimport { getMachine, stateMessage } from \"./machines.js\";\nimport type { BoxRef } from \"./refs.js\";\n\n/** The guest is asked live; a busy one gets this long before the caller hears it did not answer. */\nconst STATS_REPLY_MS = 3_000;\n\nexport async function machineStats(ref: BoxRef, p: Paths = paths()): Promise<MachineStats> {\n const m = await getMachine(ref, p);\n if (m.status !== \"running\") throw new KvboxError(`${stateMessage(ref, m.status)}; only a running box can say how it is doing`);\n try {\n return { name: m.name, owner: m.owner, stats: await stats(p.machine(m.owner, m.name).vsock, STATS_REPLY_MS) };\n } catch (err) {\n // An image older than base v0.7.0 (an agent without \"stats\", or no agent at all): no numbers, not an error.\n if (isUnknownOp(err) || isNoAgent(err)) return { name: m.name, owner: m.owner, stats: null };\n throw err;\n }\n}\n","/**\n * What the usage_events ledger (db.ts) adds up to: one box (`kvbox vm usage <box>`) or every box of\n * an owner (`kvbox usage`, #41). The arithmetic is `computeUsage` in @kvbox/shared/usage, shared with\n * the control plane, which sums the same rows after pulling them (#42).\n */\nimport type { MachineUsage, UsageReport } from \"@kvbox/shared/api\";\nimport { paths, type Paths } from \"@kvbox/shared/paths\";\nimport { computeUsage, groupUsage, sumUsage } from \"@kvbox/shared/usage\";\nimport { loadConfig } from \"./config.js\";\nimport { usageEventsFor, usageEventsInScope } from \"./db.js\";\nimport { getMachine, listMachines } from \"./machines.js\";\nimport type { BoxRef, ListScope } from \"./refs.js\";\n\nexport { computeUsage, type UsageEvent, type UsageState, type UsageTotals, type UsageWindow } from \"@kvbox/shared/usage\";\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.\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 events = usageEventsFor(box.id, box.createdAt, p);\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 * Every box of the owners in `scope` over the window, removed ones included: the ledger keeps their\n * rows, and a name removed and made again is two boxes (two ids). Listing the live boxes first closes\n * any run whose Firecracker died, so the ledger is current. A box with no row inside the window is\n * left out: it did not exist then.\n */\nexport async function usageReport(scope: ListScope, window: { from: string; to: string }, p: Paths = paths()): Promise<UsageReport> {\n const cfg = await loadConfig(p);\n const live = new Map((await listMachines(scope, p)).map((m) => [m.id, m.status]));\n const boxes = groupUsage(usageEventsInScope(scope, window, p), window, cfg.pricing, live);\n return { window, boxes, totals: sumUsage(boxes, cfg.pricing) };\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(\"listScope\"))));\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 { withBoxLock } from \"./locks.js\";\nimport { inScope, parseRef, refKey, shown, type BoxRef, type ListScope } from \"./refs.js\";\nimport {\n listSnapshotRefs,\n readMachineMeta,\n readSnapshotMeta,\n vmAlive,\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(scope: ListScope, p: Paths = paths()): Promise<Snapshot[]> {\n const out: Snapshot[] = [];\n for (const ref of await listSnapshotRefs(p)) {\n if (!inScope(ref.owner, scope)) 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 ref = parseRef(req.box, owner);\n return withBoxLock(ref, () => snapshotBox(ref, req, owner, p));\n}\n\nasync function snapshotBox(ref: BoxRef, req: CreateSnapshotRequest, owner: string, p: Paths): Promise<Snapshot> {\n const box = await readBox(ref, p);\n if (!vmAlive(box)) {\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 since = box.memSnapshots ?? 0;\n // A diff is standalone right after boot, or once merged onto the previous image. Otherwise (a\n // lineage broken by an earlier failure) dump everything.\n const mode: \"Diff\" | \"Full\" = 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 = true; // 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 await rm(m.memBase, { force: true });\n await link(s.mem, m.memBase);\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","/**\n * The SSH CA on a host (#55). `POST /ssh/trust-ca` makes every cloud box trust a new CA, `GET\n * /ssh/cloud-ca` asks the joined control plane which CA that should be. Both exist on the Unix\n * socket only: adding a trusted CA to every box is the most powerful thing a host can do, so it\n * takes someone on the host itself, never the control plane (or whoever holds its token).\n */\nimport { Hono } from \"hono\";\nimport { TrustCaRequestSchema } from \"@kvbox/shared/api\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport type { CallerOptions, Env } from \"../caller.js\";\nimport { fetchCloudCa } from \"../core/controlPlane.js\";\nimport { trustCa } from \"../core/machines.js\";\n\nexport function sshRoutes(opts: CallerOptions = {}) {\n const r = new Hono<Env>();\n if (opts.controlPlane) {\n r.all(\"/*\", (c) => c.json({ error: \"trusting a CA is done on the host itself (kvbox server trust-ca there); the control plane cannot ask a host to\" }, 403));\n return r;\n }\n r.get(\"/cloud-ca\", async (c) => c.json(await fetchCloudCa()));\n r.post(\"/trust-ca\", async (c) => {\n const body = TrustCaRequestSchema.safeParse(await c.req.json().catch(() => ({})));\n if (!body.success) throw new KvboxError(\"trust-ca: expected the CA public key as publicKey\");\n return c.json(await trustCa(body.data.publicKey));\n });\n return r;\n}\n","/**\n * The usage ledger over HTTP. `GET /usage?since=&until=` is the host-wide report (#41) for the\n * caller's boxes. `GET /usage/events?after=&limit=` hands out raw ledger rows by id for a control\n * plane to pull (#42): over HTTPS only the caller's realm (or, with `X-Kvbox-Owner`, that one\n * owner) comes back, so the host owner's local boxes never leave the host; over the socket the\n * host owner gets every row.\n */\nimport { Hono } from \"hono\";\nimport { KvboxError } from \"@kvbox/shared/errors\";\nimport { usageWindow } from \"@kvbox/shared/usage\";\nimport type { CallerOptions, Env } from \"../caller.js\";\nimport { ledgerId, usageEventsAfter } from \"../core/db.js\";\nimport { usageReport } from \"../core/usage.js\";\n\n/** Rows per pull; the control plane keeps pulling while a page comes back full. */\nexport const PULL_LIMIT = 1000;\n\nexport function usageRoutes(opts: CallerOptions = {}) {\n const r = new Hono<Env>();\n r.get(\"/\", async (c) => {\n let window;\n try {\n window = usageWindow(c.req.query(\"since\"), c.req.query(\"until\"));\n } catch (err) {\n throw new KvboxError((err as Error).message);\n }\n return c.json(await usageReport(c.get(\"listScope\"), window));\n });\n r.get(\"/events\", async (c) => {\n const after = whole(c.req.query(\"after\") ?? \"0\", \"after\");\n const limit = Math.min(whole(c.req.query(\"limit\") ?? String(PULL_LIMIT), \"limit\") || PULL_LIMIT, PULL_LIMIT);\n // The socket app trusts its caller: the whole ledger. The HTTPS app's scope is its realm or the named owner.\n const scope = opts.controlPlane === undefined ? null : c.get(\"listScope\");\n const events = usageEventsAfter(after, limit, scope);\n return c.json({ ledger: ledgerId(), events, next: events.length === 0 ? after : events[events.length - 1]!.id });\n });\n return r;\n}\n\nfunction whole(value: string, name: string): number {\n const n = Number(value);\n if (!Number.isInteger(n) || n < 0) throw new KvboxError(`${name}: expected a whole number, got \"${value}\"`);\n return n;\n}\n"],"mappings":"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","names":["z","z","chmod","readFile","z","z","z","z","readFile","chmod","readFile","readFile","closeSync","existsSync","openSync","mkdir","readFile","writeFile","mkdir","readFile","writeFile","z","z","z","mkdir","readFile","writeFile","request","request","bootArgs","existsSync","writeFile","readFile","openSync","closeSync","m","mkdir","failure","stopMachine","startMachine","setSshKeys","report","pauseMachine","resumeMachine","hibernateMachine","wakeMachine","updateMachine","rescaleMachine","setMachine","addPorts","removePorts","destroyMachine","run","chmod","mkdir","rm","writeFile","z","z","join","mkdir","writeFile","chmod","rm","readFile","readFile","round","round","readFile","rm","writeFile","Hono","require","createHash","createHash","connect","request","request","connect","Hono","Hono","Hono","Hono","Hono","existsSync","link","mkdir","readdir","rename","rm","stat","NAME_RE","readdir","stat","existsSync","mkdir","failure","rm","link","rename","Hono","Hono","Hono","Hono","Hono","Hono","rm","writeFile","readFile","shutdown","recovery","relay"]}
|