8000 T117 — Give a host-address grant box an id and open the proxy lane to its cohort by minimal-foundry[bot] · Pull Request #2861 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

T117 — Give a host-address grant box an id and open the proxy lane to its cohort - #2861

Merged
norrietaylor merged 36 commits into
mainfrom
agent/2854-give-a-host-address-grant-box-an-id-and-open-the
Nov 4, 2026
Merged

norrietaylor merged 36 commits into
mainfrom
agent/2854-give-a-host-address-grant-box-an-id-and-open-the

Conversation

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

T117 — Give a host-address grant box an id and open the proxy lane to its cohort

slice: S17
kind: task
covers: BEP-082, BEP-083
size: L
est: 400 code, 480 tests
executor: agent
difficulty: unknown ground
model: strongest
diagnostics: min box show <box> shows the host-minted box id of a host_ip grant box, and min box audit <box> reads its records by that id; a host_ip grant box on a VM host is no longer refused with "no Box Egress Proxy serves boxes on this machine"; min session policy <box> shows the credentialed-upstream row for a host_ip grant box, and the gate's drop log names ProxyLane for a cohort connection while no resident member declares a lane
observability: the existing info line of each registration names the box id, the network mode and whether a switch address was allocated, and the gate's existing debug line for a host-address verdict names the lane state of the cohort and the count of members that declare one
layers:
- registry:
- crates/minvmd/src/control.rs: RegisterBox accepts a host_ip box and returns a creation-unique box id with no switch address
- crates/minvmd/src/box_registry.rs: a host_ip registration records the minted id with no row in the address table, and its revocation check is the one an own_ip id takes
test: cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_id
- client:
- crates/minimal-client/src/box_registration.rs: register_box_for_activation registers a host_ip box on a VM host when its spec declares a credentialed upstream, and still returns None for one that declares none
- crates/minimal/src/cmd/boxes/create.rs: proxy_box_facts gets the minted id for a host_ip grant box, so the NotServed refusal prints only where no proxy serves the host
test: cargo nextest run -p minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved
- rpc:
- crates/minimald-rpc/src/lib.rs: HostIpBoxRequest carries whether the box declares a credentialed upstream
- crates/minimald-rpc/src/tests.rs: a round-trip test pins the new field and its default for an older client
test: cargo nextest run -p minimald-rpc host_ip_box_request_carries_the_lane_declaration
- client:
- crates/minimal-client/src/attach.rs: AdmitHostIpBox sends the lane declaration, and the admission completes before the box's first process starts, not after the create
test: cargo nextest run -p minimal-client host_ip_admission_carries_the_lane_and_waits_for_the_answer
- gate:
- crates/minvmd/src/box_registry.rs: HostIpBoxRules carries the lane bit, and the cohort's lane is the union of its resident members' bits
- crates/minvmd/src/net/egress_gate.rs: host_ip_verdict admits the cohort address to the proxy's listener ports while the cohort's lane is open, and drops it as ProxyLane while it is closed
test: cargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane
test: cargo nextest run -p minvmd host_ip_cohort_proxy_lane_dropped_without_a_declaring_member
produces:
- the cohort's proxy lane at the host gate
consumes: none
proof: On a Mac, a GitHub grant box started with --network host_ip is created with a box id and reaches the proxy's listener, and after it ends, a host-address box with no grant cannot reach the proxy's address.

Proof

On a VM host, min box create --network host_ip for a box with a GitHub grant registers with minvmd and gets a host-minted box id with no switch address and no row in the address table. The grant is served under that id with the host_ip stance, and the "no Box Egress Proxy serves boxes on this machine" refusal does not print. The admit tells the host gate that the box declares a credentialed upstream. While that box is resident, the gate admits a host_ip cohort frame to the proxy's listener port. When it is retired, a host_ip box with no grant drops at the proxy's address under the ProxyLane rule. Unit and in-process control-socket tests show this. Nobody ran it on a real Mac with a microVM in this session.

The admit comes after CreateSession and before ActivationStep::Finalize, so the box is admitted before its first process starts.

Notes from the agent: Spec excerpt: .implement/spec.md does not contain BEP-082 or BEP-083. Its IDs stop at BEP-079. I worked from the task text alone.

Files changed outside the layers, each one needed:

  • crates/minvmd/tests/common/mod.rs and crates/minvmd/tests/vm_escape_integration.rs: struct literals of RegisterBoxRequest and HostIpBoxRequest needed the new fields, or the minvmd test targets do not compile.
  • crates/minimal/src/cmd/boxes/vm_host.rs: one RegisterBoxRequest literal. Also new HostIpResidency::admit_declaring and host_ip_box_with_vm_host_declaring, so create.rs can send the lane bit. The min session attach re-admit now sends the record's lane bit. Without that, a re-admit replaces the member's rules with lane=false and closes the lane.
  • crates/minimal/src/dash/rpc.rs: the dashboard's attach re-admit carries the lane bit, for the same reason.

Design choices:

  • RegisterBoxRequest gained host_ip: bool (serde default false). minvmd answers a host_ip registration with the existing BoxIdMinted reply. It sends no new reply variant, so no exhaustive match changes.
  • RegisteredWithVmHost gained host_ip: bool and row_addresses(). For a host_ip registration, addresses is 0.0.0.0/0.0.0.0. create.rs does not put a host_ip registratio…[truncated]

Tests

line exit tail
cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_id 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-24e3... 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 minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-cc3c... 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 minimald-rpc host_ip_box_request_carries_the_lane_declaration 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-8225... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling common v0.0.1 (/workbench
cargo nextest run -p minimal-client host_ip_admission_carries_the_lane_and_waits_for_the_answer 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-53d4... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling version v0.8.0 (/workbench/crates/version) Compiling common v0.0.1 (/workb
cargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-b99a... 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_cohort_proxy_lane_dropped_without_a_declaring_member 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-9549... 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.

       "span_id": "b9d42f987957cddf",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "c0babd31628978d6",
                "span_id": "fa3c1a0c53f28a26",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "c0babd31628978d6",
                "queued_behind": "0",
                "span_id": "462a0fd72834bcda",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "c0babd31628978d6",
                "queued_behind": "0",
                "span_id": "50a5552b171d2c56",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "50a5552b171d2c56",
                "span_id": "c30f334edc77f63e",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "50a5552b171d2c56",
                "queued_behind": "0",
                "span_id": "200db95dc8531eb0",
                "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 [   5.014s] ( 949/1726) minimal-client box_registration::tests::resume_timeout_goes_on_and_an_absent_host_fails_closed
        PASS [   4.571s] ( 950/1726) minimal-client tty_relay::tests::resume_after_drop_prints_line_and_nudges_winsize
        PASS [   6.156s] ( 951/1726) minimal-client box_registration::tests::a_silent_daemon_does_not_hold_the_exit_past_the_deadline
────────────
     Summary [  46.976s] 951/1726 tests run: 950 passed, 1 failed, 2 skipped
        FAIL [   3.104s] ( 948/1726) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 775/1726 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

Out of scope

These files are outside the task's layers:, so this PR is a draft:

  • crates/minimal/src/cmd/boxes/vm_host.rs
  • crates/minimal/src/dash/rpc.rs
  • crates/minvmd/tests/common/mod.rs
  • crates/minvmd/tests/vm_escape_integration.rs

Closes #2854

Residuals

8000
HostIpBoxRequest says whether the box declares a credentialed upstream,
and RegisterBoxRequest says whether the box is a host_ip box. Both
default to false, so an older client's line reads as before.
A host_ip registration gets a creation-unique box id and no switch
address. The registry records the id with no row in the address table,
and the id takes the same collision check an own_ip id takes.
The gate admits a host_ip cohort frame to the proxy's listener while a
resident member declares a credentialed upstream, and drops it as
ProxyLane while none does. Its debug line names the lane state and the
count of declaring members.
register_box_for_activation registers a host_ip box whose spec declares
a credentialed upstream, and gets its box id with no row. The host_ip
admit carries the box's lane declaration and returns once answered.
min box create registers a host_ip grant box for its box id, so the
grant is served and not refused as unserved. The admit and the attach
re-admits carry the box's lane declaration to the host gate.
@coderabbitai
coderabbitai Bot commented Nov 3, 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: d8a73902-e42b-4e28-85d1-3b3f32bf69f4

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

…t-address-grant-box-an-id-and-open-the

# Conflicts:
#	crates/minimald-rpc/src/tests.rs
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

Resolved conflicts in: crates/minimald-rpc/src/tests.rs

line exit tail
cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_id 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-4647... 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 minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-a246... 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 minimald-rpc host_ip_box_request_carries_the_lane_declaration 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-9a5e... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling common v0.0.1 (/workbench
cargo nextest run -p minimal-client host_ip_admission_precedes_the_first_process 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-b8f5... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling version v0.8.0 (/workbench/crates/version) Compiling common v0.0.1 (/workb
cargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-d7c8... 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_cohort_proxy_lane_dropped_without_a_declaring_member 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-2173... 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.

       "span_id": "bb1b2c8eb152757a",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "457fd2f0a1ca46c9",
                "span_id": "3fa0bce9735957c9",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "457fd2f0a1ca46c9",
                "queued_behind": "0",
                "span_id": "9af86cbd870c31cc",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "457fd2f0a1ca46c9",
                "queued_behind": "0",
                "span_id": "ccb9fa98eb734210",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "ccb9fa98eb734210",
                "span_id": "f04ee91497afc1e2",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "ccb9fa98eb734210",
                "queued_behind": "0",
                "span_id": "01b2cb697fb587db",
                "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 [   5.010s] ( 950/1728) minimal-client box_registration::tests::resume_timeout_goes_on_and_an_absent_host_fails_closed
        PASS [   4.316s] ( 951/1728) minimal-client tty_relay::tests::resume_after_drop_prints_line_and_nudges_winsize
        PASS [   6.056s] ( 952/1728) minimal-client box_registration::tests::a_silent_daemon_does_not_hold_the_exit_past_the_deadline
────────────
     Summary [  42.004s] 952/1728 tests run: 951 passed, 1 failed, 2 skipped
        FAIL [   2.859s] ( 949/1728) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 776/1728 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

Outside the task's layers::

  • crates/minimal/src/cmd/boxes/vm_host.rs
  • crates/minimal/src/dash/rpc.rs
  • crates/minvmd/tests/common/mod.rs
  • crates/minvmd/tests/vm_escape_integration.rs

Converted to a draft: something above needs a person before review.

A GitHub grant box started with --network host_ip on a VM host gets a box id and reaches the proxy's listener. After the last declaring member ends, a host-address box with no grant cannot reach the proxy's address. The branch now merges cleanly with main.

Notes from the agent: This round resolves only the merge conflict in crates/minimald-rpc/src/tests.rs. The branch added host_ip_box_request_carries_the_lane_declaration, and main added read_log_request_round_trips, in the same place. The resolution keeps both tests. The merge commit is a51b299. All six test lines pass after the merge. The other files in the merge come from main and are not changes from this task. The on-device Mac proof was not run on this Linux box.

@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.

Review at a51b299 against T117 (#2854), BEP-082 and BEP-083. Arch ruling on this head: CONDITIONS (BEP-082 conforms, BEP-083 deviates).

Blocking

  1. BEP-083: the cohort lane does not open TCP 443 at the proxy's address. crates/minvmd/src/net/egress_gate.rs:6193 host_ip_verdict reuses egress::proxy_lane_admits, which admits only the listener (8118). The plan's gate layer and BEP-083 require the proxy's address on TCP 443 too. Under dns steering a host_ip box connects there (networking §5.4, §7.1). host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane (egress_gate.rs:16261) checks only 8118 and 22.
  2. The box record takes a second id. crates/minvmd/src/control.rs:1358 mint_box_id_reply returns a fresh mint_record_box_id() when switch_address is None, which is always the case for a host_ip box (crates/minimald/src/net/listeners.rs mint_box_id). Grants are sealed and the proxy registers the box under the id register_host_ip_box minted. min box show and min box audit use another id, against the plan's diagnostics line. BEP-084's live-box check (T119) will find no record under the sealed id.
  3. An older VM host's reply is accepted. crates/minimal-client/src/box_registration.rs:320-332: the Registered/Addresses arm records host_ip: false whatever was asked. A minvmd that predates host_ip ignores the field, allocates a switch address and an unleased row, and the create carries those addresses onto a HostNet box.

Residual (arch C3): no revoke_box/forget_box is sent for a host_ip box's minted id when the box ends (retire_host_ip_box is keyed by session; host_ip_ids keeps the id until restart). Own-address boxes get spawn_revocation (box_registry.rs ~5093, BEP-043). Not redeemable until T119, so it is filed as a residual, not fixed here.

Low

  • crates/minimal-client/src/attach.rs:1573 host_ip_admission_precedes_the_first_process shows only that host_ip_box_at blocks on its socket. Nothing orders the admit against the create or the first process.
  • New items were inserted under existing doc comments: control.rs:4108-4119 (NET-138 doc of task_addresses_registered_with_box_and_handed now sits above the new test) and egress_gate.rs:16230-16240 (NET-107/NET-085 doc now sits above host_ip_cohort_to_proxy).

The four files outside the layers are call-site plumbing for the new fields. No objection.

@norrietaylor
Copy link
Copy Markdown
Member

/revise Review 5755449559 and the arch ruling on a51b299 (CONDITIONS). Fix these four items:

  1. Open TCP 443 at the proxy's address on the cohort lane (BEP-083, arch C1). In crates/minvmd/src/net/egress_gate.rs host_ip_verdict (~line 6193), admit TCP to box_egress_proxy_address() port 443 as GateAdmit::ProxyLane while declaring > 0, beside the ProxyListener::at(dst) arm. TCP only: UDP 443 and every other port at that address stay GateDrop::ProxyLane. Do not widen the shared boxes::core::egress::proxy_lane_admits, because own-address direct TLS belongs to BEP-080 (T116 — Carry dns-steered TLS to the proxy on port 443 #2805). In host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane, assert that TCP 443 is admitted. In host_ip_cohort_proxy_lane_dropped_without_a_declaring_member, assert that TCP 443 drops before the grant member is admitted and after it retires. Name both ports in the host_ip_verdict doc comment.

  2. One id for a host_ip box. crates/minvmd/src/control.rs:1358 mint_box_id_reply returns a fresh mint_record_box_id() when switch_address is None, and a host_ip box always sends None. So the box record, min box show and min box audit carry a different id from the one register_host_ip_box minted and the grants are sealed under. Make the in-VM create of a host_ip box take the registration's minted id, claimed once per create token as a row id is. Then add a test showing that the record id equals the registration id.

  3. Refuse an older VM host's reply (arch C2). crates/minimal-client/src/box_registration.rs register_box_with_vm_host, Registered arm (~line 324) and Addresses arm: when the request has host_ip: true, return an error saying the VM host daemon is older than host_ip registration. Do not record host_ip: false. Add a unit test that serves a Registered reply to a host_ip request and expects the error.

  4. Residual (arch C3). In the PR body, add a Residuals line linking Revoke a host_ip box's minted id at the Box Egress Proxy when the box ends #2865 (revoke a host_ip box's minted id at the proxy when the box ends). No code change for it here.

Also fix these:

  • Put the doc comments back on the tests they belong to: control.rs:4108-4119 (the NET-138 doc of task_addresses_registered_with_box_and_handed) and egress_gate.rs:16230-16240 (the NET-107/NET-085 doc of box_marked_node_frame_decided_by_resident_host_ip_boxes).
  • crates/minimal-client/src/attach.rs:1573 host_ip_admission_precedes_the_first_process: make it check the admit's order against the create, or rename it to say what it checks.

The cohort lane now admits TCP 443 at the Box Egress Proxy's address
beside the listener port. UDP 443 and other ports still drop. Doc
comments return to the tests they belong to.
A VM host daemon older than host_ip registration answers with an
address row. The client now refuses that answer and never records the
box as an own-address box. The admit test takes a name that says what
it checks.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a /revise note, pushed as 55d961cd5cf1.

line exit tail
cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_id 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2ec2... 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 minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-264e... 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 minimald-rpc host_ip_box_request_carries_the_lane_declaration 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-7605... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling common v0.0.1 (/workbench
cargo nextest run -p minimal-client host_ip_admission_precedes_the_first_process 4 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-23d5... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling version v0.8.0 (/workbench/crates/version) Compiling common v0.0.1 (/workb
cargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-6e16... 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_cohort_proxy_lane_dropped_without_a_declaring_member 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-50f1... 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.

    PASS [   0.027s] ( 561/1729) minimal tests::a_unique_id_prefix_resolves_to_its_session
        PASS [   0.028s] ( 562/1729) minimal tests::activate_help_shows_network_flags
        PASS [   0.024s] ( 563/1729) minimal tests::an_ambiguous_id_prefix_cuts_at_the_f
8BD0
irst_differing_digit
        PASS [   0.024s] ( 564/1729) minimal tests::an_ambiguous_id_prefix_names_the_candidates
        PASS [   0.021s] ( 565/1729) minimal tests::an_exact_name_wins_and_an_ambiguous_fold_resolves_to_none
        PASS [   0.034s] ( 566/1729) minimal tests::an_exact_name_wins_over_an_id_prefix
        PASS [   0.025s] ( 567/1729) minimal tests::assess_at_risk_classifies_clean_dirty_and_unknowable
        PASS [   0.023s] ( 568/1729) minimal tests::attach_error_printed_after_terminal_restore
        PASS [   2.767s] ( 569/1729) minimal resolver::tests::finalize_install_undo_succeeds_on_a_clean_host
        PASS [   0.731s] ( 570/1729) minimal tests::a_stopped_vm_does_not_hold_a_box_name_resolution
        PASS [   0.022s] ( 571/1729) minimal tests::bare_status_counts_elsewhere_sessions
        PASS [   0.024s] ( 572/1729) minimal tests::bare_status_lists_at_most_two_cwd_sessions
        PASS [   0.023s] ( 573/1729) minimal tests::bare_status_renders_a_cwd_session_verbatim
        PASS [   0.022s] ( 574/1729) minimal tests::bare_status_renders_the_empty_state_verbatim
        PASS [   0.035s] ( 575/1729) minimal tests::both_creators_share_the_composition_failure_message
        PASS [   0.024s] ( 576/1729) minimal tests::box_announce_label_prefers_name_with_short_id
        PASS [   0.922s] ( 577/1729) minimal tests::box_id_is_a_csprng_uuidv7_per_creation
        FAIL [   1.801s] ( 578/1729) minimal tests::a_stopped_vm_does_not_hold_a_listing
  stdout ───

    running 1 test
    test tests::a_stopped_vm_does_not_hold_a_listing ... FAILED

    failures:

    failures:
        tests::a_stopped_vm_does_not_hold_a_listing

    test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 703 filtered out; finished in 1.77s

  stderr ───

    thread 'tests::a_stopped_vm_does_not_hold_a_listing' (6332) panicked at crates/minimal/src/tests.rs:3566:5:
    a stopped VM's stale socket must not charge the listing its connect-retry window (1.150394627s)
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   2.114s] ( 579/1729) minimal tests::attach_refuses_a_box_name_two_vms_know
        PASS [   2.512s] ( 580/1729) minimal tests::attach_fall_through_hands_off_the_owning_vm
        PASS [   2.709s] ( 581/1729) minimal tests::box_name_resolves_vm_without_flag
────────────
     Summary [  22.255s] 581/1729 tests run: 580 passed, 1 failed, 2 skipped
        FAIL [   1.801s] ( 578/1729) minimal tests::a_stopped_vm_does_not_hold_a_listing
warning: 1148/1729 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

Outside the task's layers::

  • crates/minimal/src/cmd/boxes/vm_host.rs
  • crates/minimal/src/dash/rpc.rs
  • crates/minvmd/tests/common/mod.rs
  • crates/minvmd/tests/vm_escape_integration.rs

Converted to a draft: something above needs a person before review.

A host_ip grant box on a VM host registers for a box id, and the host gate admits its cohort to the proxy's listener port and to TCP 443 at the proxy's address while a grant member is resident. After the grant member retires, a host_ip box with no grant cannot reach either port at the proxy's address. The record id still differs from the registration id (directive item 2 is not done), so min box show and min box audit do not yet show the id that the grants are sealed under.

Notes from the agent: Directive item 1 is done: host_ip_verdict admits TCP 443 at box_egress_proxy_address() as GateAdmit::ProxyLane while declaring > 0. UDP 443 and other ports drop as ProxyLane. The shared proxy_lane_admits is unchanged. Both gate tests assert TCP 443, and the first test also asserts that UDP 443 drops. Item 3 is done: register_box_with_vm_host refuses a Registered or Addresses reply to a host_ip request, and a unit test serves both replies. Item 4 is not code. The runner owns the PR body, so add this line to it: 'Residuals: #2865 (revoke a host_ip box's minted id at the proxy when the box ends)'. The two misplaced doc comments are back on their tests. ITEM 2 IS NOT DONE because it cannot be done inside this task's layers. The in-VM daemon sends MintBoxId with only switch_address and create_token, and a host_ip box sends switch_address None. So minvmd has nothing that names the host_ip registration. The fix needs a field on MintBoxIdRequest (crates/minimald-rpc/src/lib.rs, in layers), for example host_ip_box_id. The fix also needs the in-VM daemon to fill it, in crates/minimald/src/box_manager.rs create_session (it now drops config.box_id) and crates/minimald/src/net/listeners.rs mint_box_id. The client must also relay the registration id on the create (crates/minimal/src/cmd/boxes/create.rs, which says 'The create relays none (BOX-002)'). Then mint_box_id_reply can take the id when boxes.holds_host_ip_id(id) and claim it once per token. claim_row_box_id must t…[truncated]

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on a failed check suite: the coder changed nothing. noop: the directive gives a failed test-kvm job and its aggregator ci-linux-kvm-success, but the log excerpt shows no failing step. Each ::error:: line in it is the echoed source of a workflow script, not an error that the job printed. The failing harness, test or e2e case is not in the excerpt. I checked each test-kvm step against this branch's diff. (1) The VM harnesses: vm_escape_integration admits its host_ip boxes with credentialed_upstream: false, and its listener is at the host interface address, not the proxy's address, so the new ProxyLane arm in host_ip_verdict does not decide its frames. egress_allowlist_integration registers an own-address box with host_ip: false, which takes the unchanged path in control.rs. (2) The Linux session e2e: register_box_for_activation registers a host_ip box only when it declares a credentialed upstream, and the GitHub grant and BEP cases in scripts/session-e2e.sh need the Box Egress Proxy, which runs on macOS only. A default host_ip…[truncated]

@norrietaylor
norrietaylor marked this pull request as ready for review November 3, 2026 18:49
@norrietaylor
norrietaylor requested a review from a team as a code owner November 3, 2026 18:49
@minimal-foundry
minimal-foundry Bot commented Nov 3, 2026 •
Copy link
Copy Markdown
Contributor Author

Reviewed: 2 findings, none blocking at d81c7d4bec89.

Address the comments on the diff.

Clobber: none seen in the hunks read.

@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.

Re-review at 55d961c against review 5755449559 and /revise 6608860611. Arch ruling on this head: CONDITIONS.

Met

  • The cohort lane admits TCP 443 at the proxy's address while a declaring member is resident (egress_gate.rs:6199-6206). UDP 443 and other ports still drop, and both tests check 443 open and closed.
  • An older VM host's Registered or Addresses reply to a host_ip request is refused, and a test covers both.
  • The doc comments are restored, and the admission test is renamed. The plan test line on #2854 is updated to the new name.
  • The Residuals section links #2865.

Blocking: one box gets two ids (BEP-082, arch C1). This is not done. The round-1 comment says it is outside the task's layers.

  • register_host_ip_box mints id X. The grants are sealed and the proxy is registered under X.
  • Then box_manager.rs:3144 sends MintBoxIdRequest { switch_address: None }, and mint_box_id_reply (control.rs:1354) answers with a fresh id Y.
  • The record, min box show and the #2865 revocation key follow Y, while the audit and the sealed values name X. Gatehouse §6.10 line 839 requires one id per creation.
  • The fix touches minimald-rpc/src/lib.rs, minimald/src/box_manager.rs, minvmd/src/box_registry.rs and control.rs.

Medium: user-facing text in crates/minimal-client/src/box_registration.rs:310-311 HOST_IP_REGISTRATION_UNSUPPORTED:

  • "no box id" is false for a Registered reply, which carries box_id.
  • "The registration did not happen" is not proven. An older minvmd takes the unheld path and publishes a row under the box's name. Withdraw that row before refusing, or say that it may remain.
  • It gives no next step. Name min stop then min ls, as crates/minimal/src/resolver.rs:4915 does for version skew.

Nit

  • box_registration.rs:326-332: the comment about "the answer a daemon this build boots beside sends" now sits above the new refusal arm. Move it to the Registered arm.
  • egress_gate.rs:6149-6151, 6199-6206: once #2860 lands, HOST_IP_PROXY_TLS_PORT duplicates egress::PROXY_DIRECT_TLS_PORT, and the comment saying proxy_lane_admits stays listener-only is false. Whichever PR lands second drops them.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

That /revise was refused. a line under layers: matches no line form: "- record id:".

Round 3 of 10 was not counted; #2854 carries the same sentence.

@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 · 3 conditions · the full ruling

The gate side of the cohort lane is correct. The cohort union follows networking §4.3 rule 2, and the lane opens only the listener and TCP 443. The gap is the per-box half. Gatehouse §6.10 line 833 and T31 say that only a box with a credentialed lane can reach the listener. Networking §7.1 line 253 puts that check on the in-VM classifier, and its allow subtree refuses nothing today. Spec 24 calls this exposure T28, so amend the spec, file the classifier work (C1), and record the interim in the gate (C2). Also correct the Tests row that names a test that does not exist (C3).

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

Comment thread crates/minvmd/src/net/egress_gate.rs Resolved
Comment thread crates/minvmd/src/net/egress_gate.rs Resolved
Comment thread crates/minimal-client/src/attach.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

@norrietaylor
Copy link
Copy Markdown
Member

That /revise was refused. task names 13 layer files, above 10: two tasks.

Round 3 of 10 was not counted; #2854 carries the same sentence.

/revise Review 5757847992 and the arch ruling on 55d961c (CONDITIONS). The owner widened T117's layers on #2854 for item 1: a new identity layer for crates/minimald/src/box_manager.rs, and wider descriptions on the existing control.rs, box_registry.rs and minimald-rpc/src/lib.rs entries. Re-read the issue body before you start.

  1. One id per host_ip box (BEP-082, arch C1). Blocking. Today register_host_ip_box mints id X and the grants are sealed under X. Then crates/minimald/src/box_manager.rs:3144 sends MintBoxIdRequest { switch_address: None }, and mint_box_id_reply (crates/minvmd/src/control.rs:1354) answers with a fresh id Y for the record.

    • crates/minimald-rpc/src/lib.rs: add host_ip_name: Option<String> to MintBoxIdRequest, with #[serde(default, skip_serializing_if = "Option::is_none")].
    • crates/minimald/src/box_manager.rs: when the box is HostNet and has no box addresses, send its creation name as host_ip_name.
    • crates/minvmd/src/box_registry.rs: host_ip_ids keeps each minted id with its registration name and answers a lookup by name.
    • crates/minvmd/src/control.rs mint_box_id_reply: when host_ip_name names a registered id, answer that id. Claim it by one create_token, as claim_row_box_id does. Refuse an ask with another token. A name with no registration keeps the fresh mint, because a host_ip box with no grant registers nothing.
    • Test host_ip_box_record_takes_the_registration_id (minvmd): register a host_ip box agent over the control socket. A MintBoxId with host_ip_name: "agent" answers the registration's id, and a second ask with another token is refused.
  2. User-facing text. crates/minimal-client/src/box_registration.rs:310-311 HOST_IP_REGISTRATION_UNSUPPORTED:

    • Drop "no box id", because a Registered reply carries box_id.
    • Do not say "the registration did not happen": an older minvmd takes the unheld path and publishes a row under the box's name. Either withdraw that row before the refusal, or say it may remain.
    • End with the next step: run min stop, then min ls, to restart the VM with the matching VM host daemon. Follow the wording style of crates/minimal/src/resolver.rs:4915.
    • Update the test that pins the text. AGENTS.md "User-facing text" applies.
  3. Nit. At box_registration.rs:326-332, move the comment about "the answer a daemon this build boots beside sends" below the new refusal arm, onto the Registered arm it describes.

Do not change HOST_IP_PROXY_TLS_PORT or the proxy_lane_admits comment in egress_gate.rs in this round. #2860 is in the merge queue, and whichever PR lands second removes them.

@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
The in-VM create now names a host_ip box's creation name in its mint
ask. The VM host daemon answers the id the box's host_ip registration
minted under that name, claimed by one create token, so the record and
the sealed grants name one id. A name with no registration keeps the
fresh mint.
…t-address-grant-box-an-id-and-open-the

# Conflicts:
#	crates/minimal/src/cmd/boxes/vm_host.rs
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 9 of 10 on a /revise note, pushed as d1792d321694.

Resolved conflicts in: crates/minimal/src/cmd/boxes/vm_host.rs

line exit tail
cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_id 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-e159... 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 minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-aa8a... 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 minimald-rpc host_ip_box_request_carries_the_lane_declaration 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-7ed9... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling common v0.0.1 (/workbench
cargo nextest run -p minimal-client host_ip_admission_carries_the_lane_and_waits_for_the_answer 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-c47f... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling version v0.8.0 (/workbench/crates/version) Compiling common v0.0.1 (/workb
cargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-f2a8... 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_cohort_proxy_lane_dropped_without_a_declaring_member 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-9100... 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_box_record_takes_the_registration_id 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-9694... 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.

       "span_id": "04524a5e03b93e6c",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "4c1ba44a0a463f14",
                "span_id": "0fd5986b94d2354f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "4c1ba44a0a463f14",
                "queued_behind": "0",
                "span_id": "eef56dbbe959220e",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "4c1ba44a0a463f14",
                "queued_behind": "0",
                "span_id": "ad0479c92bc7e9ac",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "ad0479c92bc7e9ac",
                "span_id": "cbd3a8bb6e1daf86",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "ad0479c92bc7e9ac",
                "queued_behind": "0",
                "span_id": "60e2a6c20f88f2ce",
                "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 [   0.044s] ( 946/3107) minimal-client file_upload::tests::tar_zst_archive_survives_drop_without_finish
        PASS [   5.039s] ( 947/3107) minimal-client box_registration::tests::resume_timeout_goes_on_and_an_absent_host_fails_closed
        PASS [   6.136s] ( 948/3107) minimal-client box_registration::tests::a_silent_daemon_does_not_hold_the_exit_past_the_deadline
────────────
     Summary [  76.999s] 948/3107 tests run: 947 passed, 1 failed, 27 skipped
        FAIL [   6.130s] ( 945/3107) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 2159/3107 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

Outside the task's layers::

  • crates/minimal/src/cmd/boxes/vm_host.rs
  • crates/minimal/src/cmd/mod.rs
  • crates/minimal/src/dash/rpc.rs
  • crates/minimald/src/net/listeners.rs
  • crates/minvmd/tests/common/mod.rs
  • crates/minvmd/tests/vm_escape_integration.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👎 invalid — crates/minvmd/src/net/egress_gate.rs:6290: The cohort union is what BEP-083 in this task's spec requires: while one resident host_ip box declares a credentialed upstream, the cohort address reaches the listener and TCP 443. Cohort members share the node's address, so the host gate cannot tell them apart. The doc comment names this interim an
  • 👎 invalid — crates/minvmd/src/box_registry.rs:4662: On this branch only min task run sets fresh_instance (task.rs:673), and task.rs never calls register_box_for_activation. activate_box registers under created_box_name, which is the name the daemon gives a box that is not a fresh instance. So a fresh <name>-<n> box never meets this refusa

On a Mac, a GitHub grant box started with --network host_ip gets a box id and reaches the proxy's listener. After it ends, a host-address box with no grant cannot reach the proxy's address. This round, a Ctrl-C during min session activate of such a box also frees its name on the VM host, so the next create under that name is not refused.

Notes from the agent: Round 9 does the three items in the note. (1) arm_activation_interrupt now withdraws a host_ip box's name with the registration's id. activate_box hands the id to the guard through ActivationInterrupt::withdraw_host_ip_name_as, so the min task run call site in task.rs keeps its signature. That path registers no host_ip box. Test: interrupted_host_ip_activation_withdraws_its_name_by_id. crates/minimal/src/cmd/mod.rs is outside the layers, and the owner accepted it. (2) min dash destroy: at this head, settle_destroyed_box (called from destroy) already sends RetireHostIpBox for a HostNet record with no address pair, when the host is a VM host (vm_host_control_sock accepts only a local-minvmd<N> dir). That retire also withdraws the registration name (retire_host_ip_box). So I changed no product code there. The new test tui_destroy_retires_a_host_ip_box pins it. crates/minimal/src/dash/rpc.rs is outside the layers, and the note asks for this test there. (3) REGISTERED_ID_MISMATCH now reads exactly as the note gives it, and host_ip_grant_box_with_another_id_is_refused pins it. I did not run just clippy-strict.

@norrietaylor
norrietaylor marked this pull request as ready for review November 4, 2026 18:30
@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: 2 of 3 personas ran (correctness, security); did not complete: supply-chain.

Comment thread crates/minvmd/src/net/egress_gate.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@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 compare closes the name gaps for BEP-082, and both merges with main are clean. One path still fails open. The Ctrl-C handler withdraws the name and then exits with 130. It never retires the host_ip admit, so the gone box keeps its rules and its lane bit in the cohort union. Section 4.3 line 84 counts only live members, and section 7.1 line 244 withdraws facts at box end. Send the retire in withdraw_interrupted_box and pin it in the test, as C1 says.

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

Comment thread crates/minimal/src/cmd/mod.rs Resolved
The set of minted host_ip ids never shrinks, on purpose: it keeps an
ended box's id out of a later mint's reach. Say so, and give its bound.
@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 · 2 conditions · the full ruling

This head adds one doc comment that states the bound of the HostIpIds set. The comment is true of the code. The merge of #2871 is clean and does not change the proxy lane. The host-minted id (BEP-082) and the cohort lane (BEP-083) conform to networking §7.1 line 244 and §4.3 rule 2. Two design obligations stay open as filed issues. C1 is the revocation of the minted id at box end (#2865). C2 is the in-VM refusal of a member with no lane (#2876). The change can merge with them open.

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

Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/minvmd/src/net/egress_gate.rs Resolved
@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: 16 unresolved threads — minimal-arch[bot] crates/minvmd/src/net/egress_gate.rs:6389, minimal-arch[bot] crates/minvmd/src/net/egress_gate.rs:16579, minimal-arch[bot] crates/minimal-client/src/attach.rs:1572, minimal-arch[bot] crates/minvmd/src/box_registry.rs:4713, minimal-arch[bot] crates/minvmd/src/control.rs:1389, …. No findings.

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

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 10 of 10 on the runtime's review findings, pushed as 37f4ead90428.

line exit tail
cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_id 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-4c67... 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 minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved 0 Compiling version v0.8.0 (/workbench/crates/version) Compiling postcard v1.1.3 Compiling ssh-encoding v0.3.0 Compiling darling_core v0.24.0 Compiling close_fds v0.3.2 Compiling caps v0.5.6 Compiling sendfd v0.4.4 Compiling signal-hook v0.3.18 Compiling lcache v0.0.1 (/workbe
cargo nextest run -p minimald-rpc host_ip_box_request_carries_the_lane_declaration 0 plement-test-2 in session task-runtime-implement-test-2-3123... Compiling parking_lot_core v0.9.12 Compiling errno v0.3.14 Compiling mio v1.2.2 Compiling socket2 v0.6.5 Compiling parking_lot v0.12.5 Compiling futures-util v0.3.34 Compilin 10BC8 g aws-lc-rs v1.18.1 Compiling hybrid-a
cargo nextest run -p minimal-client host_ip_admission_carries_the_lane_and_waits_for_the_answer 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-be35... Compiling tokio v1.53.3 Compiling rustls v0.23.46 Compiling aead v0.6.1 Compiling opentelemetry_sdk v0.33.1 Compiling aes-gcm v0.11.0 Compiling miette v7.6.0 Compili
cargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lane 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-a647... 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_cohort_proxy_lane_dropped_without_a_declaring_member 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-da5a... 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_box_record_takes_the_registration_id 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-8e82... 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.

     "span_id": "d0b8653b018d4916",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "fe7bf0948eb451bc",
                "span_id": "be3ea645e3ad7e7e",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "fe7bf0948eb451bc",
                "queued_behind": "0",
                "span_id": "279b51aa8b15591d",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "fe7bf0948eb451bc",
                "queued_behind": "0",
                "span_id": "ef106f476e15f23f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "ef106f476e15f23f",
                "span_id": "03e325f012a8ec4a",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "HandOverName",
                "parent_span_id": "ef106f476e15f23f",
                "queued_behind": "0",
                "span_id": "aca4486f07547596",
                "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 [   5.013s] ( 974/3119) minimal-client box_registration::tests::resume_timeout_goes_on_and_an_absent_host_fails_closed
        PASS [   4.555s] ( 975/3119) minimal-client tty_relay::tests::resume_after_drop_prints_line_and_nudges_winsize
        PASS [   6.238s] ( 976/3119) minimal-client box_registration::tests::a_silent_daemon_does_not_hold_the_exit_past_the_deadline
────────────
     Summary [  48.311s] 976/3119 tests run: 975 passed, 1 failed, 27 skipped
        FAIL [   3.271s] ( 973/3119) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 2143/3119 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

Outside the task's layers::

  • crates/minimal/src/cmd/boxes/vm_host.rs
  • crates/minimal/src/cmd/mod.rs
  • crates/minimal/src/dash/rpc.rs
  • crates/minimald/src/net/listeners.rs
  • crates/minvmd/tests/common/mod.rs
  • crates/minvmd/tests/vm_escape_integration.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👎 invalid — crates/minvmd/src/net/egress_gate.rs:6434: The task covers BEP-083, which says: WHILE a resident host_ip box declares a credentialed upstream, admit the cohort address to the proxy listener and TCP 443. Cohort members share one source address, so the gate cannot decide per box. The spec records this as the T28 residual (networking §4.3 rule
  • 👍 valid — crates/minvmd/src/box_registry.rs:4674: The doc on HostIpIds now says the id set never shrinks on purpose. It keeps an ended host_ip box's id out of a later mint because no row holds that id. The bound is one 16-byte id per registration since the daemon started, and a restart clears it. I did not change the code, because pruning the set w

On a Mac, a GitHub grant box started with --network host_ip gets a box id from the VM host and reaches the proxy's listener. After the last declaring box ends, a host-address box with no grant cannot reach the proxy's address. This round changes only a doc comment, so the behaviour from earlier rounds stays the same.

Notes from the agent: Round 10 changes one doc comment on HostIpIds in box_registry.rs. It states that the minted-id set never shrinks on purpose, and gives its bound. The code does not change. I ran only the minvmd test lines this round, because the other crates did not change. The HIGH security thread repeats PRRT_kwDOPdfcxM6zZeLh, which an earlier round judged invalid. BEP-083 in the spec requires the cohort-wide lane, and the spec records the T28 residual. If the cohort lane must close, the spec must change first.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft November 4, 2026 19:00
The Ctrl-C handler ends with std::process::exit(130), so the
activation's HostIpResidency never drops and no client retires the
box. minvmd then keeps the box's rules and its lane declaration until
it restarts, and a box that declared a credentialed upstream keeps the
cohort's proxy lane open.

withdraw_interrupted_box now sends RetireHostIpBox for a HostNet
record's id, with the retries a destroy uses, before it withdraws the
name. The interrupt test answers each exchange and checks the order:
the retire for the record's id first, then the withdrawal carrying the
minted id.
@norrietaylor
norrietaylor marked this pull request as ready for review November 4, 2026 21:15
@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/net/egress_gate.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry minimal-foundry Bot added the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Nov 4, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

The runtime will not revise this pull request again on its own: round 11 would exceed the cap of 10; 2 base merges were not counted (the last trigger was the runtime's review findings). A person decides now. Remove needs-human from this pull request to let /revise <note> or the automatic rounds resume, or finish #2854 by hand.

@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 · 2 conditions · the full ruling

The new commit closes the Ctrl-C gap. Before it, an aborted host_ip activation left its lane bit in the gate's union after the box ended. Section 7.1 line 244 says the facts are withdrawn at box end. withdraw_interrupted_box now retires the box with the existing helper, over the host door only. The change can merge. C1 (#2865) and C2 (#2876) stay open as filed residuals, as on 37f4ead9.

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

Comment thread crates/minvmd/src/box_registry.rs Resolved
# Conflicts:
#	crates/minimal/src/cmd/boxes/vm_host.rs
@norrietaylor norrietaylor removed the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Nov 4, 2026
@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.

Babysitter review at d81c7d4, against the T117 plan block in #2854 and BEP-082 / BEP-083.

  • BEP-082: a host_ip grant box registers for a host-minted id, and ensure_registered_id refuses a record whose id is not the registration's. The id set never shrinks, so no id is reused. A name with no admitted box is freed after HOST_IP_UNADMITTED_NAME_BOUND (300 s). The activation's failure paths, Ctrl-C, min session destroy and the dashboard destroy all withdraw the name by id.
  • BEP-083: every resident admit and re-admit carries the lane flag from the box's policy: create.rs admit_declaring, the attach/exec re-admit in rehold_held_name_before_attach (now behind main's host_net guard), and the dashboard attach. The plain admit in the dashboard-create and task paths is correct, because both build BoxPolicy::default(). The gate opens the proxy listener and 443 only while a resident member declares.
  • 06f832a: a Ctrl-C after the admit now retires the box before the name withdrawal, so the box's rules and lane bit leave minvmd. The test pins the order. One race remains: a Ctrl-C while the admit is in flight. The window is one control exchange.
  • d81c7d4: a merge of main. The vm_host.rs resolution keeps #2969's host_net && guard and T117's _declaring call.

Residuals, all filed and listed in the body: #2865 (revoke the minted id at the proxy; it blocks T119), #2876 (the in-VM classifier; the owner accepted the interim), and #3007 (a fresh-instance registration per creation; no path reaches it today).

Arch: PASS at d1792d3 and at 06f832a. The arch bot reported PASS_WITH_CONDITIONS, and its conditions are #2865 and #2876.

@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 · 1 condition · the full ruling

The merge of main keeps the lane bit on the attach re-admit, so the earlier ruling stands. The gate opens the proxy lane for the cohort union and drops it as ProxyLane when no member declares one, as §7.1 line 253 says. The per-box refusal is the in-VM classifier's, and issue #2876 tracks it. One item stays open: the task's Mac proof has no e2e leg, and nobody ran it. Add the leg in C1, and record its run in the PR body.

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

Comment thread crates/minimal/src/cmd/boxes/create.rs Resolved
Comment thread crates/minvmd/src/net/egress_gate.rs Resolved
@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.

Gate passed at d81c7d4. Residuals: #2865, #2876, #3007, and the Mac proof under #2858.

@norrietaylor
norrietaylor added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 228e681 Nov 4, 2026
36 checks passed
@norrietaylor
norrietaylor deleted the agent/2854-give-a-host-address-grant-box-an-id-and-open-the branch November 4, 2026 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

T117 — Give a host-address grant box an id and open the proxy lane to its cohort

1 participant

0