/** * `celilo system ensure-fleet-key` — mint celilo's fleet SSH keypair if it * is absent, record its public half, and print it. * * The celilo-side half of "minting the fleet key is not the module's job" * (openspec/changes/hook-process-boundary, design D9b). celilo-mgmt's * `on_install` used to generate the keypair itself, writing into celilo's * data directory from inside a hook — the one directory the hook jail * exists to keep out of the mount set. The hook now asks for the key * through this command and receives the public half, rather than producing * it. * * Idempotent: an existing key is reused. Re-keying would strand every * machine whose authorized_keys holds the old public half. */ import { getDb } from '../../db/client'; import { ensureFleetKey, getFleetSshDir } from '../../services/fleet-key'; import { initializeSystem } from '../../services/system-init'; import type { CommandResult } from '../types'; export async function handleSystemEnsureFleetKey(): Promise { let key: ReturnType; try { key = ensureFleetKey(); } catch (err) { return { success: false, error: `Could not create the fleet SSH key in ${getFleetSshDir()}: ${ err instanceof Error ? err.message : String(err) }`, }; } try { initializeSystem(getDb(), { 'ssh.public_key': key.publicKey }); } catch (err) { return { success: false, error: `Fleet key is on disk but recording ssh.public_key failed: ${ err instanceof Error ? err.message : String(err) }`, }; } // The public key alone, and `rawOutput` to say so on the record: this // command exists to be read by celilo-mgmt's on_install as much as by an // operator, and the key IS the answer either way (an operator pastes it into // a machine's authorized_keys). Wrapping it in prose would make the caller // parse for it, which is how a hook ends up depending on a sentence. return { success: true, message: key.publicKey, rawOutput: true }; }