From 11c2db1ee5d889b7e6e0dd1a966037fbd469b58a Mon Sep 17 00:00:00 2001 From: codex Date: Thu, 9 Jul 2026 15:45:51 +0000 Subject: [PATCH] docs: draft smolmachines sidecar vm prd --- docs/prds/prd-new-smolmachines-sidecar-vm.md | 104 +++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/prds/prd-new-smolmachines-sidecar-vm.md diff --git a/docs/prds/prd-new-smolmachines-sidecar-vm.md b/docs/prds/prd-new-smolmachines-sidecar-vm.md new file mode 100644 index 0000000..1c980e3 --- /dev/null +++ b/docs/prds/prd-new-smolmachines-sidecar-vm.md @@ -0,0 +1,104 @@ +# PRD prd-new: smolmachines sidecar VM + +- **Status:** Draft +- **Author:** codex +- **Created:** 2026-07-09 +- **Issue:** #332 + +## Summary + +Run the smolmachines backend's trusted sidecar bundle as its own smolVM instead +of a Docker container. A bottle then consists of an agent VM plus a sidecar VM, +with the agent VM's TSI allowlist limited to the per-bottle agent-facing +sidecar surface. + +## Problem + +The smolmachines backend currently runs the agent in smolVM but keeps +egress/git-gate/supervise in a Docker sidecar bundle. That hybrid launch path +keeps Docker in the trusted runtime path and leaves smolmachines with a +different isolation boundary than its agent VM design suggests. + +The existing Docker sidecar path also uses Docker port publishing to bind only +agent-facing services to the per-bottle host address. TSI is IP-only, so the +smolVM replacement must preserve that scoping: publishing sidecar services on +generic host localhost would let the agent reach unrelated host services or +other bottle sidecars if those services share the allowed address. + +## Goals / Success Criteria + +1. `BOT_BOTTLE_BACKEND=smolmachines ./cli.py start ` runs with both the + agent and sidecar as smolVMs. +2. The smolmachines launch path no longer uses `docker run` for the sidecar + bundle. +3. Agent-facing egress, git-gate, and supervise endpoints are exposed only + through the bottle's own published sidecar surface. +4. Internal sidecar-only ports are not reachable from the agent VM. +5. The agent VM TSI allowlist remains fail-closed and limited to the per-bottle + address. +6. Sidecar config, secrets, and state are delivered to the sidecar VM without + exposing provider or forge credentials to the agent VM. +7. Teardown removes both VMs and any host-side published port state. + +## Non-goals + +- Rewriting the egress, git-gate, or supervise daemons. +- Changing the Docker backend's sidecar bundle behavior. +- Replacing the existing agent image build and pack pipeline except where shared + helper extraction is needed for sidecar image packing. +- Weakening the current smolmachines TSI allowlist checks. + +## Design + +The sidecar VM should continue to use the existing sidecar bundle image and +`/app/sidecar_init.py` supervisor. The launch flow builds the sidecar image, +packs it into a `.smolmachine` artifact, creates a per-bottle sidecar VM from +that artifact, passes the same daemon-selection environment the Docker bundle +uses today, mounts or copies the same daemon-private config/state inputs, starts +the sidecar VM, discovers the host-side published ports, then starts the agent +VM with `--allow-cidr /32`. + +Agent-facing URLs are stamped from the sidecar VM's published ports: + +- `HTTP_PROXY` / `HTTPS_PROXY` point at the published egress proxy port. +- `GIT_GATE_URL` points at the published git HTTP port when git-gate is enabled. +- `MCP_SUPERVISE_URL` points at the published supervise port when supervise is + enabled. + +Internal sidecar-only services stay bound inside the sidecar VM and are not +published. + +## Open blocker + +The implementation depends on host-side port publishing that can bind to the +per-bottle address. Current smolVM documentation and upstream source shape show +`-p/--port` accepting `HOST:GUEST`, with `HOST` represented as a port number, +not an IP address plus port. If smolVM cannot bind a guest port to a specific +host address such as `127.0.0.16:`, bot-bottle needs one of these before +implementation can proceed: + +1. smolVM support for address-scoped port publishing; +2. a host-side forwarding layer that binds only the per-bottle address and + forwards into the sidecar VM; or +3. a different sidecar VM networking design that preserves the same IP-only TSI + isolation property. + +Publishing sidecar ports on generic host localhost is not acceptable because +TSI's allowlist is IP-only and would no longer prove that the agent can reach +only its own sidecar surface. + +## Implementation chunks + +1. Confirm or add an address-scoped sidecar VM port publishing mechanism. +2. Extract the existing image-to-smolmachine pack helper so agent and sidecar + artifacts share the same cache and registry path. +3. Add a sidecar VM launch spec and lifecycle helpers: pack, create, start, + publish/discover ports, stop, delete. +4. Switch smolmachines launch from Docker sidecar bundle lifecycle to sidecar VM + lifecycle. +5. Update egress apply / reload paths for the sidecar VM supervisor. +6. Add unit tests for argv shape, URL stamping, teardown, and fail-closed + behavior. +7. Add or update integration coverage for agent-to-sidecar reachability, host + localhost denial, other-bottle alias denial, internal port denial, and + teardown cleanup.