8000 T135 — The VM host drops a gone host-address box's rules from its gate by minimal-foundry[bot] · Pull Request #3014 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

T135 — The VM host drops a gone host-address box's rules from its gate - #3014

Merged
norrietaylor merged 19 commits into
mainfrom
agent/2944-the-vm-host-drops-a-gone-host-address-box-s-rule
Nov 5, 2026
Merged

norrietaylor merged 19 commits into
mainfrom
agent/2944-the-vm-host-drops-a-gone-host-address-box-s-rule

Conversation

@minimal-foundry
@minimal-foundry minimal-foundry Bot commented Nov 4, 2026 •
Copy link
Copy Markdown
Contributor

T135 — The VM host drops a gone host-address box's rules from its gate

slice: S16
kind: task
covers: NET-085
size: M
est: 160 code, 160 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: the diagnostics bundle's VM host daemon log carries one line per host-address box the reconcile dropped from or admitted back to the gate's union, naming the box and why
observability: one info line per box the reconcile drops or admits again, with the box, the guest's state for it and the trigger (a box event or the timer)
layers:
- host:
- crates/minvmd/src/box_registry.rs: reconcile_host_ip_boxes drops from host_ip_boxes every box the in-VM daemon does not report running, and admits again a box it reports running whose row still holds its rules
- crates/minvmd/src/control.rs: runs the reconcile against the in-VM daemon's session list on each box event the guest door sees and every 30 s
test: cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box
test: cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted
produces: none
consumes: none
depends on:
- blocked by #2929
proof: On a VM host, after the VM reaps or stops a host_ip box with no client asking, root inside the VM can no longer reach what only that box's rules allowed.

Proof

On a VM host, a host_ip box that the VM reaps, stops or exits with no client retire leaves the egress gate's union within 30 s, or sooner on the next box event at the guest door. After that, root inside the VM can no longer reach what only that box's rules allowed. A box the VM runs again gets back the rules the host client admitted. The VM host daemon log carries one info line per box dropped or admitted again, with the session, guest_state and trigger.

Notes from the agent: Design: BoxRegistry::reconcile_host_ip_boxes takes the guest's session-to-BoxState map. It treats active, pending and materializing as running. A resident box in any other state leaves the union. If the guest still lists it, its rules are set aside in a new dormant map, and they come back when the guest reports it running again. A box the guest does not list is forgotten. A client admit or retire clears the set-aside rules. The guest list can only narrow the union to rules a host client admitted. control.rs starts a reconcile thread beside the guest report door. It reads ListSessions over ssh.sock beside control.sock, the same path the stop flow uses. It runs on a nudge from guest-door box events (mint_box_id, listen_notice, admit_port, withdraw_port) and every 30 s, at most once a second. It does nothing while no host_ip box is held. A failed read changes nothing and logs one warn line until a read succeeds again. Not done: the end-to-end proof (root in the VM, a real reap) is not run here. Only the registry-level tests ran, plus the full minvmd suite once (695 passed). There is no control.rs test that drives the thread against 8000 a fake guest daemon. crates/minimal/src/cmd/boxes/vm_host.rs still has a doc comment (HostIpResidency::keep) that says the rules stay until destroy and cites issue 2747. That file is outside this task's layers, so I did not change it. A follow-up can update it.

Tests

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2ca5... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-bc61... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify

min task run agent-verify passed ([tasks.verify]).

Residuals

  • #3015: after a VM host daemon restart, a resumed host_ip box gets no egress until a client admits it again.

Closes #2944

The VM host daemon now reads the in-VM daemon's session list on each
box event the guest report door sees and every 30 s. A host_ip box the
VM no longer runs (reaped, stopped or exited with no client retire)
leaves the union the egress gate decides box-marked frames by. A box
the VM runs again rejoins with the rules the host client admitted.
The guest's list can only narrow the union, never widen it.
@coderabbitai
coderabbitai Bot commented Nov 4, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d21d3cbd-4707-4700-976d-f2506c967314

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@minimal-foundry
minimal-foundry Bot commented Nov 4, 2026 •
Copy link
Copy Markdown
Contributor Author

Approved: no findings at 0b9d428a661e.

Nothing to do.

Clobber: none seen: the removed doc text is replaced by text that describes the new reconcile.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Nov 4, 2026
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 3 conditions · the full ruling

The reconcile conforms to §4.3 rule 2 and §5.5. The gate now decides cohort frames by the live host_ip boxes only. The guest list can only narrow the union. The work that the PR leaves undone has no issue. File an issue for the end-to-end leg and the thread test (C1). Fix or file the stale HostIpResidency::keep comment (C2). Restore an issue link for the restart case (C3).

Ruled at d860695 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

Comment thread crates/minvmd/src/control.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@norrietaylor
Copy link
Copy Markdown
Member

/revise Arch conditions at d860695. The task's layers now carry scripts/session-e2e.sh and crates/minimal/src/cmd/boxes/vm_host.rs, so do all four. Do not file an issue for the first two: build them here.

  1. C1, end to end: add a leg to scripts/session-e2e.sh. Root inside the VM reaches a destination that only a host_ip box's rules allow. The in-VM daemon reaps or stops that box with no client retire. The same reach is refused within 30 s. After a resume, it is admitted again.
  2. C1, thread test: add host_ip_reconcile_thread_runs_on_nudge_and_timer for spawn_host_ip_reconcile in crates/minvmd/src/control.rs. Cover a nudge, the 30 s timer, and a failed read that changes nothing.
  3. C2: HostIpResidency::keep in crates/minimal/src/cmd/boxes/vm_host.rs still says the policy stays in the union until destroy, and cites Drop a gone host_ip box's rules from the VM gate's union after a reap or a failed retire #2747. Say the VM host's reconci 8000 le drops the rules while the box is not running and restores them on resume.
  4. C3: on the admit_host_ip_box doc in crates/minvmd/src/box_registry.rs, link A resumed host_ip box has no egress after a VM host daemon restart until a client admits it #3015 for the restart case, and list it under Residuals in the PR body.

The thread takes its interval and its session-list read as arguments,
so a test covers a nudge, the timer and a failed read that changes
nothing. The keep doc in the min CLI now says the reconcile drops a
stopped box's rules and a resume restores them. The admit doc links
#3015 for the restart case.
New case host_ip_rules_follow_the_running_box. Root in the VM wears the
node's address and the box mark at the gate. A host_ip box's rules admit
the probe while the box runs. After min box stop, which retires nothing
on the host, the gate drops the probe within the reconcile's 30 s timer.
After a resume through min session attach, the gate admits it again.
The spoofer takes --dscp and --src-port for the probes.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

The change conforms to NET-085. The reconcile drops a box that the VM does not run from the cohort union, as §4.3 rule 2 and §5.5 require. A failed read holds the last state, as §4.3 rule 3 requires. This head adds the reconcile thread test and a hard e2e leg. It also links the restart gap to #3015, and that gap fails closed. No condition is open.

Ruled at 1239cb0 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry minimal-foundry Bot removed the review:approved minimal-review approved the current head label Nov 4, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a /revise note, pushed as 1239cb095208.

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-fd56... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-ab86... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-d881... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "7c11d511cf35486d",
                "span_id": "9a94a687d78f6746",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "7c11d511cf35486d",
                "span_id": "ba7fc3f1b5035ef6",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "7c11d511cf35486d",
                "queued_behind": "0",
                "span_id": "ec6c7fe0020d5dd3",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "7c11d511cf35486d",
                "queued_behind": "0",
                "span_id": "e7f3d4b69400a9fb",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "e7f3d4b69400a9fb",
                "span_id": "ae5f38d823e55518",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "e7f3d4b69400a9fb",
                "queued_behind": "0",
                "span_id": "ec9426167b3b8017",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.019s] ( 892/1575) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.219s] ( 893/1575) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.011s] ( 894/1575) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  49.350s] 894/1575 tests run: 893 passed, 1 failed, 2 skipped
        FAIL [   3.148s] ( 891/1575) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 681/1575 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Review threads the coder judged:

  • 👍 valid — crates/minvmd/src/control.rs:1049: Per the /revise note, I built both here and filed no issue. host_ip_reconcile_thread_runs_on_nudge_and_timer drives the thread on a nudge, on its timer, and on a failed read that changes nothing. scripts/session-e2e.sh host_ip_rules_follow_the_running_box is the end-to-end leg. It is not yet run, be
  • 👍 valid — crates/minvmd/src/box_registry.rs:6085: The restart sentence on admit_host_ip_box now links A resumed host_ip box has no egress after a VM host daemon restart until a client admits it #3015, and notes ask for it under Residuals in the PR body.

On a VM host, scripts/session-e2e.sh host_ip_rules_follow_the_running_box shows the reach that root in the VM gets through the box mark at the node address. A running host_ip box's rules admit that reach. After min box stop, which retires nothing on the host, the gate drops the same probe within the reconcile's 30 s timer, and the log shows the reconcile's drop line for the box. After a resume, the gate admits the probe again. The case is written but did not run on this box (no /dev/kvm), so the proof is not yet observed end to end. The unit and thread tests pass.

Notes from the agent: Revise round 1. All four directive items are done. (1) New e2e case host_ip_rules_follow_the_running_box in scripts/session-e2e.sh. It is wired into the whole-lane order after escapes_and_builds_stay_inside_box_rules, into the direct-call VM case list, into the named-case dispatch and usage, and into the header. The spoofer that the case shares with the escape-union case now takes --dscp and --src-port. Defaults keep the old behaviour. Design: a spoofed SYN from the node address cannot complete, because the switch sends the SYN-ACK to the real guest's MAC. So the case reads the gate's per-SYN debug line 'decided a box-marked frame' (target minvmd::egress_gate::marked) for each probe's source port. It does not use a listener. The stop arm allows 35 s: the 30 s timer plus 5 s for the session-list read and the probe. NOT RUN: this box has no /dev/kvm. The e2e case needs the KVM or macOS VM lane (just e2e). bash -n and shellcheck -S warning are clean. Assumptions the lane will test: a host_ip box with no egress section admits a TCP SYN to 198.51.100.9:443 in the current egress-default phase (the case fails on the running arm and prints min session policy if not), and the in-VM daemon lists a box stopped by min box stop as stopped. (2) host_ip_reconcile_thread_runs_on_nudge_and_timer: spawn_host_ip_reconcile now calls spawn_host_ip_reconcile_with(boxes, interval, reader), so t…[truncated]

A reconcile applied a session list that could predate a client admit, so
a box created or resumed while the list was in flight lost its rules with
nothing set aside. The reconcile now takes an admit mark read before the
list and leaves alone every box a client admitted after it.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

This head conforms to NET-085. The new admit mark stops a reconcile from dropping a box on a session list that is older than the box's client admit. The skip lasts one pass and adds no rules, so the guest list still only narrows the union (§4.3 line 88). The merge of main is clean. No conditions are open. Issue #3015 still owns the restart case.

Ruled at 5e114c1 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 3 unresolved threads — minimal-arch[bot] crates/minvmd/src/control.rs:1049, minimal-arch[bot] crates/minvmd/src/box_registry.rs:6085, minimal-foundry[bot] crates/minvmd/src/box_registry.rs:6272. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on a failed check suite, pushed as 5e114c191c2b.

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2f1b... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-e07f... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-9c8d... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "bacaaf85173baf8c",
                "span_id": "c3fc94cdcf2e720d",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "bacaaf85173baf8c",
                "span_id": "fb93288341b4c293",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "bacaaf85173baf8c",
                "queued_behind": "0",
                "span_id": "2be127fc93be6d30",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "bacaaf85173baf8c",
                "queued_behind": "0",
                "span_id": "13813071d8ef2058",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "13813071d8ef2058",
                "span_id": "bddc783b4e3af236",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "13813071d8ef2058",
                "queued_behind": "0",
                "span_id": "0df3422392105be1",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.028s] ( 892/1575) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.222s] ( 893/1575) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.014s] ( 894/1575) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  51.010s] 894/1575 tests run: 893 passed, 1 failed, 2 skipped
        FAIL [   3.186s] ( 891/1575) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 681/1575 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Review threads the coder judged:

  • 👍 valid — crates/minvmd/src/box_registry.rs:6272: Added an admit generation: the reconcile thread reads host_ip_admit_mark() before the session list, and reconcile_host_ip_boxes leaves alone any box a client admitted after that mark. A test pins the race.

On a VM host, the VM host daemon drops a host_ip box's rules from the gate's union within 30 s after the VM reaps or stops the box with no client asking. Root inside the VM then cannot reach what only that box's rules allowed. A box that a client admits while a session list read is in progress keeps its rules for that pass.

Notes from the agent: This round fixes the review thread. The reconcile takes a HostIpAdmitMark that the thread reads before the in-VM session list. A box that a client admitted after the mark survives that pass. host_ip_rules_retired_when_guest_no_longer_runs_box now covers this race. The failed test-kvm check: the job excerpt in the directive shows only the workflow's script text and no failing step, so I could not find the cause. This box has no /dev/kvm, so I did not run scripts/session-e2e.sh (host_ip_rules_follow_the_running_box). bash -n on the script passes. If the failure is in that case, its hrf_fail output in the full job log names the arm. I did not run just clippy-strict.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — every review thread is resolved; @norrietaylor closed the last one. The review of 5e114c191c2b withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.

@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read at 5e114c1. The thread test and the end-to-end leg are in, the restart case links #3015, and the admit mark closes the stale-list race. Arch passes.

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Nov 4, 2026
…t-drops-a-gone-host-address-box-s-rule

Keep both sides of box_registry.rs: the reconcile types and main's
host_ip registration ids. The reconcile now withdraws the registration
name of a box the guest no longer lists, as a retire does. A box it set
aside as stopped keeps its name, so a stale-name check counts it.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: CONDITIONS · 1 condition · the full ruling

The merge of #2861 edits register_host_ip_box_as(). With that edit, a stopped host_ip box keeps its registration name against a new box. The design, architecture.md line 389, says that a name is unique only am 10BC8 ong running boxes, and that a new box may reuse a stopped box's name. A resume runs under the box's own box_id, so it does not need the name entry. Remove the dormant term from that check, and make the new test prove reuse after the bound. That is C1. The rest of the merge conforms, and NET-085 keeps its PASS from 5e114c19.

Ruled at 8fe9469 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 3, not counted against the cap (1 of 3), pushed as 8fe9469a58bd.

Resolved conflicts in: crates/minvmd/src/box_registry.rs

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-3ce8... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-22ee... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-ff5c... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "a6224d32bf710172",
                "span_id": "d99b85ce59d08b2b",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "a6224d32bf710172",
                "span_id": "ae385cb30cf276e0",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "a6224d32bf710172",
                "queued_behind": "0",
                "span_id": "b5d5b3f769264b00",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "a6224d32bf710172",
                "queued_behind": "0",
                "span_id": "622804eaaee56a08",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "622804eaaee56a08",
                "span_id": "cbe7548252aaf44f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "622804eaaee56a08",
                "queued_behind": "0",
                "span_id": "0b5eecb41eebf966",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.020s] ( 903/1591) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.219s] ( 904/1591) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.015s] ( 905/1591) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  47.202s] 905/1591 tests run: 904 passed, 1 failed, 2 skipped
        FAIL [   3.057s] ( 902/1591) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 686/1591 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

On a VM host, after the VM reaps or stops a host_ip box with no client asking, the reconcile drops that box's rules from the gate's union within 30 s, so root inside the VM can no longer reach what only that box's rules allowed. A resume restores them. This holds at the branch head after the merge with main.

Notes from the agent: Conflict round. The one conflict in crates/minvmd/src/box_registry.rs was two independent additions next to each other: this branch's reconcile types and main's HostIpIds/HostIpName. Both sides are kept. Main's merge also added host_ip registration names, so two integration fixes are in the merge commit. First, reconcile_host_ip_boxes now withdraws the registration name of a box the guest no longer lists, the same as retire_host_ip_box does. Second, register_host_ip_box's stale-name check counts a set-aside (stopped) box as admitted, so a stopped box keeps its name for its resume. A new test pins both: host_ip_rules_retired_when_guest_no_longer_runs_box_withdraws_only_an_ended_name. The first test line's filter matches it. cargo clippy -p minvmd --all-targets is clean. I did not run just ci or the e2e script.

@norrietaylor
Copy link
Copy Markdown
Member

/revise Arch at 8fe9469, C1, in crates/minvmd/src/box_registry.rs. In register_host_ip_box_as(), compute admitted as resident.boxes.contains_key(&session) only, and remove || resident.dormant.contains_key(&session) and its comment. Then fix the test at line 13736: after the Stopped reconcile, call registry.advance_clock(HOST_IP_UNADMITTED_NAME_BOUND) and assert that register_host_ip_box("held") returns Ok with a new id. Change nothing else.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/control.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 5 of 10 on a /revise note, pushed as 98375967ab03.

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-33e5... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-4ab1... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-7102... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "ad6ed69a44e8e7d1",
                "span_id": "1eef23f6571d2fb5",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "ad6ed69a44e8e7d1",
                "span_id": "78c5c0bd980303e6",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "ad6ed69a44e8e7d1",
                "queued_behind": "0",
                "span_id": "26d0aa1afc49488f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "ad6ed69a44e8e7d1",
                "queued_behind": "0",
                "span_id": "834b3b06332b6a26",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "834b3b06332b6a26",
                "span_id": "d9341b4543ab9f8e",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "834b3b06332b6a26",
                "queued_behind": "0",
                "span_id": "02143fbc4312ec10",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.015s] ( 914/1604) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.223s] ( 915/1604) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.013s] ( 916/1604) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  51.588s] 916/1604 tests run: 915 passed, 1 failed, 2 skipped
        FAIL [   3.165s] ( 913/1604) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 688/1604 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Review threads the coder judged:

  • 👎 invalid — PRRT_kwDOPdfcxM6z5X7L: The host answerer does not read the host_ip id set's by_name. zone_view builds from rows and held_names only. So a pass that only forgets a set-aside box's name changes no answer, and no ping is needed. retire_host_ip_box pings only when it drops resident rules, not on a name withdrawal alone. (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — crates/minvmd/src/control.rs: Each pass now takes boxes.host_ip_admit_mark() before read_guest(), as at 1e445e0 (reverted 305615b). A resumed box that was dropped gets a follow-up pass after HOST_IP_RECONCILE_MIN_GAP.
  • 👍 valid — crates/minvmd/src/control.rs: Removed previous and the std::mem::replace. The pass's mark is the admit count before the read. A new previous only decides whether a follow-up pass runs. It never keeps a box's rules.
  • 👍 valid — crates/minvmd/src/box_registry.rs: Restored the reconcile_host_ip_boxes, host_ip_admit_mark and HostIpAdmitMark docs to the 1e445e0 text.
  • 👍 valid — crates/minvmd/src/box_registry.rs: Replaced the test with host_ip_box_running_again_is_readmitted_after_a_drop_on_a_stopped_list. The box listed Stopped is dropped into dormant, and the next Active list admits it again with its rules.

On a VM host, when the VM reaps or stops a host_ip box with no client asking, the next reconcile pass (a box event, or at most 30 s) drops that box's rules from the gate's union. A box the guest lists as stopped never keeps its rules for an extra pass. After a resume, the thread runs one more pass after 1 s, so the box gets its rules back as soon as the guest lists it running.

Notes from the agent: Round 5. 6d2912a reverts 305615b: the mark is taken after the holds_host_ip_boxes() check and before read_guest(), and the box_registry docs and control.rs tests are back to their 1e445e0 text. 9837596 adds BoxRegistry::host_ip_admitted_after and a follow-up pass in spawn_host_ip_reconcile_with: when a pass drops a box admitted since the previous pass's mark, the thread runs one more pass after HOST_IP_RECONCILE_MIN_GAP. That pass logs trigger=timer. The first pass of the thread has no previous mark, so any drop on it runs a follow-up. That costs one extra read. New tests: host_ip_box_running_again_is_readmitted_after_a_drop_on_a_stopped_list (box_registry) and host_ip_reconcile_thread_runs_again_after_dropping_a_new_admit (control). scripts/session-e2e.sh was not run here: it needs a KVM VM. clippy -p minvmd --all-targets is clean. I did not run just clippy-strict.

@norrietaylor
Copy link
Copy Markdown
Member

/revise One line, in spawn_host_ip_reconcile_with in crates/minvmd/src/control.rs: set previous only in the Ok arm of read_guest(), so a failed read does not advance it. Add a test that an admit before a failed read still gets its follow-up pass. Change nothing else.

A failed session-list read no longer moves the mark of the last pass
that read the list, so an admit from before the failed read still gets
its follow-up pass.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

This push makes a failed session-list read leave the reconcile mark where the last good read put it. Before, a failed read moved the mark, and a resumed box that the next pass dropped had to wait for the 30 s timer. Section 5.5 line 184 says a resume re-enters by the same path as creation. A failed read still changes no rules, so section 4.3 line 85 (never fail open) holds. The new thread test fails on the old head and passes on this one. The rest of the PR keeps the PASS on 98375967.

Ruled at d0727e6 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 2 findings, 2 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 6 of 10 on a /revise note, pushed as d0727e6088e8.

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-5ccf... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-c463... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-7c14... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "d770de06a8d6f502",
                "span_id": "71c19e9c64346417",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "d770de06a8d6f502",
                "span_id": "809932980095bb9f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "d770de06a8d6f502",
                "queued_behind": "0",
                "span_id": "d871f29933094bc0",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "d770de06a8d6f502",
                "queued_behind": "0",
                "span_id": "0ba39861cf50a698",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "0ba39861cf50a698",
                "span_id": "3e6bdc5664ffeb8d",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "0ba39861cf50a698",
                "queued_behind": "0",
                "span_id": "2a9df7765a812eec",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.026s] ( 914/1605) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.220s] ( 915/1605) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.011s] ( 916/1605) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  50.739s] 916/1605 tests run: 915 passed, 1 failed, 2 skipped
        FAIL [   3.031s] ( 913/1605) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 689/1605 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Review threads the coder judged:

  • 👍 valid — PRRT_kwDOPdfcxM6z6aCt: previous now advances only in the Ok arm of read_guest(). A new test, host_ip_reconcile_thread_runs_again_after_a_failed_read, shows that an admit from before a failed read still gets its follow-up pass. (not posted on the thread: not an open thread on the pull request)

On a VM host, after the VM reaps or stops a host_ip box with no client asking, root inside the VM can no longer reach what only that box's rules allowed. With this round, a box that a client resumes just before a failed session-list read also rejoins on the follow-up pass, and does not wait for the 30 s timer.

Notes from the agent: This round sets previous only in the Ok arm of read_guest() in spawn_host_ip_reconcile_with, and adds host_ip_reconcile_thread_runs_again_after_a_failed_read. I ran the new test against the old code and it failed at the follow-up-pass expectation. With the fix, it passes. No test: line names the new test, so I ran it on its own. clippy -p minvmd --all-targets and cargo fmt --check are clean. Nothing else changed.

…t-drops-a-gone-host-address-box-s-rule

# Conflicts:
#	scripts/session-e2e.sh
The reconcile admits a set-aside box again on the guest's word, as a
real resume does. Retired rules are never set aside.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

The compare has a merge of main (#3028) and one doc-comment commit. The merge conflict in scripts/session-e2e.sh resolves to keep both e2e legs. The new comment on reconcile_host_ip_boxes agrees with the code. It also agrees with the §4.3 line 88 bound: a guest list selects only within the rules that a host client admitted. NET-085 conforms, as in the PASS on d0727e60.

Ruled at 11ab51b against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 7, not counted against the cap (2 of 3), pushed as 11ab51ba56fc.

Resolved conflicts in: scripts/session-e2e.sh

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-bc1a... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-7548... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-c369... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "892d06570d0ea229",
                "span_id": "1840e34975ecfd22",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "892d06570d0ea229",
                "span_id": "439cf8ddd445860e",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "892d06570d0ea229",
                "queued_behind": "0",
                "span_id": "b72838a688a53486",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "892d06570d0ea229",
                "queued_behind": "0",
                "span_id": "29fc2e5d63909033",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "29fc2e5d63909033",
                "span_id": "4226060a5aa961c8",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "29fc2e5d63909033",
                "queued_behind": "0",
                "span_id": "db5763a698f9ae38",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.021s] ( 914/1605) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.219s] ( 915/1605) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.011s] ( 916/1605) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  50.523s] 916/1605 tests run: 915 passed, 1 failed, 2 skipped
        FAIL [   3.057s] ( 913/1605) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 689/1605 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Review threads the coder judged:

  • 👎 invalid — crates/minvmd/src/box_registry.rs:6494: NET-085 bounds root in the VM to the union of resident boxes' declared egress. Root can resume a stopped box for real, and that brings back the same rules a false list can. The task's layer asks the reconcile to admit a box again when the guest reports it running. The guest can only bring back rules
  • 👎 invalid — PRRT_kwDOPdfcxM6z60Pr: The premise is wrong. create.rs runs ActivationStep::CreateSession at line 1935, and the admit_declaring call at line 2044 uses the id that the create returned. So the guest create always comes before the admit. A pass takes its mark before it reads the list. If that list was read before the create, (not posted on the thread: not an open thread on the pull request)

On a VM host, when the VM reaps or stops a host_ip box and no client asks, the reconcile removes that box's rules from the gate within 30 s. After that, root inside the VM can no longer reach what only those rules allowed. A resume in the VM brings the rules back.

Notes from the agent: The merge with main conflicted in scripts/session-e2e.sh, on one line of the standalone-case list. I kept both host_ip_rules_follow_the_running_box and host_exposures_follow_the_table, and both proofs still dispatch. I did not run the session-e2e case on this box. I changed only the reconcile doc in box_registry.rs. It now says exactly what a guest's session list can bring back. The e2e proof is not run here because it needs a KVM lane.

@norrietaylor
Copy link
Copy Markdown
Member

/revise Comments only. The minimal-review threads on reconcile_host_ip_boxes are right that two comments overstate the bound. Root in the VM controls the list, so a false running can restore a dormant box's rules. Those rules are still ones a host client admitted, so the union stays within the resident set (NET-085, design line 88). Say that in both places: crates/minvmd/src/control.rs:865 (only narrows the union) and crates/minvmd/src/box_registry.rs:6435 (never widen it). State that a guest can move the union only within what host clients admitted, never past it. Change no code.

Root in the VM controls the in-VM daemon's session list. A false running
can restore a set-aside box's rules, so the list does not only narrow the
union. It moves the union only within the rules host clients admitted.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

This push changes only two comments, and the merge of main is clean. The new comments say a guest's session list moves the host_ip union only within the rules host clients admitted. Section 4.3 line 88 gives that bound to a node-asserted input. The PASS on 11ab51ba stands, and nothing more is necessary.

Ruled at e190a7c against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 8 unresolved threads — minimal-arch[bot] crates/minvmd/src/box_registry.rs, minimal-arch[bot] crates/minvmd/src/box_registry.rs, minimal-arch[bot] crates/minvmd/src/control.rs, minimal-arch[bot] crates/minvmd/src/control.rs, minimal-arch[bot] crates/minvmd/src/box_registry.rs, …. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 7 of 10 on a /revise note, pushed as e190a7ccaf55.

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-21a7... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-cb6c... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-3179... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "b618587da1758269",
                "span_id": "fa22ee14bf51ce6c",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "b618587da1758269",
                "span_id": "b8c13285dd958510",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "b618587da1758269",
                "queued_behind": "0",
                "span_id": "fab753e6d218ae8c",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "b618587da1758269",
                "queued_behind": "0",
                "span_id": "de86219504b3c67f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "de86219504b3c67f",
                "span_id": "7278beac760e3378",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "de86219504b3c67f",
                "queued_behind": "0",
                "span_id": "b54dd1d4a43ce366",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.021s] ( 922/1613) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.220s] ( 923/1613) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.010s] ( 924/1613) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  50.311s] 924/1613 tests run: 923 passed, 1 failed, 2 skipped
        FAIL [   2.995s] ( 921/1613) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 689/1613 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Review threads the coder judged:

  • 👍 valid — crates/minvmd/src/box_registry.rs:6496: The comments in control.rs and on reconcile_host_ip_boxes now state the trust limit: root in the VM can restore a set-aside box's rules with a false running, so it moves the union only within what host clients admitted, never past it. The behaviour stays as NET-085 designs it.

On a VM host, after the VM reaps or stops a host_ip box with no client asking, root inside the VM can no longer reach what only that box's rules allowed. This round changes no behaviour. The comments in control.rs and on reconcile_host_ip_boxes now state that root in the VM can move the union only within the rules host clients admitted, never past them.

Notes from the agent: Comments only, as the /revise note asked. No code changed. The comment at control.rs:865 no longer says the list only narrows the union. The doc on reconcile_host_ip_boxes no longer says a lying guest can never widen egress. Both say that a false running can restore a set-aside box's rules, within the resident set.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — every review thread is resolved; @norrietaylor closed the last one. The review of e190a7ccaf55 withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.

@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read at e190a7c. The mark is taken before the read, previous moves only on a good read, a stopped box never keeps its rules, and the comments state the real trust limit. Arch passes.

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Nov 5, 2026
…t-drops-a-gone-host-address-box-s-rule

# Conflicts:
#	scripts/session-e2e.sh
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

The new head is one merge of main and has no branch commit. The one conflict is in scripts/session-e2e.sh, and the resolution keeps both proofs in the case list and in the run order. The reconcile, the dormant set and the reconcile thread do not change. NET-085 conforms to §4.3 line 84 and §5.5 line 183, as on e190a7cc. Residual #3015 stays filed.

Ruled at 0b9d428 against gominimal/arch@7a86ec7bb3c0 by claude-opus-5-5.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 8, not counted against the cap (3 of 3), pushed as 0b9d428a661e.

Resolved conflicts in: scripts/session-e2e.sh

line exit tail
cargo nextest run -p minvmd host_ip_rules_retired_when_guest_no_longer_runs_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-b78c... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minvmd host_ip_box_running_again_is_readmitted 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-9a8a... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil
cargo nextest run -p minvmd host_ip_reconcile_thread_runs_on_nudge_and_timer 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-9697... Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minvmd v0.8.0 (/workbench/crates/minvmd) Finished 'test' profil

Verify min task run agent-verify exited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ent_span_id": "9ac5f6d275c332fd",
                "span_id": "5eb7aede419a65c2",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "9ac5f6d275c332fd",
                "span_id": "db6678ae53c14fc2",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "9ac5f6d275c332fd",
                "queued_behind": "0",
                "span_id": "9788a09678327f2e",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "9ac5f6d275c332fd",
                "queued_behind": "0",
                "span_id": "35988198fd153918",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "35988198fd153918",
                "span_id": "da1516f56c1b114a",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "35988198fd153918",
                "queued_behind": "0",
                "span_id": "9051e391faf3a390",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   3.018s] ( 927/1621) minvmd box_registry::tests::a_closed_shuttle_detaches_rows_until_the_grace
        PASS [   2.218s] ( 928/1621) minvmd box_registry::tests::a_reattributed_box_keeps_its_row
        PASS [   5.011s] ( 929/1621) minvmd box_registry::tests::a_registration_refused_for_a_held_address_spends_no_switch_address
────────────
     Summary [  55.410s] 929/1621 tests run: 928 passed, 1 failed, 2 skipped
        FAIL [   3.041s] ( 926/1621) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 692/1621 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

On a VM host, after the VM reaps or stops a host_ip box with no client asking, the reconcile drops that box's rules from the gate, so root inside the VM can no longer reach what only those rules allowed. The merge with main keeps the host_ip_rules_follow_the_running_box e2e case beside main's new host_stop_stops_boxes_then_daemon_and_vm case.

Notes from the agent: Conflict round only. The merge of origin/main conflicted in scripts/session-e2e.sh in two places: the VM-case list and the proof run order. I kept both sides in each place. host_ip_rules_follow_the_running_box runs before main's host_stop_stops_boxes_then_daemon_and_vm proof. bash -n passes on the script. I did not run the e2e script, because it needs a KVM host. The other merged files came from main and merged without conflict.

@no
DE59
rrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approved at 0b9d428. This head only merges main. The conflict resolution keeps T135's and T28's e2e cases side by side. box_registry.rs is unchanged, and control.rs gains only T140's clear_down from main. CI, arch-review and minimal-review pass, and the host_ip proof printed OK on both VM lanes.

@norrietaylor
norrietaylor added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit 41a7dd7 Nov 5, 2026
36 checks passed
@norrietaylor
norrietaylor deleted the agent/2944-the-vm-host-drops-a-gone-host-address-box-s-rule branch November 5, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review:approved minimal-review approved the current head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

T135 — The VM host drops a gone host-address box's rules from its gate

1 participant

0