docs: draft smolmachines sidecar vm prd

This commit is contained in:
2026-07-09 15:45:51 +00:00
committed by didericis
parent fa7c6ab9d8
commit 46a77aec31
@@ -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 <agent>` 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 <per-bottle-address>/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:<random>`, 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.