git-gate provisioning into the running gateway was hard-wired to docker
exec/cp. Extract a backend-neutral `GatewayTransport` (exec + cp_into) so
the same provisioning logic serves both the docker gateway container and
the firecracker gateway VM (over SSH, added with the launch swap).
- `provision_git_gate` / `deprovision_git_gate` now take a transport
instead of a gateway name; `DockerGatewayTransport` wraps the existing
docker exec/cp behavior. deprovision is best-effort (catches the
transport error) — matching the prior idempotent teardown.
- both consolidated_launch callers pass `DockerGatewayTransport(name)` —
no behavior change; the firecracker swap flips only its own to SSH.
Pure refactor: docker path unchanged, gateway_provision tests updated to
construct the transport, all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
Replace the per-bottle Docker sidecar bundle with the shared per-host
orchestrator + gateway, mirroring what the Docker backend already has.
- Add `bot_bottle/backend/firecracker/consolidated_launch.py`:
`_FirecrackerOrchestratorService` (subclasses `OrchestratorService`,
overrides `_gateway()` to return a `DockerGateway` with host port
bindings so Firecracker VMs can reach it via their TAP link);
`launch_consolidated()` registers the bottle by guest IP (attribution
key), provisions git-gate into the shared gateway, and returns the
shared CA + orchestrator URL for teardown; `teardown_consolidated()`
deregisters and cleans up.
- Rewrite `bot_bottle/backend/firecracker/launch.py`: removes the
per-bottle sidecar bundle (`_start_sidecar_bundle`, `_stage_git_gate`,
etc.) and `_mint_certs`; wires `launch_consolidated()` instead. The VM
still sends to `host_tap_ip:PORT` — Docker's PREROUTING DNAT + the nft
`ct status dnat accept` rule in the forward chain route the traffic to
the shared gateway container.
- Extend `DockerGateway` with `host_port_bindings` so the Firecracker
gateway publishes its ports on the host (`0.0.0.0:PORT`).
- Parameterise `OrchestratorService` with `orchestrator_name` /
`orchestrator_label` so Docker and Firecracker orchestrators can
coexist on the same host (`bot-bottle-orchestrator` vs
`bot-bottle-fc-orchestrator`).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>