diff --git a/docs/prds/0070-per-host-orchestrator.md b/docs/prds/0070-per-host-orchestrator.md index fec1974..1e8986d 100644 --- a/docs/prds/0070-per-host-orchestrator.md +++ b/docs/prds/0070-per-host-orchestrator.md @@ -327,8 +327,8 @@ orchestrator becomes a VM. Decouple the two risks instead: ### Slices -Built bottom-up as a stack of small PRs off this one (status: **1–4 -implemented** in #352 → #356 → #357 → #358): +Built bottom-up as a stack of small PRs off this one (status: **1–5 +implemented** in #352 → #356 → #357 → #358 → #360): 1. **Dev-harness core** ✅ — SQLite registry (runtime state) + fail-closed attribution (source IP + identity token) + the HTTP control plane. @@ -339,14 +339,33 @@ implemented** in #352 → #356 → #357 → #358): 3. **Docker launch broker** ✅ — the first real broker: `docker run` / `rm` per bottle, built only from the request's static fields; proves the `BottleBackend` seam on the cheapest backend. -4. **Consolidated per-host sidecar** ✅ — one persistent sidecar shared by - all bottles (idempotent singleton) instead of one per bottle — the core - consolidation win, source-IP-keyed via the attribution invariant. -5. **Firecracker broker + sidecar** — the real work: the shim + VM-to-VM + + **The consolidated-sidecar arc** (the core consolidation win — one + persistent sidecar shared by all bottles instead of one per bottle): + +4. **Sidecar — lifecycle** ✅ — the idempotent-singleton `Sidecar` / + `DockerSidecar` (ensure-running is a no-op when already up, stop is + idempotent); one container per host. +5. **Sidecar — build the real bundle image** ✅ — the orchestrator builds + the `bot-bottle-sidecars` bundle from `Dockerfile.sidecars` when missing + and launches *that* (not a placeholder) as the singleton. +6. **Sidecar — source-IP-keyed multi-tenant config** — the functional + core: the per-bottle CA / egress routes / git-gate keys / policy, today + baked per bottle, become **multi-tenant and selected by the verified + source IP**, with per-bottle add/remove (live reload) on launch/teardown + through the control plane. Until this lands, one shared instance can't + serve multiple bottles' distinct policies. +7. **Sidecar — route agent bottles through it** — wire each agent bottle's + egress/git to the shared sidecar (DNAT / network) instead of a per-bottle + bundle. + + **Remaining backends** (docker done above; the rest against the proven + dev-harness): + +8. **Firecracker broker + sidecar** — the real work: the shim + VM-to-VM routing (host forwards `bbfcN` → orchestrator TAP; the nft table grows - forward rules where today it drops all non-DNAT egress), against the - already-proven dev-harness. -6. **macOS (Apple container)** — last (container-to-container networking). + forward rules where today it drops all non-DNAT egress). +9. **macOS (Apple container)** — last (container-to-container networking). Backends land cheapest-first (docker → firecracker → macOS); keep the sidecar **service one shared thing** throughout.