Enforce Architectural Guard in MicroVM sessions

Task 5999 · Done · Coder · created · updated

Epic 5896 (Architectural Guard), finish-phase gap. PRD R3.3 says the guard covers every session Jaah launches, runners AND console sessions, on every in-scope project. Sessions on a MicroVM node get no guard at all today. ## What I observed (read-only, develop @ 4edf65443) - Static runners: `apps/api/app/lease_drain.py:1235` puts `guard=guard_runtime.lease_stanza(session, project_id)` on the `lease_slot` intent. Console: `apps/api/app/routes/console.py:385-390` and `apps/api/app/console_direct.py:710`. The node turns that stanza into a bundle file plus env (`apps/jaahd/guard_bundle.py::prepare_launch`, called from `fleet_dispatch.py`, `console.py` and `clauded_wt.py`). Hooks only enforce when `JAAH_GUARD_BUNDLE` is set. - MicroVM: `apps/api/app/microvm_placement.py:267` `admit()` composes the prompt and mints `provision` and `launch` (`_model_launch`). It never calls `guard_runtime.lease_stanza`. Nothing under `apps/jaahd/microvm_*.py` (`microvm_session.py`, `microvm_console.py`, `microvmd.py`) mentions `guard_bundle` or `JAAH_GUARD_*`. Task 5931's report confirms it: "MicroVM runners do not receive the stanza yet". - Effect: in an org with Compliance and Advanced Compliance both on, a task or console session placed on a MicroVM node passes no per-write check, no shell-commit check and no pre-push guard step. The rules sit in an Antigravity prompt at most. That breaks the epic's "absolute, unyielding" ask without any error. ## Fix (reuse what exists; add no new surface) 1. CP: put the same `guard` stanza (`guard_runtime.lease_stanza`) on the MicroVM model-runner launch and on the MicroVM console launch. When the guard is unavailable, the payload must stay byte-identical. 2. Node and guest: when the stanza is present, run the same `guard_bundle` fetch and refresh for the VM session, so the guest sees `JAAH_GUARD_BUNDLE`, `JAAH_GUARD_RUNTIME`, `JAAH_GUARD_BASE` and `JAAH_GUARD_STATE`. Wire the same `fleet_launch` lifecycle chain entries with `guard=True`. Prefer the mechanism project-memory bundles already use to reach a VM, if one exists. Decisions use the existing `guard.record` call or the spool. 3. Keep G-1: a miss is fail-open and recorded as `error`. ## Out of scope - Do not change static-pool or console behaviour, the guard engine or rule kinds, the waiver or escalation flow, or the MicroVM egress, sizing and retention rules. - No new UI. No merge-time block. ## Done means - Unit test: a MicroVM admit for a guard-available project carries `guard: {project_id}`. An unavailable org's admit payload is unchanged (byte-identical golden). - Unit/contract test: the VM session's env carries `JAAH_GUARD_BUNDLE` only when the stanza is present. - Dev oracle: in org-b on a MicroVM node, a Claude coder task told to write `import requests` into a `*.py` file under the "Use httpx" gate rule (or an equivalent gate rule) is denied. A Guard activity row appears with the task number, and the httpx retry lands. - `./dc check full` green; Jaah Deploy to dev succeeds.

Outcome

MicroVM runner and console sessions now get the Architectural Guard (CP stanza plus a VM bundle, env and hooks, hardened against guest planting). PR #5226 merged, dev deploy OK. Not verified: the live dev oracle (no org has both the guard and a MicroVM node). Deferred: per-write hooks for no-number console tabs.

Pull request

Artifacts

Activity

  • Ready
  • Runner started
  • Runner ended (done)