-- Phase B1: make 'microvm' a runtime a mission can ask for, and give nodes a -- place to declare what they can actually host. -- -- Placement for microVMs is a HARD predicate, not a preference. gw-04 — where -- every mission runs today — is itself a VM without nested virtualisation, so -- it has no /dev/kvm and never will. tank / morpheus / architect do. A microvm -- mission scheduled onto a node without KVM cannot start, so the scheduler has -- to be able to tell the difference, which means the node has to report it. -- -- `capabilities` is deliberately a jsonb blob rather than a `has_kvm boolean`: -- the next predicate (a baked rootfs present, a particular CLI image, a GPU) -- should not need a migration, and the node is the only honest source for any -- of them. ALTER TABLE missions DROP CONSTRAINT IF EXISTS missions_runtime_kind_check; ALTER TABLE missions ADD CONSTRAINT missions_runtime_kind_check CHECK (runtime_kind IN ('zeroclaw', 'local_herdr', 'microvm')); -- Default '{}' and not null: a node that has never reported is "capable of -- nothing known", which is the safe reading. An absent capability must never -- be mistaken for an unqueried one — a node with no entry and a node that -- reported `kvm: false` should both fail a KVM predicate, and with this -- default they do. ALTER TABLE nodes ADD COLUMN IF NOT EXISTS capabilities jsonb NOT NULL DEFAULT '{}'::jsonb; -- Placement asks "which online nodes have KVM", so index the lookup. CREATE INDEX IF NOT EXISTS nodes_capabilities_idx ON nodes USING gin (capabilities);