@krovacloud/cli 0.6.5 → 0.6.7

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/index.js CHANGED
@@ -6,6 +6,7 @@ import { homedir } from "node:os";
6
6
  import { dirname, join } from "node:path";
7
7
  import { KrovaClient } from "@krovacloud/sdk";
8
8
  import { spawn } from "node:child_process";
9
+ import { isIP } from "node:net";
9
10
  import { createServer } from "node:http";
10
11
  import { verifyKrovaWebhookOrThrow } from "@krovacloud/webhook";
11
12
  const DEFAULT_CONTEXT_NAME = "default";
@@ -134,6 +135,21 @@ function maskKey(key) {
134
135
  function printJSON(value) {
135
136
  process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
136
137
  }
138
+ /**
139
+ * Where to connect for a TCP mapping: `host:port`.
140
+ *
141
+ * `host` is the Cube's OWN stable hostname, which survives migration to
142
+ * another server — not the server's hostname, which does not. Shared by
143
+ * `tcp list` and `tcp add` so the two can never disagree about how a connect
144
+ * target is spelled.
145
+ *
146
+ * Falls back to the bare port when the Cube has no host (no server assigned).
147
+ * Printing a port alone is honest about what is known; inventing a host, or
148
+ * printing `null:30000`, is not.
149
+ */
150
+ function mappingConnectTarget(mapping) {
151
+ return mapping.host ? `${mapping.host}:${mapping.hostPort}` : String(mapping.hostPort);
152
+ }
137
153
  function printTable(header, rows) {
138
154
  const widths = header.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? "").length)));
139
155
  const fmt = (cols) => cols.map((c, i) => (c ?? "").padEnd(widths[i] ?? 0)).join(" ").replace(/\s+$/, "");
@@ -964,6 +980,23 @@ function knownHostsHost(host, port) {
964
980
  function knownHostsPath() {
965
981
  return join(configDir(), "known_hosts");
966
982
  }
983
+ /** True for a DNS hostname (e.g. the Cube's stable SSH hostname), false for a
984
+ * bare IPv4/IPv6 address. */
985
+ function isHostname(host) {
986
+ return isIP(host) === 0;
987
+ }
988
+ /** True when `host:port` has no existing known_hosts pin yet — used to print a
989
+ * one-time note the first time we pin a Cube's hostname rather than its IP. */
990
+ function isUnpinned(host, port) {
991
+ const field = knownHostsHost(host, port);
992
+ let existing = "";
993
+ try {
994
+ existing = readFileSync(knownHostsPath(), "utf8");
995
+ } catch {
996
+ existing = "";
997
+ }
998
+ return !existing.split("\n").some((line) => line.split(/\s+/)[0] === field);
999
+ }
967
1000
  /** Pin the cube's host keys to ~/.config/krova/known_hosts (0600), pruning any
968
1001
  * stale line for the same host:port (rebuilt cubes can reuse an IP+DNAT port). */
969
1002
  function writeKnownHosts(info) {
@@ -1040,8 +1073,10 @@ function sshCommand() {
1040
1073
  validateSSHUser(info.user);
1041
1074
  if (info.port < 0 || info.port > 65535) throw new Error("invalid ssh port");
1042
1075
  let knownHosts = "";
1043
- if (info.hostKeys.length) knownHosts = writeKnownHosts(info);
1044
- else process.stderr.write("note: this server didn't provide host keysusing ssh trust-on-first-use (host-key checking stays on).\n");
1076
+ if (info.hostKeys.length) {
1077
+ if (isHostname(info.host) && isUnpinned(info.host, info.port)) process.stderr.write("note: this Cube now has a stable SSH hostname (it stays the same even if the Cube migrates to another server) pinning it is expected and only happens once.\n");
1078
+ knownHosts = writeKnownHosts(info);
1079
+ } else process.stderr.write("note: this server didn't provide host keys — using ssh trust-on-first-use (host-key checking stays on).\n");
1045
1080
  const args = buildSSHArgs(info, {
1046
1081
  identity: opts.identity,
1047
1082
  localFwd: opts.localForward,
@@ -1067,7 +1102,7 @@ function tcpCommand() {
1067
1102
  printTable([
1068
1103
  "ID",
1069
1104
  "CUBE PORT",
1070
- "HOST PORT",
1105
+ "CONNECT",
1071
1106
  "LABEL",
1072
1107
  "STATUS",
1073
1108
  "SSH",
@@ -1075,7 +1110,7 @@ function tcpCommand() {
1075
1110
  ], maps.map((m) => [
1076
1111
  m.id,
1077
1112
  String(m.cubePort),
1078
- String(m.hostPort),
1113
+ mappingConnectTarget(m),
1079
1114
  m.label ?? "",
1080
1115
  m.status,
1081
1116
  m.isSsh ? "yes" : "no",
@@ -1099,7 +1134,7 @@ function tcpCommand() {
1099
1134
  ...opts.udp === false ? { udpEnabled: false } : {}
1100
1135
  });
1101
1136
  if (rt.json) return printJSON(mapping);
1102
- process.stdout.write(`Mapped cube port ${mapping.cubePort} → host port ${mapping.hostPort} (${mapping.id})\n`);
1137
+ process.stdout.write(`Mapped cube port ${mapping.cubePort} → ${mappingConnectTarget(mapping)} (${mapping.id})\n`);
1103
1138
  });
1104
1139
  cmd.command("rm").argument("<cube>", "cube name or ID").argument("<mapping-id>", "the mapping ID (see `krova tcp list`)").description("remove a TCP port mapping").action(async (cubeRef, mappingId, _opts, c) => {
1105
1140
  const rt = getRuntime(c);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/lib/config.ts","../src/lib/output.ts","../src/lib/client.ts","../src/lib/runtime.ts","../src/lib/persist.ts","../src/commands/auth.ts","../src/commands/catalog.ts","../src/commands/context.ts","../src/lib/resolve.ts","../src/commands/cubes.ts","../src/commands/domains.ts","../src/commands/login.ts","../src/commands/snapshots.ts","../src/lib/ssh.ts","../src/commands/ssh.ts","../src/commands/tcp.ts","../src/commands/version.ts","../src/commands/webhooks.ts","../src/commands/whoami.ts","../src/index.ts"],"sourcesContent":["// Reads/writes ~/.config/krova/config.json in the EXACT shape the Go CLI used,\n// so existing configs keep working. Multi-context, with legacy single-key\n// migration. The file is always tightened to 0600 on save.\n\nimport { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport const DEFAULT_BASE_URL = \"https://krova.cloud/api/v1\";\nexport const DEFAULT_CONTEXT_NAME = \"default\";\n\nexport const ENV = {\n apiKey: \"KROVA_API_KEY\",\n spaceId: \"KROVA_SPACE_ID\",\n baseUrl: \"KROVA_BASE_URL\",\n context: \"KROVA_CONTEXT\",\n} as const;\n\nexport interface Context {\n name: string;\n apiKey?: string;\n spaceId?: string;\n spaceName?: string;\n baseUrl?: string;\n}\n\nexport interface Config {\n currentContext?: string;\n contexts?: Context[];\n // legacy (pre-context) fields — parsed then migrated into a \"default\" context\n apiKey?: string;\n spaceId?: string;\n baseUrl?: string;\n}\n\nexport function configDir(): string {\n const xdg = (process.env.XDG_CONFIG_HOME ?? \"\").trim();\n if (xdg) return join(xdg, \"krova\");\n return join(homedir(), \".config\", \"krova\");\n}\n\nexport function configPath(): string {\n return join(configDir(), \"config.json\");\n}\n\nexport function load(): Config {\n let cfg: Config = {};\n try {\n cfg = JSON.parse(readFileSync(configPath(), \"utf8\")) as Config;\n } catch {\n cfg = {};\n }\n return migrate(cfg);\n}\n\n// If only legacy fields are set, synthesize a \"default\" context from them.\nfunction migrate(cfg: Config): Config {\n if ((cfg.apiKey ?? \"\").trim() && (!cfg.contexts || cfg.contexts.length === 0)) {\n cfg.contexts = [\n {\n name: DEFAULT_CONTEXT_NAME,\n apiKey: cfg.apiKey,\n spaceId: cfg.spaceId,\n baseUrl: cfg.baseUrl,\n },\n ];\n cfg.currentContext = DEFAULT_CONTEXT_NAME;\n }\n cfg.apiKey = undefined;\n cfg.spaceId = undefined;\n cfg.baseUrl = undefined;\n return cfg;\n}\n\nexport function save(cfg: Config): void {\n const path = configPath();\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n // clear legacy fields; only serialize non-empty keys (matches Go omitempty)\n const clean: Config = {};\n if (cfg.currentContext) clean.currentContext = cfg.currentContext;\n if (cfg.contexts && cfg.contexts.length) {\n clean.contexts = cfg.contexts.map((c) => {\n const o: Context = { name: c.name };\n if (c.apiKey) o.apiKey = c.apiKey;\n if (c.spaceId) o.spaceId = c.spaceId;\n if (c.spaceName) o.spaceName = c.spaceName;\n if (c.baseUrl) o.baseUrl = c.baseUrl;\n return o;\n });\n }\n writeFileSync(path, `${JSON.stringify(clean, null, 2)}\\n`, { mode: 0o600 });\n // writeFileSync only applies mode on creation — re-tighten an existing file.\n chmodSync(path, 0o600);\n}\n\nexport function find(cfg: Config, name: string): Context | undefined {\n return (cfg.contexts ?? []).find((c) => c.name === name);\n}\n\n/** The active context: `override` (e.g. --context) wins, else currentContext. */\nexport function current(cfg: Config, override?: string): Context | undefined {\n const name = (override ?? \"\").trim() || (cfg.currentContext ?? \"\").trim();\n if (!name) return undefined;\n return find(cfg, name);\n}\n\n/** Merge-in a context: only NON-EMPTY apiKey/spaceId/spaceName/baseUrl\n * overwrite an existing value. This keeps a transient per-command override\n * (e.g. a one-off `--base-url`) from being silently persisted over the\n * context's real base URL. First-ever context becomes current. Returns it. */\nexport function upsert(cfg: Config, incoming: Context): Context {\n cfg.contexts ??= [];\n let ctx = cfg.contexts.find((c) => c.name === incoming.name);\n if (!ctx) {\n ctx = { name: incoming.name };\n cfg.contexts.push(ctx);\n if (!cfg.currentContext) cfg.currentContext = ctx.name;\n }\n if ((incoming.apiKey ?? \"\").trim()) ctx.apiKey = incoming.apiKey;\n if ((incoming.spaceId ?? \"\").trim()) ctx.spaceId = incoming.spaceId;\n if ((incoming.spaceName ?? \"\").trim()) ctx.spaceName = incoming.spaceName;\n if ((incoming.baseUrl ?? \"\").trim()) ctx.baseUrl = incoming.baseUrl;\n return ctx;\n}\n\nexport function remove(cfg: Config, name: string): boolean {\n const before = (cfg.contexts ?? []).length;\n cfg.contexts = (cfg.contexts ?? []).filter((c) => c.name !== name);\n if (cfg.contexts.length === before) return false;\n if (cfg.currentContext === name) {\n cfg.currentContext = cfg.contexts[0]?.name ?? \"\";\n }\n return true;\n}\n\nexport type Source = \"flag\" | \"env\" | \"context\" | \"\";\n\nexport interface Resolved {\n apiKey: string;\n spaceId: string;\n baseUrl: string;\n apiKeySource: Source;\n spaceIdSource: Source;\n contextName: string;\n}\n\nexport interface GlobalFlags {\n apiKey?: string;\n space?: string;\n baseUrl?: string;\n context?: string;\n}\n\n/** Resolve credentials with precedence flag > env > active context. */\nexport function resolve(cfg: Config, flags: GlobalFlags): Resolved {\n const ctx = current(cfg, (flags.context ?? \"\").trim() || process.env[ENV.context]);\n const pick = (\n flag: string | undefined,\n env: string | undefined,\n ctxVal: string | undefined\n ): [string, Source] => {\n if ((flag ?? \"\").trim()) return [flag as string, \"flag\"];\n if ((env ?? \"\").trim()) return [env as string, \"env\"];\n if ((ctxVal ?? \"\").trim()) return [ctxVal as string, \"context\"];\n return [\"\", \"\"];\n };\n const [apiKey, apiKeySource] = pick(flags.apiKey, process.env[ENV.apiKey], ctx?.apiKey);\n const [spaceId, spaceIdSource] = pick(flags.space, process.env[ENV.spaceId], ctx?.spaceId);\n const [baseUrlRaw] = pick(flags.baseUrl, process.env[ENV.baseUrl], ctx?.baseUrl);\n return {\n apiKey,\n spaceId,\n baseUrl: baseUrlRaw || DEFAULT_BASE_URL,\n apiKeySource,\n spaceIdSource,\n contextName: ctx?.name ?? \"\",\n };\n}\n\nexport function sanitizeContextName(name: string): string {\n return name.trim().toLowerCase().replace(/\\s+/g, \"-\");\n}\n\nexport function maskKey(key: string): string {\n if (!key) return \"\";\n if (key.length <= 8) return \"****\";\n return `${key.slice(0, 6)}…${key.slice(-4)}`;\n}\n","export function printJSON(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nexport function printTable(header: string[], rows: string[][]): void {\n const widths = header.map((h, i) =>\n Math.max(h.length, ...rows.map((r) => (r[i] ?? \"\").length))\n );\n const fmt = (cols: string[]) =>\n cols\n .map((c, i) => (c ?? \"\").padEnd(widths[i] ?? 0))\n .join(\" \")\n .replace(/\\s+$/, \"\");\n process.stdout.write(`${fmt(header)}\\n`);\n for (const r of rows) process.stdout.write(`${fmt(r)}\\n`);\n}\n\nexport function printKeyValue(pairs: Array<[string, string]>): void {\n const w = Math.max(0, ...pairs.map(([k]) => k.length));\n for (const [k, v] of pairs) {\n process.stdout.write(`${k.padEnd(w)} ${v}\\n`);\n }\n}\n","import { KrovaClient } from \"@krovacloud/sdk\";\n\nimport type { Resolved } from \"./config.js\";\n\n/** Build the SDK client, or throw the same message the Go CLI used. */\nexport function makeClient(res: Resolved): KrovaClient {\n if (!res.apiKey) {\n throw new Error(\n \"no API key found: run `krova auth login`, set KROVA_API_KEY, or pass --api-key\"\n );\n }\n return new KrovaClient({ apiKey: res.apiKey, baseUrl: res.baseUrl });\n}\n\n/** Raw JSON request for endpoints the SDK doesn't cover:\n * GET /space, GET .../ssh, POST /auth/cli/start, POST /auth/cli/poll. */\nexport async function rawRequest<T>(opts: {\n method: string;\n baseUrl: string;\n path: string;\n apiKey?: string;\n body?: unknown;\n timeoutMs: number;\n}): Promise<{ status: number; data: T | undefined }> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs);\n try {\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (opts.apiKey) headers[\"X-API-KEY\"] = opts.apiKey;\n if (opts.body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n const res = await fetch(`${opts.baseUrl.replace(/\\/+$/, \"\")}${opts.path}`, {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n redirect: \"manual\",\n signal: controller.signal,\n });\n let data: T | undefined;\n const text = await res.text();\n if (text) {\n try {\n data = JSON.parse(text) as T;\n } catch {\n data = undefined;\n }\n }\n return { status: res.status, data };\n } finally {\n clearTimeout(timer);\n }\n}\n","import type { Command } from \"commander\";\n\nimport {\n type Config,\n type GlobalFlags,\n type Resolved,\n load,\n resolve,\n save,\n upsert,\n} from \"./config.js\";\nimport { makeClient, rawRequest } from \"./client.js\";\n\n/** Parse a Go-style duration (\"30s\", \"500ms\", \"2m\", \"1h\") to ms. Non-positive\n * or unparseable floors to 30s (matches the Go requestTimeout behavior). */\nexport function parseDuration(input: string | undefined): number {\n const s = (input ?? \"\").trim();\n if (!s) return 30_000;\n let total = 0;\n const re = /(\\d+(?:\\.\\d+)?)(ms|s|m|h)/g;\n let m: RegExpExecArray | null = re.exec(s);\n let matched = false;\n while (m) {\n matched = true;\n const n = Number(m[1]);\n const unit = m[2];\n total += unit === \"ms\" ? n : unit === \"s\" ? n * 1000 : unit === \"m\" ? n * 60_000 : n * 3_600_000;\n m = re.exec(s);\n }\n if (!matched) {\n const n = Number(s);\n if (Number.isFinite(n)) total = n * 1000; // bare number = seconds\n }\n return total > 0 ? total : 30_000;\n}\n\nexport interface Runtime {\n flags: GlobalFlags;\n cfg: Config;\n res: Resolved;\n json: boolean;\n timeoutMs: number;\n}\n\nexport function getRuntime(cmd: Command): Runtime {\n const opts = cmd.optsWithGlobals() as Record<string, unknown>;\n const flags: GlobalFlags = {\n apiKey: opts.apiKey as string | undefined,\n space: opts.space as string | undefined,\n baseUrl: opts.baseUrl as string | undefined,\n context: opts.context as string | undefined,\n };\n const cfg = load();\n const res = resolve(cfg, flags);\n return {\n flags,\n cfg,\n res,\n json: Boolean(opts.json),\n timeoutMs: parseDuration(opts.timeout as string | undefined),\n };\n}\n\nexport interface SpaceInfo {\n id: string;\n name?: string;\n slug?: string;\n}\n\n/**\n * The outcome of actually asking the server whether a key works.\n *\n * A stored key is NOT a working key: it can be revoked server-side at any\n * time, and the local config has no way to know. Every caller that wants to\n * report on credentials must distinguish \"rejected\" from \"couldn't reach the\n * server\" — collapsing either into a plain boolean is what made `auth status`\n * print \"Authenticated: yes\" for a key the API answers 401 to.\n */\nexport type AuthProbe =\n /** The server accepted the key and told us which space it belongs to. */\n | { state: \"valid\"; space: SpaceInfo }\n /** The key is absent locally — nothing to check. */\n | { state: \"missing\" }\n /** The server actively rejected the key (revoked, deleted, wrong env). */\n | { state: \"rejected\"; status: number }\n /** Endpoint absent (older server) — the key may still be fine. */\n | { state: \"unsupported\" }\n /** Network/DNS/timeout — says nothing about the key's validity. */\n | { state: \"unreachable\"; error: string };\n\n/** Ask the server whether `apiKey` is actually accepted. Never throws. */\nexport async function probeAuth(\n baseUrl: string,\n apiKey: string,\n timeoutMs: number\n): Promise<AuthProbe> {\n if (!apiKey) return { state: \"missing\" };\n try {\n const { status, data } = await rawRequest<SpaceInfo>({\n method: \"GET\",\n baseUrl,\n path: \"/space\",\n apiKey,\n timeoutMs,\n });\n if (status === 200 && data?.id) return { state: \"valid\", space: data };\n if (status === 401 || status === 403) return { state: \"rejected\", status };\n if (status === 404) return { state: \"unsupported\" };\n return { state: \"unreachable\", error: `HTTP ${status}` };\n } catch (err) {\n return {\n state: \"unreachable\",\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/** Resolve the active space id: explicit value wins, else auto-detect via\n * GET /space (and cache it into the current context). */\nexport async function resolveSpace(rt: Runtime): Promise<string> {\n if (rt.res.spaceId) return rt.res.spaceId;\n const { status, data } = await rawRequest<SpaceInfo>({\n method: \"GET\",\n baseUrl: rt.res.baseUrl,\n path: \"/space\",\n apiKey: rt.res.apiKey,\n timeoutMs: rt.timeoutMs,\n });\n if (status === 200 && data?.id) {\n // Best-effort cache of the resolved space into the current named context.\n // Deliberately does NOT write baseUrl: rt.res.baseUrl already folds in a\n // one-off --base-url / KROVA_BASE_URL override, and persisting that here\n // would permanently rewrite the context's real base URL from a transient\n // flag. Only the space id/name are cached.\n if (rt.res.contextName) {\n upsert(rt.cfg, {\n name: rt.res.contextName,\n spaceId: data.id,\n spaceName: data.name,\n });\n try {\n save(rt.cfg);\n } catch {\n /* non-fatal */\n }\n }\n return data.id;\n }\n if (status === 404) {\n throw new Error(\n \"couldn't auto-detect your space (the server doesn't support it yet) — pass --space, set KROVA_SPACE_ID, or run `krova login`\"\n );\n }\n if (status === 401 || status === 403) {\n throw new Error(`auto-detect space failed: the API key was rejected (HTTP ${status})`);\n }\n throw new Error(`auto-detect space failed (HTTP ${status})`);\n}\n\nexport { makeClient };\n","import { DEFAULT_CONTEXT_NAME, load, sanitizeContextName, save, upsert } from \"./config.js\";\nimport { probeAuth } from \"./runtime.js\";\n\n/** Save + switch to a context after a login. Best-effort space lookup fills in\n * spaceId/spaceName and a nicer context name. Mirrors the Go persistLogin. */\nexport async function persistLogin(input: {\n apiKey: string;\n baseUrl: string;\n spaceId?: string;\n ctxName?: string;\n timeoutMs: number;\n}): Promise<{ ctxName: string; spaceName: string }> {\n const cfg = load();\n let spaceId = input.spaceId ?? \"\";\n let spaceName = \"\";\n let derivedName = \"\";\n\n const probe = await probeAuth(input.baseUrl, input.apiKey, input.timeoutMs);\n const sp = probe.state === \"valid\" ? probe.space : null;\n if (sp) {\n // Prefer an explicitly-provided --space over the fetched id; only fall back\n // to the resolved space when the caller didn't pin one.\n if (!spaceId) spaceId = sp.id;\n spaceName = sp.name ?? \"\";\n derivedName = (sp.slug || sp.name || \"\").trim();\n }\n\n let name = (input.ctxName ?? \"\").trim();\n if (!name) name = derivedName || DEFAULT_CONTEXT_NAME;\n name = sanitizeContextName(name);\n\n const cur = upsert(cfg, {\n name,\n apiKey: input.apiKey,\n spaceId,\n spaceName,\n baseUrl: input.baseUrl,\n });\n cfg.currentContext = cur.name; // login always switches current\n save(cfg);\n return { ctxName: cur.name, spaceName: cur.spaceName ?? \"\" };\n}\n","import { Command } from \"commander\";\n\nimport { configPath, maskKey } from \"../lib/config.js\";\nimport { printJSON, printKeyValue } from \"../lib/output.js\";\nimport { persistLogin } from \"../lib/persist.js\";\nimport { getRuntime, probeAuth } from \"../lib/runtime.js\";\n\n/** Prompt for an API key. Hidden echo when stdin is a TTY. */\nfunction promptAPIKey(): Promise<string> {\n return new Promise((resolve, reject) => {\n process.stdout.write(\"Krova API key: \");\n const stdin = process.stdin;\n const tty = Boolean(stdin.isTTY);\n let buf = \"\";\n if (tty) stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n const finish = (fn: () => void) => {\n if (tty) stdin.setRawMode(false);\n stdin.pause();\n stdin.removeListener(\"data\", onData);\n fn();\n };\n const onData = (ch: string) => {\n for (const c of ch) {\n const code = c.charCodeAt(0);\n if (code === 10 || code === 13) {\n finish(() => {\n process.stdout.write(\"\\n\");\n resolve(buf.trim());\n });\n return;\n }\n if (code === 3) {\n finish(() => reject(new Error(\"cancelled\")));\n return;\n }\n if (code === 127 || code === 8) {\n buf = buf.slice(0, -1);\n } else if (code >= 32) {\n buf += c;\n }\n }\n };\n stdin.on(\"data\", onData);\n });\n}\n\nexport function authCommand(): Command {\n const auth = new Command(\"auth\").description(\"manage Krova Cloud credentials\");\n\n auth\n .command(\"login\")\n .description(\"log in by pasting an API key\")\n .option(\"--api-key <key>\", \"API key (else you'll be prompted)\")\n .option(\"--space <id>\", \"Space ID to store with the key\")\n .option(\"--context <name>\", \"name for the saved context\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n let key = (opts.apiKey as string) || rt.flags.apiKey || \"\";\n if (!key.trim()) key = await promptAPIKey();\n if (!key.trim()) throw new Error(\"no API key provided\");\n const { ctxName, spaceName } = await persistLogin({\n apiKey: key.trim(),\n baseUrl: rt.res.baseUrl,\n spaceId: opts.space as string | undefined,\n ctxName: opts.context as string | undefined,\n timeoutMs: rt.timeoutMs,\n });\n process.stdout.write(`Logged in. Saved context \"${ctxName}\" to ${configPath()}\\n`);\n if (spaceName) process.stdout.write(`Space: ${spaceName}\\n`);\n });\n\n auth\n .command(\"status\")\n .description(\"show the resolved credentials and verify them against the API\")\n .option(\"--offline\", \"skip the live check; only report what's stored locally\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const offline = Boolean(opts.offline);\n\n // A STORED key is not a WORKING key — it can be revoked server-side at\n // any time. Reporting local presence as \"Authenticated: yes\" sends the\n // user hunting for a config problem that isn't there, so unless they ask\n // for --offline we go and ask the API.\n const probe = offline\n ? ({ state: \"missing\" } as const)\n : await probeAuth(rt.res.baseUrl, rt.res.apiKey, rt.timeoutMs);\n\n const hasKey = Boolean(rt.res.apiKey);\n const authenticated = offline ? hasKey : probe.state === \"valid\";\n\n const detail =\n offline || !hasKey\n ? \"\"\n : probe.state === \"rejected\"\n ? `the API rejected this key (HTTP ${probe.status}) — it was revoked or belongs to another environment; run \\`krova login\\``\n : probe.state === \"unreachable\"\n ? `could not reach ${rt.res.baseUrl} (${probe.error}) — the key was NOT verified`\n : probe.state === \"unsupported\"\n ? \"this server has no /space endpoint, so the key could not be verified\"\n : \"\";\n\n // Live space beats the cached copy: a stale spaceId in the config is\n // exactly the kind of drift this command exists to surface.\n const spaceId = probe.state === \"valid\" ? probe.space.id : rt.res.spaceId;\n\n if (rt.json) {\n return printJSON({\n authenticated,\n verified: probe.state === \"valid\",\n checkState: offline ? \"skipped\" : probe.state,\n detail: detail || undefined,\n context: rt.res.contextName,\n apiKeySource: rt.res.apiKeySource,\n apiKeyMasked: maskKey(rt.res.apiKey),\n spaceId,\n spaceSource: rt.res.spaceIdSource,\n baseUrl: rt.res.baseUrl,\n configPath: configPath(),\n });\n }\n\n const label = !hasKey\n ? \"no (no API key found)\"\n : offline\n ? \"not checked (--offline; a key is stored)\"\n : probe.state === \"valid\"\n ? \"yes (verified against the API)\"\n : probe.state === \"rejected\"\n ? \"NO — key rejected by the API\"\n : \"unknown (could not verify)\";\n\n printKeyValue([\n [\"Authenticated\", label],\n [\"Context\", rt.res.contextName || \"—\"],\n [\"API key\", rt.res.apiKey ? `${maskKey(rt.res.apiKey)} (${rt.res.apiKeySource})` : \"—\"],\n [\"Space ID\", spaceId ? `${spaceId} (${rt.res.spaceIdSource})` : \"—\"],\n [\"Base URL\", rt.res.baseUrl],\n [\"Config\", configPath()],\n ]);\n if (detail) process.stdout.write(`\\n${detail}\\n`);\n\n // Exit non-zero only when the credentials are KNOWN to be unusable, so\n // scripts and CI can gate on `krova auth status` (matches\n // `gh auth status`). An unreachable or too-old API says nothing about\n // the key, so those stay 0 rather than failing a build over a blip.\n if (!hasKey || probe.state === \"rejected\") process.exitCode = 1;\n });\n\n return auth;\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printKeyValue, printTable } from \"../lib/output.js\";\nimport { getRuntime, makeClient } from \"../lib/runtime.js\";\n\nfunction fmtVal(v: unknown): string {\n if (v === null || v === undefined) return \"\";\n if (typeof v === \"object\") return JSON.stringify(v);\n return String(v);\n}\n\n/** Flatten a top-level object field one level deep into `key.subkey` rows, so\n * nested objects (e.g. pricing's `rates`) render as readable key/value pairs\n * instead of a JSON blob. Exported for testing. */\nexport function flattenRows(entries: [string, unknown][]): [string, string][] {\n const rows: [string, string][] = [];\n for (const [k, v] of entries) {\n if (v && typeof v === \"object\" && !Array.isArray(v)) {\n for (const [sk, sv] of Object.entries(v as Record<string, unknown>)) {\n rows.push([`${k}.${sk}`, fmtVal(sv)]);\n }\n } else {\n rows.push([k, fmtVal(v)]);\n }\n }\n return rows;\n}\n\n/**\n * Render a catalog payload as text. If the payload has an array field, print any\n * scalar/object fields first (as key/value) and then the array as a table —\n * otherwise the non-array fields are silently dropped. This matters for\n * `pricing`, whose per-resource `rates` (the actual hourly prices), `currency`,\n * and `note` sit alongside the `tiers` array. `regions`/`images` have only the\n * array, so their output is unchanged.\n */\nfunction renderCatalog(obj: Record<string, unknown>): void {\n const arrKey = Object.keys(obj).find((k) => Array.isArray(obj[k]));\n if (!arrKey) {\n printKeyValue(flattenRows(Object.entries(obj)));\n return;\n }\n const rest = flattenRows(Object.entries(obj).filter(([k]) => k !== arrKey));\n if (rest.length) printKeyValue(rest);\n const arr = (obj[arrKey] as Record<string, unknown>[]) ?? [];\n const cols = [...new Set(arr.flatMap((o) => Object.keys(o)))];\n printTable(\n cols.map((c) => c.toUpperCase()),\n arr.map((o) => cols.map((c) => fmtVal(o[c])))\n );\n}\n\nfunction catalogCmd(\n name: string,\n desc: string,\n fetch: (c: ReturnType<typeof makeClient>) => Promise<Record<string, unknown>>\n): Command {\n return new Command(name)\n .description(desc)\n .action(async (_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const data = await fetch(client);\n if (rt.json) return printJSON(data);\n renderCatalog(data);\n });\n}\n\nexport function regionsCommand(): Command {\n return catalogCmd(\"regions\", \"list regions with available capacity\", (c) =>\n c.catalog.regions() as Promise<Record<string, unknown>>\n );\n}\nexport function imagesCommand(): Command {\n return catalogCmd(\"images\", \"list available OS images\", (c) =>\n c.catalog.images() as Promise<Record<string, unknown>>\n );\n}\nexport function pricingCommand(): Command {\n return catalogCmd(\"pricing\", \"show per-resource hourly pricing\", (c) =>\n c.catalog.pricing() as Promise<Record<string, unknown>>\n );\n}\n","import { Command } from \"commander\";\n\nimport { load, maskKey, remove, save } from \"../lib/config.js\";\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\nexport function contextCommand(): Command {\n const ctx = new Command(\"context\")\n .aliases([\"ctx\", \"contexts\"])\n .description(\"manage named credential contexts (like kubectl/aws profiles)\");\n\n ctx\n .command(\"list\")\n .aliases([\"ls\"])\n .description(\"list all contexts\")\n .action((_opts, cmd: Command) => {\n const { json } = getRuntime(cmd);\n const cfg = load();\n if (json) {\n return printJSON({\n currentContext: cfg.currentContext ?? \"\",\n contexts: (cfg.contexts ?? []).map((c) => ({\n name: c.name,\n apiKey: maskKey(c.apiKey ?? \"\"),\n spaceId: c.spaceId ?? \"\",\n spaceName: c.spaceName ?? \"\",\n baseUrl: c.baseUrl ?? \"\",\n })),\n });\n }\n printTable(\n [\"CURRENT\", \"NAME\", \"SPACE\", \"SPACE ID\", \"BASE URL\"],\n (cfg.contexts ?? []).map((c) => [\n c.name === cfg.currentContext ? \"*\" : \"\",\n c.name,\n c.spaceName ?? \"\",\n c.spaceId ?? \"\",\n c.baseUrl ?? \"\",\n ])\n );\n });\n\n ctx\n .command(\"current\")\n .description(\"print the current context name\")\n .action(() => {\n const cfg = load();\n if (!cfg.currentContext) throw new Error(\"no current context set\");\n process.stdout.write(`${cfg.currentContext}\\n`);\n });\n\n ctx\n .command(\"use\")\n .argument(\"<name>\", \"context name\")\n .description(\"switch the current context\")\n .action((name: string) => {\n const cfg = load();\n if (!(cfg.contexts ?? []).some((c) => c.name === name)) {\n throw new Error(`no context named \"${name}\"`);\n }\n cfg.currentContext = name;\n save(cfg);\n process.stdout.write(`Switched to context ${name}\\n`);\n });\n\n ctx\n .command(\"rename\")\n .argument(\"<old>\", \"current name\")\n .argument(\"<new>\", \"new name\")\n .description(\"rename a context\")\n .action((oldName: string, newName: string) => {\n const cfg = load();\n if (!newName.trim()) throw new Error(\"new name must not be empty\");\n const c = (cfg.contexts ?? []).find((x) => x.name === oldName);\n if (!c) throw new Error(`no context named \"${oldName}\"`);\n if ((cfg.contexts ?? []).some((x) => x.name === newName)) {\n throw new Error(`a context named \"${newName}\" already exists`);\n }\n c.name = newName;\n if (cfg.currentContext === oldName) cfg.currentContext = newName;\n save(cfg);\n process.stdout.write(`Renamed ${oldName} → ${newName}\\n`);\n });\n\n ctx\n .command(\"delete\")\n .aliases([\"rm\"])\n .argument(\"<name>\", \"context name\")\n .description(\"delete a context\")\n .action((name: string) => {\n const cfg = load();\n if (!remove(cfg, name)) throw new Error(`no context named \"${name}\"`);\n save(cfg);\n process.stdout.write(`Deleted context ${name}\\n`);\n });\n\n return ctx;\n}\n","import type { KrovaClient } from \"@krovacloud/sdk\";\n\n/** Resolve a cube name-or-id to an id (parity with the Go resolveCube):\n * exact id wins; else exactly one exact name match; else a clear error. */\nexport async function resolveCube(\n client: KrovaClient,\n spaceId: string,\n ref: string\n): Promise<string> {\n const { cubes } = await client.cubes.list(spaceId);\n if (cubes.some((c) => c.id === ref)) return ref;\n const byName = cubes.filter((c) => c.name === ref);\n if (byName.length === 1) return byName[0]!.id;\n if (byName.length === 0) {\n throw new Error(\n `no cube named or with ID \"${ref}\" in this space (see \\`krova cubes list\\`)`\n );\n }\n const ids = byName.map((c) => c.id).join(\", \");\n throw new Error(\n `cube name \"${ref}\" is ambiguous: it matches ${byName.length} cubes (${ids}) — use the cube ID instead`\n );\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printKeyValue, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\nfunction listCmd(): Command {\n return new Command(\"list\")\n .aliases([\"ls\"])\n .description(\"list Cubes in the space\")\n .action(async (_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const { cubes } = await client.cubes.list(space);\n if (rt.json) return printJSON(cubes);\n printTable(\n [\"ID\", \"NAME\", \"STATE\", \"VCPU\", \"RAM(GB)\", \"DISK(GB)\", \"IMAGE\", \"IPV4\"],\n cubes.map((c) => [\n c.id,\n c.name,\n c.state,\n String(c.resources.vcpu),\n String(c.resources.ramGb),\n String(c.resources.diskGb),\n c.image,\n c.publicIpv4 ?? \"—\",\n ])\n );\n });\n}\n\nfunction getCmd(): Command {\n return new Command(\"get\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"show a single Cube\")\n .action(async (cubeRef: string, _opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const cube = await client.cubes.get(space, id);\n if (rt.json) return printJSON(cube);\n printKeyValue([\n [\"ID\", cube.id],\n [\"Name\", cube.name],\n [\"State\", cube.state],\n [\"Image\", cube.image],\n [\"vCPU\", String(cube.resources.vcpu)],\n [\"RAM (GB)\", String(cube.resources.ramGb)],\n [\"Disk (GB)\", String(cube.resources.diskGb)],\n [\"Public IPv4\", cube.publicIpv4 ?? \"—\"],\n [\"Cost/hour\", `$${cube.costPerHour}`],\n ]);\n });\n}\n\nfunction createCmd(): Command {\n return new Command(\"create\")\n .description(\"provision a new Cube\")\n .requiredOption(\"--name <name>\", \"cube name\")\n .requiredOption(\"--image <slug>\", \"OS image slug (see `krova images`)\")\n .requiredOption(\"--ssh-key <key>\", \"SSH public key written to authorized_keys\")\n .option(\"--vcpu <n>\", \"number of vCPUs\", \"1\")\n .option(\"--ram <gb>\", \"RAM in GB\", \"1\")\n .option(\"--disk <gb>\", \"disk size in GB\", \"10\")\n .option(\"--region <slug>\", \"region slug (see `krova regions`)\")\n .option(\"--user-data <script>\", \"cloud-init script\")\n .option(\"--idempotency-key <key>\", \"idempotency key (24h dedupe)\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n // Validate resources client-side so bad input fails with a clear message\n // rather than being coerced to NaN → JSON null → a generic server 400.\n const posInt = (flag: string, raw: string): number => {\n const n = Number(raw);\n if (!Number.isInteger(n) || n <= 0) {\n throw new Error(`--${flag} must be a positive integer (got \"${raw}\").`);\n }\n return n;\n };\n const body: Record<string, unknown> = {\n name: opts.name,\n image: opts.image,\n sshPublicKey: opts.sshKey,\n resources: {\n vcpu: posInt(\"vcpu\", opts.vcpu),\n ramGb: posInt(\"ram\", opts.ram),\n diskGb: posInt(\"disk\", opts.disk),\n },\n };\n if (opts.region) body.region = opts.region;\n if (opts.userData) body.userData = opts.userData;\n const cube = await client.cubes.create(\n space,\n body as never,\n opts.idempotencyKey ? { idempotencyKey: opts.idempotencyKey } : undefined\n );\n if (rt.json) return printJSON(cube);\n process.stdout.write(`Created cube ${cube.id} (${cube.state})\\n`);\n });\n}\n\nfunction actionCmd(\n name: string,\n past: string,\n fn: (c: ReturnType<typeof makeClient>[\"cubes\"], space: string, id: string) => Promise<unknown>\n): Command {\n return new Command(name)\n .argument(\"<cube>\", \"cube name or ID\")\n .description(`${name} a Cube`)\n .action(async (cubeRef: string, _opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await fn(client.cubes, space, id);\n if (rt.json) return printJSON({ id, result: past });\n process.stdout.write(`${past} cube ${id}\\n`);\n });\n}\n\nfunction restartCmd(): Command {\n return new Command(\"restart\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"restart a Cube (cold restart — picks up a refreshed kernel)\")\n .action(async (cubeRef: string, _opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.cubes.restart(space, id);\n if (rt.json) return printJSON({ id, result: \"Restarting\" });\n // Say COLD explicitly. A `reboot` from inside the Cube looks equivalent\n // but cannot change the kernel — Firecracker treats a guest reboot as a\n // shutdown and the kernel comes from the host.\n process.stdout.write(\n `Restarting cube ${id} (cold restart — disk state is preserved)\\n`,\n );\n });\n}\n\nfunction sshPortCmd(): Command {\n return new Command(\"ssh-port\")\n .argument(\"<cube>\", \"cube name or ID\")\n .requiredOption(\n \"--port <n>\",\n \"the port INSIDE the Cube that sshd listens on (default 22)\",\n )\n .description(\"change the in-Cube port that SSH is forwarded to (not the host port)\")\n .action(async (cubeRef: string, opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const cubePort = Number(opts.port);\n if (!Number.isInteger(cubePort) || cubePort < 1 || cubePort > 65535) {\n throw new Error(\"--port must be an integer between 1 and 65535\");\n }\n await client.cubes.update(space, id, { cubePort } as never);\n if (rt.json) return printJSON({ id, cubePort });\n // Be explicit about WHICH side changed. The host port is assigned by\n // Krova and is not affected by this call, so pointing this at a port\n // nothing is listening on inside the Cube silently breaks SSH access.\n process.stdout.write(\n `Cube ${id}: SSH now forwarded to in-Cube port ${cubePort}.\\n` +\n (cubePort === 22\n ? \"\"\n : `Warning: sshd inside the Cube must be listening on ${cubePort}, ` +\n \"or SSH will stop working. The default is 22.\\n\"),\n );\n });\n}\n\nexport function cubesCommand(): Command {\n const cubes = new Command(\"cubes\").description(\"manage Cubes (Firecracker microVMs)\");\n cubes.addCommand(listCmd());\n cubes.addCommand(getCmd());\n cubes.addCommand(createCmd());\n cubes.addCommand(\n actionCmd(\"power-off\", \"Powering off\", (c, s, id) => c.powerOff(s, id)),\n );\n cubes.addCommand(actionCmd(\"wake\", \"Starting\", (c, s, id) => c.wake(s, id)));\n cubes.addCommand(actionCmd(\"delete\", \"Deleting\", (c, s, id) => c.delete(s, id)));\n cubes.addCommand(restartCmd());\n cubes.addCommand(sshPortCmd());\n return cubes;\n}\n\n// `list` and `get` are also mounted at the root (parity with the Go CLI).\nexport const rootListCommand = listCmd;\nexport const rootGetCommand = getCmd;\n","import { Command } from \"commander\";\n\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\n/**\n * Narrow a `--origin-scheme` / positional scheme to the two the API accepts.\n * Returns undefined when the flag was omitted, so callers can leave the field\n * off the request entirely rather than sending an explicit default.\n */\nexport function parseOriginScheme(value: unknown): \"http\" | \"https\" | undefined {\n if (value === undefined || value === null || value === \"\") return undefined;\n if (value === \"http\" || value === \"https\") return value;\n throw new Error(`--origin-scheme must be \"http\" or \"https\" (got \"${String(value)}\").`);\n}\n\ntype PrintableRecord = {\n type: string;\n host: string;\n value: string;\n note?: string | null;\n mustBeGrey?: boolean;\n state?: string;\n detail?: string;\n};\n\n/** How each live state reads on a terminal. */\nconst STATE_LABEL: Record<string, string> = {\n found: \"found\",\n // ⛔ NOT \"failed\". Before you publish a record, absent is the expected state.\n missing: \"not added yet\",\n mismatch: \"needs a change\",\n // ⛔ OUR lookup failed. Never phrased as the user's mistake.\n unknown: \"couldn't check\",\n};\n\n/**\n * Print the DNS records a domain needs.\n *\n * Both the host AND the value, because a record cannot be created from the\n * value alone — which is what made the old guidance impossible to act on.\n */\nfunction printRecords(records: PrintableRecord[], withState = false): void {\n if (records.length === 0) return;\n process.stdout.write(\"\\nDNS records to publish:\\n\");\n for (const r of records) {\n const state = withState && r.state ? ` [${STATE_LABEL[r.state] ?? r.state}]` : \"\";\n process.stdout.write(`\\n ${r.type.padEnd(5)} ${r.host}${state}\\n`);\n process.stdout.write(` -> ${r.value}\\n`);\n if (r.mustBeGrey) {\n // The single most common wildcard failure: proxied, so the CA sees\n // Cloudflare's addresses instead of the record.\n process.stdout.write(\" On Cloudflare: DNS only (grey cloud)\\n\");\n }\n if (withState && r.detail && r.state !== \"found\") {\n process.stdout.write(` ${r.detail}\\n`);\n }\n }\n}\n\n/** `krova domains` — manage a Cube's custom domains. */\nexport function domainsCommand(): Command {\n const cmd = new Command(\"domains\").description(\"manage a Cube's custom domains\");\n\n cmd\n .command(\"list\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"list the custom domains attached to a Cube\")\n .action(async (cubeRef: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const domains = await client.domains.list(space, id);\n if (rt.json) return printJSON(domains);\n printTable(\n [\"ID\", \"DOMAIN\", \"PORT\", \"STATUS\"],\n domains.map((d) => [d.id, d.domain, String(d.port ?? \"\"), d.status]),\n );\n });\n\n cmd\n .command(\"add\")\n .argument(\"<cube>\", \"cube name or ID\")\n .requiredOption(\"--domain <domain>\", \"the domain name to attach\")\n .requiredOption(\"--port <n>\", \"the in-Cube port to route to\")\n .option(\"--origin-scheme <scheme>\", \"transport the edge uses to reach the Cube: http (default) or https when the Cube terminates TLS itself\")\n .description(\"attach a custom domain to a Cube\")\n .action(async (cubeRef: string, opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const port = Number(opts.port);\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n throw new Error(`--port must be a valid port (got \"${opts.port}\").`);\n }\n const originScheme = parseOriginScheme(opts.originScheme);\n const { domain, records } = await client.domains.create(space, id, {\n domain: opts.domain,\n port,\n ...(originScheme ? { originScheme } : {}),\n });\n if (rt.json) return printJSON({ domain, records });\n process.stdout.write(`Attached ${domain.domain} (${domain.id}) — status ${domain.status}\\n`);\n // ⛔ Print the records. Attaching a domain does nothing until they exist,\n // and before this the CLI sent people away to find out what to publish —\n // for a wildcard, two of the three records were not discoverable from\n // anything the CLI printed.\n printRecords(records);\n process.stdout.write(\n `\\nAfter publishing them: krova domains records ${cubeRef} ${domain.id}\\n`,\n );\n });\n\n cmd\n .command(\"records\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<domain-id>\", \"the domain mapping ID (see `krova domains list`)\")\n .description(\"show the DNS records a domain needs, and whether they resolve yet\")\n .action(async (cubeRef: string, mappingId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const out = await client.domains.records(space, id, mappingId);\n if (rt.json) return printJSON(out);\n process.stdout.write(\n `${out.domain} — ${out.summary.found} of ${out.summary.total} records found\\n`,\n );\n printRecords(out.records, true);\n if (!out.summary.complete) {\n process.stdout.write(\"\\nDNS changes can take a few minutes to spread.\\n\");\n }\n });\n\n cmd\n .command(\"set-origin\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<domain-id>\", \"the domain mapping ID (see `krova domains list`)\")\n .argument(\"<scheme>\", \"http or https\")\n .description(\"set the transport the edge uses to reach the Cube\")\n .action(async (cubeRef: string, mappingId: string, scheme: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const originScheme = parseOriginScheme(scheme);\n if (!originScheme) {\n throw new Error(`scheme must be \"http\" or \"https\" (got \"${scheme}\").`);\n }\n const domain = await client.domains.update(space, id, mappingId, { originScheme });\n if (rt.json) return printJSON(domain);\n process.stdout.write(`${domain.domain} now reached over ${originScheme}\\n`);\n });\n\n cmd\n .command(\"rm\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<domain-id>\", \"the domain mapping ID (see `krova domains list`)\")\n .description(\"detach a custom domain from a Cube\")\n .action(async (cubeRef: string, mappingId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.domains.delete(space, id, mappingId);\n if (rt.json) return printJSON({ id: mappingId, result: \"detached\" });\n process.stdout.write(`Detached domain ${mappingId}\\n`);\n });\n\n return cmd;\n}\n","import { spawn } from \"node:child_process\";\n\nimport { Command } from \"commander\";\n\nimport { rawRequest } from \"../lib/client.js\";\nimport { configPath } from \"../lib/config.js\";\nimport { persistLogin } from \"../lib/persist.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\ninterface StartResponse {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n interval: number;\n expiresIn: number;\n}\ninterface PollResponse {\n apiKey: string;\n spaceId: string;\n}\n\nconst BROWSER_UNAVAILABLE =\n \"Browser login isn't enabled on this server yet — run `krova auth login` to paste an API key from https://krova.cloud\";\n\n/** Only open https URLs, or http to a loopback host. Everything else is unsafe. */\nexport function safeBrowserURL(raw: string): string | null {\n let u: URL;\n try {\n u = new URL(raw);\n } catch {\n return null;\n }\n if (u.protocol === \"https:\" && u.hostname) return raw;\n if (\n u.protocol === \"http:\" &&\n (u.hostname === \"localhost\" || u.hostname === \"127.0.0.1\" || u.hostname === \"::1\")\n ) {\n return raw;\n }\n return null;\n}\n\nfunction openBrowser(url: string): void {\n const cmd =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"\", url] : [url];\n const child = spawn(cmd, args, { stdio: \"ignore\", detached: true, shell: process.platform === \"win32\" });\n child.on(\"error\", () => {\n /* fall through — the URL was already printed */\n });\n child.unref();\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nexport function loginCommand(): Command {\n return new Command(\"login\")\n .description(\"log in through your browser (device authorization)\")\n .option(\"--no-browser\", \"don't open a browser; just print the URL\")\n .option(\"--context <name>\", \"name for the saved context\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const baseUrl = rt.res.baseUrl;\n\n const start = await rawRequest<StartResponse>({\n method: \"POST\",\n baseUrl,\n path: \"/auth/cli/start\",\n timeoutMs: rt.timeoutMs,\n });\n if (start.status === 404) throw new Error(BROWSER_UNAVAILABLE);\n if (start.status !== 200 || !start.data?.deviceCode) {\n throw new Error(`device login failed to start (HTTP ${start.status})`);\n }\n const s = start.data;\n process.stdout.write(`Your verification code is: ${s.userCode}\\n`);\n\n const target = s.verificationUriComplete || s.verificationUri;\n const safe = safeBrowserURL(target);\n if (safe && opts.browser !== false) {\n process.stdout.write(`Opening ${safe} …\\n`);\n openBrowser(safe);\n } else {\n process.stdout.write(`Open this URL to approve the login:\\n ${target}\\n`);\n }\n\n const intervalMs = Math.max((s.interval || 5) * 1000, 5000);\n const deadline = Date.now() + Math.max(s.expiresIn || 600, 1) * 1000;\n process.stdout.write(\"Waiting for approval…\\n\");\n\n // poll loop\n // eslint-disable-next-line no-constant-condition\n for (;;) {\n if (Date.now() >= deadline) {\n throw new Error(\n \"login timed out: the verification code expired before it was approved\"\n );\n }\n await sleep(intervalMs);\n const poll = await rawRequest<PollResponse>({\n method: \"POST\",\n baseUrl,\n path: \"/auth/cli/poll\",\n body: { deviceCode: s.deviceCode },\n timeoutMs: rt.timeoutMs,\n });\n if (poll.status === 200) {\n if (!poll.data?.apiKey) throw new Error(\"login succeeded but no API key was returned\");\n const { ctxName, spaceName } = await persistLogin({\n apiKey: poll.data.apiKey,\n baseUrl,\n spaceId: poll.data.spaceId,\n ctxName: opts.context as string | undefined,\n timeoutMs: rt.timeoutMs,\n });\n process.stdout.write(`Logged in. Saved context \"${ctxName}\" to ${configPath()}\\n`);\n if (spaceName) process.stdout.write(`Space: ${spaceName}\\n`);\n return;\n }\n if (poll.status === 202 || poll.status === 425 || poll.status === 428) continue;\n if (poll.status === 410) {\n throw new Error(\"login expired: request a new code with `krova login`\");\n }\n if (poll.status === 404) throw new Error(BROWSER_UNAVAILABLE);\n throw new Error(`login failed while polling (HTTP ${poll.status})`);\n }\n });\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\n/** `krova snapshots` — snapshot and restore a Cube's disk. */\nexport function snapshotsCommand(): Command {\n const cmd = new Command(\"snapshots\").description(\"snapshot and restore a Cube's disk\");\n\n cmd\n .command(\"list\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"list a Cube's snapshots\")\n .action(async (cubeRef: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const snaps = await client.snapshots.list(space, id);\n if (rt.json) return printJSON(snaps);\n printTable(\n [\"ID\", \"NAME\", \"STATUS\", \"KIND\", \"SIZE (BYTES)\", \"CREATED\"],\n snaps.map((s) => [\n s.id,\n s.name,\n s.status,\n s.kind,\n s.sizeBytes == null ? \"\" : String(s.sizeBytes),\n s.createdAt,\n ]),\n );\n });\n\n cmd\n .command(\"create\")\n .argument(\"<cube>\", \"cube name or ID\")\n .option(\"--name <name>\", \"a name for the snapshot\")\n .description(\"create a snapshot of a Cube's disk\")\n .action(async (cubeRef: string, opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const snap = await client.snapshots.create(space, id, opts.name ? { name: opts.name } : {});\n if (rt.json) return printJSON(snap);\n process.stdout.write(`Created snapshot ${snap.id} (${snap.status})\\n`);\n });\n\n cmd\n .command(\"rm\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<snapshot-id>\", \"the snapshot ID (see `krova snapshots list`)\")\n .description(\"delete a snapshot\")\n .action(async (cubeRef: string, snapshotId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.snapshots.delete(space, id, snapshotId);\n if (rt.json) return printJSON({ id: snapshotId, result: \"deleted\" });\n process.stdout.write(`Deleted snapshot ${snapshotId}\\n`);\n });\n\n cmd\n .command(\"restore\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<snapshot-id>\", \"the snapshot to restore the Cube's disk from\")\n .description(\"restore a Cube's disk from one of its snapshots (replaces the disk)\")\n .action(async (cubeRef: string, snapshotId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.cubes.restore(space, id, snapshotId);\n if (rt.json) return printJSON({ id, snapshotId, result: \"restore enqueued\" });\n process.stdout.write(`Restore of cube ${id} from ${snapshotId} enqueued\\n`);\n });\n\n return cmd;\n}\n","// SSH: fetch connection info, pin host keys, build a hardened `ssh` argv, exec.\n// Ports the Go CLI's option-injection guards and known_hosts pinning verbatim.\n\nimport { spawn } from \"node:child_process\";\nimport { appendFileSync, chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { configDir } from \"./config.js\";\nimport { join } from \"node:path\";\n\nexport interface SshHostKey {\n type: string;\n key: string;\n}\nexport interface SshInfo {\n host: string;\n port: number;\n user: string;\n hostKeys: SshHostKey[];\n}\n\nexport interface SshOptions {\n identity?: string;\n localFwd?: string[];\n remoteFwd?: string[];\n knownHosts?: string;\n remoteCmd?: string[];\n}\n\n// Characters an ssh host must never contain (option/metacharacter injection).\nconst HOST_BANNED = new Set(\n \"@/\\\\'\\\"`$;&|<>(){}*?!#=,\".split(\"\")\n);\n// User is slightly looser — it may contain '=' (host may not).\nconst USER_BANNED = new Set(\n \"@/\\\\'\\\"`$;&|<>(){}*?!#,\".split(\"\")\n);\n\nexport function validateSSHHost(host: string): void {\n const h = host.trim();\n if (!h) throw new Error(\"empty host\");\n if (h.startsWith(\"-\")) throw new Error(\"host must not start with '-'\");\n for (const r of h) {\n const code = r.codePointAt(0) ?? 0;\n if (code <= 0x20 || code === 0x7f) {\n throw new Error(\"host contains whitespace or control characters\");\n }\n if (HOST_BANNED.has(r)) {\n throw new Error(`host contains a disallowed character ${JSON.stringify(r)}`);\n }\n }\n}\n\nexport function validateSSHUser(user: string): void {\n const u = user.trim();\n if (!u) return; // empty user is allowed\n if (u.startsWith(\"-\")) throw new Error(\"user must not start with '-'\");\n for (const r of u) {\n const code = r.codePointAt(0) ?? 0;\n if (code <= 0x20 || code === 0x7f) {\n throw new Error(\"user contains whitespace or control characters\");\n }\n if (USER_BANNED.has(r)) {\n throw new Error(`user contains a disallowed character ${JSON.stringify(r)}`);\n }\n }\n}\n\n/** known_hosts host field: \"[host]:port\" when the port isn't the default 22. */\nexport function knownHostsHost(host: string, port: number): string {\n if (port > 0 && port !== 22) return `[${host}]:${port}`;\n return host;\n}\n\nexport function knownHostsPath(): string {\n return join(configDir(), \"known_hosts\");\n}\n\n/** Pin the cube's host keys to ~/.config/krova/known_hosts (0600), pruning any\n * stale line for the same host:port (rebuilt cubes can reuse an IP+DNAT port). */\nexport function writeKnownHosts(info: SshInfo): string {\n const path = knownHostsPath();\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const field = knownHostsHost(info.host, info.port);\n\n let existing = \"\";\n try {\n existing = readFileSync(path, \"utf8\");\n } catch {\n existing = \"\";\n }\n const kept = existing\n .split(\"\\n\")\n .filter((line) => line.trim() && line.split(/\\s+/)[0] !== field);\n writeFileSync(path, kept.length ? `${kept.join(\"\\n\")}\\n` : \"\", { mode: 0o600 });\n chmodSync(path, 0o600);\n\n for (const k of info.hostKeys) {\n appendFileSync(path, `${field} ${k.type} ${k.key}\\n`);\n }\n return path;\n}\n\n/** Build the ssh argv. `--` is placed immediately before the destination —\n * the primary option-injection guard (with the validators above). */\nexport function buildSSHArgs(info: SshInfo, o: SshOptions): string[] {\n const args: string[] = [];\n if (o.knownHosts) {\n args.push(\"-o\", `UserKnownHostsFile=${o.knownHosts}`, \"-o\", \"StrictHostKeyChecking=yes\");\n }\n if ((o.identity ?? \"\").trim()) args.push(\"-i\", o.identity as string);\n if (info.port > 0) args.push(\"-p\", String(info.port));\n for (const l of o.localFwd ?? []) if (l.trim()) args.push(\"-L\", l);\n for (const r of o.remoteFwd ?? []) if (r.trim()) args.push(\"-R\", r);\n const user = info.user.trim();\n const target = user ? `${user}@${info.host}` : info.host;\n args.push(\"--\", target);\n args.push(...(o.remoteCmd ?? []));\n return args;\n}\n\n/** Exec system ssh, inheriting stdio (interactive unless a remote cmd is given). */\nexport function execSSH(args: string[]): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"ssh\", args, { stdio: \"inherit\" });\n child.on(\"error\", reject);\n child.on(\"exit\", (code) => resolve(code ?? 0));\n });\n}\n","import { Command } from \"commander\";\n\nimport { rawRequest } from \"../lib/client.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\nimport {\n type SshInfo,\n buildSSHArgs,\n execSSH,\n validateSSHHost,\n validateSSHUser,\n writeKnownHosts,\n} from \"../lib/ssh.js\";\n\nconst collect = (v: string, acc: string[]) => {\n acc.push(v);\n return acc;\n};\n\nexport function sshCommand(): Command {\n return new Command(\"ssh\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"[command...]\", \"command to run non-interactively (after --)\")\n .description(\"open an SSH session to a Cube (by name or ID)\")\n .option(\"-i, --identity <file>\", \"SSH identity (private key) file, passed to ssh -i\")\n .option(\"-L, --local-forward <spec>\", \"local port forward, passed to ssh -L (repeatable)\", collect, [])\n .option(\"-R, --remote-forward <spec>\", \"remote port forward, passed to ssh -R (repeatable)\", collect, [])\n .action(async (cubeRef: string, command: string[], opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n\n const { status, data } = await rawRequest<SshInfo>({\n method: \"GET\",\n baseUrl: rt.res.baseUrl,\n path: `/spaces/${space}/cubes/${id}/ssh`,\n apiKey: rt.res.apiKey,\n timeoutMs: rt.timeoutMs,\n });\n if (status === 404) {\n throw new Error(\n `SSH info isn't available on this server yet — try \\`krova cubes get ${cubeRef}\\` for the Cube's IP and ssh manually`\n );\n }\n if (status === 401 || status === 403) {\n throw new Error(`SSH info request was rejected (HTTP ${status})`);\n }\n if (status !== 200 || !data?.host) {\n throw new Error(`couldn't fetch SSH info (HTTP ${status})`);\n }\n\n const info: SshInfo = {\n host: data.host,\n port: data.port ?? 0,\n user: data.user ?? \"\",\n hostKeys: data.hostKeys ?? [],\n };\n validateSSHHost(info.host);\n validateSSHUser(info.user);\n if (info.port < 0 || info.port > 65535) throw new Error(\"invalid ssh port\");\n\n let knownHosts = \"\";\n if (info.hostKeys.length) {\n knownHosts = writeKnownHosts(info);\n } else {\n process.stderr.write(\n \"note: this server didn't provide host keys — using ssh trust-on-first-use (host-key checking stays on).\\n\"\n );\n }\n\n const args = buildSSHArgs(info, {\n identity: opts.identity as string | undefined,\n localFwd: opts.localForward as string[],\n remoteFwd: opts.remoteForward as string[],\n knownHosts,\n remoteCmd: command,\n });\n process.exitCode = await execSSH(args);\n });\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\n/** `krova tcp` — manage a Cube's TCP port mappings. */\nexport function tcpCommand(): Command {\n const cmd = new Command(\"tcp\").description(\"manage a Cube's TCP port mappings\");\n\n cmd\n .command(\"list\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"list a Cube's TCP port mappings\")\n .action(async (cubeRef: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const maps = await client.tcpMappings.list(space, id);\n if (rt.json) return printJSON(maps);\n printTable(\n [\"ID\", \"CUBE PORT\", \"HOST PORT\", \"LABEL\", \"STATUS\", \"SSH\", \"UDP\"],\n maps.map((m) => [\n m.id,\n String(m.cubePort),\n String(m.hostPort),\n m.label ?? \"\",\n m.status,\n m.isSsh ? \"yes\" : \"no\",\n m.udpEnabled ? \"yes\" : \"no\",\n ]),\n );\n });\n\n cmd\n .command(\"add\")\n .argument(\"<cube>\", \"cube name or ID\")\n .requiredOption(\"--port <n>\", \"the in-Cube port to expose\")\n .option(\n \"--whitelist <cidr>\",\n \"restrict access to this IP/CIDR (repeatable)\",\n (val: string, acc: string[]) => {\n acc.push(val);\n return acc;\n },\n [] as string[],\n )\n .option(\"--no-udp\", \"don't forward UDP on this port (UDP is forwarded by default alongside TCP)\")\n .description(\"expose a Cube TCP port on the host, optionally IP-restricted\")\n .action(async (cubeRef: string, opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const cubePort = Number(opts.port);\n if (!Number.isInteger(cubePort) || cubePort <= 0 || cubePort > 65535) {\n throw new Error(`--port must be a valid port (got \"${opts.port}\").`);\n }\n const whitelist = opts.whitelist as string[];\n // ⛔ `whitelistedIps` — NOT `whitelistIps`. The published spec named the\n // field `whitelistIps` while the server has always read\n // `whitelistedIps`, so every `--whitelist` mapping this CLI created was\n // silently published WORLD-OPEN, with a 201 and no error. Reproduced on\n // production 2026-09-02: a mapping added with `--whitelist\n // 203.0.113.0/24` served content to an off-list address.\n //\n // The server now accepts both names, so an older CLI keeps working; this\n // sends the canonical one.\n //\n // ⛔ `udpEnabled` — omit it unless `--no-udp` was passed. The server\n // defaults `udpEnabled` to `true` when the field is absent, so this must\n // NOT send `udpEnabled: opts.udp` (commander defaults `opts.udp` to\n // `true`, but sending that explicitly is fine — sending `false` on mere\n // silence would not be). Only `--no-udp` sets `opts.udp` to `false`, and\n // only then do we send the field at all.\n const mapping = await client.tcpMappings.create(space, id, {\n cubePort,\n ...(whitelist.length ? { whitelistedIps: whitelist } : {}),\n ...(opts.udp === false ? { udpEnabled: false } : {}),\n });\n if (rt.json) return printJSON(mapping);\n process.stdout.write(\n `Mapped cube port ${mapping.cubePort} → host port ${mapping.hostPort} (${mapping.id})\\n`,\n );\n });\n\n cmd\n .command(\"rm\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<mapping-id>\", \"the mapping ID (see `krova tcp list`)\")\n .description(\"remove a TCP port mapping\")\n .action(async (cubeRef: string, mappingId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.tcpMappings.delete(space, id, mappingId);\n if (rt.json) return printJSON({ id: mappingId, result: \"removed\" });\n process.stdout.write(`Removed TCP mapping ${mappingId}\\n`);\n });\n\n return cmd;\n}\n","import { createRequire } from \"node:module\";\n\nimport { Command } from \"commander\";\n\nimport { printJSON } from \"../lib/output.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\nconst require = createRequire(import.meta.url);\nconst pkg = require(\"../package.json\") as { version: string };\n\nexport const CLI_VERSION = pkg.version;\n\nexport function versionCommand(): Command {\n return new Command(\"version\")\n .description(\"print the krova CLI version\")\n .action((_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const info = {\n version: CLI_VERSION,\n node: process.version,\n platform: `${process.platform}/${process.arch}`,\n };\n if (rt.json) return printJSON(info);\n process.stdout.write(`krova ${info.version} (node ${info.node}, ${info.platform})\\n`);\n });\n}\n","import { createServer } from \"node:http\";\n\nimport { verifyKrovaWebhookOrThrow } from \"@krovacloud/webhook\";\nimport { Command } from \"commander\";\n\nimport { printJSON } from \"../lib/output.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\nconst DEFAULT_LISTEN_HOST = \"127.0.0.1\";\nconst DEFAULT_LISTEN_PORT = 4666;\n\n/**\n * Parse a `--addr` value into `{ host, port }`. Handles `host:port`, a bare host\n * (e.g. `localhost`), a bare port, bracketed IPv6 (`[::1]:4666`), and bare IPv6\n * (`::1`). Exported for testing.\n */\nexport function parseListenAddr(addr: string): { host: string; port: number } {\n const s = (addr ?? \"\").trim();\n // Bracketed IPv6: [::1] or [::1]:4666\n const bracket = s.match(/^\\[([^\\]]+)\\](?::(\\d+))?$/);\n if (bracket) {\n return { host: bracket[1] as string, port: bracket[2] ? Number(bracket[2]) : DEFAULT_LISTEN_PORT };\n }\n // Two or more colons and no brackets ⇒ a bare IPv6 address with no port.\n if ((s.match(/:/g)?.length ?? 0) >= 2) {\n return { host: s, port: DEFAULT_LISTEN_PORT };\n }\n // Single colon ⇒ host:port.\n const i = s.lastIndexOf(\":\");\n if (i > 0) {\n const port = Number(s.slice(i + 1));\n return {\n host: s.slice(0, i),\n port: Number.isInteger(port) && port > 0 && port <= 65535 ? port : DEFAULT_LISTEN_PORT,\n };\n }\n // No colon ⇒ a bare port (all digits) or a bare host.\n if (/^\\d+$/.test(s)) {\n const port = Number(s);\n return { host: DEFAULT_LISTEN_HOST, port: port > 0 && port <= 65535 ? port : DEFAULT_LISTEN_PORT };\n }\n return { host: s || DEFAULT_LISTEN_HOST, port: DEFAULT_LISTEN_PORT };\n}\n\nexport function webhooksCommand(): Command {\n const wh = new Command(\"webhooks\").description(\"developer tools for Krova Cloud webhooks\");\n\n wh.command(\"listen\")\n .description(\"run a local server that verifies + prints incoming webhook deliveries\")\n .option(\"--addr <host:port>\", \"address to listen on\", \"127.0.0.1:4666\")\n .option(\"--path <path>\", \"path to accept POSTs on\", \"/\")\n .option(\"--secret <secret>\", \"signing secret (or the KROVA_WEBHOOK_SECRET env var)\")\n .action((opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const secret = (opts.secret as string) || process.env.KROVA_WEBHOOK_SECRET || \"\";\n if (!secret) {\n throw new Error(\n \"a signing secret is required: pass --secret or set KROVA_WEBHOOK_SECRET\"\n );\n }\n const { host, port } = parseListenAddr(String(opts.addr));\n const wantPath = String(opts.path);\n\n const server = createServer((req, res) => {\n const reqPath = (req.url ?? \"/\").split(\"?\")[0];\n if (req.method !== \"POST\" || reqPath !== wantPath) {\n res.writeHead(405);\n res.end(\"method not allowed\");\n return;\n }\n const chunks: Buffer[] = [];\n let size = 0;\n req.on(\"data\", (c: Buffer) => {\n size += c.length;\n if (size <= 1_048_576) chunks.push(c);\n });\n req.on(\"end\", () => {\n const body = Buffer.concat(chunks).toString(\"utf8\");\n const sig = (req.headers[\"x-krova-signature\"] as string) || \"\";\n try {\n verifyKrovaWebhookOrThrow({ payload: body, signature: sig, secret });\n } catch (e) {\n process.stderr.write(`✗ rejected delivery: ${(e as Error).message}\\n`);\n res.writeHead(400);\n res.end(\"invalid signature\");\n return;\n }\n try {\n const event = JSON.parse(body);\n if (rt.json) process.stdout.write(`${JSON.stringify(event)}\\n`);\n else printJSON(event);\n } catch {\n process.stdout.write(`${body}\\n`);\n }\n res.writeHead(200);\n res.end(\"ok\");\n });\n });\n\n server.listen(port, host, () => {\n process.stderr.write(`Listening for webhooks on http://${host}:${port}${wantPath}\\n`);\n });\n const stop = () => server.close(() => process.exit(0));\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n });\n\n return wh;\n}\n","import { Command } from \"commander\";\n\nimport { find, maskKey } from \"../lib/config.js\";\nimport { printJSON, printKeyValue } from \"../lib/output.js\";\nimport { getRuntime, probeAuth } from \"../lib/runtime.js\";\n\nexport function whoamiCommand(): Command {\n return new Command(\"whoami\")\n .description(\"show the current context, space, and base URL\")\n .action(async (_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const ctx = find(rt.cfg, rt.res.contextName);\n let spaceId = rt.res.spaceId;\n let spaceName = ctx?.spaceName ?? \"\";\n\n const probe = await probeAuth(rt.res.baseUrl, rt.res.apiKey, rt.timeoutMs);\n if (probe.state === \"valid\") {\n spaceId = probe.space.id;\n spaceName = probe.space.name ?? spaceName;\n }\n const spaceLive = probe.state === \"valid\";\n\n // A rejected key used to render as a bare \"Space —\", which reads like a\n // missing setting rather than dead credentials. Say so out loud.\n const warning =\n probe.state === \"rejected\"\n ? `the API rejected this key (HTTP ${probe.status}) — run \\`krova login\\`. The values below are cached locally and may be stale.`\n : probe.state === \"unreachable\"\n ? `could not reach ${rt.res.baseUrl} (${probe.error}) — showing locally cached values.`\n : \"\";\n\n if (rt.json) {\n return printJSON({\n context: rt.res.contextName,\n spaceId,\n spaceName,\n apiKeyMasked: maskKey(rt.res.apiKey),\n apiKeySource: rt.res.apiKeySource,\n baseUrl: rt.res.baseUrl,\n spaceLive,\n checkState: probe.state,\n warning: warning || undefined,\n });\n }\n printKeyValue([\n [\"Context\", rt.res.contextName || \"—\"],\n [\"Space\", spaceName || \"—\"],\n [\"Space ID\", spaceId || \"—\"],\n [\"API key\", rt.res.apiKey ? `${maskKey(rt.res.apiKey)} (${rt.res.apiKeySource})` : \"—\"],\n [\"Base URL\", rt.res.baseUrl],\n ]);\n if (warning) process.stdout.write(`\\n${warning}\\n`);\n if (probe.state === \"rejected\") process.exitCode = 1;\n });\n}\n","import { Command } from \"commander\";\n\nimport { authCommand } from \"./commands/auth.js\";\nimport { imagesCommand, pricingCommand, regionsCommand } from \"./commands/catalog.js\";\nimport { contextCommand } from \"./commands/context.js\";\nimport { cubesCommand, rootGetCommand, rootListCommand } from \"./commands/cubes.js\";\nimport { domainsCommand } from \"./commands/domains.js\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { snapshotsCommand } from \"./commands/snapshots.js\";\nimport { sshCommand } from \"./commands/ssh.js\";\nimport { tcpCommand } from \"./commands/tcp.js\";\nimport { CLI_VERSION, versionCommand } from \"./commands/version.js\";\nimport { webhooksCommand } from \"./commands/webhooks.js\";\nimport { whoamiCommand } from \"./commands/whoami.js\";\n\nconst program = new Command();\nprogram\n .name(\"krova\")\n .description(\n \"krova is the command-line interface for Krova Cloud — manage Cubes (Firecracker microVMs), browse the catalog, and receive webhooks.\"\n )\n .version(CLI_VERSION, \"-v, --version\", \"print the krova CLI version\")\n .showHelpAfterError();\n\nprogram.addCommand(loginCommand());\nprogram.addCommand(authCommand());\nprogram.addCommand(contextCommand());\nprogram.addCommand(whoamiCommand());\nprogram.addCommand(cubesCommand());\nprogram.addCommand(domainsCommand());\nprogram.addCommand(snapshotsCommand());\nprogram.addCommand(tcpCommand());\nprogram.addCommand(sshCommand());\nprogram.addCommand(rootListCommand()); // `krova list` (alias `ls`)\nprogram.addCommand(rootGetCommand()); // `krova get`\nprogram.addCommand(regionsCommand());\nprogram.addCommand(imagesCommand());\nprogram.addCommand(pricingCommand());\nprogram.addCommand(webhooksCommand());\nprogram.addCommand(versionCommand());\n\n// cobra-style persistent flags: usable on any command, before or after it.\n// Skips a flag a command already defines locally (e.g. login's own --context).\nconst applyGlobals = (cmd: Command): void => {\n const have = new Set(cmd.options.map((o) => o.long));\n const add = (flags: string, desc: string, def?: string) => {\n const long = flags.split(/[ ,<[]/).find((f) => f.startsWith(\"--\"));\n if (long && !have.has(long)) cmd.option(flags, desc, def);\n };\n add(\"--api-key <key>\", \"Krova Cloud API key (overrides env and context)\");\n add(\"--space <id>\", \"Space ID (overrides KROVA_SPACE_ID and context)\");\n add(\"--base-url <url>\", \"override the API base URL\");\n add(\"--context <name>\", \"use a named context (overrides KROVA_CONTEXT)\");\n add(\"--json\", \"output machine-readable JSON instead of a table\");\n add(\"--timeout <duration>\", \"per-request timeout\", \"30s\");\n for (const c of cmd.commands) applyGlobals(c);\n};\napplyGlobals(program);\n\nasync function main(): Promise<void> {\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Error: ${msg}\\n`);\n process.exitCode = 1;\n }\n}\n\nvoid main();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/lib/config.ts","../src/lib/output.ts","../src/lib/client.ts","../src/lib/runtime.ts","../src/lib/persist.ts","../src/commands/auth.ts","../src/commands/catalog.ts","../src/commands/context.ts","../src/lib/resolve.ts","../src/commands/cubes.ts","../src/commands/domains.ts","../src/commands/login.ts","../src/commands/snapshots.ts","../src/lib/ssh.ts","../src/commands/ssh.ts","../src/commands/tcp.ts","../src/commands/version.ts","../src/commands/webhooks.ts","../src/commands/whoami.ts","../src/index.ts"],"sourcesContent":["// Reads/writes ~/.config/krova/config.json in the EXACT shape the Go CLI used,\n// so existing configs keep working. Multi-context, with legacy single-key\n// migration. The file is always tightened to 0600 on save.\n\nimport { chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport const DEFAULT_BASE_URL = \"https://krova.cloud/api/v1\";\nexport const DEFAULT_CONTEXT_NAME = \"default\";\n\nexport const ENV = {\n apiKey: \"KROVA_API_KEY\",\n spaceId: \"KROVA_SPACE_ID\",\n baseUrl: \"KROVA_BASE_URL\",\n context: \"KROVA_CONTEXT\",\n} as const;\n\nexport interface Context {\n name: string;\n apiKey?: string;\n spaceId?: string;\n spaceName?: string;\n baseUrl?: string;\n}\n\nexport interface Config {\n currentContext?: string;\n contexts?: Context[];\n // legacy (pre-context) fields — parsed then migrated into a \"default\" context\n apiKey?: string;\n spaceId?: string;\n baseUrl?: string;\n}\n\nexport function configDir(): string {\n const xdg = (process.env.XDG_CONFIG_HOME ?? \"\").trim();\n if (xdg) return join(xdg, \"krova\");\n return join(homedir(), \".config\", \"krova\");\n}\n\nexport function configPath(): string {\n return join(configDir(), \"config.json\");\n}\n\nexport function load(): Config {\n let cfg: Config = {};\n try {\n cfg = JSON.parse(readFileSync(configPath(), \"utf8\")) as Config;\n } catch {\n cfg = {};\n }\n return migrate(cfg);\n}\n\n// If only legacy fields are set, synthesize a \"default\" context from them.\nfunction migrate(cfg: Config): Config {\n if ((cfg.apiKey ?? \"\").trim() && (!cfg.contexts || cfg.contexts.length === 0)) {\n cfg.contexts = [\n {\n name: DEFAULT_CONTEXT_NAME,\n apiKey: cfg.apiKey,\n spaceId: cfg.spaceId,\n baseUrl: cfg.baseUrl,\n },\n ];\n cfg.currentContext = DEFAULT_CONTEXT_NAME;\n }\n cfg.apiKey = undefined;\n cfg.spaceId = undefined;\n cfg.baseUrl = undefined;\n return cfg;\n}\n\nexport function save(cfg: Config): void {\n const path = configPath();\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n // clear legacy fields; only serialize non-empty keys (matches Go omitempty)\n const clean: Config = {};\n if (cfg.currentContext) clean.currentContext = cfg.currentContext;\n if (cfg.contexts && cfg.contexts.length) {\n clean.contexts = cfg.contexts.map((c) => {\n const o: Context = { name: c.name };\n if (c.apiKey) o.apiKey = c.apiKey;\n if (c.spaceId) o.spaceId = c.spaceId;\n if (c.spaceName) o.spaceName = c.spaceName;\n if (c.baseUrl) o.baseUrl = c.baseUrl;\n return o;\n });\n }\n writeFileSync(path, `${JSON.stringify(clean, null, 2)}\\n`, { mode: 0o600 });\n // writeFileSync only applies mode on creation — re-tighten an existing file.\n chmodSync(path, 0o600);\n}\n\nexport function find(cfg: Config, name: string): Context | undefined {\n return (cfg.contexts ?? []).find((c) => c.name === name);\n}\n\n/** The active context: `override` (e.g. --context) wins, else currentContext. */\nexport function current(cfg: Config, override?: string): Context | undefined {\n const name = (override ?? \"\").trim() || (cfg.currentContext ?? \"\").trim();\n if (!name) return undefined;\n return find(cfg, name);\n}\n\n/** Merge-in a context: only NON-EMPTY apiKey/spaceId/spaceName/baseUrl\n * overwrite an existing value. This keeps a transient per-command override\n * (e.g. a one-off `--base-url`) from being silently persisted over the\n * context's real base URL. First-ever context becomes current. Returns it. */\nexport function upsert(cfg: Config, incoming: Context): Context {\n cfg.contexts ??= [];\n let ctx = cfg.contexts.find((c) => c.name === incoming.name);\n if (!ctx) {\n ctx = { name: incoming.name };\n cfg.contexts.push(ctx);\n if (!cfg.currentContext) cfg.currentContext = ctx.name;\n }\n if ((incoming.apiKey ?? \"\").trim()) ctx.apiKey = incoming.apiKey;\n if ((incoming.spaceId ?? \"\").trim()) ctx.spaceId = incoming.spaceId;\n if ((incoming.spaceName ?? \"\").trim()) ctx.spaceName = incoming.spaceName;\n if ((incoming.baseUrl ?? \"\").trim()) ctx.baseUrl = incoming.baseUrl;\n return ctx;\n}\n\nexport function remove(cfg: Config, name: string): boolean {\n const before = (cfg.contexts ?? []).length;\n cfg.contexts = (cfg.contexts ?? []).filter((c) => c.name !== name);\n if (cfg.contexts.length === before) return false;\n if (cfg.currentContext === name) {\n cfg.currentContext = cfg.contexts[0]?.name ?? \"\";\n }\n return true;\n}\n\nexport type Source = \"flag\" | \"env\" | \"context\" | \"\";\n\nexport interface Resolved {\n apiKey: string;\n spaceId: string;\n baseUrl: string;\n apiKeySource: Source;\n spaceIdSource: Source;\n contextName: string;\n}\n\nexport interface GlobalFlags {\n apiKey?: string;\n space?: string;\n baseUrl?: string;\n context?: string;\n}\n\n/** Resolve credentials with precedence flag > env > active context. */\nexport function resolve(cfg: Config, flags: GlobalFlags): Resolved {\n const ctx = current(cfg, (flags.context ?? \"\").trim() || process.env[ENV.context]);\n const pick = (\n flag: string | undefined,\n env: string | undefined,\n ctxVal: string | undefined\n ): [string, Source] => {\n if ((flag ?? \"\").trim()) return [flag as string, \"flag\"];\n if ((env ?? \"\").trim()) return [env as string, \"env\"];\n if ((ctxVal ?? \"\").trim()) return [ctxVal as string, \"context\"];\n return [\"\", \"\"];\n };\n const [apiKey, apiKeySource] = pick(flags.apiKey, process.env[ENV.apiKey], ctx?.apiKey);\n const [spaceId, spaceIdSource] = pick(flags.space, process.env[ENV.spaceId], ctx?.spaceId);\n const [baseUrlRaw] = pick(flags.baseUrl, process.env[ENV.baseUrl], ctx?.baseUrl);\n return {\n apiKey,\n spaceId,\n baseUrl: baseUrlRaw || DEFAULT_BASE_URL,\n apiKeySource,\n spaceIdSource,\n contextName: ctx?.name ?? \"\",\n };\n}\n\nexport function sanitizeContextName(name: string): string {\n return name.trim().toLowerCase().replace(/\\s+/g, \"-\");\n}\n\nexport function maskKey(key: string): string {\n if (!key) return \"\";\n if (key.length <= 8) return \"****\";\n return `${key.slice(0, 6)}…${key.slice(-4)}`;\n}\n","export function printJSON(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\n/**\n * Where to connect for a TCP mapping: `host:port`.\n *\n * `host` is the Cube's OWN stable hostname, which survives migration to\n * another server — not the server's hostname, which does not. Shared by\n * `tcp list` and `tcp add` so the two can never disagree about how a connect\n * target is spelled.\n *\n * Falls back to the bare port when the Cube has no host (no server assigned).\n * Printing a port alone is honest about what is known; inventing a host, or\n * printing `null:30000`, is not.\n */\nexport function mappingConnectTarget(mapping: {\n host?: string | null;\n hostPort: number;\n}): string {\n return mapping.host\n ? `${mapping.host}:${mapping.hostPort}`\n : String(mapping.hostPort);\n}\n\nexport function printTable(header: string[], rows: string[][]): void {\n const widths = header.map((h, i) =>\n Math.max(h.length, ...rows.map((r) => (r[i] ?? \"\").length))\n );\n const fmt = (cols: string[]) =>\n cols\n .map((c, i) => (c ?? \"\").padEnd(widths[i] ?? 0))\n .join(\" \")\n .replace(/\\s+$/, \"\");\n process.stdout.write(`${fmt(header)}\\n`);\n for (const r of rows) process.stdout.write(`${fmt(r)}\\n`);\n}\n\nexport function printKeyValue(pairs: Array<[string, string]>): void {\n const w = Math.max(0, ...pairs.map(([k]) => k.length));\n for (const [k, v] of pairs) {\n process.stdout.write(`${k.padEnd(w)} ${v}\\n`);\n }\n}\n","import { KrovaClient } from \"@krovacloud/sdk\";\n\nimport type { Resolved } from \"./config.js\";\n\n/** Build the SDK client, or throw the same message the Go CLI used. */\nexport function makeClient(res: Resolved): KrovaClient {\n if (!res.apiKey) {\n throw new Error(\n \"no API key found: run `krova auth login`, set KROVA_API_KEY, or pass --api-key\"\n );\n }\n return new KrovaClient({ apiKey: res.apiKey, baseUrl: res.baseUrl });\n}\n\n/** Raw JSON request for endpoints the SDK doesn't cover:\n * GET /space, GET .../ssh, POST /auth/cli/start, POST /auth/cli/poll. */\nexport async function rawRequest<T>(opts: {\n method: string;\n baseUrl: string;\n path: string;\n apiKey?: string;\n body?: unknown;\n timeoutMs: number;\n}): Promise<{ status: number; data: T | undefined }> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs);\n try {\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (opts.apiKey) headers[\"X-API-KEY\"] = opts.apiKey;\n if (opts.body !== undefined) headers[\"Content-Type\"] = \"application/json\";\n const res = await fetch(`${opts.baseUrl.replace(/\\/+$/, \"\")}${opts.path}`, {\n method: opts.method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n redirect: \"manual\",\n signal: controller.signal,\n });\n let data: T | undefined;\n const text = await res.text();\n if (text) {\n try {\n data = JSON.parse(text) as T;\n } catch {\n data = undefined;\n }\n }\n return { status: res.status, data };\n } finally {\n clearTimeout(timer);\n }\n}\n","import type { Command } from \"commander\";\n\nimport {\n type Config,\n type GlobalFlags,\n type Resolved,\n load,\n resolve,\n save,\n upsert,\n} from \"./config.js\";\nimport { makeClient, rawRequest } from \"./client.js\";\n\n/** Parse a Go-style duration (\"30s\", \"500ms\", \"2m\", \"1h\") to ms. Non-positive\n * or unparseable floors to 30s (matches the Go requestTimeout behavior). */\nexport function parseDuration(input: string | undefined): number {\n const s = (input ?? \"\").trim();\n if (!s) return 30_000;\n let total = 0;\n const re = /(\\d+(?:\\.\\d+)?)(ms|s|m|h)/g;\n let m: RegExpExecArray | null = re.exec(s);\n let matched = false;\n while (m) {\n matched = true;\n const n = Number(m[1]);\n const unit = m[2];\n total += unit === \"ms\" ? n : unit === \"s\" ? n * 1000 : unit === \"m\" ? n * 60_000 : n * 3_600_000;\n m = re.exec(s);\n }\n if (!matched) {\n const n = Number(s);\n if (Number.isFinite(n)) total = n * 1000; // bare number = seconds\n }\n return total > 0 ? total : 30_000;\n}\n\nexport interface Runtime {\n flags: GlobalFlags;\n cfg: Config;\n res: Resolved;\n json: boolean;\n timeoutMs: number;\n}\n\nexport function getRuntime(cmd: Command): Runtime {\n const opts = cmd.optsWithGlobals() as Record<string, unknown>;\n const flags: GlobalFlags = {\n apiKey: opts.apiKey as string | undefined,\n space: opts.space as string | undefined,\n baseUrl: opts.baseUrl as string | undefined,\n context: opts.context as string | undefined,\n };\n const cfg = load();\n const res = resolve(cfg, flags);\n return {\n flags,\n cfg,\n res,\n json: Boolean(opts.json),\n timeoutMs: parseDuration(opts.timeout as string | undefined),\n };\n}\n\nexport interface SpaceInfo {\n id: string;\n name?: string;\n slug?: string;\n}\n\n/**\n * The outcome of actually asking the server whether a key works.\n *\n * A stored key is NOT a working key: it can be revoked server-side at any\n * time, and the local config has no way to know. Every caller that wants to\n * report on credentials must distinguish \"rejected\" from \"couldn't reach the\n * server\" — collapsing either into a plain boolean is what made `auth status`\n * print \"Authenticated: yes\" for a key the API answers 401 to.\n */\nexport type AuthProbe =\n /** The server accepted the key and told us which space it belongs to. */\n | { state: \"valid\"; space: SpaceInfo }\n /** The key is absent locally — nothing to check. */\n | { state: \"missing\" }\n /** The server actively rejected the key (revoked, deleted, wrong env). */\n | { state: \"rejected\"; status: number }\n /** Endpoint absent (older server) — the key may still be fine. */\n | { state: \"unsupported\" }\n /** Network/DNS/timeout — says nothing about the key's validity. */\n | { state: \"unreachable\"; error: string };\n\n/** Ask the server whether `apiKey` is actually accepted. Never throws. */\nexport async function probeAuth(\n baseUrl: string,\n apiKey: string,\n timeoutMs: number\n): Promise<AuthProbe> {\n if (!apiKey) return { state: \"missing\" };\n try {\n const { status, data } = await rawRequest<SpaceInfo>({\n method: \"GET\",\n baseUrl,\n path: \"/space\",\n apiKey,\n timeoutMs,\n });\n if (status === 200 && data?.id) return { state: \"valid\", space: data };\n if (status === 401 || status === 403) return { state: \"rejected\", status };\n if (status === 404) return { state: \"unsupported\" };\n return { state: \"unreachable\", error: `HTTP ${status}` };\n } catch (err) {\n return {\n state: \"unreachable\",\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n/** Resolve the active space id: explicit value wins, else auto-detect via\n * GET /space (and cache it into the current context). */\nexport async function resolveSpace(rt: Runtime): Promise<string> {\n if (rt.res.spaceId) return rt.res.spaceId;\n const { status, data } = await rawRequest<SpaceInfo>({\n method: \"GET\",\n baseUrl: rt.res.baseUrl,\n path: \"/space\",\n apiKey: rt.res.apiKey,\n timeoutMs: rt.timeoutMs,\n });\n if (status === 200 && data?.id) {\n // Best-effort cache of the resolved space into the current named context.\n // Deliberately does NOT write baseUrl: rt.res.baseUrl already folds in a\n // one-off --base-url / KROVA_BASE_URL override, and persisting that here\n // would permanently rewrite the context's real base URL from a transient\n // flag. Only the space id/name are cached.\n if (rt.res.contextName) {\n upsert(rt.cfg, {\n name: rt.res.contextName,\n spaceId: data.id,\n spaceName: data.name,\n });\n try {\n save(rt.cfg);\n } catch {\n /* non-fatal */\n }\n }\n return data.id;\n }\n if (status === 404) {\n throw new Error(\n \"couldn't auto-detect your space (the server doesn't support it yet) — pass --space, set KROVA_SPACE_ID, or run `krova login`\"\n );\n }\n if (status === 401 || status === 403) {\n throw new Error(`auto-detect space failed: the API key was rejected (HTTP ${status})`);\n }\n throw new Error(`auto-detect space failed (HTTP ${status})`);\n}\n\nexport { makeClient };\n","import { DEFAULT_CONTEXT_NAME, load, sanitizeContextName, save, upsert } from \"./config.js\";\nimport { probeAuth } from \"./runtime.js\";\n\n/** Save + switch to a context after a login. Best-effort space lookup fills in\n * spaceId/spaceName and a nicer context name. Mirrors the Go persistLogin. */\nexport async function persistLogin(input: {\n apiKey: string;\n baseUrl: string;\n spaceId?: string;\n ctxName?: string;\n timeoutMs: number;\n}): Promise<{ ctxName: string; spaceName: string }> {\n const cfg = load();\n let spaceId = input.spaceId ?? \"\";\n let spaceName = \"\";\n let derivedName = \"\";\n\n const probe = await probeAuth(input.baseUrl, input.apiKey, input.timeoutMs);\n const sp = probe.state === \"valid\" ? probe.space : null;\n if (sp) {\n // Prefer an explicitly-provided --space over the fetched id; only fall back\n // to the resolved space when the caller didn't pin one.\n if (!spaceId) spaceId = sp.id;\n spaceName = sp.name ?? \"\";\n derivedName = (sp.slug || sp.name || \"\").trim();\n }\n\n let name = (input.ctxName ?? \"\").trim();\n if (!name) name = derivedName || DEFAULT_CONTEXT_NAME;\n name = sanitizeContextName(name);\n\n const cur = upsert(cfg, {\n name,\n apiKey: input.apiKey,\n spaceId,\n spaceName,\n baseUrl: input.baseUrl,\n });\n cfg.currentContext = cur.name; // login always switches current\n save(cfg);\n return { ctxName: cur.name, spaceName: cur.spaceName ?? \"\" };\n}\n","import { Command } from \"commander\";\n\nimport { configPath, maskKey } from \"../lib/config.js\";\nimport { printJSON, printKeyValue } from \"../lib/output.js\";\nimport { persistLogin } from \"../lib/persist.js\";\nimport { getRuntime, probeAuth } from \"../lib/runtime.js\";\n\n/** Prompt for an API key. Hidden echo when stdin is a TTY. */\nfunction promptAPIKey(): Promise<string> {\n return new Promise((resolve, reject) => {\n process.stdout.write(\"Krova API key: \");\n const stdin = process.stdin;\n const tty = Boolean(stdin.isTTY);\n let buf = \"\";\n if (tty) stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n const finish = (fn: () => void) => {\n if (tty) stdin.setRawMode(false);\n stdin.pause();\n stdin.removeListener(\"data\", onData);\n fn();\n };\n const onData = (ch: string) => {\n for (const c of ch) {\n const code = c.charCodeAt(0);\n if (code === 10 || code === 13) {\n finish(() => {\n process.stdout.write(\"\\n\");\n resolve(buf.trim());\n });\n return;\n }\n if (code === 3) {\n finish(() => reject(new Error(\"cancelled\")));\n return;\n }\n if (code === 127 || code === 8) {\n buf = buf.slice(0, -1);\n } else if (code >= 32) {\n buf += c;\n }\n }\n };\n stdin.on(\"data\", onData);\n });\n}\n\nexport function authCommand(): Command {\n const auth = new Command(\"auth\").description(\"manage Krova Cloud credentials\");\n\n auth\n .command(\"login\")\n .description(\"log in by pasting an API key\")\n .option(\"--api-key <key>\", \"API key (else you'll be prompted)\")\n .option(\"--space <id>\", \"Space ID to store with the key\")\n .option(\"--context <name>\", \"name for the saved context\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n let key = (opts.apiKey as string) || rt.flags.apiKey || \"\";\n if (!key.trim()) key = await promptAPIKey();\n if (!key.trim()) throw new Error(\"no API key provided\");\n const { ctxName, spaceName } = await persistLogin({\n apiKey: key.trim(),\n baseUrl: rt.res.baseUrl,\n spaceId: opts.space as string | undefined,\n ctxName: opts.context as string | undefined,\n timeoutMs: rt.timeoutMs,\n });\n process.stdout.write(`Logged in. Saved context \"${ctxName}\" to ${configPath()}\\n`);\n if (spaceName) process.stdout.write(`Space: ${spaceName}\\n`);\n });\n\n auth\n .command(\"status\")\n .description(\"show the resolved credentials and verify them against the API\")\n .option(\"--offline\", \"skip the live check; only report what's stored locally\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const offline = Boolean(opts.offline);\n\n // A STORED key is not a WORKING key — it can be revoked server-side at\n // any time. Reporting local presence as \"Authenticated: yes\" sends the\n // user hunting for a config problem that isn't there, so unless they ask\n // for --offline we go and ask the API.\n const probe = offline\n ? ({ state: \"missing\" } as const)\n : await probeAuth(rt.res.baseUrl, rt.res.apiKey, rt.timeoutMs);\n\n const hasKey = Boolean(rt.res.apiKey);\n const authenticated = offline ? hasKey : probe.state === \"valid\";\n\n const detail =\n offline || !hasKey\n ? \"\"\n : probe.state === \"rejected\"\n ? `the API rejected this key (HTTP ${probe.status}) — it was revoked or belongs to another environment; run \\`krova login\\``\n : probe.state === \"unreachable\"\n ? `could not reach ${rt.res.baseUrl} (${probe.error}) — the key was NOT verified`\n : probe.state === \"unsupported\"\n ? \"this server has no /space endpoint, so the key could not be verified\"\n : \"\";\n\n // Live space beats the cached copy: a stale spaceId in the config is\n // exactly the kind of drift this command exists to surface.\n const spaceId = probe.state === \"valid\" ? probe.space.id : rt.res.spaceId;\n\n if (rt.json) {\n return printJSON({\n authenticated,\n verified: probe.state === \"valid\",\n checkState: offline ? \"skipped\" : probe.state,\n detail: detail || undefined,\n context: rt.res.contextName,\n apiKeySource: rt.res.apiKeySource,\n apiKeyMasked: maskKey(rt.res.apiKey),\n spaceId,\n spaceSource: rt.res.spaceIdSource,\n baseUrl: rt.res.baseUrl,\n configPath: configPath(),\n });\n }\n\n const label = !hasKey\n ? \"no (no API key found)\"\n : offline\n ? \"not checked (--offline; a key is stored)\"\n : probe.state === \"valid\"\n ? \"yes (verified against the API)\"\n : probe.state === \"rejected\"\n ? \"NO — key rejected by the API\"\n : \"unknown (could not verify)\";\n\n printKeyValue([\n [\"Authenticated\", label],\n [\"Context\", rt.res.contextName || \"—\"],\n [\"API key\", rt.res.apiKey ? `${maskKey(rt.res.apiKey)} (${rt.res.apiKeySource})` : \"—\"],\n [\"Space ID\", spaceId ? `${spaceId} (${rt.res.spaceIdSource})` : \"—\"],\n [\"Base URL\", rt.res.baseUrl],\n [\"Config\", configPath()],\n ]);\n if (detail) process.stdout.write(`\\n${detail}\\n`);\n\n // Exit non-zero only when the credentials are KNOWN to be unusable, so\n // scripts and CI can gate on `krova auth status` (matches\n // `gh auth status`). An unreachable or too-old API says nothing about\n // the key, so those stay 0 rather than failing a build over a blip.\n if (!hasKey || probe.state === \"rejected\") process.exitCode = 1;\n });\n\n return auth;\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printKeyValue, printTable } from \"../lib/output.js\";\nimport { getRuntime, makeClient } from \"../lib/runtime.js\";\n\nfunction fmtVal(v: unknown): string {\n if (v === null || v === undefined) return \"\";\n if (typeof v === \"object\") return JSON.stringify(v);\n return String(v);\n}\n\n/** Flatten a top-level object field one level deep into `key.subkey` rows, so\n * nested objects (e.g. pricing's `rates`) render as readable key/value pairs\n * instead of a JSON blob. Exported for testing. */\nexport function flattenRows(entries: [string, unknown][]): [string, string][] {\n const rows: [string, string][] = [];\n for (const [k, v] of entries) {\n if (v && typeof v === \"object\" && !Array.isArray(v)) {\n for (const [sk, sv] of Object.entries(v as Record<string, unknown>)) {\n rows.push([`${k}.${sk}`, fmtVal(sv)]);\n }\n } else {\n rows.push([k, fmtVal(v)]);\n }\n }\n return rows;\n}\n\n/**\n * Render a catalog payload as text. If the payload has an array field, print any\n * scalar/object fields first (as key/value) and then the array as a table —\n * otherwise the non-array fields are silently dropped. This matters for\n * `pricing`, whose per-resource `rates` (the actual hourly prices), `currency`,\n * and `note` sit alongside the `tiers` array. `regions`/`images` have only the\n * array, so their output is unchanged.\n */\nfunction renderCatalog(obj: Record<string, unknown>): void {\n const arrKey = Object.keys(obj).find((k) => Array.isArray(obj[k]));\n if (!arrKey) {\n printKeyValue(flattenRows(Object.entries(obj)));\n return;\n }\n const rest = flattenRows(Object.entries(obj).filter(([k]) => k !== arrKey));\n if (rest.length) printKeyValue(rest);\n const arr = (obj[arrKey] as Record<string, unknown>[]) ?? [];\n const cols = [...new Set(arr.flatMap((o) => Object.keys(o)))];\n printTable(\n cols.map((c) => c.toUpperCase()),\n arr.map((o) => cols.map((c) => fmtVal(o[c])))\n );\n}\n\nfunction catalogCmd(\n name: string,\n desc: string,\n fetch: (c: ReturnType<typeof makeClient>) => Promise<Record<string, unknown>>\n): Command {\n return new Command(name)\n .description(desc)\n .action(async (_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const data = await fetch(client);\n if (rt.json) return printJSON(data);\n renderCatalog(data);\n });\n}\n\nexport function regionsCommand(): Command {\n return catalogCmd(\"regions\", \"list regions with available capacity\", (c) =>\n c.catalog.regions() as Promise<Record<string, unknown>>\n );\n}\nexport function imagesCommand(): Command {\n return catalogCmd(\"images\", \"list available OS images\", (c) =>\n c.catalog.images() as Promise<Record<string, unknown>>\n );\n}\nexport function pricingCommand(): Command {\n return catalogCmd(\"pricing\", \"show per-resource hourly pricing\", (c) =>\n c.catalog.pricing() as Promise<Record<string, unknown>>\n );\n}\n","import { Command } from \"commander\";\n\nimport { load, maskKey, remove, save } from \"../lib/config.js\";\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\nexport function contextCommand(): Command {\n const ctx = new Command(\"context\")\n .aliases([\"ctx\", \"contexts\"])\n .description(\"manage named credential contexts (like kubectl/aws profiles)\");\n\n ctx\n .command(\"list\")\n .aliases([\"ls\"])\n .description(\"list all contexts\")\n .action((_opts, cmd: Command) => {\n const { json } = getRuntime(cmd);\n const cfg = load();\n if (json) {\n return printJSON({\n currentContext: cfg.currentContext ?? \"\",\n contexts: (cfg.contexts ?? []).map((c) => ({\n name: c.name,\n apiKey: maskKey(c.apiKey ?? \"\"),\n spaceId: c.spaceId ?? \"\",\n spaceName: c.spaceName ?? \"\",\n baseUrl: c.baseUrl ?? \"\",\n })),\n });\n }\n printTable(\n [\"CURRENT\", \"NAME\", \"SPACE\", \"SPACE ID\", \"BASE URL\"],\n (cfg.contexts ?? []).map((c) => [\n c.name === cfg.currentContext ? \"*\" : \"\",\n c.name,\n c.spaceName ?? \"\",\n c.spaceId ?? \"\",\n c.baseUrl ?? \"\",\n ])\n );\n });\n\n ctx\n .command(\"current\")\n .description(\"print the current context name\")\n .action(() => {\n const cfg = load();\n if (!cfg.currentContext) throw new Error(\"no current context set\");\n process.stdout.write(`${cfg.currentContext}\\n`);\n });\n\n ctx\n .command(\"use\")\n .argument(\"<name>\", \"context name\")\n .description(\"switch the current context\")\n .action((name: string) => {\n const cfg = load();\n if (!(cfg.contexts ?? []).some((c) => c.name === name)) {\n throw new Error(`no context named \"${name}\"`);\n }\n cfg.currentContext = name;\n save(cfg);\n process.stdout.write(`Switched to context ${name}\\n`);\n });\n\n ctx\n .command(\"rename\")\n .argument(\"<old>\", \"current name\")\n .argument(\"<new>\", \"new name\")\n .description(\"rename a context\")\n .action((oldName: string, newName: string) => {\n const cfg = load();\n if (!newName.trim()) throw new Error(\"new name must not be empty\");\n const c = (cfg.contexts ?? []).find((x) => x.name === oldName);\n if (!c) throw new Error(`no context named \"${oldName}\"`);\n if ((cfg.contexts ?? []).some((x) => x.name === newName)) {\n throw new Error(`a context named \"${newName}\" already exists`);\n }\n c.name = newName;\n if (cfg.currentContext === oldName) cfg.currentContext = newName;\n save(cfg);\n process.stdout.write(`Renamed ${oldName} → ${newName}\\n`);\n });\n\n ctx\n .command(\"delete\")\n .aliases([\"rm\"])\n .argument(\"<name>\", \"context name\")\n .description(\"delete a context\")\n .action((name: string) => {\n const cfg = load();\n if (!remove(cfg, name)) throw new Error(`no context named \"${name}\"`);\n save(cfg);\n process.stdout.write(`Deleted context ${name}\\n`);\n });\n\n return ctx;\n}\n","import type { KrovaClient } from \"@krovacloud/sdk\";\n\n/** Resolve a cube name-or-id to an id (parity with the Go resolveCube):\n * exact id wins; else exactly one exact name match; else a clear error. */\nexport async function resolveCube(\n client: KrovaClient,\n spaceId: string,\n ref: string\n): Promise<string> {\n const { cubes } = await client.cubes.list(spaceId);\n if (cubes.some((c) => c.id === ref)) return ref;\n const byName = cubes.filter((c) => c.name === ref);\n if (byName.length === 1) return byName[0]!.id;\n if (byName.length === 0) {\n throw new Error(\n `no cube named or with ID \"${ref}\" in this space (see \\`krova cubes list\\`)`\n );\n }\n const ids = byName.map((c) => c.id).join(\", \");\n throw new Error(\n `cube name \"${ref}\" is ambiguous: it matches ${byName.length} cubes (${ids}) — use the cube ID instead`\n );\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printKeyValue, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\nfunction listCmd(): Command {\n return new Command(\"list\")\n .aliases([\"ls\"])\n .description(\"list Cubes in the space\")\n .action(async (_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const { cubes } = await client.cubes.list(space);\n if (rt.json) return printJSON(cubes);\n printTable(\n [\"ID\", \"NAME\", \"STATE\", \"VCPU\", \"RAM(GB)\", \"DISK(GB)\", \"IMAGE\", \"IPV4\"],\n cubes.map((c) => [\n c.id,\n c.name,\n c.state,\n String(c.resources.vcpu),\n String(c.resources.ramGb),\n String(c.resources.diskGb),\n c.image,\n c.publicIpv4 ?? \"—\",\n ])\n );\n });\n}\n\nfunction getCmd(): Command {\n return new Command(\"get\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"show a single Cube\")\n .action(async (cubeRef: string, _opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const cube = await client.cubes.get(space, id);\n if (rt.json) return printJSON(cube);\n printKeyValue([\n [\"ID\", cube.id],\n [\"Name\", cube.name],\n [\"State\", cube.state],\n [\"Image\", cube.image],\n [\"vCPU\", String(cube.resources.vcpu)],\n [\"RAM (GB)\", String(cube.resources.ramGb)],\n [\"Disk (GB)\", String(cube.resources.diskGb)],\n [\"Public IPv4\", cube.publicIpv4 ?? \"—\"],\n [\"Cost/hour\", `$${cube.costPerHour}`],\n ]);\n });\n}\n\nfunction createCmd(): Command {\n return new Command(\"create\")\n .description(\"provision a new Cube\")\n .requiredOption(\"--name <name>\", \"cube name\")\n .requiredOption(\"--image <slug>\", \"OS image slug (see `krova images`)\")\n .requiredOption(\"--ssh-key <key>\", \"SSH public key written to authorized_keys\")\n .option(\"--vcpu <n>\", \"number of vCPUs\", \"1\")\n .option(\"--ram <gb>\", \"RAM in GB\", \"1\")\n .option(\"--disk <gb>\", \"disk size in GB\", \"10\")\n .option(\"--region <slug>\", \"region slug (see `krova regions`)\")\n .option(\"--user-data <script>\", \"cloud-init script\")\n .option(\"--idempotency-key <key>\", \"idempotency key (24h dedupe)\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n // Validate resources client-side so bad input fails with a clear message\n // rather than being coerced to NaN → JSON null → a generic server 400.\n const posInt = (flag: string, raw: string): number => {\n const n = Number(raw);\n if (!Number.isInteger(n) || n <= 0) {\n throw new Error(`--${flag} must be a positive integer (got \"${raw}\").`);\n }\n return n;\n };\n const body: Record<string, unknown> = {\n name: opts.name,\n image: opts.image,\n sshPublicKey: opts.sshKey,\n resources: {\n vcpu: posInt(\"vcpu\", opts.vcpu),\n ramGb: posInt(\"ram\", opts.ram),\n diskGb: posInt(\"disk\", opts.disk),\n },\n };\n if (opts.region) body.region = opts.region;\n if (opts.userData) body.userData = opts.userData;\n const cube = await client.cubes.create(\n space,\n body as never,\n opts.idempotencyKey ? { idempotencyKey: opts.idempotencyKey } : undefined\n );\n if (rt.json) return printJSON(cube);\n process.stdout.write(`Created cube ${cube.id} (${cube.state})\\n`);\n });\n}\n\nfunction actionCmd(\n name: string,\n past: string,\n fn: (c: ReturnType<typeof makeClient>[\"cubes\"], space: string, id: string) => Promise<unknown>\n): Command {\n return new Command(name)\n .argument(\"<cube>\", \"cube name or ID\")\n .description(`${name} a Cube`)\n .action(async (cubeRef: string, _opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await fn(client.cubes, space, id);\n if (rt.json) return printJSON({ id, result: past });\n process.stdout.write(`${past} cube ${id}\\n`);\n });\n}\n\nfunction restartCmd(): Command {\n return new Command(\"restart\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"restart a Cube (cold restart — picks up a refreshed kernel)\")\n .action(async (cubeRef: string, _opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.cubes.restart(space, id);\n if (rt.json) return printJSON({ id, result: \"Restarting\" });\n // Say COLD explicitly. A `reboot` from inside the Cube looks equivalent\n // but cannot change the kernel — Firecracker treats a guest reboot as a\n // shutdown and the kernel comes from the host.\n process.stdout.write(\n `Restarting cube ${id} (cold restart — disk state is preserved)\\n`,\n );\n });\n}\n\nfunction sshPortCmd(): Command {\n return new Command(\"ssh-port\")\n .argument(\"<cube>\", \"cube name or ID\")\n .requiredOption(\n \"--port <n>\",\n \"the port INSIDE the Cube that sshd listens on (default 22)\",\n )\n .description(\"change the in-Cube port that SSH is forwarded to (not the host port)\")\n .action(async (cubeRef: string, opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const cubePort = Number(opts.port);\n if (!Number.isInteger(cubePort) || cubePort < 1 || cubePort > 65535) {\n throw new Error(\"--port must be an integer between 1 and 65535\");\n }\n await client.cubes.update(space, id, { cubePort } as never);\n if (rt.json) return printJSON({ id, cubePort });\n // Be explicit about WHICH side changed. The host port is assigned by\n // Krova and is not affected by this call, so pointing this at a port\n // nothing is listening on inside the Cube silently breaks SSH access.\n process.stdout.write(\n `Cube ${id}: SSH now forwarded to in-Cube port ${cubePort}.\\n` +\n (cubePort === 22\n ? \"\"\n : `Warning: sshd inside the Cube must be listening on ${cubePort}, ` +\n \"or SSH will stop working. The default is 22.\\n\"),\n );\n });\n}\n\nexport function cubesCommand(): Command {\n const cubes = new Command(\"cubes\").description(\"manage Cubes (Firecracker microVMs)\");\n cubes.addCommand(listCmd());\n cubes.addCommand(getCmd());\n cubes.addCommand(createCmd());\n cubes.addCommand(\n actionCmd(\"power-off\", \"Powering off\", (c, s, id) => c.powerOff(s, id)),\n );\n cubes.addCommand(actionCmd(\"wake\", \"Starting\", (c, s, id) => c.wake(s, id)));\n cubes.addCommand(actionCmd(\"delete\", \"Deleting\", (c, s, id) => c.delete(s, id)));\n cubes.addCommand(restartCmd());\n cubes.addCommand(sshPortCmd());\n return cubes;\n}\n\n// `list` and `get` are also mounted at the root (parity with the Go CLI).\nexport const rootListCommand = listCmd;\nexport const rootGetCommand = getCmd;\n","import { Command } from \"commander\";\n\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\n/**\n * Narrow a `--origin-scheme` / positional scheme to the two the API accepts.\n * Returns undefined when the flag was omitted, so callers can leave the field\n * off the request entirely rather than sending an explicit default.\n */\nexport function parseOriginScheme(value: unknown): \"http\" | \"https\" | undefined {\n if (value === undefined || value === null || value === \"\") return undefined;\n if (value === \"http\" || value === \"https\") return value;\n throw new Error(`--origin-scheme must be \"http\" or \"https\" (got \"${String(value)}\").`);\n}\n\ntype PrintableRecord = {\n type: string;\n host: string;\n value: string;\n note?: string | null;\n mustBeGrey?: boolean;\n state?: string;\n detail?: string;\n};\n\n/** How each live state reads on a terminal. */\nconst STATE_LABEL: Record<string, string> = {\n found: \"found\",\n // ⛔ NOT \"failed\". Before you publish a record, absent is the expected state.\n missing: \"not added yet\",\n mismatch: \"needs a change\",\n // ⛔ OUR lookup failed. Never phrased as the user's mistake.\n unknown: \"couldn't check\",\n};\n\n/**\n * Print the DNS records a domain needs.\n *\n * Both the host AND the value, because a record cannot be created from the\n * value alone — which is what made the old guidance impossible to act on.\n */\nfunction printRecords(records: PrintableRecord[], withState = false): void {\n if (records.length === 0) return;\n process.stdout.write(\"\\nDNS records to publish:\\n\");\n for (const r of records) {\n const state = withState && r.state ? ` [${STATE_LABEL[r.state] ?? r.state}]` : \"\";\n process.stdout.write(`\\n ${r.type.padEnd(5)} ${r.host}${state}\\n`);\n process.stdout.write(` -> ${r.value}\\n`);\n if (r.mustBeGrey) {\n // The single most common wildcard failure: proxied, so the CA sees\n // Cloudflare's addresses instead of the record.\n process.stdout.write(\" On Cloudflare: DNS only (grey cloud)\\n\");\n }\n if (withState && r.detail && r.state !== \"found\") {\n process.stdout.write(` ${r.detail}\\n`);\n }\n }\n}\n\n/** `krova domains` — manage a Cube's custom domains. */\nexport function domainsCommand(): Command {\n const cmd = new Command(\"domains\").description(\"manage a Cube's custom domains\");\n\n cmd\n .command(\"list\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"list the custom domains attached to a Cube\")\n .action(async (cubeRef: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const domains = await client.domains.list(space, id);\n if (rt.json) return printJSON(domains);\n printTable(\n [\"ID\", \"DOMAIN\", \"PORT\", \"STATUS\"],\n domains.map((d) => [d.id, d.domain, String(d.port ?? \"\"), d.status]),\n );\n });\n\n cmd\n .command(\"add\")\n .argument(\"<cube>\", \"cube name or ID\")\n .requiredOption(\"--domain <domain>\", \"the domain name to attach\")\n .requiredOption(\"--port <n>\", \"the in-Cube port to route to\")\n .option(\"--origin-scheme <scheme>\", \"transport the edge uses to reach the Cube: http (default) or https when the Cube terminates TLS itself\")\n .description(\"attach a custom domain to a Cube\")\n .action(async (cubeRef: string, opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const port = Number(opts.port);\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n throw new Error(`--port must be a valid port (got \"${opts.port}\").`);\n }\n const originScheme = parseOriginScheme(opts.originScheme);\n const { domain, records } = await client.domains.create(space, id, {\n domain: opts.domain,\n port,\n ...(originScheme ? { originScheme } : {}),\n });\n if (rt.json) return printJSON({ domain, records });\n process.stdout.write(`Attached ${domain.domain} (${domain.id}) — status ${domain.status}\\n`);\n // ⛔ Print the records. Attaching a domain does nothing until they exist,\n // and before this the CLI sent people away to find out what to publish —\n // for a wildcard, two of the three records were not discoverable from\n // anything the CLI printed.\n printRecords(records);\n process.stdout.write(\n `\\nAfter publishing them: krova domains records ${cubeRef} ${domain.id}\\n`,\n );\n });\n\n cmd\n .command(\"records\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<domain-id>\", \"the domain mapping ID (see `krova domains list`)\")\n .description(\"show the DNS records a domain needs, and whether they resolve yet\")\n .action(async (cubeRef: string, mappingId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const out = await client.domains.records(space, id, mappingId);\n if (rt.json) return printJSON(out);\n process.stdout.write(\n `${out.domain} — ${out.summary.found} of ${out.summary.total} records found\\n`,\n );\n printRecords(out.records, true);\n if (!out.summary.complete) {\n process.stdout.write(\"\\nDNS changes can take a few minutes to spread.\\n\");\n }\n });\n\n cmd\n .command(\"set-origin\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<domain-id>\", \"the domain mapping ID (see `krova domains list`)\")\n .argument(\"<scheme>\", \"http or https\")\n .description(\"set the transport the edge uses to reach the Cube\")\n .action(async (cubeRef: string, mappingId: string, scheme: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const originScheme = parseOriginScheme(scheme);\n if (!originScheme) {\n throw new Error(`scheme must be \"http\" or \"https\" (got \"${scheme}\").`);\n }\n const domain = await client.domains.update(space, id, mappingId, { originScheme });\n if (rt.json) return printJSON(domain);\n process.stdout.write(`${domain.domain} now reached over ${originScheme}\\n`);\n });\n\n cmd\n .command(\"rm\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<domain-id>\", \"the domain mapping ID (see `krova domains list`)\")\n .description(\"detach a custom domain from a Cube\")\n .action(async (cubeRef: string, mappingId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.domains.delete(space, id, mappingId);\n if (rt.json) return printJSON({ id: mappingId, result: \"detached\" });\n process.stdout.write(`Detached domain ${mappingId}\\n`);\n });\n\n return cmd;\n}\n","import { spawn } from \"node:child_process\";\n\nimport { Command } from \"commander\";\n\nimport { rawRequest } from \"../lib/client.js\";\nimport { configPath } from \"../lib/config.js\";\nimport { persistLogin } from \"../lib/persist.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\ninterface StartResponse {\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n interval: number;\n expiresIn: number;\n}\ninterface PollResponse {\n apiKey: string;\n spaceId: string;\n}\n\nconst BROWSER_UNAVAILABLE =\n \"Browser login isn't enabled on this server yet — run `krova auth login` to paste an API key from https://krova.cloud\";\n\n/** Only open https URLs, or http to a loopback host. Everything else is unsafe. */\nexport function safeBrowserURL(raw: string): string | null {\n let u: URL;\n try {\n u = new URL(raw);\n } catch {\n return null;\n }\n if (u.protocol === \"https:\" && u.hostname) return raw;\n if (\n u.protocol === \"http:\" &&\n (u.hostname === \"localhost\" || u.hostname === \"127.0.0.1\" || u.hostname === \"::1\")\n ) {\n return raw;\n }\n return null;\n}\n\nfunction openBrowser(url: string): void {\n const cmd =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n const args = process.platform === \"win32\" ? [\"\", url] : [url];\n const child = spawn(cmd, args, { stdio: \"ignore\", detached: true, shell: process.platform === \"win32\" });\n child.on(\"error\", () => {\n /* fall through — the URL was already printed */\n });\n child.unref();\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nexport function loginCommand(): Command {\n return new Command(\"login\")\n .description(\"log in through your browser (device authorization)\")\n .option(\"--no-browser\", \"don't open a browser; just print the URL\")\n .option(\"--context <name>\", \"name for the saved context\")\n .action(async (opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const baseUrl = rt.res.baseUrl;\n\n const start = await rawRequest<StartResponse>({\n method: \"POST\",\n baseUrl,\n path: \"/auth/cli/start\",\n timeoutMs: rt.timeoutMs,\n });\n if (start.status === 404) throw new Error(BROWSER_UNAVAILABLE);\n if (start.status !== 200 || !start.data?.deviceCode) {\n throw new Error(`device login failed to start (HTTP ${start.status})`);\n }\n const s = start.data;\n process.stdout.write(`Your verification code is: ${s.userCode}\\n`);\n\n const target = s.verificationUriComplete || s.verificationUri;\n const safe = safeBrowserURL(target);\n if (safe && opts.browser !== false) {\n process.stdout.write(`Opening ${safe} …\\n`);\n openBrowser(safe);\n } else {\n process.stdout.write(`Open this URL to approve the login:\\n ${target}\\n`);\n }\n\n const intervalMs = Math.max((s.interval || 5) * 1000, 5000);\n const deadline = Date.now() + Math.max(s.expiresIn || 600, 1) * 1000;\n process.stdout.write(\"Waiting for approval…\\n\");\n\n // poll loop\n // eslint-disable-next-line no-constant-condition\n for (;;) {\n if (Date.now() >= deadline) {\n throw new Error(\n \"login timed out: the verification code expired before it was approved\"\n );\n }\n await sleep(intervalMs);\n const poll = await rawRequest<PollResponse>({\n method: \"POST\",\n baseUrl,\n path: \"/auth/cli/poll\",\n body: { deviceCode: s.deviceCode },\n timeoutMs: rt.timeoutMs,\n });\n if (poll.status === 200) {\n if (!poll.data?.apiKey) throw new Error(\"login succeeded but no API key was returned\");\n const { ctxName, spaceName } = await persistLogin({\n apiKey: poll.data.apiKey,\n baseUrl,\n spaceId: poll.data.spaceId,\n ctxName: opts.context as string | undefined,\n timeoutMs: rt.timeoutMs,\n });\n process.stdout.write(`Logged in. Saved context \"${ctxName}\" to ${configPath()}\\n`);\n if (spaceName) process.stdout.write(`Space: ${spaceName}\\n`);\n return;\n }\n if (poll.status === 202 || poll.status === 425 || poll.status === 428) continue;\n if (poll.status === 410) {\n throw new Error(\"login expired: request a new code with `krova login`\");\n }\n if (poll.status === 404) throw new Error(BROWSER_UNAVAILABLE);\n throw new Error(`login failed while polling (HTTP ${poll.status})`);\n }\n });\n}\n","import { Command } from \"commander\";\n\nimport { printJSON, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\n/** `krova snapshots` — snapshot and restore a Cube's disk. */\nexport function snapshotsCommand(): Command {\n const cmd = new Command(\"snapshots\").description(\"snapshot and restore a Cube's disk\");\n\n cmd\n .command(\"list\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"list a Cube's snapshots\")\n .action(async (cubeRef: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const snaps = await client.snapshots.list(space, id);\n if (rt.json) return printJSON(snaps);\n printTable(\n [\"ID\", \"NAME\", \"STATUS\", \"KIND\", \"SIZE (BYTES)\", \"CREATED\"],\n snaps.map((s) => [\n s.id,\n s.name,\n s.status,\n s.kind,\n s.sizeBytes == null ? \"\" : String(s.sizeBytes),\n s.createdAt,\n ]),\n );\n });\n\n cmd\n .command(\"create\")\n .argument(\"<cube>\", \"cube name or ID\")\n .option(\"--name <name>\", \"a name for the snapshot\")\n .description(\"create a snapshot of a Cube's disk\")\n .action(async (cubeRef: string, opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const snap = await client.snapshots.create(space, id, opts.name ? { name: opts.name } : {});\n if (rt.json) return printJSON(snap);\n process.stdout.write(`Created snapshot ${snap.id} (${snap.status})\\n`);\n });\n\n cmd\n .command(\"rm\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<snapshot-id>\", \"the snapshot ID (see `krova snapshots list`)\")\n .description(\"delete a snapshot\")\n .action(async (cubeRef: string, snapshotId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.snapshots.delete(space, id, snapshotId);\n if (rt.json) return printJSON({ id: snapshotId, result: \"deleted\" });\n process.stdout.write(`Deleted snapshot ${snapshotId}\\n`);\n });\n\n cmd\n .command(\"restore\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<snapshot-id>\", \"the snapshot to restore the Cube's disk from\")\n .description(\"restore a Cube's disk from one of its snapshots (replaces the disk)\")\n .action(async (cubeRef: string, snapshotId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.cubes.restore(space, id, snapshotId);\n if (rt.json) return printJSON({ id, snapshotId, result: \"restore enqueued\" });\n process.stdout.write(`Restore of cube ${id} from ${snapshotId} enqueued\\n`);\n });\n\n return cmd;\n}\n","// SSH: fetch connection info, pin host keys, build a hardened `ssh` argv, exec.\n// Ports the Go CLI's option-injection guards and known_hosts pinning verbatim.\n\nimport { spawn } from \"node:child_process\";\nimport { appendFileSync, chmodSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { isIP } from \"node:net\";\nimport { dirname } from \"node:path\";\n\nimport { configDir } from \"./config.js\";\nimport { join } from \"node:path\";\n\nexport interface SshHostKey {\n type: string;\n key: string;\n}\nexport interface SshInfo {\n host: string;\n port: number;\n user: string;\n hostKeys: SshHostKey[];\n}\n\nexport interface SshOptions {\n identity?: string;\n localFwd?: string[];\n remoteFwd?: string[];\n knownHosts?: string;\n remoteCmd?: string[];\n}\n\n// Characters an ssh host must never contain (option/metacharacter injection).\nconst HOST_BANNED = new Set(\n \"@/\\\\'\\\"`$;&|<>(){}*?!#=,\".split(\"\")\n);\n// User is slightly looser — it may contain '=' (host may not).\nconst USER_BANNED = new Set(\n \"@/\\\\'\\\"`$;&|<>(){}*?!#,\".split(\"\")\n);\n\nexport function validateSSHHost(host: string): void {\n const h = host.trim();\n if (!h) throw new Error(\"empty host\");\n if (h.startsWith(\"-\")) throw new Error(\"host must not start with '-'\");\n for (const r of h) {\n const code = r.codePointAt(0) ?? 0;\n if (code <= 0x20 || code === 0x7f) {\n throw new Error(\"host contains whitespace or control characters\");\n }\n if (HOST_BANNED.has(r)) {\n throw new Error(`host contains a disallowed character ${JSON.stringify(r)}`);\n }\n }\n}\n\nexport function validateSSHUser(user: string): void {\n const u = user.trim();\n if (!u) return; // empty user is allowed\n if (u.startsWith(\"-\")) throw new Error(\"user must not start with '-'\");\n for (const r of u) {\n const code = r.codePointAt(0) ?? 0;\n if (code <= 0x20 || code === 0x7f) {\n throw new Error(\"user contains whitespace or control characters\");\n }\n if (USER_BANNED.has(r)) {\n throw new Error(`user contains a disallowed character ${JSON.stringify(r)}`);\n }\n }\n}\n\n/** known_hosts host field: \"[host]:port\" when the port isn't the default 22. */\nexport function knownHostsHost(host: string, port: number): string {\n if (port > 0 && port !== 22) return `[${host}]:${port}`;\n return host;\n}\n\nexport function knownHostsPath(): string {\n return join(configDir(), \"known_hosts\");\n}\n\n/** True for a DNS hostname (e.g. the Cube's stable SSH hostname), false for a\n * bare IPv4/IPv6 address. */\nexport function isHostname(host: string): boolean {\n return isIP(host) === 0;\n}\n\n/** True when `host:port` has no existing known_hosts pin yet — used to print a\n * one-time note the first time we pin a Cube's hostname rather than its IP. */\nexport function isUnpinned(host: string, port: number): boolean {\n const field = knownHostsHost(host, port);\n let existing = \"\";\n try {\n existing = readFileSync(knownHostsPath(), \"utf8\");\n } catch {\n existing = \"\";\n }\n return !existing.split(\"\\n\").some((line) => line.split(/\\s+/)[0] === field);\n}\n\n/** Pin the cube's host keys to ~/.config/krova/known_hosts (0600), pruning any\n * stale line for the same host:port (rebuilt cubes can reuse an IP+DNAT port). */\nexport function writeKnownHosts(info: SshInfo): string {\n const path = knownHostsPath();\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n const field = knownHostsHost(info.host, info.port);\n\n let existing = \"\";\n try {\n existing = readFileSync(path, \"utf8\");\n } catch {\n existing = \"\";\n }\n const kept = existing\n .split(\"\\n\")\n .filter((line) => line.trim() && line.split(/\\s+/)[0] !== field);\n writeFileSync(path, kept.length ? `${kept.join(\"\\n\")}\\n` : \"\", { mode: 0o600 });\n chmodSync(path, 0o600);\n\n for (const k of info.hostKeys) {\n appendFileSync(path, `${field} ${k.type} ${k.key}\\n`);\n }\n return path;\n}\n\n/** Build the ssh argv. `--` is placed immediately before the destination —\n * the primary option-injection guard (with the validators above). */\nexport function buildSSHArgs(info: SshInfo, o: SshOptions): string[] {\n const args: string[] = [];\n if (o.knownHosts) {\n args.push(\"-o\", `UserKnownHostsFile=${o.knownHosts}`, \"-o\", \"StrictHostKeyChecking=yes\");\n }\n if ((o.identity ?? \"\").trim()) args.push(\"-i\", o.identity as string);\n if (info.port > 0) args.push(\"-p\", String(info.port));\n for (const l of o.localFwd ?? []) if (l.trim()) args.push(\"-L\", l);\n for (const r of o.remoteFwd ?? []) if (r.trim()) args.push(\"-R\", r);\n const user = info.user.trim();\n const target = user ? `${user}@${info.host}` : info.host;\n args.push(\"--\", target);\n args.push(...(o.remoteCmd ?? []));\n return args;\n}\n\n/** Exec system ssh, inheriting stdio (interactive unless a remote cmd is given). */\nexport function execSSH(args: string[]): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"ssh\", args, { stdio: \"inherit\" });\n child.on(\"error\", reject);\n child.on(\"exit\", (code) => resolve(code ?? 0));\n });\n}\n","import { Command } from \"commander\";\n\nimport { rawRequest } from \"../lib/client.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\nimport {\n type SshInfo,\n buildSSHArgs,\n execSSH,\n isHostname,\n isUnpinned,\n validateSSHHost,\n validateSSHUser,\n writeKnownHosts,\n} from \"../lib/ssh.js\";\n\nconst collect = (v: string, acc: string[]) => {\n acc.push(v);\n return acc;\n};\n\nexport function sshCommand(): Command {\n return new Command(\"ssh\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"[command...]\", \"command to run non-interactively (after --)\")\n .description(\"open an SSH session to a Cube (by name or ID)\")\n .option(\"-i, --identity <file>\", \"SSH identity (private key) file, passed to ssh -i\")\n .option(\"-L, --local-forward <spec>\", \"local port forward, passed to ssh -L (repeatable)\", collect, [])\n .option(\"-R, --remote-forward <spec>\", \"remote port forward, passed to ssh -R (repeatable)\", collect, [])\n .action(async (cubeRef: string, command: string[], opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n\n const { status, data } = await rawRequest<SshInfo>({\n method: \"GET\",\n baseUrl: rt.res.baseUrl,\n path: `/spaces/${space}/cubes/${id}/ssh`,\n apiKey: rt.res.apiKey,\n timeoutMs: rt.timeoutMs,\n });\n if (status === 404) {\n throw new Error(\n `SSH info isn't available on this server yet — try \\`krova cubes get ${cubeRef}\\` for the Cube's IP and ssh manually`\n );\n }\n if (status === 401 || status === 403) {\n throw new Error(`SSH info request was rejected (HTTP ${status})`);\n }\n if (status !== 200 || !data?.host) {\n throw new Error(`couldn't fetch SSH info (HTTP ${status})`);\n }\n\n const info: SshInfo = {\n host: data.host,\n port: data.port ?? 0,\n user: data.user ?? \"\",\n hostKeys: data.hostKeys ?? [],\n };\n validateSSHHost(info.host);\n validateSSHUser(info.user);\n if (info.port < 0 || info.port > 65535) throw new Error(\"invalid ssh port\");\n\n let knownHosts = \"\";\n if (info.hostKeys.length) {\n if (isHostname(info.host) && isUnpinned(info.host, info.port)) {\n process.stderr.write(\n \"note: this Cube now has a stable SSH hostname (it stays the same even if the Cube migrates to another server) — pinning it is expected and only happens once.\\n\"\n );\n }\n knownHosts = writeKnownHosts(info);\n } else {\n process.stderr.write(\n \"note: this server didn't provide host keys — using ssh trust-on-first-use (host-key checking stays on).\\n\"\n );\n }\n\n const args = buildSSHArgs(info, {\n identity: opts.identity as string | undefined,\n localFwd: opts.localForward as string[],\n remoteFwd: opts.remoteForward as string[],\n knownHosts,\n remoteCmd: command,\n });\n process.exitCode = await execSSH(args);\n });\n}\n","import { Command } from \"commander\";\n\nimport { mappingConnectTarget, printJSON, printTable } from \"../lib/output.js\";\nimport { resolveCube } from \"../lib/resolve.js\";\nimport { getRuntime, makeClient, resolveSpace } from \"../lib/runtime.js\";\n\n/** `krova tcp` — manage a Cube's TCP port mappings. */\nexport function tcpCommand(): Command {\n const cmd = new Command(\"tcp\").description(\"manage a Cube's TCP port mappings\");\n\n cmd\n .command(\"list\")\n .argument(\"<cube>\", \"cube name or ID\")\n .description(\"list a Cube's TCP port mappings\")\n .action(async (cubeRef: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const maps = await client.tcpMappings.list(space, id);\n if (rt.json) return printJSON(maps);\n // CONNECT is what a reader actually needs: the table used to print a\n // host port with no host, so building a connect string meant a second\n // command and knowing to combine the two. `host` is the Cube's own\n // stable name (it survives migration), so this string keeps working\n // after the Cube moves — unlike the server's hostname.\n printTable(\n [\n \"ID\",\n \"CUBE PORT\",\n \"CONNECT\",\n \"LABEL\",\n \"STATUS\",\n \"SSH\",\n \"UDP\",\n ],\n maps.map((m) => [\n m.id,\n String(m.cubePort),\n mappingConnectTarget(m),\n m.label ?? \"\",\n m.status,\n m.isSsh ? \"yes\" : \"no\",\n m.udpEnabled ? \"yes\" : \"no\",\n ]),\n );\n });\n\n cmd\n .command(\"add\")\n .argument(\"<cube>\", \"cube name or ID\")\n .requiredOption(\"--port <n>\", \"the in-Cube port to expose\")\n .option(\n \"--whitelist <cidr>\",\n \"restrict access to this IP/CIDR (repeatable)\",\n (val: string, acc: string[]) => {\n acc.push(val);\n return acc;\n },\n [] as string[],\n )\n .option(\"--no-udp\", \"don't forward UDP on this port (UDP is forwarded by default alongside TCP)\")\n .description(\"expose a Cube TCP port on the host, optionally IP-restricted\")\n .action(async (cubeRef: string, opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n const cubePort = Number(opts.port);\n if (!Number.isInteger(cubePort) || cubePort <= 0 || cubePort > 65535) {\n throw new Error(`--port must be a valid port (got \"${opts.port}\").`);\n }\n const whitelist = opts.whitelist as string[];\n // ⛔ `whitelistedIps` — NOT `whitelistIps`. The published spec named the\n // field `whitelistIps` while the server has always read\n // `whitelistedIps`, so every `--whitelist` mapping this CLI created was\n // silently published WORLD-OPEN, with a 201 and no error. Reproduced on\n // production 2026-09-02: a mapping added with `--whitelist\n // 203.0.113.0/24` served content to an off-list address.\n //\n // The server now accepts both names, so an older CLI keeps working; this\n // sends the canonical one.\n //\n // ⛔ `udpEnabled` — omit it unless `--no-udp` was passed. The server\n // defaults `udpEnabled` to `true` when the field is absent, so this must\n // NOT send `udpEnabled: opts.udp` (commander defaults `opts.udp` to\n // `true`, but sending that explicitly is fine — sending `false` on mere\n // silence would not be). Only `--no-udp` sets `opts.udp` to `false`, and\n // only then do we send the field at all.\n const mapping = await client.tcpMappings.create(space, id, {\n cubePort,\n ...(whitelist.length ? { whitelistedIps: whitelist } : {}),\n ...(opts.udp === false ? { udpEnabled: false } : {}),\n });\n if (rt.json) return printJSON(mapping);\n // Say where to reach it, not just which port was picked — the point of\n // adding a mapping is to connect to it. Falls back to the bare port if\n // the Cube has no host yet (no server assigned).\n process.stdout.write(\n `Mapped cube port ${mapping.cubePort} → ${mappingConnectTarget(mapping)} (${mapping.id})\\n`,\n );\n });\n\n cmd\n .command(\"rm\")\n .argument(\"<cube>\", \"cube name or ID\")\n .argument(\"<mapping-id>\", \"the mapping ID (see `krova tcp list`)\")\n .description(\"remove a TCP port mapping\")\n .action(async (cubeRef: string, mappingId: string, _opts, c: Command) => {\n const rt = getRuntime(c);\n const client = makeClient(rt.res);\n const space = await resolveSpace(rt);\n const id = await resolveCube(client, space, cubeRef);\n await client.tcpMappings.delete(space, id, mappingId);\n if (rt.json) return printJSON({ id: mappingId, result: \"removed\" });\n process.stdout.write(`Removed TCP mapping ${mappingId}\\n`);\n });\n\n return cmd;\n}\n","import { createRequire } from \"node:module\";\n\nimport { Command } from \"commander\";\n\nimport { printJSON } from \"../lib/output.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\nconst require = createRequire(import.meta.url);\nconst pkg = require(\"../package.json\") as { version: string };\n\nexport const CLI_VERSION = pkg.version;\n\nexport function versionCommand(): Command {\n return new Command(\"version\")\n .description(\"print the krova CLI version\")\n .action((_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const info = {\n version: CLI_VERSION,\n node: process.version,\n platform: `${process.platform}/${process.arch}`,\n };\n if (rt.json) return printJSON(info);\n process.stdout.write(`krova ${info.version} (node ${info.node}, ${info.platform})\\n`);\n });\n}\n","import { createServer } from \"node:http\";\n\nimport { verifyKrovaWebhookOrThrow } from \"@krovacloud/webhook\";\nimport { Command } from \"commander\";\n\nimport { printJSON } from \"../lib/output.js\";\nimport { getRuntime } from \"../lib/runtime.js\";\n\nconst DEFAULT_LISTEN_HOST = \"127.0.0.1\";\nconst DEFAULT_LISTEN_PORT = 4666;\n\n/**\n * Parse a `--addr` value into `{ host, port }`. Handles `host:port`, a bare host\n * (e.g. `localhost`), a bare port, bracketed IPv6 (`[::1]:4666`), and bare IPv6\n * (`::1`). Exported for testing.\n */\nexport function parseListenAddr(addr: string): { host: string; port: number } {\n const s = (addr ?? \"\").trim();\n // Bracketed IPv6: [::1] or [::1]:4666\n const bracket = s.match(/^\\[([^\\]]+)\\](?::(\\d+))?$/);\n if (bracket) {\n return { host: bracket[1] as string, port: bracket[2] ? Number(bracket[2]) : DEFAULT_LISTEN_PORT };\n }\n // Two or more colons and no brackets ⇒ a bare IPv6 address with no port.\n if ((s.match(/:/g)?.length ?? 0) >= 2) {\n return { host: s, port: DEFAULT_LISTEN_PORT };\n }\n // Single colon ⇒ host:port.\n const i = s.lastIndexOf(\":\");\n if (i > 0) {\n const port = Number(s.slice(i + 1));\n return {\n host: s.slice(0, i),\n port: Number.isInteger(port) && port > 0 && port <= 65535 ? port : DEFAULT_LISTEN_PORT,\n };\n }\n // No colon ⇒ a bare port (all digits) or a bare host.\n if (/^\\d+$/.test(s)) {\n const port = Number(s);\n return { host: DEFAULT_LISTEN_HOST, port: port > 0 && port <= 65535 ? port : DEFAULT_LISTEN_PORT };\n }\n return { host: s || DEFAULT_LISTEN_HOST, port: DEFAULT_LISTEN_PORT };\n}\n\nexport function webhooksCommand(): Command {\n const wh = new Command(\"webhooks\").description(\"developer tools for Krova Cloud webhooks\");\n\n wh.command(\"listen\")\n .description(\"run a local server that verifies + prints incoming webhook deliveries\")\n .option(\"--addr <host:port>\", \"address to listen on\", \"127.0.0.1:4666\")\n .option(\"--path <path>\", \"path to accept POSTs on\", \"/\")\n .option(\"--secret <secret>\", \"signing secret (or the KROVA_WEBHOOK_SECRET env var)\")\n .action((opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const secret = (opts.secret as string) || process.env.KROVA_WEBHOOK_SECRET || \"\";\n if (!secret) {\n throw new Error(\n \"a signing secret is required: pass --secret or set KROVA_WEBHOOK_SECRET\"\n );\n }\n const { host, port } = parseListenAddr(String(opts.addr));\n const wantPath = String(opts.path);\n\n const server = createServer((req, res) => {\n const reqPath = (req.url ?? \"/\").split(\"?\")[0];\n if (req.method !== \"POST\" || reqPath !== wantPath) {\n res.writeHead(405);\n res.end(\"method not allowed\");\n return;\n }\n const chunks: Buffer[] = [];\n let size = 0;\n req.on(\"data\", (c: Buffer) => {\n size += c.length;\n if (size <= 1_048_576) chunks.push(c);\n });\n req.on(\"end\", () => {\n const body = Buffer.concat(chunks).toString(\"utf8\");\n const sig = (req.headers[\"x-krova-signature\"] as string) || \"\";\n try {\n verifyKrovaWebhookOrThrow({ payload: body, signature: sig, secret });\n } catch (e) {\n process.stderr.write(`✗ rejected delivery: ${(e as Error).message}\\n`);\n res.writeHead(400);\n res.end(\"invalid signature\");\n return;\n }\n try {\n const event = JSON.parse(body);\n if (rt.json) process.stdout.write(`${JSON.stringify(event)}\\n`);\n else printJSON(event);\n } catch {\n process.stdout.write(`${body}\\n`);\n }\n res.writeHead(200);\n res.end(\"ok\");\n });\n });\n\n server.listen(port, host, () => {\n process.stderr.write(`Listening for webhooks on http://${host}:${port}${wantPath}\\n`);\n });\n const stop = () => server.close(() => process.exit(0));\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n });\n\n return wh;\n}\n","import { Command } from \"commander\";\n\nimport { find, maskKey } from \"../lib/config.js\";\nimport { printJSON, printKeyValue } from \"../lib/output.js\";\nimport { getRuntime, probeAuth } from \"../lib/runtime.js\";\n\nexport function whoamiCommand(): Command {\n return new Command(\"whoami\")\n .description(\"show the current context, space, and base URL\")\n .action(async (_opts, cmd: Command) => {\n const rt = getRuntime(cmd);\n const ctx = find(rt.cfg, rt.res.contextName);\n let spaceId = rt.res.spaceId;\n let spaceName = ctx?.spaceName ?? \"\";\n\n const probe = await probeAuth(rt.res.baseUrl, rt.res.apiKey, rt.timeoutMs);\n if (probe.state === \"valid\") {\n spaceId = probe.space.id;\n spaceName = probe.space.name ?? spaceName;\n }\n const spaceLive = probe.state === \"valid\";\n\n // A rejected key used to render as a bare \"Space —\", which reads like a\n // missing setting rather than dead credentials. Say so out loud.\n const warning =\n probe.state === \"rejected\"\n ? `the API rejected this key (HTTP ${probe.status}) — run \\`krova login\\`. The values below are cached locally and may be stale.`\n : probe.state === \"unreachable\"\n ? `could not reach ${rt.res.baseUrl} (${probe.error}) — showing locally cached values.`\n : \"\";\n\n if (rt.json) {\n return printJSON({\n context: rt.res.contextName,\n spaceId,\n spaceName,\n apiKeyMasked: maskKey(rt.res.apiKey),\n apiKeySource: rt.res.apiKeySource,\n baseUrl: rt.res.baseUrl,\n spaceLive,\n checkState: probe.state,\n warning: warning || undefined,\n });\n }\n printKeyValue([\n [\"Context\", rt.res.contextName || \"—\"],\n [\"Space\", spaceName || \"—\"],\n [\"Space ID\", spaceId || \"—\"],\n [\"API key\", rt.res.apiKey ? `${maskKey(rt.res.apiKey)} (${rt.res.apiKeySource})` : \"—\"],\n [\"Base URL\", rt.res.baseUrl],\n ]);\n if (warning) process.stdout.write(`\\n${warning}\\n`);\n if (probe.state === \"rejected\") process.exitCode = 1;\n });\n}\n","import { Command } from \"commander\";\n\nimport { authCommand } from \"./commands/auth.js\";\nimport { imagesCommand, pricingCommand, regionsCommand } from \"./commands/catalog.js\";\nimport { contextCommand } from \"./commands/context.js\";\nimport { cubesCommand, rootGetCommand, rootListCommand } from \"./commands/cubes.js\";\nimport { domainsCommand } from \"./commands/domains.js\";\nimport { loginCommand } from \"./commands/login.js\";\nimport { snapshotsCommand } from \"./commands/snapshots.js\";\nimport { sshCommand } from \"./commands/ssh.js\";\nimport { tcpCommand } from \"./commands/tcp.js\";\nimport { CLI_VERSION, versionCommand } from \"./commands/version.js\";\nimport { webhooksCommand } from \"./commands/webhooks.js\";\nimport { whoamiCommand } from \"./commands/whoami.js\";\n\nconst program = new Command();\nprogram\n .name(\"krova\")\n .description(\n \"krova is the command-line interface for Krova Cloud — manage Cubes (Firecracker microVMs), browse the catalog, and receive webhooks.\"\n )\n .version(CLI_VERSION, \"-v, --version\", \"print the krova CLI version\")\n .showHelpAfterError();\n\nprogram.addCommand(loginCommand());\nprogram.addCommand(authCommand());\nprogram.addCommand(contextCommand());\nprogram.addCommand(whoamiCommand());\nprogram.addCommand(cubesCommand());\nprogram.addCommand(domainsCommand());\nprogram.addCommand(snapshotsCommand());\nprogram.addCommand(tcpCommand());\nprogram.addCommand(sshCommand());\nprogram.addCommand(rootListCommand()); // `krova list` (alias `ls`)\nprogram.addCommand(rootGetCommand()); // `krova get`\nprogram.addCommand(regionsCommand());\nprogram.addCommand(imagesCommand());\nprogram.addCommand(pricingCommand());\nprogram.addCommand(webhooksCommand());\nprogram.addCommand(versionCommand());\n\n// cobra-style persistent flags: usable on any command, before or after it.\n// Skips a flag a command already defines locally (e.g. login's own --context).\nconst applyGlobals = (cmd: Command): void => {\n const have = new Set(cmd.options.map((o) => o.long));\n const add = (flags: string, desc: string, def?: string) => {\n const long = flags.split(/[ ,<[]/).find((f) => f.startsWith(\"--\"));\n if (long && !have.has(long)) cmd.option(flags, desc, def);\n };\n add(\"--api-key <key>\", \"Krova Cloud API key (overrides env and context)\");\n add(\"--space <id>\", \"Space ID (overrides KROVA_SPACE_ID and context)\");\n add(\"--base-url <url>\", \"override the API base URL\");\n add(\"--context <name>\", \"use a named context (overrides KROVA_CONTEXT)\");\n add(\"--json\", \"output machine-readable JSON instead of a table\");\n add(\"--timeout <duration>\", \"per-request timeout\", \"30s\");\n for (const c of cmd.commands) applyGlobals(c);\n};\napplyGlobals(program);\n\nasync function main(): Promise<void> {\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Error: ${msg}\\n`);\n process.exitCode = 1;\n }\n}\n\nvoid main();\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krovacloud/cli",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "description": "Krova Cloud CLI (krova) — manage Cubes (Firecracker microVMs), browse the catalog, and log in, from your terminal.",
5
5
  "license": "MIT",
6
6
  "author": "Krova Inc.",
@@ -39,7 +39,7 @@
39
39
  "node": ">=20"
40
40
  },
41
41
  "dependencies": {
42
- "@krovacloud/sdk": "0.4.5",
42
+ "@krovacloud/sdk": "0.4.7",
43
43
  "@krovacloud/webhook": "0.1.4",
44
44
  "commander": "^15.0.0"
45
45
  },