Repository navigation
T117 — Give a host-address grant box an id and open the proxy lane to its cohort - #2861
norrietaylor merged 36 commits into
Conversation
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.
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
…t-address-grant-box-an-id-and-open-the # Conflicts: # crates/minimald-rpc/src/tests.rs
|
A merge of main before round 1, not counted against the cap (1 of 3), pushed as Resolved conflicts in:
Verify Outside the task's
Converted to a draft: something above needs a person before review. A GitHub grant box started with 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. |
There was a problem hiding this comment.
Review at a51b299 against T117 (#2854), BEP-082 and BEP-083. Arch ruling on this head: CONDITIONS (BEP-082 conforms, BEP-083 deviates).
Blocking
- BEP-083: the cohort lane does not open TCP 443 at the proxy's address.
crates/minvmd/src/net/egress_gate.rs:6193host_ip_verdictreusesegress::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. Underdnssteering ahost_ipbox 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. - The box record takes a second id.
crates/minvmd/src/control.rs:1358mint_box_id_replyreturns a freshmint_record_box_id()whenswitch_addressisNone, which is always the case for ahost_ipbox (crates/minimald/src/net/listeners.rsmint_box_id). Grants are sealed and the proxy registers the box under the idregister_host_ip_boxminted.min box showandmin box audituse another id, against the plan's diagnostics line. BEP-084's live-box check (T119) will find no record under the sealed id. - An older VM host's reply is accepted.
crates/minimal-client/src/box_registration.rs:320-332: theRegistered/Addressesarm recordshost_ip: falsewhatever was asked. A minvmd that predateshost_ipignores the field, allocates a switch address and an unleased row, and the create carries those addresses onto aHostNetbox.
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:1573host_ip_admission_precedes_the_first_processshows only thathost_ip_box_atblocks 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 oftask_addresses_registered_with_box_and_handednow sits above the new test) andegress_gate.rs:16230-16240(NET-107/NET-085 doc now sits abovehost_ip_cohort_to_proxy).
The four files outside the layers are call-site plumbing for the new fields. No objection.
|
/revise Review 5755449559 and the arch ruling on a51b299 (CONDITIONS). Fix these four items:
Also fix these:
|
…t-address-grant-box-an-id-and-open-the
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.
|
Round 1 of 10 on a /revise note, pushed as
Verify Outside the task's
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 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] |
|
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] |
|
Reviewed: 2 findings, none blocking at Address the comments on the diff. Clobber: none seen in the hunks read. |
There was a problem hiding this comment.
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
RegisteredorAddressesreply 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_boxmints id X. The grants are sealed and the proxy is registered under X.- Then
box_manager.rs:3144sendsMintBoxIdRequest { switch_address: None }, andmint_box_id_reply(control.rs:1354) answers with a fresh id Y. - The record,
min box showand 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.rsandcontrol.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
Registeredreply, which carriesbox_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 stopthenmin ls, ascrates/minimal/src/resolver.rs:4915does 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 theRegisteredarm.egress_gate.rs:6149-6151, 6199-6206: once #2860 lands,HOST_IP_PROXY_TLS_PORTduplicatesegress::PROXY_DIRECT_TLS_PORT, and the comment sayingproxy_lane_admitsstays listener-only is false. Whichever PR lands second drops them.
|
That Round 3 of 10 was not counted; #2854 carries the same sentence. |
There was a problem hiding this comment.
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.
|
That 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
Do not change |
…t-address-grant-box-an-id-and-open-the
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
|
Round 9 of 10 on a /revise note, pushed as Resolved conflicts in:
Verify Outside the task's
Converted to a draft: something above needs a person before review. Review threads the coder judged:
On a Mac, a GitHub grant box started with Notes from the agent: Round 9 does the three items in the note. (1) |
There was a problem hiding this comment.
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.
…t-address-grant-box-an-id-and-open-the
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
|
Round 10 of 10 on the runtime's review findings, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. Review threads the coder judged:
On a Mac, a GitHub grant box started with Notes from the agent: Round 10 changes one doc comment on |
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.
|
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 |
There was a problem hiding this comment.
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.
# Conflicts: # crates/minimal/src/cmd/boxes/vm_host.rs
There was a problem hiding this comment.
Babysitter review at d81c7d4, against the T117 plan block in #2854 and BEP-082 / BEP-083.
- BEP-082: a
host_ipgrant box registers for a host-minted id, andensure_registered_idrefuses 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 afterHOST_IP_UNADMITTED_NAME_BOUND(300 s). The activation's failure paths, Ctrl-C,min session destroyand 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 inrehold_held_name_before_attach(now behind main'shost_netguard), and the dashboard attach. The plainadmitin the dashboard-create and task paths is correct, because both buildBoxPolicy::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.rsresolution keeps #2969'shost_net &&guard and T117's_declaringcall.
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.
There was a problem hiding this comment.
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.
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 ahost_ipgrant box, andmin box audit <box>reads its records by that id; ahost_ipgrant 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 ahost_ipgrant box, and the gate's drop log namesProxyLanefor a cohort connection while no resident member declares a laneobservability: 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:
RegisterBoxaccepts ahost_ipbox and returns a creation-unique box id with no switch address- crates/minvmd/src/box_registry.rs: a
host_ipregistration records the minted id with no row in the address table, and its revocation check is the one anown_ipid takestest: 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_activationregisters ahost_ipbox on a VM host when its spec declares a credentialed upstream, and still returnsNonefor one that declares none- crates/minimal/src/cmd/boxes/create.rs:
proxy_box_factsgets the minted id for ahost_ipgrant box, so theNotServedrefusal prints only where no proxy serves the hosttest: cargo nextest run -p minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unserved
- rpc:
- crates/minimald-rpc/src/lib.rs:
HostIpBoxRequestcarries 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:
AdmitHostIpBoxsends the lane declaration, and the admission completes before the box's first process starts, not after the createtest: cargo nextest run -p minimal-client host_ip_admission_carries_the_lane_and_waits_for_the_answer
- gate:
- crates/minvmd/src/box_registry.rs:
HostIpBoxRulescarries 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_verdictadmits the cohort address to the proxy's listener ports while the cohort's lane is open, and drops it asProxyLanewhile it is closedtest: 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_ipis 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_ipfor 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
CreateSessionand beforeActivationStep::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:
min session attachre-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.Design choices:
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.host_ip: boolandrow_addresses(). For a host_ip registration,addressesis 0.0.0.0/0.0.0.0. create.rs does not put a host_ip registratio…[truncated]Tests
cargo nextest run -p minvmd host_ip_box_registration_mints_a_creation_unique_idcargo nextest run -p minimal host_ip_grant_box_on_vm_host_is_not_refused_as_unservedcargo nextest run -p minimald-rpc host_ip_box_request_carries_the_lane_declarationcargo nextest run -p minimal-client host_ip_admission_carries_the_lane_and_waits_for_the_answercargo nextest run -p minvmd host_ip_cohort_reaches_proxy_while_a_member_declares_a_lanecargo nextest run -p minvmd host_ip_cohort_proxy_lane_dropped_without_a_declaring_memberVerify
min task run agent-verifyexited 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.Out of scope
These files are outside the task's
layers:, so this PR is a draft:crates/minimal/src/cmd/boxes/vm_host.rscrates/minimal/src/dash/rpc.rscrates/minvmd/tests/common/mod.rscrates/minvmd/tests/vm_escape_integration.rsCloses #2854
Residuals
min task runsets a fresh instance, and it registers nothing. It must land with the first fresh-instance path that declares a credentialed upstream (min box run, spec 28).host_ipgrant box gets a box id and reaches the proxy's listener, and a later no-granthost_ipbox cannot reach the proxy's address) runs as thebep_host_ip_grant_box_reaches_the_proxy_lanecase ofscripts/session-e2e.sh(arch C1 on d81c7d4). Nobody ran it on a Mac for this PR.