From 38bc555dbfd530829f5476629102cf0c31c564eb Mon Sep 17 00:00:00 2001 From: didericis Date: Thu, 16 Jul 2026 18:24:45 -0400 Subject: [PATCH] =?UTF-8?q?fix(supervise):=20single=20migrated=20DB=20for?= =?UTF-8?q?=20firecracker=20=E2=80=94=20orchestrator=20owns=20supervise=20?= =?UTF-8?q?tables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The firecracker supervise MCP daemon 500'd (-32603) on egress-allow/block: it ran with no BOT_BOTTLE_ROOT/SUPERVISE_DB_PATH, so it targeted a stray, unmigrated SQLite file and `write_proposal` hit "no such table: supervise_proposals". Meanwhile the in-VM control plane migrated only the registry table (orchestrator_bottles) into its own DB, and the host operator reads a third, disconnected DB — three files, none shared. Consolidate to one DB per host, owned by the control plane on the persisted registry volume (/var/lib/bot-bottle/db/bot-bottle.db): - orchestrator startup now migrates the supervise queue + audit tables into the same file it migrates the registry into (StoreManager), so the control-plane DB carries every table. - the in-VM supervise daemon is pointed at that same file via SUPERVISE_DB_PATH, so daemon and control plane share one queue. `list-egress-routes` already worked (no DB); egress-allow now queues + waits on the single persisted DB instead of erroring. Validated against a live infra VM: migrate + write_proposal succeeds and the proposal is queued. The host-operator HTTP bridge (so approvals complete from the host, unifying docker onto the same path) is the follow-up. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck --- bot_bottle/backend/firecracker/infra_vm.py | 1 + bot_bottle/orchestrator/__main__.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/bot_bottle/backend/firecracker/infra_vm.py b/bot_bottle/backend/firecracker/infra_vm.py index ee957d2..e236eef 100644 --- a/bot_bottle/backend/firecracker/infra_vm.py +++ b/bot_bottle/backend/firecracker/infra_vm.py @@ -411,6 +411,7 @@ BOT_BOTTLE_ROOT=/var/lib/bot-bottle python3 -m bot_bottle.orchestrator \\ # entrypoint the consolidated model doesn't use) is left out. BOT_BOTTLE_GATEWAY_DAEMONS=egress,git-http,supervise \\ BOT_BOTTLE_ORCHESTRATOR_URL=http://127.0.0.1:{CONTROL_PLANE_PORT} \\ +SUPERVISE_DB_PATH=/var/lib/bot-bottle/db/bot-bottle.db \\ python3 /app/gateway_init.py & # Reap as PID 1; children are backgrounded, so `wait` blocks. diff --git a/bot_bottle/orchestrator/__main__.py b/bot_bottle/orchestrator/__main__.py index 26c6f40..1606e12 100644 --- a/bot_bottle/orchestrator/__main__.py +++ b/bot_bottle/orchestrator/__main__.py @@ -16,6 +16,7 @@ import secrets from pathlib import Path from .. import log +from ..store_manager import StoreManager from .broker import LaunchBroker, StubBroker from .control_plane import make_server from .docker_broker import DockerBroker @@ -45,6 +46,11 @@ def main(argv: list[str] | None = None) -> int: registry = RegistryStore(args.db) registry.migrate() + # One DB per host: the supervise queue + audit tables live in the SAME + # SQLite file the registry owns, so the control plane is the single + # source of truth. The in-VM supervise daemon writes here; the host + # operator reaches it over HTTP (never a second, disconnected DB). + StoreManager(registry.db_path).migrate() # An ephemeral signing secret ties the orchestrator (signer) to its # broker (verifier). 'stub' records launches instead of starting