Repository navigation
sandbox: record the launch's options without the old launch profile (SL3.10d) - #1503
Merged
Pedro Henrique Penna (ppenna) merged 1 commit intoNov 12, 2026
Conversation
Contributor
This pull request changes existing testsIt modifies or removes 6 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests. Test code
Relocated unchanged: 0; added: 1. Compared the merge base |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are blocking the sandbox CLI record refactor.
No open issues 🎉
What changed in this PR
This PR advances #1112 by replacing the sandbox CLI’s old launch-profile objects with CLI-owned records and VmConfig, while preserving existing behavior and record format.
Changes:
- Carries images, hostname, workload identity, and shares through
ProvisionConfiginstead ofSandboxLaunch. - Moves workload and image validation into the record layer and updates lifecycle code to use record accessors.
- Retains the old launch plan only for command-line validation in
start.rs, with new regression coverage for reserved boot tokens.
| File | Description |
|---|---|
nvx-rs/tests/cli/lifecycle.rs |
Adds coverage for reserved command-line token refusals without state changes. |
nvx-rs/src/host/cli/sandbox/state/tests.rs |
Builds record round-trip fixtures without launch-profile objects. |
nvx-rs/src/host/cli/sandbox/state.rs |
Adds record-owned validation and accessors; constructs VmConfig directly. |
nvx-rs/src/host/cli/sandbox/mod.rs |
Prepares images and recorded options without the old launch types. |
nvx-rs/src/host/cli/sandbox/lifecycle/start/tests.rs |
Adapts lifecycle and share-overlap tests to the new record inputs. |
nvx-rs/src/host/cli/sandbox/lifecycle/start.rs |
Uses record accessors while retaining legacy command-line checks. |
nvx-rs/src/host/cli/sandbox/lifecycle/mod.rs |
Expands ProvisionConfig and provisions records from explicit image inputs. |
Review effort: Balanced
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10c-network-record
branch
from
November 12, 2026 01:16
d5fdcc6 to
8b606c6
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10d-cli-record
branch
from
November 12, 2026 01:16
d6029a9 to
53a4cf1
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10c-network-record
branch
from
November 12, 2026 03:59
8b606c6 to
83b0eca
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10d-cli-record
branch
from
November 12, 2026 03:59
53a4cf1 to
b1b664a
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10c-network-record
branch
from
November 12, 2026 04:18
83b0eca to
b107c09
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10d-cli-record
branch
from
November 12, 2026 04:19
b1b664a to
566caf0
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10c-network-record
branch
from
November 12, 2026 04:41
b107c09 to
c5afedc
Compare
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10d-cli-record
branch
from
November 12, 2026 04:42
566caf0 to
4af6c5a
Compare
Base automatically changed from
agents/slim-sl3-10c-network-record
to
feature/nvx-refactor
November 12, 2026 05:21
The four shared sandbox modules still built and read back the launch of `host::sandbox`, the old launch profile: `run_from` made a `SandboxLaunch` of the layers, a `SandboxUpper` and `SandboxSettings`, `provision` and `sandbox run` serialized the configuration from it, and each start and run read the configuration back into one, to check it and to take its images, its workload identity and its shares. `provision` and `sandbox run` now pass the distro layer, the scratch image and the options that the configuration records, the hostname, the workload identity and the export plan among them, in `ProvisionConfig`. The checks that the launch made move into the CLI's record, in `state.rs`, with the old messages and order: `check_workload` refuses the entrypoint, arguments, hostname and a root identity as the plan's settings did; `check_images` refuses the images and the shares as the plan's `validated` did; and `Config::check` checks a recorded configuration at each start as `Config::launch` did, the RAM upper's cap, the layer's UUID, the workload, the export plan and the images. `run_from` refuses duplicate layers as the launch did, and verifies the distro layer with `DistroBinding::verify`, which `validate_sandbox_systemd_policy` called once it had refused a systemd entrypoint, which the options' own check already refuses. As before, the workload that `run_from` checks is the default one for a run and a restore, whose workloads are exec requests that no boot token carries. `refuse_own_files` takes the image, the scratch image and the export plan in place of the launch, for a state directory, a run's VM directory and a restored sandbox's snapshot store alike. `Config::vm_config` reads the workload identity and the shares from the record itself. A start and a run still refuse the user's `nvx_*` and `virtfs_*` boot tokens, a NUL, and a command line over the 1024-byte budget as the plan of the sandbox profile did, which `VmConfig::check` does only in part. The new `check_command_line` in `start.rs` builds that plan from the record for this alone, so the old launch leaves the four modules but not yet `start.rs`, which a later slice handles. This is the third and last step of SL3.10b, whose split was approved once its measured scope came to about ten times its estimate. Tests: the new `starts_refuse_the_kernel_tokens_of_the_sandbox_profile_and_of_its_mounts` in tests/cli/lifecycle.rs checks that a start refuses the profile's and `--mount`'s tokens, also in their dashed and quoted forms, without changing the state directory, and fails without that refusal. The restore tests of `deprovision` and of a share of the snapshot store, the overlap test of `sandbox run` and the round trip of a restored sandbox's record build the configuration without a `SandboxLaunch`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pedro Henrique Penna (ppenna)
force-pushed
the
agents/slim-sl3-10d-cli-record
branch
from
November 12, 2026 05:21
4af6c5a to
c7fec09
Compare
Pedro Henrique Penna (ppenna)
marked this pull request as ready for review
November 12, 2026 05:22
Pedro Henrique Penna (ppenna)
merged commit Nov 12, 2026
580adf0
into
feature/nvx-refactor
82 of 85 checks passed
Pedro Henrique Penna (ppenna)
deleted the
agents/slim-sl3-10d-cli-record
branch
November 12, 2026 06:09
This was referenced Nov 12, 2026
This was referenced Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1112: SL3.10b, step 3 of 3 (the CLI no longer uses the old launch, store or config APIs). Follows #1497 and #1501, which have merged.
What and why
SL3.10b removes the last uses of
nvx's old launch, store and config APIs from the CLI's four shared sandbox modules:host/cli/sandbox/{mod,options,state}.rsandsandbox/lifecycle/mod.rs. Its measured scope came to about ten times its estimate of 20 core lines, sinceSandboxLaunch,SandboxSettings,SandboxUpperandSandboxNetworkstill carry provision, start and the sandbox's record. The split of SL3.10b into three stacked pull requests, each with one goal, was approved for Pedro Henrique Penna (@ppenna):NetworkConfig, and the record to format 10.SandboxLaunch,SandboxSettingsandSandboxUpperleave the four modules for the CLI's record and aVmConfig.Before,
run_frommade aSandboxLaunchof the layers, aSandboxUpperandSandboxSettings;provisionandsandbox runserialized the record from it; and each start and run read the record back into one, to check it and to take its images, workload identity and shares, throughConfig::launch. Now:provisionandsandbox runpass the distro layer, the scratch image, and the options that the record keeps, the hostname, workload identity and export plan among them, inProvisionConfig.sandbox/state.rs), with their messages, codes and order:check_workloadrefuses the entrypoint, arguments, hostname and a root identity as the plan's settings did;check_imagesrefuses the images and the shares as the plan'svalidateddid; andConfig::checkchecks a record at each start asConfig::launchdid: the RAM upper's cap, the layer's UUID, the workload with the default entrypoint, the export plan for the container root, and the images.Config::vm_configtakes the workload identity and the shares from the record itself.run_fromrefuses duplicate layers with the launch's message, and verifies the distro layer withDistroBinding::verify, whichvalidate_sandbox_systemd_policycalled after its systemd-entrypoint refusal;SandboxOptions::check, earlier inrun_from, already refuses those entrypoints forrun,provisionandexec. As before, the workload that it checks for a run and for a restore is the default/bin/sh, since theirs are exec requests that no boot token carries.refuse_own_filestakes the image, the scratch image and the export plan in place of the launch, for a state directory, a run's VM directory and a restored sandbox's snapshot store alike.start.rschanges only where removing the types forces it:start,runandrecordtake the record's accessors. It keeps every refusal, including that of the user'snvx_*andvirtfs_*boot tokens, a NUL, and a command line over the 1024-byte budget, whichVmConfig::checkmakes only in part. Its newcheck_command_linestill builds the old plan of the sandbox profile from the record for that refusal alone, so the old launch leaves the four modules, but not yetstart.rs; see Left for later slices.cli/run.rsdoes not change.No output, record, message or public API changes.
Size. 261 core lines, 4 counted files:
sandbox/state.rs118,sandbox/mod.rs72,sandbox/lifecycle/start.rs58 andsandbox/lifecycle/mod.rs13. The public API,BOOT_CONTRACT_VERSIONandCONTROL_CONTRACT_REVISIONdo not change.Stack. This branch is based on
feature/nvx-refactor533bbb81f8d, which holds #1497 and #1501. Review its one commit,c7fec0980ca.Case matrix. No row of
doc/acceptance-case-matrix.mdlists a test that this changes or names one as coverage, and the new CLI test belongs to none of its inventoried sets.Left for later slices
Old launch, store and config APIs that the CLI still uses outside the four modules, which this split leaves alone:
sandbox/lifecycle/start.rs:check_command_linebuildsSandboxLaunch,SandboxSettingsandSandboxUpperfor the command-line refusal above, untilVmConfig::checkrefuses what the old plan'skernel_command_linerefuses.sandbox/lifecycle/stop.rs:host::supervisor::StopOutcome.sandbox/lifecycle/directory.rs:host::store::SandboxStore.store/files.rs:host::store::{files, regular}.snapshots/capture.rs:host::store::files::create_new.cli/run.rs:host::sandbox::SANDBOX_COMMAND_LINE_MAX_SIZEandmount::export_command_line_fragment, the old plan's command-line budget and rendering.sandbox/lifecycle/tests.rs(host::supervisor::StopOutcome),store/tests.rs(host::store),store/tests/{liveness,recovery}.rsandsnapshots/capture/tests.rs(host::spawn),snapshots/tests.rsandsnapshots/capture/tests.rs(host::store::files), andrun/tests.rs(the command-line budget).Validation
At this head (
c7fec0980ca), onfeature/nvx-refactor533bbb81f8d; this step's commit has had the same content since53a4cf1e61d, which Copilot reviewed:cargo fmt --check; Clippy--all-targets --all-featureswith-D warnings;cargo test --all-features --lib -- host::cliand--test cli;test_microvm_tests.PublicSandboxRamUpperTestsandPublicSandboxGptLayerTests, andtest_nvx_tools.CiConfigurationTests;check_test_layout.py;check_markdown_links.pycli111scripts/test_microvm_tests.py(353 tests)cli120nvx.py test-microvm --backend kvmwith every public sandbox scenario:managed-exec-config,sandbox-gpt-layer,sandbox-lifecycle,sandbox-proxy-only,sandbox-ram-upper,snapshot-core,snapshot-tiersandvm-lifecyclenvx-rsand the Alpine initramfs built at this head; OpenVMM, the kernel and the scratch template of releasev0.1.0-dev.53ad09678bc1, which pins the same OpenVMM; the Ubuntu distro layer offeature/nvx-refactor64ad98afacc's CI run, whose guest inputs this head keeps53a4cf1e61dand at that of its base,feature/nvx-refactor14ca2671205:snapshot capture;snapshot restorewith a RAM upper and a workload with whitespace and double quotes;sandbox exec,stop,start,exec,stopanddeprovisionof the restored sandbox;run --restore-snapshotwith a RAM upper and with a scratch upper, with a workload that exits with status 7, and with--netand--workload-user 0:0, which it refusesrun --restore-snapshotwith--workload-user 1000:1000and--hostname restoredfails at both, withguest-exit status 125Earlier rebases onto #1489 and #1491, then onto SL5.1b, SL5.1c, SL5.2, #1508 and #1511, and then onto #1497 and #1501 as they merged, changed none of this step's content after the first of them, which resolved three conflicts with #1489: in
sandbox/mod.rs, a restore's workload is the default one too, asrun's, whichrun_fromkeeps; instart.rs, a restored start refuses a share of its snapshot store, whichrefuse_own_filesnow does with the record's image, scratch image and shares; and instart/tests.rs, whose restore tests SL3.8a moved tostart/tests/restore.rs, wherea_restored_start_refuses_a_share_of_its_snapshot_store, which came with SL3.8a, also builds its record without aSandboxLaunch. The size grew from 253 to 261 core lines then.rebase_check.py verifyreports only #1501's commit, which merged as533bbb81f8d.Before those rebases, at
d6029a97a3fon the temporary base, every gate of check-nvx-rs and validate-nvx passed on Windows and on nvx-kvm-test, but for failures that the base shares, and two Windows timeouts under load, which passed when rerun. A code review found no issue.CI runs the remaining gates, MSHV and WHP among them.
Tests modified
check_test_changes.py --base origin/feature/nvx-refactorlists 6 changes to existing tests and 1 new test:starts_refuse_the_kernel_tokens_of_the_sandbox_profile_and_of_its_mounts(tests/cli/lifecycle.rs). A start refusesnvx_entrypointrecorded at provision,nvx-sandbox=0(dashed),"a nvx_mode=one-shot"(quoted) andvirtfs_tag=microvm, withunsupportedand the old messages, without changing the state directory. It fails once the refusal is removed.deprovision_removes_a_restored_sandboxs_view_only_under_its_snapshots_lockanda_restored_start_refuses_a_share_of_its_snapshot_store(start/tests/restore.rs),run_checks_again_that_its_shares_do_not_overlap(start/tests.rs), andrestored_sandbox_records_round_trip_only_their_own_source(state/tests.rs) build the record without aSandboxLaunch: the layer, the scratch path and the export plan, with the default hostname and workload identity inProvisionConfig. They check what they checked before, and the imports ofstart/tests.rsandstart/tests/restore.rsfollow.