diff --git a/docs/designs/DECISIONS.md b/docs/designs/DECISIONS.md index 40e8b139..4605a205 100644 --- a/docs/designs/DECISIONS.md +++ b/docs/designs/DECISIONS.md @@ -145,6 +145,7 @@ check enforces the mechanical half. Full rationale: | DL-288 | The profile's model axis resolves through the RIG-1715 LLM gateway (single egress; agents hold no provider creds) and REFERENCES the RIG-2845 role taxonomy + stable-name routing policy — this record delivers per-Manager profile selection + propagation, RIG-2845 owns the policy the model fields name, and RIG-1716 is where the deferred extensions axis will resolve | Active (Matt, 2026-08-29) | [per-Manager profiles §Adjacency](agent/compass-per-agent-overrides/design.md#adjacency-compose-do-not-duplicate) | | DL-289 | The agent-facing spawn path may carry `profile` — a Manager may select its subtree's profile (RIG-2937 ruled YES, unconditional): no selectable-set policy, no cross-family conditioning (cross-family stays an advisory `profiles/` PR-review check, not a door lint); the oversight-degradation-by-composition residual risk is accepted; owner-fence and set-at-creation-only are unchanged | Active (Matt, 2026-08-29) | [per-Manager profiles §Two-layer contract](agent/compass-per-agent-overrides/design.md#the-two-layer-contract-reframed-at-profile-granularity) | | DL-290 | A profile-named model that fails registry resolution FAILS LOUD on ALL sessions (every session carries a profile; `default` included) — the spawn fails with a frame-visible error (the Manager belt `cli.ts:991-1005` fires on `session.model === undefined`); a model that resolves but has no working auth fails loud as a frame-visible HARD error (at spawn if T6 auth-pre-flights the pinned model, else at first turn), never a silent substitution. Compass never relies on the SDK's built-in silent auth-fallback substitution | Active (Matt, 2026-08-29) | [per-Manager profiles §T6](agent/compass-per-agent-overrides/design.md#t6--agent-profile-resolution--model-stack-render) | +| DL-318 | The runner end state splits by trust model (RIG-3070): the managed multi-tenant service is microVM-only (KVM hardware boundary, unchanged — podman remains its transitional running boundary only until the OQ-1 readiness bar (floor) and no later than the frozen first-external-multi-tenant-tenant milestone (ceiling)); self-host single-tenant deployments keep podman as a permanent, supported entry tier requiring no `/dev/kvm`, with microVM the recommended (not required) upgrade for defense-in-depth or an operator running untrusted code. AMENDS the frozen KVM-only amendment (`microvm-kvm-only-amendment.md:96-97`, "A KVM-absent host does not get a lesser boundary; it does not run") with a self-host carve-out, RATIFIES DL-259 (KVM stack); the `ContainerRuntime` interface stays frozen; DL-235's client-only charter is REVERSED by the compass-native embedded-revival record (its own ledger row), and this record does not itself alter compass-app architecture | Active (Matt, 2026-08-31) | [runner topology & adoption §The ruled topology](infra/runtime/compass-runner-adoption-strategy/design.md#the-ruled-topology-ratifies-dl-259-records-the-deferred-reversal-of-dl-235-amends-the-kvm-only-amendment-for-self-host) | ## Comms & tools diff --git a/docs/designs/infra/runtime/compass-runner-adoption-strategy/design.md b/docs/designs/infra/runtime/compass-runner-adoption-strategy/design.md new file mode 100644 index 00000000..820fcc7b --- /dev/null +++ b/docs/designs/infra/runtime/compass-runner-adoption-strategy/design.md @@ -0,0 +1,510 @@ +# Compass self-host runner topology and adoption strategy + +Status: Active +Tracking: RIG-3070 +Owner: compass-obs (design) → compass-runner (impl, runtime/sequencing) + +## Problem / Intent + +The runtime corpus froze a microVM trajectory (DL-259 self-host KVM stack, +the KVM-only no-fallback amendment, DL-235 client-only app) while podman +remains the shipping production default, and the adoption question — how a +new user actually gets onto Compass — was never written down as a contract. +Matt has ruled the topology and the adoption strategy (2026-08, amended +2026-08-31); this record documents that ruling as a frozen-on-merge +contract: **the security boundary follows the trust model, not the +deployment uniformly**. The managed multi-tenant service keeps microVM as +its sole runtime end state; self-host single-tenant deployments get podman +as a permanent, supported entry tier requiring no `/dev/kvm`, with microVM +recommended but not required; and embedded-local mode is revived as the +cross-OS (macOS/Linux/Windows-WSL) podman-backed developer front door, +whose app-architecture reversal is designed in the compass-native lane's +embedded-revival record. Managed-service adoption strategy (the cheap +managed on-ramp) is designed in the private monorepo's own records, not +here. + +## Approach + +### The ruled topology (ratifies DL-259, records the deferred reversal of DL-235, amends the KVM-only amendment for self-host) + +**The runner end state splits by trust model.** The managed multi-tenant +service runs untrusted tenant code and needs the hardware isolation +boundary: microVM (cloud-hypervisor/KVM) remains its sole runtime end +state, unchanged. A self-host single-tenant deployment runs the operator's +own agents on their own code on their own box — there is no untrusted +tenant to isolate from — so the KVM hardware boundary is optional there: +podman is a permanent, supported self-host entry tier, and microVM is the +recommended (not required) self-host upgrade, for defense-in-depth or for +an operator who runs untrusted code or shares the box. + +This RATIFIES one frozen record (DL-259), records the deferred reversal of a +second (DL-235), and AMENDS a third: + +- **DL-259 stands** — the self-host stack is a host-level KVM bring-up, no + compose/Swarm packaging (`docs/designs/DECISIONS.md`, DL-259: "The self-host + stack stays a host-level bring-up on a KVM-capable Linux machine + (`compass-stack up`; microVM D3 hard-fail consumed, no compose/Swarm + packaging)"). DL-259 covers the microVM path's stack shape; it is + untouched by the carve-out, which adds a podman tier beside it rather + than repackaging the KVM stack. +- **DL-235 is being REVERSED** — its client-only charter retired embedded + supervision (`docs/designs/DECISIONS.md`, DL-235: "The Compass native + app is CLIENT-ONLY: `compass-app` retires embedded mode entirely + (supervisor invocation, host preflight, UDS bridge target, embedded + config arm) and connects exclusively over the authenticated TLS door to + a headless Compass stack"). Under the 2026-08-31 embedded-revival + ruling that charter is reversed by the compass-native lane's + embedded-revival record; THIS record records only the topology + direction that motivates the reversal — podman is permanent for + self-host single-tenant, and a single-tenant local box has no untrusted + tenant to isolate, so embedded-local is a legitimate deployment of the + same podman tier — and defers the whole app-architecture reversal + (un-retiring supervision, config, bundle) to that record. +- **The KVM-only amendment is AMENDED with a self-host carve-out.** This + record reopens a frozen decision, and says so honestly: the amendment + ruled that "the runtime is KVM-only" with no degrade-to-container + fallback, and that "A KVM-absent host does not get a lesser boundary; it + does not run" (`docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-kvm-only-amendment.md:96-97`). + That posture is RATIFIED for the managed multi-tenant service, where the + boundary isolates untrusted tenants from each other, and AMENDED for + self-host single-tenant deployments, where the operator is the only + tenant: there, podman is a first-class permanent runtime choice, not a + fallback and not a lesser boundary imposed on an unwitting tenant. The + self-host carve-out is the net-new ruling in this record (Matt, + 2026-08-31: "keep podman for the entry tier, say in docs that microVM is + recommended even on selfhost, but podman/container is usable for users + who don't want to pay a kvm premium"). + +The elastic-session record already froze the transitional shape the +MANAGED side of this record sequences +(`docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-runner.md:403-405`: +"**Transitional container path, then microVM-only (D2).** The rootless +container remains the running boundary through Dogfood + trusted-tenant Beta +… and is then **removed**: microVM is the sole runtime"). Under the +trust-model split that removal now scopes to the managed deployment; the +podman backend stays shipped for self-host. + +### Decision — podman: transitional for managed, permanent for self-host + +This section sequences the trust-model split ruled above. + +**Managed: podman stays the running boundary until the microVM backend +meets a stated production-readiness bar (OQ-1), and is then dropped from +the managed deployment — microVM becomes the managed service's sole +runtime.** Sequencing invariant: Compass never ships without a working +runner — the proven backend is the floor until the replacing backend clears +the bar. + +The OQ-1 bar is only the FLOOR — the earliest the managed drop may happen. +The frozen corpus already sets a hard UPPER BOUND on the managed podman +window: the first-external-multi-tenant-tenant milestone +(`docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-runner.md:403-407`: +"The rootless container remains the running boundary through Dogfood + +trusted-tenant Beta … and is then **removed**: microVM is the sole +runtime. This work runs in parallel with M0/S1/P2/C3 and gates nothing +before the first external multi-tenant tenant"; the bound is stated +literally by the KVM-only amendment's OQ-5 gloss, +`docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-kvm-only-amendment.md:79-82`, +quoting elastic-runtime `docs/designs/infra/runtime/compass-elastic-session-runtime/design.md:892-894`: "I1 lands the microVM before +the first external multi-tenant tenant"). If OQ-1's bar is not +met by that milestone, external multi-tenant onboarding blocks — the +tenant waits; podman never extends past that boundary on managed. OQ-1 +permits dropping podman from managed EARLIER than the milestone; it does +not move the ceiling. + +**Self-host: podman is permanent.** The entry tier stays supported +indefinitely — it is not dropped at the OQ-1 bar or any later milestone. +The honest cost is stated up front: the byte-identical-behavior constraint +and the two-runtime-shape maintenance surface, which the prior draft +treated as a transitional burden that retires at the drop, are now +PERMANENT for self-host. What makes the permanent split cheap is that both +backends already ship behind one constructor-time seam — this decision +KEEPS a working backend rather than building one. + +The same permanent podman path is also what backs the revived +embedded-local front door: a single-tenant local box selects the podman +backend through the same `SelectBackend` seam, so embedded-local rides +the self-host entry tier rather than adding a third runtime shape. + +Grounding the current state: + +- Podman IS the production default today. `SelectBackend` defaults to it + (`go/internal/runtime/microvm.go:111-112`: + `case "", "podman": return NewPodmanCLI(), nil`), and its doc states the + posture verbatim (`go/internal/runtime/microvm.go:102-105`: "During the + transitional period both backends ship and the default is podman: the + proven container path stays the floor while the microVM backend is brought + up, so an unset backend never silently switches an operator onto the + unfinished path"). The microVM backend is opt-in via + `BackendConfig.Backend = "microvm"` + (`go/internal/runtime/microvm.go:56-58`: "Backend names the runtime + backend: \"podman\" (or empty, the transitional default) or \"microvm\"") + and is still in the boot-spike/CI-enablement phase per the `microvm-v2*` + and `microvm-ci-dev-enablement` records in + `docs/designs/infra/runtime/compass-elastic-session-runtime/`. +- The seam is exactly what makes the permanent split cheap. The podman + implementation is explicitly a thin seam + (`go/internal/runtime/podman.go:10-13`: "podman.go — a thin + ContainerRuntime over the podman CLI: the only place a subprocess is + spawned. Everything above depends on the interface"), backend selection is + constructor-time (`go/internal/runtime/microvm.go:109`: + `func SelectBackend(cfg BackendConfig) (ContainerRuntime, error)`), and + the frozen record pins byte-identical container behavior during + coexistence + (`docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-runner.md:397-402`: + "While both backends coexist (D2), selecting the container backend yields + behavior byte-identical to today's podman path … This constraint retires + when the container path is removed"). Under the trust-model split the + container path is never removed from the shipped seam, so that parity + constraint becomes permanent for self-host rather than retiring. +- The seam doc's post-drop shape (`go/internal/runtime/microvm.go:105-108`: + "Once the microVM backend is the sole runtime, the default collapses to + microVM guarded by a VerifyMicroVMSupport hard gate at startup — a legible + refusal when the host cannot run microVMs, with no fallback to the + container path") predates this amendment: under the trust-model split it + describes the MANAGED deployment's end state (its configuration pins the + microVM backend behind the hard gate), not a deletion of the podman + backend from the shipped seam. + +### Embedded-local: the developer front door (dual runners accepted) + +Embedded-local mode is REVIVED as the zero-setup, cross-OS developer +front door (Matt, 2026-08-31: "with us bringing back the podman runtime +and committing to the double runtimes — we just bring back the full +embedded stack mode, that you can run on macOS (can use podman), linux, +and windows (via wsl), and then our front door is easy — just brew +install the app, launch it, sign in with your Claude Code/Codex account, +and you are off to the races, same as if you had installed OMP or another +harness"). The trust-model split is what makes this viable: podman is +permanent for self-host single-tenant, and a developer's own laptop is +the single-tenant case in its purest form — there is no untrusted tenant +to isolate, so the podman boundary that is legitimate on a self-host box +is equally legitimate locally. And on the user's own box, restricted-tier +subscription sign-in is allowed (their box, their IP, their risk), which +is exactly the zero-friction on-ramp the managed service cannot offer to +the subscription-first cohort. + +The always-on-server argument survives as the GRADUATION motivation, not +an argument against embedded. Compass is fundamentally an always-on +server — agents keep working while you are away — and a personal laptop +sleeps; so embedded-local is the try-it-on-your-box on-ramp, and a user +who wants always-on operation graduates to a self-host stack on a +dedicated box or VPS, or to managed. The funnel: embedded-local (front +door, your box) → self-host stack (always-on, dedicated box) → managed +(hosted always-on). + +The embedded supervision subsystem was deleted under DL-235 +(`docs/designs/product/compass-native-client-only/design.md:42-43`: "The +work here is DELETION of built, merged, working embedded code") and is +being RE-INTRODUCED by the compass-native lane's embedded-revival record, +which owns the whole app-architecture reversal — un-retiring supervisor +invocation, the embedded config arm, the thin-client→embedded bundle +change, mode selection, macOS podman-machine provisioning — none of which +is designed here. In this record "dual runtimes" still means podman and +microVM as STACK runner backends behind `SelectBackend`, both of which +already exist; embedded-local runs the same podman backend locally, not a +third runtime. + +Permanent dual runners were rejected in the prior draft on +maintenance-doubling grounds (a fix on one backend can break the other). +Under the 2026-08-31 ruling that cost is now the ACCEPTED tradeoff for +self-host, for two reasons: the podman backend already exists and works, so +the cost is KEEPING a proven backend rather than building one; and it +removes the KVM premium at the self-host front door — cheap VPS tiers +mostly do not expose `/dev/kvm`, and a single-tenant operator gains little +from a hardware boundary that exists to isolate untrusted tenants. The +standing two-backend maintenance surface is the acknowledged price, bounded +by the frozen `ContainerRuntime` seam and the now-permanent byte-identical +parity constraint. + +### Guided onboarding: embedded-local front door, then self-host + +The adoption funnel starts before self-host: the zero-setup front door is +embedded-local — brew install the app, launch it, sign in with your own +subscription, and agents run locally on the podman backend (the +app-architecture that delivers this is the compass-native lane's +embedded-revival record, not this record). Self-host is the graduation +tier for always-on operation, and its bring-up must be near-one-command +on the user's own Linux box or a VPS. The entrypoint already exists: +`compass-stack` dispatches +`up|down|status|preflight` (`go/cmd/compass-stack/main.go:8-13`: "up: bring +the embedded stack to Ready (or attach to a live one) … preflight: check the +host's KVM/podman/microVM prerequisites"), and DL-259's install surface is +"the flake + preflight + self-host doc" (`docs/designs/DECISIONS.md`, +DL-259). Under the trust-model split, self-host no longer requires a +KVM-capable box: the podman entry tier runs on ANY cheap VPS or Linux +machine with no `/dev/kvm`. This record adds the adoption framing on top: +an onboarding guide (T2) that walks the funnel — the embedded-local front +door first, then both self-host graduation paths: the zero-KVM podman +path on any VPS or box (the entry tier), and the recommended microVM path +on a KVM-capable box or nested-virt-enabled instance (the docs recommend +microVM even on self-host; podman remains fully supported for users who +don't want the KVM premium). The specific VPS provider recommendation is +deferred to doc-writing time (OQ-2). The guide content itself is an impl +task (T2), not frozen prose here. + +### macOS reality (designed against, not designed around) + +- The microVM VMM is cloud-hypervisor, a KVM-backed VMM + (`docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-runner.md:80-81`: + "Per D1, the VMM is **cloud-hypervisor**. The design relies only on the + **virtio-fs-preserving shape** — a KVM-backed VMM"), which needs Linux + `/dev/kvm`. No Mac has `/dev/kvm`. Running the Compass microVM on macOS is + only possible NESTED (macOS → a Linux VM via Apple + Virtualization.framework → cloud-hypervisor inside), which requires + hardware nested virtualization available only on M3+/macOS 15 — bleeding + edge, not a supported path. The distribution record is blunt + (`docs/designs/infra/release/compass-distribution/design.md:111-113`: "every + stack install channel targets **Linux x86_64 with KVM**; there is no macOS + or no-KVM stack story, ever, in this record"). +- Podman on macOS also runs a Linux VM (podman-machine) but is + containers-in-a-VM: mature, works on ANY Mac, no nested virt needed. The + local-dev record already runs the whole runner inside such a VM on macOS + (`docs/designs/infra/ci/compass-local-dev/design.md:194-196`: "The runner + cannot run natively on macOS against a remote podman connection: the + per-container agent sockets are AF_UNIX bind-mounts whose source must be + local to the container host"; `:210`: "VM engine: `podman machine` + (recommended over colima; OQ1)"). +- Implication: under the trust-model split, a Mac self-host user can + PERMANENTLY run the stack via podman-machine — no nested virtualization + needed, works on any Mac — since podman is a permanent self-host tier, + not a transitional window. This same podman-machine path is now ALSO + the embedded-local front-door path on Mac ("can run on macOS (can use + podman)", Matt 2026-08-31), not only a self-host option. The microVM + path on a Mac remains nested-only/bleeding-edge and unsupported. + Alternatively the Mac user + points the client app at a remote Linux stack — the DL-235 + client-only posture already supports exactly this + (`docs/designs/DECISIONS.md`, DL-235: "connects exclusively over the + authenticated TLS door to a headless Compass stack — normally on a + dedicated KVM-capable machine"). One open technical unknown is scoped as + a spike, not a blocker: whether the AF_UNIX per-session socket + cross-boundary limitation documented for the runner-in-a-VM shape + (`compass-local-dev/design.md:194-199`) also affects podman-machine + bind-mounts for a Mac self-host stack (OQ-3). + +## Alternatives considered + +- **Option 1 — permanent dual podman+microVM + revive embedded + (macOS/Linux/WSL).** Previously rejected; now, in substance, the + ADOPTED posture (Matt, 2026-08-31), refined by two splits: the + trust-model split (managed stays microVM-only; podman is permanent only + where there is no untrusted tenant) and the direction/architecture + split (this record fixes the direction — embedded-local as the + podman-backed cross-OS front door — while the compass-native lane's + embedded-revival record designs the app-architecture reversal of the + DL-235 deletion, + `docs/designs/product/compass-native-client-only/design.md:43-44`). +- **Option 1-lite — permanent dual runners, no embedded.** Briefly the + chosen interim posture; now subsumed by Option 1 (embedded-local adds + the front door on the same podman tier). The + prior draft rejected it for the permanent two-runtime maintenance cost + and for forfeiting the clean single-runtime end state the KVM-only + amendment argued for (`microvm-kvm-only-amendment.md:95-96`: "it splits + every downstream path (C3 burst, D4 density) into two runtime shapes + forever"). The split preserves that argument where it bites — the + managed service, whose burst/density paths stay single-runtime microVM — + and accepts the two-shape cost only for self-host, where podman already + ships and removes the KVM premium at the front door. + Honesty note: the KVM-only amendment's OWN alternatives already + considered and rejected a self-host carve-out ("Keep the + degrade-to-container path as a self-host / KVM-absent convenience", + `docs/designs/infra/runtime/compass-elastic-session-runtime/microvm-kvm-only-amendment.md:91-97`, + rejected 2026-08-23 as "a standing hole in the security posture"). That + rejection was about the untrusted-multi-tenant microVM boundary, where + a shared-kernel fallback is a real hole in the isolation the managed + service sells; this record's carve-out is self-host single-tenant, + where there is no untrusted tenant — a different case, not a reversal + of that specific finding. +- **Uniform KVM-only everywhere (the prior draft's ruling).** Reconsidered + by Matt (2026-08-31): it taxed self-host single-tenant users for a + hardware isolation boundary that exists to isolate untrusted tenants + they do not have, and priced them onto KVM-capable hosts when cheap VPS + tiers mostly cannot expose `/dev/kvm`. The boundary now follows the + trust model instead. +- **KVM-mandatory-everywhere immediately (drop podman now).** Not chosen + either: the microVM backend is still in the boot-spike/CI-enablement + phase, and dropping podman before the readiness bar would violate the + never-without-a-working-runner invariant. Podman stays the floor while + microVM matures — exactly the `SelectBackend` posture + (`go/internal/runtime/microvm.go:102-105`) — and, per the trust-model + split, stays permanently for self-host. + +## Global Constraints + +1. **KVM/Linux floor — managed, and the self-host microVM path only.** The + managed runtime and any self-host deployment that selects the microVM + backend must expose `/dev/kvm`; on the microVM path, KVM-absent + hard-fails with no silent degrade + (`docs/designs/infra/release/compass-distribution/design.md:108-110`, quoting + microvm-runner D3: "KVM-absent ⇒ hard-fail (D3): with no container + fallback, `/dev/kvm` absence (or any preflight failure) aborts Runner + startup"). The self-host podman entry tier has NO KVM floor — it runs + on any box or VPS without `/dev/kvm`; the universal KVM floor the + distribution record consumed is amended for that tier by this record's + trust-model split. +2. **Always-on-server invariant → the graduation motivation.** Compass is + an always-on server; no design may assume an always-on deployment + lives on a machine that sleeps. Embedded-local is the on-ramp — the + always-on invariant is the reason a user graduates from it to a + self-host stack or managed, not an argument against its existence. +3. **Embedded-local is the developer front door.** Its app-architecture + reversal (reversing DL-235's client-only charter) is designed in the + compass-native lane's embedded-revival record, not here; this record + fixes only the direction and the topology rationale. +4. **Never without a working runner.** The MANAGED podman drop happens only + after the microVM production-readiness bar (OQ-1) is met; until then + podman remains the default and the byte-identical-behavior constraint of + `microvm-runner.md:397-402` holds. OQ-1 is the floor permitting an + earlier drop; the frozen first-external-multi-tenant-tenant milestone + (`microvm-runner.md:403-407`, the ceiling stated literally by + `microvm-kvm-only-amendment.md:79-82`: "I1 lands the microVM before the + first external multi-tenant tenant") is the hard upper bound on the + managed podman window — if the bar is unmet at that milestone, external + multi-tenant onboarding blocks; podman never extends past that boundary + on managed. Self-host is unaffected by the drop: it keeps the podman + backend permanently, so the parity constraint is permanent there rather + than retiring. +5. **Enrollment policy is consumed, not redesigned.** The RIG-3050 + consumption-eligibility matrix + (`compass-gateway-oauth-enrollment/design.md:66-87`) governs which + credential kinds each mode offers; this record layers adoption framing + on top of it. + +## Plan + +The embedded-local app-architecture (un-retiring supervision, config, +bundle; reversing DL-235) is designed and implemented in the +compass-native lane's embedded-revival record — deliberately NOT a task +in this record. + +### T1 — microVM production-readiness bar + managed podman-drop sequencing + +- **Owner:** compass-runner (runtime lane). +- **Do:** freeze the checklist that gates dropping podman from the MANAGED + deployment (proposed bar in OQ-1), then execute the managed cutover when + it is met: pin the managed deployment's `BackendConfig.Backend` to + `"microvm"` behind the `VerifyMicroVMSupport` startup hard gate the seam + doc already names (`go/internal/runtime/microvm.go:105-108`). The podman + backend, `PodmanCLI`, and the `"podman"` backend value are NOT deleted — + they remain the permanent self-host entry tier per the trust-model + split; the prior draft's deletion step is cancelled. +- **Interfaces:** consumes the frozen `ContainerRuntime` interface and + `SelectBackend(cfg BackendConfig) (ContainerRuntime, error)` + (`go/internal/runtime/microvm.go:109`); consumes the microVM e2e/CI + suites (`microvm-ci-dev-enablement.md`). Produces the managed deployment + pinned to the microVM backend with the startup hard gate, and the updated + `compass-stack preflight` checks (`go/cmd/compass-stack/preflight.go`) + distinguishing the podman and microVM paths' prerequisites. +- **Deps:** the microVM V-series tasks in + `compass-elastic-session-runtime/` reaching the OQ-1 bar. Blocks nothing + in T2. + +### T2 — Guided self-host onboarding + +- **Owner:** distribution/docs lane (extends DL-259's T9 self-host doc). +- **Do:** the onboarding guide, opening with the embedded-local front + door (brew install the app → launch → sign in with your own + subscription; the delivering app-architecture is the compass-native + lane's embedded-revival record, not this task), then near-one-command + bring-up documentation and polish around `compass-stack up` covering + BOTH self-host graduation paths: the zero-KVM podman + entry tier on any cheap VPS or Linux box (no `/dev/kvm` needed), and the + recommended microVM path with KVM-capable instance types + (nested-virt-enabled instances) — stating the recommendation that + microVM is preferred even on self-host while podman remains fully + supported. Also covers the dedicated-Linux-box path, the one-box + localhost-TLS path (client-only OQ-6 ruling), and the Mac paths: + podman-machine as a PERMANENT supported option on any Mac, or the client + app pointed at a remote Linux stack per the DL-235 client-only posture + (`docs/designs/product/compass-native-client-only/design.md:43-44`). + Provider picks are decided at doc-writing time (OQ-2). +- **Interfaces:** consumes `compass-stack up|preflight` + (`go/cmd/compass-stack/main.go:8-13`) and the DL-259 install surface + (flake + preflight + `docs/self-host.md`, + `docs/designs/DECISIONS.md`, DL-259). Produces the onboarding + guide. +- **Deps:** DL-259 T6/T9 (flake, preflight, self-host doc). None on T1. + +## Tasks + +- [ ] **T1** Readiness bar frozen (OQ-1 ruled); managed cutover executed + when met: managed deployment pinned to microVM + + `VerifyMicroVMSupport` hard gate; podman backend retained for self-host. +- [ ] **T2** Onboarding guide: embedded-local front door, then self-host + graduation — zero-KVM podman path (any VPS/box) and recommended microVM + path (KVM instance types), dedicated-box, one-box localhost-TLS, and + Mac paths (podman-machine permanent; Mac→remote-Linux). + +## Open Questions + +- **OQ-1 [load-bearing for T1's execution, not for this record's freeze] — + the microVM production-readiness bar.** The bar gates the MANAGED podman + drop, so its criteria must be ruled before T1 executes; the topology + decision itself is already ruled and does not wait on it. + **Recommendation** (a concrete bar to ratify or amend): + 1. the microVM e2e/acceptance suites green in CI (the + `microvm-ci-dev-enablement.md` lane) including the gateway suites over + the hybrid-vsock transport; + 2. the guest supervisor exec path (V2b) and session teardown proven + under the same acceptance suite the podman backend is judged by — + this record's parity bar, composing with (not derived from) the + byte-identical-coexistence constraint of `microvm-runner.md:397-402`, + which constrains the CONTAINER backend during coexistence; + 3. a documented self-host bring-up path: `compass-stack preflight` green + on a clean KVM host → `up` → one agent session end-to-end (the DL-259 + T9 test cycle shape); + 4. a dogfood soak: the microVM backend as the opt-in default on the + dogfood stack; the soak-window length and the boundary-regression + definition are quantified in the bar-ruling artifact (below). + + **Ruling vehicle:** OQ-1 is ruled either as a short amendment in + `compass-elastic-session-runtime/` (the directory's established + amendment mechanism) or as its own ledger row when the managed drop + executes — that artifact is what "OQ-1 ruled" concretely looks like for + compass-runner, and it carries the soak window and regression definition + criterion 4 delegates. +- **OQ-2 [deferral] — which VPS provider(s) the onboarding guide + recommends.** Doc content, decided at T2 writing time. With the podman + entry tier, KVM-capable instance types are a requirement only for the + recommended microVM path, not for self-host as such; the guide + recommends providers for both tiers. +- **OQ-3 [deferral, spike] — macOS podman-machine socket-mount + feasibility.** Whether the AF_UNIX per-session socket cross-boundary + limitation (`compass-local-dev/design.md:194-199`, written for the + runner-in-a-VM dev shape) also affects a podman-machine-hosted stack on + macOS. This now matters MORE than a permanent self-host convenience: + podman-machine is the embedded-local front-door path on Mac ("can use + podman", Matt 2026-08-31), so the spike gates the Mac front door. Still + a spike, not a blocker for this record's freeze: the Mac user always + has the remote-Linux client path either way. + +## Ledger delta (for the coordinator to encode at freeze) + +One decision in this record is net-new and covered by no existing DL row +(DL-259 and DL-235 cover the KVM stack and the client-only app, not the +runtime split or the adoption framing). Recommended row, mirroring the +freeze-time delta shape the directory's amendments use +(`microvm-kvm-only-amendment.md:112-117`): + +1. **Permanent trust-model runtime split; embedded-local revived on the + podman tier.** The security boundary follows the trust model: the + managed multi-tenant service is microVM-only (KVM hardware boundary, + unchanged — podman remains its transitional running boundary only + until the OQ-1 readiness bar, floor, and no later than the frozen + first-external-multi-tenant-tenant milestone, + `microvm-runner.md:403-407`, ceiling); self-host single-tenant + deployments keep podman as a permanent, supported entry tier requiring + no `/dev/kvm`, with microVM the recommended (not required) upgrade. + The permanent self-host podman tier is also what enables embedded-local + as the revived cross-OS (macOS/Linux/Windows-WSL) developer front + door; the app-architecture reversal that delivers it (reversing + DL-235's client-only charter) is designed in the compass-native lane's + embedded-revival record and carries its own ledger row there. AMENDS + the frozen KVM-only amendment (`microvm-kvm-only-amendment.md:96-97`) + with the self-host carve-out; the `ContainerRuntime` interface stays + frozen. + +This stanza is human-readable guidance for the freeze coordinator; the +ledger rows themselves are encoded at freeze time via the submission +process, not appended here.