GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — host: delete the old config types and launch paths (SL6.3) by ppenna · Pull Request #1530 · microsoft/nvx

Conversation

@ppenna

@ppenna Pedro Henrique Penna (ppenna) commented Nov 12, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Leaving code only. This PR changes only code that this effort removes from NVX: the old config types (LaunchSpec, SandboxPlan, SandboxLaunch, SandboxSettings, SandboxNetwork, CaptureClass), the rest of host::launch, the prepared launch and its checked-file handoff, the transitional host::supervisor with spawn_command, the boot rendering of shares, WORKLOAD_ACCOUNT_TOKEN, and the shell /init's reading of OpenVMM's lifecycle and workload tokens, with the crate-private code that only they used and the edits that remove references to them. Nothing that stays changes, and no later PR uses what it changes, so the size limits for kept code don't apply.

Beyond what leaves, it carries out the decisions that the orchestrator made for Pedro Henrique Penna (@ppenna) on #1122 (D1 to D6): the external-launch example starts its VMM with a minimal launcher of its own (D1); the workload-identity and managed-lifecycle scenarios also give the CLI's tokens (D5); and the tests of code that stays move out of the deleted test files to the owners of that code. What only the CLI uses now allows dead code without the cli feature, as host::spawn does.

Part of #1122 (SL6.3, "The old config types are gone"). Umbrella #1076.

Stacked on #1526 (SL6.0f), whose branch is this PR's base: the CLI checks the command line that it launches there, so this PR deletes the old types whole (D2, D3). SL6.3 was built on SL6.1's branch (#1520, 5bffcd7f); since #1520 merged, both are restacked on feature/nvx-refactor f03c21c3f0c: #1526 as 93469a4aca7, which since fixes its Copilot review thread, and this PR's 7 commits on it, unchanged (git range-diff).

What and why

SL6.1 (#1520) left the old launch path without callers: the CLI's sandbox start and run name their images by path in a VmConfig, vm::create and vm::spawn launch every VM, and since SL6.0f the CLI checks the command line that it launches. What remained of the old path served only itself, the transitional host::supervisor re-exports and the tests. The commits, in order (consumers before providers):

  1. a188e91c96e examples: launch the external-launch VM with a launcher of its own (D1). The example handed vm::create's command to supervisor::spawn_vm. It now starts the VMM on std::process: the capability through a pipe closed to writers before the spawn, the log as standard output and error, a process group of its own, and on Windows no console and the command's breakaway flag. It holds the VMM through a ProcessRef whose start time it reads itself, as ProcessRef defines it (the starttime field of /proc/<pid>/stat on Linux, the creation time on Windows), and takes Transport from host::transport, so it uses nothing of host::platform, which SL6.14 (host: make the platform layer private to nvx (SL6.14) #1529) makes crate-private. Its docs list what it leaves out, which a production launcher adds, as vm::spawn does: it passes no descriptor or handle besides the standard streams (and refuses a command that allows any); on Linux no new session and the caller's umask; on Windows every inheritable handle of the caller and no log-named job. No public API is added.
  2. 44830cf9941 host: delete the prepared launch and its checked-file handoff. host::sandbox::prepared (PreparedLaunch, with adapter_arguments), Inherited::proc_path, Windows Process::close_inherited and ProcessHandle::close_inherited, and what only they used: Linux move_above_standard_streams, Windows seal::final_path, CheckedDistro's and CheckedScratch's file_mut, and CheckedDistro::bound. CheckedScratch::claim, which only the CLI reads, is gated by cli. The README's "Checked handoff" section becomes "Images by path" (D6, below).
  3. e19664c6817 host: delete the transitional supervisor path of the spawn. host::supervisor goes whole, with spawn, spawn_vm, VmmCommand::new, Launched::kill_and_wait with the Windows LaunchedProcess::terminate that only it called, and spawn_command. VmmCommand, Launched and Inherited become crate-private; spawn_vm_with_mode takes their docs. The spawn lock and the termination after a failed spawn stay, as vm::spawn's private foreground mode does (D4: inherit_only, SpawnMode::Foreground, Windows LaunchedProcess::wait_timeout).
  4. ac2d47238b3 host: delete the capture class. CaptureClass, ClassIdentity, its domain and SnapshotKey::new; a key comes from its CaptureContext through SnapshotKey::from_capture. The conformance vectors lose their CLASS lines; the KEY vectors don't change.
  5. f6e2add01a7 host: delete the old sandbox plan and launch. host::sandbox::plan (SandboxPlan, SandboxDistro, SandboxUpper, SandboxNetwork, BlockRole, PLAN_VERSION), SandboxLaunch, SandboxSettings, the profile's KERNEL_COMMAND_LINE_MAX_SIZE, OPENVMM_COMMAND_LINE_RESERVE and SANDBOX_COMMAND_LINE_MAX_SIZE, the workload limits, options::validate_sandbox_systemd_policy, and the boot rendering of shares: BootShares, boot_shares, aggregate_share_tokens, aggregate_command_line_fragment, export_command_line_fragment, aggregate_child_name, aggregate_child_argument and mount_argument. plan_mounts, plan_mounts_with and path_text stay for nvx-rs slimming 4.3.1: image staging, artifact discovery, the policy-file reader and the mount syntax are private to the CLI #1124, at their owners.
  6. e1d33b71473 host: delete the old launch. host::launch goes whole: LaunchSpec, VmmLaunch with RESERVE and arguments, WorkloadIdentity's DEFAULT and select, MAX_TIMEOUT, DEFAULT_MEMORY_MIB, DEFAULT_HOSTNAME, base_command_line, kernel_parameters_problem, timeout_problem, check_process_command_line, and its re-exports of host::config's helpers, which stay there with COMMAND_LINE_BUDGET, DEFAULT_GUEST_NETWORK, OPENVMM_COMMAND_LINE_RESERVE and VmConfig::check_command_line, unchanged. protocol::WORKLOAD_ACCOUNT_TOKEN goes; the fake OpenVMM spells its own.
  7. 604d8dacccb guest: stop reading OpenVMM's lifecycle tokens in the shell init. guest/common/init no longer reads nvx_lifecycle=, nvx_workload_uid= or nvx_workload_gid=, and starts nvx-init for every layered root instead of handing one with nvx_lifecycle= to nvx-init-agent. A blockless guest takes its lifecycle from nvx_mode= and its identity from nvx_identity= alone. The workload-identity and managed-lifecycle scenarios, which start OpenVMM directly, keep OpenVMM's --microvm-workload-identity and --microvm-lifecycle, which OpenVMM itself checks, and also give the CLI's nvx_identity= and nvx_mode=managed (D5). No NVX launch passes OpenVMM's options any more: the old launch paths are gone.

Public API. The snapshots lose 231 items on Linux and 230 on Windows, and gain none: the modules host::launch, host::supervisor, host::sandbox::plan and host::sandbox::prepared, the plan's re-exports from host::sandbox, the boot rendering of host::sandbox::mount, options::validate_sandbox_systemd_policy, CaptureClass, ClassIdentity and SnapshotKey::new, and protocol::WORKLOAD_ACCOUNT_TOKEN. protocol's WorkloadIdentity, which activation payloads carry and which was public only through host::launch, becomes pub(crate).

Crate-private code that the deletions leave unused, as warning-denied builds of every feature set find it on Linux and Windows, goes: move_above_standard_streams (Linux), seal::final_path (Windows), CheckedDistro::file_mut and bound, CheckedScratch::file_mut, Process::close_inherited and ProcessHandle::close_inherited (Windows), LaunchedProcess::terminate (Windows), host::sys::effective_ids, and mount::request::command_line_fragment with the bootstrap-token constants of mount. What only the CLI uses now allows dead code without cli, with a reason, as host::spawn does: host::process::KILL_TIMEOUT, Launched::wait_timeout and its reaping and status helpers, Windows LaunchedProcess::wait_timeout, CheckedScratch's claim (its field, and Windows' claim(), which only the CLI calls), mount::check_distinct_export_roots and its re-export beside HostQueries, and config::reject_container_path; outside Windows, the spawn lock, which only the tests take there, and VmmCommand::breakaway_from_job, which only Windows reads. protocol re-exports its workload module only for the CLI and the guest.

The by-path model (D6, Pedro Henrique Penna (@ppenna)'s note on #1122)

Confirmed as the intended model: a launch names its images by path. The checks, DistroBinding::check and ScratchBinding::check, find a staged image unchanged from its metadata alone and return it open, but what takes an image's path after its check is what OpenVMM opens. The docs of host::sandbox::distro, host::sandbox::scratch and host::seal require callers to stage their images in a directory that only their own account can write, so no other account can replace a checked path. On Windows, a held checked distro layer also denies other opens for writing or deleting it, and the scratch image's guard denies deleting and renaming it; the VMM inherits the scratch claim. SL5.1a's security checklist checks the precondition (tests/security_checklist.rs::a_staged_image_that_was_replaced_fails_its_check). The README's "Images by path" section states it, and the case matrix retires images_replaced_after_the_checks_never_reach_the_vm under it and drops checked_handoff.rs from the coverage of a_layered_launch_hands_openvmm_the_checked_images.

Every removed test, and its fate

python scripts/check_test_changes.py --base 93469a4aca7 reports 371 changes to existing tests: 78 removed tests, 76 modified tests, 96 removed and 89 modified helpers, and imports, attributes and modules; 33 tests relocate unchanged and 42 are added (moved or renamed). No removed test is named in the case matrix, as coverage or otherwise (git grep of each name), but for the doc test of PreparedLaunch and the module doc test of host::supervisor, whose rows say where their coverage went. The fates, by deleted code:

host::launch: 14 retire

kernel_command_line_sets_the_hostname, arguments_select_the_managed_direct_guest, mappings_add_the_export_and_the_mapping_count, oversized_process_command_lines_are_rejected, launches_may_use_the_reserve_that_provisioning_keeps, every_launch_names_its_own_inputs_alike, the_reserve_of_a_plan_holds_the_rest_of_a_launch_of_inputs_of_max_path, kernel_parameters_are_checked, kernel_parameters_are_read_as_the_kernel_reads_them, reserved_parameters_are_refused_whatever_separates_them, the_kernel_reads_the_hostname_after_accepted_parameters, every_command_line_checks_the_specification, timeouts_are_bounded, workloads_that_map_host_paths_take_the_host_identity. The helpers that stay keep their tests in host::config: process_command_lines_are_measured_as_windows_quotes_them, a_process_command_line_fits_while_it_leaves_its_reserve and configuration_command_lines_keep_the_same_reserve_on_every_host, with vm::tests::creation_checks_the_complete_actual_command_line_at_the_windows_boundary.

host::sandbox::plan: 23 retire

adapter_launches_are_planned_with_room_for_the_rest_of_the_launch, adapter_plans_persist_without_settings_or_an_export, adapter_plans_refuse_the_settings_of_their_root_that_they_do_not_name, adapter_plans_refuse_what_their_root_and_openvmm_own, adapter_plans_render_their_root_and_devices_alone, every_format_and_upper_plans_and_renders, launches_carry_their_network_into_their_plans, launches_plan_the_image_that_the_binding_of_their_distro_layer_records, launches_plan_their_distro_layer_over_ram, launches_plan_their_distro_layer_over_their_scratch_image, networks_check_their_guest_network_and_their_policy, persisted_plans_that_break_the_form_or_the_checks_are_refused, plans_check_the_images_of_their_block_devices_against_the_host, plans_check_their_export_plan_for_the_container_root, plans_check_their_settings_as_launches_do, plans_persist_in_their_versioned_form, plans_refuse_the_command_lines_that_the_guest_refuses, plans_refuse_the_tokens_that_the_guest_init_reads_in_quoted_values, plans_render_and_report_their_network, plans_require_properly_nested_disk_path_brackets, the_guest_reads_the_root_of_every_plan_from_its_command_line, the_longest_boot_tokens_fit_the_command_line_budget_to_the_byte, the_managed_lifecycle_exports_the_shares_and_announces_their_mapping_table. What stays of their checks is tested where it lives now: the CLI's command line in starts_check_the_kernel_command_line_that_they_launch and cold_share_command_lines_fit_the_kernel_budget_to_the_byte (SL6.0f), the rendering of roots, networks and exports in host::config's cold_boot_arguments_* tests, the disk paths in cold_boot_arguments_refuse_disk_syntax_in_image_and_scratch_paths and tests/cli/validation.rs, and the proxy's URL in network::tests::proxy_urls_name_the_gateway_as_the_guest_sees_it.

host::sandbox::prepared and the checked-file handoff: 16 retire, 2 move

The 10 unit tests of prepared: a_release_through_a_process_that_inherited_nothing_closes_none_of_its_handles, an_adapter_s_launch_renders_complete_arguments_that_fit_a_command_line, an_upper_in_ram_takes_no_scratch_image, gpt_disks_are_prepared_from_their_bindings, no_plan_encodes_root_as_the_workload_identity, prepared_launches_accept_balanced_brackets_in_final_paths, prepared_launches_hand_the_vmm_the_checked_files, prepared_launches_refuse_final_paths_that_openvmm_cannot_take, prepared_launches_take_only_the_checked_files_of_their_plan, staging_checking_and_preparing_a_launch_read_no_content. The 4 handoff cases of tests/checked_handoff.rs: a_prepared_launch_hands_the_vmm_its_checked_images_alone, a_vmm_keeps_the_scratch_images_claim_once_its_launcher_is_gone, a_vmm_finds_the_checked_images_past_replaced_links_from_another_directory, a_launch_passes_a_checked_file_that_took_a_standard_streams_descriptor. Windows a_child_loses_only_the_inherited_handle_that_is_closed_in_it (of close_inherited) and seal::windows::tests::final_paths_hold_no_nul_whatever_their_length (of final_path). The file's 2 cases of the spawn that stays, launched_waits_return_and_retain_the_actual_exit_status and strict_cleanup_terminates_and_confirms_a_running_child, move to host::spawn's unit tests, and its exit_status_fixture joins their vmm_fixture. gpt_disks_bind_by_their_disk_guid no longer checks bound(), and checks_claim_the_image_without_reading_it no longer checks proc_path.

host::supervisor: the 11 kept cases move

As the notes on #1122 and D1 ask, tests/supervisor.rs becomes tests/process.rs, with its 7 tests of host::process, whose processes a fixture of its own starts through std::process: processes_can_be_shared_between_threads, a_child_that_exits_wakes_its_waiter, a_process_that_is_not_a_child_wakes_its_waiters, a_reused_process_id_is_never_signaled, references_that_name_no_process_are_never_opened, and on Windows a_process_that_this_user_may_not_query_has_an_unknown_state and a_process_that_this_user_may_not_terminate_is_waited_for_but_never_signaled. Its 4 tests of the spawn move to src/host/spawn/tests.rs, which now builds on Linux and Windows: working_directory_limits_include_trailing_separators (Windows), a_restarted_launcher_finds_its_vmm_again_and_ends_it (the breakaway), vmms_inherit_only_their_streams_and_allowed_descriptors_while_others_spawn and a_job_that_ends_its_vmm_wakes_the_waiters (Windows), with the launcher fixture; its vmm_fixture joins the spawn tests' one. The spawn's Linux tests move to src/host/spawn/tests/linux.rs, unchanged but for the strict spawn. Windows a_vmm_whose_log_is_no_file_of_a_disk_volume_starts_without_a_job becomes ..._is_refused: the start without a job that only supervisor::spawn made goes, its refusal by the strict spawn stays. The tests that spawned through the old paths spawn through spawn_vm_with_mode (host::platform::windows::tests, host::restore::tests, host::cli::store::tests::liveness), and host_modules' graph test loses the edge from supervisor to spawn.

CaptureClass: 2 retire, 13 rewritten

the_guest_build_is_not_part_of_a_snapshot_key and each_field_of_a_class_changes_its_identity retire, with the class's part of identities_have_a_text_form. The key's other tests derive their keys from contexts through from_capture (a_capture_that_does_not_match_its_class_is_refused, which loses the case of a network whose policy attaches no NIC, a_class_selects_a_profile_as_openvmm_does, a_generations_own_metadata_leaves_the_key_as_it_is, a_key_holds_what_its_capture_made, a_key_that_holds_its_network_s_lowering_after_its_invariants_is_refused, complete_capture_time_round_trips_without_changing_compatibility_identity, each_part_of_the_key_changes_it, keys_of_machines_that_no_manifest_describes_are_refused, keys_read_back_from_their_canonical_encoding, keys_with_the_removed_guest_build_field_are_refused, the_conformance_vectors_decode_and_encode), and invalid_classes_are_refused becomes captures_of_invalid_contexts_are_refused. The snapshot fixtures class() and network_class() become context() and network_context() (snapshot_open_refuses_*, the capture tests).

The sandbox profile's own tests: 17 retire, 21 rewritten

Retired with the plan and the launch: launch_contract_builds_agent_command_line, launch_contract_rejects_duplicates_and_reserved_tokens, launch_settings_are_checked_in_order, launch_rejects_limits_the_guest_cgroup_cannot_store, launch_contract_attaches_mount_and_reserves_bootstrap_tokens, launch_contract_attaches_several_shares_as_an_aggregate, launch_bounds_shares_by_the_kernel_command_line, launch_contract_rejects_disk_option_delimiters_and_unbalanced_brackets (the CLI's refusal stays tested in tests/cli/validation.rs); the specifications aggregate_child_name_known_answer, launch_arguments_follow_the_openvmm_contract, accepted_launch_shapes_keep_their_arguments_and_kernel_tokens, shares_follow_the_openvmm_and_guest_contracts, launch_settings_follow_the_guest_contract, caller_parameters_follow_linux_and_guest_rules, aggregate_child_names_follow_the_restore_contract, kernel_command_line_stays_within_1024_bytes and reserved_kernel_tokens_are_always_refused; and the share tests aggregate_child_names_pin_their_targets and boot_tokens_refuse_what_the_shell_cannot_bind.

Rewritten, keeping their checks of code that stays: launch_contract_attaches_a_file_as_an_aggregate_child becomes file_shares_take_no_policy_paths_or_reserved_targets and launch_validation_requires_the_layers_and_the_scratch_image becomes missing_files_are_named_with_their_components_alone (require_file); launch_validation_rejects_overlapping_or_foreign_host_paths, shares_that_only_a_verbatim_path_names_are_refused, launch_validation_rejects_shares_that_came_to_overlap and launch_validation_requires_plain_mount_directory plan their shares with plan_mounts and check them again as a start does, with check_distinct_export_roots and ExportPlan::verify; the specifications layer_values_are_role_path_uuid, kernel_token_values_refuse_separators, the_reproduction_of_microsoft_nvx_723_is_refused and accepted_values_stay_one_kernel_parameter keep their checks of layers and targets, and canonical_layer_uuids_reach_the_guest becomes canonical_layer_uuids_round_trip; the share tests mount_parser_defaults_to_read_only_and_accepts_rw, mount_parser_accepts_host_paths_with_commas, mount_owner_defaults_to_vmm_and_forwards_caller, mount_access_policy_is_validated_and_forwarded and shares_are_planned_through_the_export_planner drop the boot rendering; and the option tests distro_manifest_binds_the_layer, systemd_entrypoints_and_images_are_refused_independently, sandbox_allows_non_systemd_sbin_init, the_entrypoint_check_needs_no_manifest_and_precedes_the_distro_verification, sandbox_rejects_systemd_from_bound_distro_metadata and distro_manifests_are_strict_json run the CLI's preflight, validate_sandbox_entrypoint and DistroBinding::verify, while sandbox_command_shares_a_file and sandbox_command_attributes_mount_deny_to_the_preceding_mount check the export plan's kernel token.

Elsewhere: 1 renamed, helpers adjusted

config::tests::cold_command_lines_keep_the_old_root_view_and_mapping_values compared a configuration's command line with those of LaunchSpec and SandboxPlan; as cold_command_lines_carry_the_root_the_view_and_the_mapping_count, it checks the line against the configuration, and its case-matrix row follows the rename. The restore driver's test workload spells the identity that WorkloadIdentity::DEFAULT named, and tests/cli/openvmm.rs's two_share_command_line_room the tokens that OpenVMM appends. The CLI's capture and store tests build VmmCommand as a struct.

The shell /init and the scenarios

test_old_lifecycle_tokens_keep_the_old_layered_init becomes test_old_lifecycle_tokens_no_longer_select_the_old_layered_init, and the new test_old_workload_identity_tokens_name_no_identity checks that the init no longer reads nvx_workload_uid=/nvx_workload_gid=; test_exec_override_cannot_bypass_the_new_sandbox_init and test_missing_helpers_or_selected_init_fail_without_fallback expect nvx-init for a layered root with nvx_lifecycle=. All four fail on the old init. The scenarios' unit tests check the CLI's tokens on the command line.

Size

Measured against 93469a4aca7, by #1076's rules: leaving code only, no limit. The workstream's measuring script counts 221 added or changed code lines in 29 Rust files, plus 20 in scripts/nvx_tools/microvm_tests.py and 2 in guest/common/init: 31 counted files. Of the 221, the 117 in nvx-rs/src only gate items by cli or by platform, make items crate-private, or shorten the import and re-export lists of what goes, and so don't count; the other 104 are the example's own launcher (D1). The 22 lines of the scenarios (D5) and of the init's remaining case and condition count. The estimate was 0 core lines and 9 counted files. 76 files change: +2785 and −12587 lines, tests and docs included. BOOT_CONTRACT_VERSION and CONTROL_CONTRACT_REVISION don't change.

Left as is

  • nvx-init-agent and the container scripts, which no launch starts any more; doc/project-structure.md says so. Their removal is not in SL6.3's Scope.
  • The CLI's run accepts nvx_lifecycle=, nvx_workload_uid= and nvx_workload_gid= in --cmdline as aliases of its own nvx_mode= and nvx_identity=, which it renders before the guest reads them, and the fake OpenVMM keeps emulating OpenVMM's options, as nvx-rs slimming 3.1.4: run uses the new interface and the CLI's own guest tokens #1109 left it.
  • doc/modules, which CI draws again after the merge.

Not in this PR

Rewriting, refactoring or improving retained mount planning, path handling, VM configuration or VM spawning; re-homing the deleted APIs or adding replacements (no public constructor of ProcessRef was added for the example); deleting plan_mounts, plan_mounts_with or path_text (#1124); changing DEFAULT_GUEST_NETWORK, COMMAND_LINE_BUDGET, the Windows command-line helpers, the private spawn lock or the failed-spawn termination; incrementing a contract version.

Validation

The checks ran on a3d93c075ad, and the test suites again on c04cd8a7b18, whose tree differs only by one Linux test helper (below), and on this head (after the tables), with Rust 1.95.0 and NVX_BUNDLE=skip, locally on Windows, on nvx-mshv-test (Azure Linux 3, kernel 6.18, linux-mshv, virtual machine), nvx-kvm-test (Azure Linux 3, kernel 6.6, linux-kvm, virtual machine) and nvx-whp-test (Windows, WHP, virtual machine), in temporary worktrees. The gates are those that local_gates.py --files selects, run from this branch's actions.

Check Windows (local) Linux
cargo fmt --all --check passed passed (MSHV)
Clippy -D warnings: --all-targets --all-features, --lib, --lib --no-default-features, --lib --no-default-features --features serde, --lib --bins --features cli, --lib --bins --no-default-features --features testing, --all-targets passed, natively and for --target x86_64-unknown-linux-gnu; every commit also passes cargo check --all-targets --all-features on both passed (MSHV)
cargo check --all-targets --all-features --target aarch64-apple-darwin; guest Clippy for x86_64-unknown-linux-musl passed
cargo test --locked --all-features passed: 16 suites, 1279 tests, 25 ignored (a3d93c075ad; the change since is Linux-only) MSHV: passed, 95 suites, 2292 tests, 65 ignored. KVM: the 28 guest:: failures of the base on kernel 6.6, the same names, and none else
cargo test --locked passed: 13 suites, 847 tests MSHV and KVM: passed 3 times each, 840 tests; the lib binary 20 more times on each, with no failure
cargo build --lib --no-default-features, cargo test --lib --no-default-features passed: 246 passed: 246 (MSHV)
The bundled-artifact check with a synthetic release passed: 21 (MSHV)
RUSTDOCFLAGS=-D warnings cargo doc --no-deps --all-features passed passed (MSHV)
public_api.py updated with --update, then passed passed (MSHV)
cargo +1.89 check --all-targets --all-features (MSRV) passed (MSHV)
check-guest-binaries, then build-guest-binaries and test-guest-binaries MSHV: passed, 64 suites, 1211 tests, 47 ignored; 33. KVM: the base's guest:: failures on kernel 6.6
check_test_layout.py, check_markdown_links.py, SL5.2's check_matrix.py passed
Python: ruff check, ruff format --check, pyright (Linux and Windows) of the changed scripts; shellcheck --shell=sh guest/common/init; GuestInitRoutingTests, GuestInitWorkloadIdentityTests and the scenarios' unit tests passed

The microVM scenarios and the example ran on a3d93c075ad with the static nvx-rs that each host built, the Alpine initramfs that nvx.py build-initramfs built from this branch on nvx-kvm-test (its /init is guest/common/init byte for byte; copied to the other hosts and checked by SHA-256), and CI run 43168368915's kernel, Ubuntu distro layer, scratch template and OpenVMM builds of the pin 14dc4116, with their provenance:

nvx-kvm-test nvx-mshv-test nvx-whp-test
workload-identity, managed-lifecycle (D5) passed passed passed
guest-boot, lifecycle, vm-lifecycle passed passed passed
sandbox-lifecycle, sandbox-ram-upper, sandbox-blocks, managed-exec-config passed passed passed
sandbox-gpt-layer, sandbox-proxy-only passed passed
filesystem-shares, snapshot-core, command-line-limit, structured-outcome passed passed passed
filesystem-comma-paths, filesystem-owner, platform-filesystem, platform-aggregate-export passed passed
external-launch: a cold boot, then a restore up to its restore-ready event from a snapshot that nvx-rs snapshot capture captured passed passed passed

The microVM scenarios ran with the default signal dispositions. They also passed on 38dd99330ba, before the restack on f03c21c3f0c.

This head, 604d8dacccb, differs from c04cd8a7b18 only by #1526's fix of its review thread, in sandbox/lifecycle/start.rs and its tests. On it, Windows passed cargo test --all-features (16 suites, 1279 tests, 25 ignored), cargo test (13 suites, 847 tests), cargo test --lib --no-default-features (246), cargo doc with -D warnings, public_api.py, check_test_layout.py, and Clippy --all-targets --all-features, --lib --no-default-features and --lib --bins --features cli, natively and for x86_64-unknown-linux-gnu, with the macOS check. nvx-mshv-test passed cargo test --all-features (95 suites, 2292 tests, 65 ignored), cargo test (13 suites, 840 tests), Clippy --all-targets --all-features, and sandbox-lifecycle, sandbox-ram-upper, managed-exec-config, workload-identity and managed-lifecycle with nvx-rs built at this head.

Changes to existing tests (tests-modified)

check_test_changes.py --base 93469a4aca7 lists 371 changes, explained by deleted code in "Every removed test, and its fate" above: the tests of deleted code retire; the tests of code that stays move to its owners, or drop the assertions on deleted rendering, or run what the CLI runs; one renamed test follows its new reference. Two changes go beyond a move:

  • vmms_inherit_only_their_streams_and_allowed_descriptors_while_others_spawn now runs beside the crate's other unit tests, where its check that a process spawned through std::process holds none of the VMMs' descriptors failed on Linux, consistently in the default-feature lib binary on nvx-mshv-test: the kernel wakes posix_spawn's parent before the child's exec closes its close-on-exec descriptors, so for an instant the child's table still lists every descriptor of the parent, both ends of the test's pipes included. held_objects looks again until the objects are gone or a second passes: an inherited descriptor stays for the child's life. The same check in tests/supervisor.rs had this race; it showed in the busier process. With the fix, 20 runs of that binary passed on each Linux host, where 20 of 20 failed without it.
  • tests/vectors/snapshot-key-v1.txt loses its CLASS vectors, whose type goes; its KEY vectors don't change.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ppenna Pedro Henrique Penna (ppenna) added tests-modified Changes existing tests, test data, or test wiring feat-nvx-refactor labels Nov 12, 2026
@ppenna Pedro Henrique Penna (ppenna) self-assigned this Nov 12, 2026
@ppenna
Pedro Henrique Penna (ppenna) requested a balanced review from Copilot November 12, 2026 09:30
@github-actions

github-actions Bot commented Nov 12, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 372 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

Change What Before After
modified attributes the inner attributes of host::launch::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and test did) nvx-rs/src/host/launch/tests.rs:1 nvx-rs/src/host/spawn/tests/linux.rs:1
modified attributes the inner attributes of host::spawn::tests (it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:1 nvx-rs/src/host/spawn/tests.rs:1
modified attributes the inner attributes of supervisor/restricted (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test and windows hold, not where any ( target_os = "linux" , windows ) and feature = "host" and windows did) nvx-rs/tests/supervisor.rs:978 nvx-rs/src/host/spawn/tests.rs:876
modified helper fn runtime in host::cli::snapshots::capture::tests nvx-rs/src/host/cli/snapshots/capture/tests.rs:185 nvx-rs/src/host/cli/snapshots/capture/tests.rs:186
modified helper fn fake_spawn in host::cli::snapshots::capture::tests nvx-rs/src/host/cli/snapshots/capture/tests.rs:263 nvx-rs/src/host/cli/snapshots/capture/tests.rs:264
modified helper fn running in host::cli::store::tests::recovery::process nvx-rs/src/host/cli/store/tests/recovery.rs:140 nvx-rs/src/host/cli/store/tests/recovery.rs:140
modified helper fn finish in host::platform::windows::tests, impl HeldSpawn`` nvx-rs/src/host/platform/windows/tests.rs:683 nvx-rs/src/host/platform/windows/tests.rs:633
modified helper fn start in host::restore::tests, impl Client`` nvx-rs/src/host/restore/tests.rs:49 nvx-rs/src/host/restore/tests.rs:49
modified helper fn drop in host::restore::tests::live_init, impl Drop for OwnedVm`` nvx-rs/src/host/restore/tests/live_init.rs:31 nvx-rs/src/host/restore/tests/live_init.rs:31
modified helper fn run in host::restore::tests::live_init nvx-rs/src/host/restore/tests/live_init.rs:160 nvx-rs/src/host/restore/tests/live_init.rs:160
modified helper fn workload in host::restore_driver::tests nvx-rs/src/host/restore_driver/tests.rs:182 nvx-rs/src/host/restore_driver/tests.rs:182
modified helper fn new in host::sandbox::options::tests, impl Shares`` nvx-rs/src/host/sandbox/options/tests.rs:916 nvx-rs/src/host/sandbox/options/tests.rs:903
modified helper fn run in host::sandbox::options::tests, impl Shares`` nvx-rs/src/host/sandbox/options/tests.rs:939 nvx-rs/src/host/sandbox/options/tests.rs:924
modified helper fn layer in host::sandbox::prepared::tests, impl Staged`` (moved, and it now compiles where feature = "host" and `test` hold, not where `any ( target_os = "linux" , windows )` and `feature = "host"` and `test` did) nvx-rs/src/host/sandbox/prepared/tests.rs:106 nvx-rs/src/host/sandbox/options/tests.rs:80
modified helper fn host_text in host::sandbox::tests (moved, and it now compiles where feature = "host" and test and windows hold, not where feature = "host" and test did) nvx-rs/src/host/sandbox/tests.rs:60 nvx-rs/src/host/sandbox/tests.rs:46
modified helper fn new in host::sandbox::tests, impl Fixture`` nvx-rs/src/host/sandbox/tests.rs:788 nvx-rs/src/host/sandbox/tests.rs:218
modified helper fn planned in host::sandbox::tests, impl Fixture`` nvx-rs/src/host/sandbox/tests.rs:816 nvx-rs/src/host/sandbox/tests.rs:230
modified helper fn new in host::snapshot::capture::tests, impl Fixture`` nvx-rs/src/host/snapshot/capture/tests.rs:78 nvx-rs/src/host/snapshot/capture/tests.rs:78
modified helper fn key in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:33 nvx-rs/src/host/snapshot/key/tests.rs:33
modified helper fn network_key in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:38 nvx-rs/src/host/snapshot/key/tests.rs:38
modified helper type Change in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:43 nvx-rs/src/host/snapshot/key/tests.rs:44
modified helper fn identity_after in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:47 nvx-rs/src/host/snapshot/key/tests.rs:48
modified helper fn set_memory in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:54 nvx-rs/src/host/snapshot/key/tests.rs:69
modified helper fn assert_mismatched in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:442 nvx-rs/src/host/snapshot/key/tests.rs:442
modified helper fn vector_class in host::snapshot::key::tests (renamed to vector_context) nvx-rs/src/host/snapshot/key/tests.rs:984 nvx-rs/src/host/snapshot/key/tests.rs:882
modified helper fn network_class in host::snapshot::tests (renamed to network_context) nvx-rs/src/host/snapshot/tests.rs:995 nvx-rs/src/host/snapshot/tests.rs:1003
modified helper fn new in host::snapshot::tests, impl SnapshotFixture`` nvx-rs/src/host/snapshot/tests.rs:1012 nvx-rs/src/host/snapshot/tests.rs:1020
modified helper fn new in host::snapshot::tests, impl RestoreFixture`` nvx-rs/src/host/snapshot/tests.rs:1473 nvx-rs/src/host/snapshot/tests.rs:1481
modified helper fn write_metadata in host::snapshot::tests, impl RestoreFixture`` nvx-rs/src/host/snapshot/tests.rs:1550 nvx-rs/src/host/snapshot/tests.rs:1558
modified helper struct Reaped in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:11 nvx-rs/tests/process.rs:174
modified helper impl Drop for Reaped in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:13 nvx-rs/tests/process.rs:176
modified helper fn drop in host::spawn::tests, impl Drop for Reaped`` (moved, and it now compiles where any ( target_os = "linux" , windows ) and `feature = "host"` hold, not where `feature = "host"` and `target_os = "linux"` and `test` did) nvx-rs/src/host/spawn/tests.rs:14 nvx-rs/tests/process.rs:177
modified helper fn object in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:22 nvx-rs/src/host/spawn/tests/linux.rs:24
modified helper fn holds in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:27 nvx-rs/src/host/spawn/tests/linux.rs:29
modified helper fn close_on_exec in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:34 nvx-rs/src/host/spawn/tests/linux.rs:36
modified helper fn child_inherits_writer in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:44 nvx-rs/src/host/spawn/tests/linux.rs:46
modified helper fn sleeper in host::spawn::tests (it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:57 nvx-rs/src/host/spawn/tests.rs:789
modified helper fn spawn_sleeper in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:64 nvx-rs/src/host/spawn/tests/linux.rs:66
modified helper fn umask_in in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:149 nvx-rs/src/host/spawn/tests/linux.rs:152
modified helper fn assert_spawns_clear_the_owners_bits in host::spawn::tests (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where feature = "host" and target_os = "linux" and test did) nvx-rs/src/host/spawn/tests.rs:162 nvx-rs/src/host/spawn/tests/linux.rs:165
modified helper const VMM_MARKER in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:36 nvx-rs/src/host/spawn/tests.rs:41
modified helper const GO_MARKER in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:38 nvx-rs/src/host/spawn/tests.rs:47
modified helper const STARTED_REPORT in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:40 nvx-rs/src/host/spawn/tests.rs:49
modified helper const DESCRIPTORS_REPORT in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" did) nvx-rs/tests/checked_handoff.rs:49 nvx-rs/src/host/spawn/tests.rs:53
modified helper const CAPABILITY in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:62 nvx-rs/src/host/spawn/tests.rs:67
modified helper const VMM_LIFETIME in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:66 nvx-rs/src/host/spawn/tests.rs:71
modified helper fn write_whole in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:128 nvx-rs/src/host/spawn/tests.rs:122
modified helper fn report_descriptors in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" and target_os = "linux" did) nvx-rs/tests/checked_handoff.rs:149 nvx-rs/src/host/spawn/tests.rs:131
modified helper struct VmmDirectory in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:311 nvx-rs/src/host/spawn/tests.rs:237
modified helper impl VmmDirectory in checked_handoff (tests) (moved, and it now compiles where any ( target_os = "linux" , windows ) and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" did) nvx-rs/tests/checked_handoff.rs:318 nvx-rs/src/host/spawn/tests.rs:246

... and 319 more, which the job's summary lists.

Test data

Change What Before After
modified file nvx-rs/tests/vectors/snapshot-key-v1.txt nvx-rs/tests/vectors/snapshot-key-v1.txt nvx-rs/tests/vectors/snapshot-key-v1.txt

End-to-end tests

Change What Before After
modified helper def run_workload_identity in scripts/nvx_tools/microvm_tests.py scripts/nvx_tools/microvm_tests.py:1311 scripts/nvx_tools/microvm_tests.py:1312
modified helper def run_managed_lifecycle in scripts/nvx_tools/microvm_tests.py scripts/nvx_tools/microvm_tests.py:1410 scripts/nvx_tools/microvm_tests.py:1446

Relocated unchanged: 33; added: 45. Compared the merge base 230a1b0877d5 with c5d2ee8d0b7c.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Copilot started reviewing on behalf of Pedro Henrique Penna (ppenna) November 12, 2026 09:31
View session
Copilot AI reviewed Nov 12, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues remain for the legacy launch API removal and transition to CLI-owned lifecycle and identity tokens.

No open issues 🎉

What changed in this PR

This PR implements SL6.3 of #1122, advancing #1076’s move toward a smaller NVX library centered on host::vm. It removes obsolete configuration and launch APIs while preserving the current VM launch path.

Changes:

  • Removes legacy launch, checked-file handoff, capture-class, and share-rendering code.
  • Gives external-launch its own minimal launcher and switches guest initialization to CLI-owned lifecycle and identity tokens.
  • Relocates or updates retained tests and documents the path-based image model and retired coverage.
File Description
scripts/​test_nvx_tools.py Tests new init routing and rejection of obsolete identity tokens.
scripts/​test_microvm_tests.py Checks scenarios supply CLI-owned boot tokens.
scripts/​nvx_tools/​microvm_tests.py Adds identity and lifecycle tokens to direct OpenVMM scenarios.
nvx-rs/​tests/​vectors/​snapshot-key-v1.txt Removes capture-class vectors; preserves key vectors.
nvx-rs/​tests/​vectors/​README.md Documents snapshot-key vectors without capture classes.
nvx-rs/​tests/​host_modules.rs Removes the deleted supervisor dependency assertion.
nvx-rs/​tests/​cli/​openvmm.rs Replaces deleted rendering helpers with explicit fixture tokens.
nvx-rs/​src/​protocol/​mod.rs Removes the account-token export and narrows workload gating.
nvx-rs/​src/​protocol/​boot.rs Deletes WORKLOAD_ACCOUNT_TOKEN.
nvx-rs/​src/​protocol/​app.rs Makes workload identity crate-private and narrows feature gating.
nvx-rs/​src/​host/​sys/​process.rs Deletes descriptor relocation used by checked-file handoff.
nvx-rs/​src/​host/​sys/​mod.rs Removes unused identity helpers and descriptor-helper exports.
nvx-rs/​src/​host/​supervisor/​mod.rs Deletes the transitional supervisor module.
nvx-rs/​src/​host/​spawn/​tests/​linux.rs Houses retained Linux inheritance and umask tests.
nvx-rs/​src/​host/​spawn.rs Removes legacy spawn wrappers and narrows remaining types’ visibility.
nvx-rs/​src/​host/​snapshot/​tests.rs Builds snapshot fixtures from capture contexts.
nvx-rs/​src/​host/​snapshot/​key.rs Removes capture classes and the legacy key constructor.
nvx-rs/​src/​host/​snapshot/​capture/​tests.rs Uses the shared capture-context fixture.
nvx-rs/​src/​host/​snapshot/​canonical.rs Updates module comments to describe key encoding only.
nvx-rs/​src/​host/​snapshot.rs Removes capture-class exports and updates documentation.
nvx-rs/​src/​host/​session/​tests/​managed_lifecycle.rs Updates a comment to reference vm::spawn.
nvx-rs/​src/​host/​seal/​windows/​tests.rs Retires tests for deleted final-path handling.
nvx-rs/​src/​host/​seal/​windows.rs Deletes Windows final-path resolution helpers.
nvx-rs/​src/​host/​seal.rs Removes the final-path wrapper.
nvx-rs/​src/​host/​sandbox/​scratch/​tests.rs Checks the Windows claim through its retained field.
nvx-rs/​src/​host/​sandbox/​scratch.rs Removes handoff-only accessors and updates claim documentation.
nvx-rs/​src/​host/​sandbox/​options.rs Deletes preflight tied to SandboxLaunch.
nvx-rs/​src/​host/​sandbox/​mount/​tests.rs Retains planning checks while retiring renderer assertions.
nvx-rs/​src/​host/​sandbox/​mount/​request.rs Deletes the bootstrap-token rendering helper.
nvx-rs/​src/​host/​sandbox/​mount/​mod.rs Removes renderer exports and obsolete token constants.
nvx-rs/​src/​host/​sandbox/​mount/​host_paths.rs Allows the CLI-only recheck to be unused without cli.
nvx-rs/​src/​host/​sandbox/​mount/​boot.rs Removes boot rendering while retaining path-text conversion.
nvx-rs/​src/​host/​sandbox/​mount/​aggregate.rs Removes legacy aggregate naming and argument rendering.
nvx-rs/​src/​host/​sandbox/​layer.rs Updates documentation after BlockRole removal.
nvx-rs/​src/​host/​sandbox/​distro/​tests.rs Removes the deleted binding-accessor assertion.
nvx-rs/​src/​host/​sandbox/​distro.rs Deletes handoff-only fields and accessors.
nvx-rs/​src/​host/​restore/​tests/​live_init.rs Uses private strict spawning and confirmed cleanup.
nvx-rs/​src/​host/​restore/​tests.rs Replaces the deleted spawn helper with test-owned locking.
nvx-rs/​src/​host/​restore_driver/​tests.rs Specifies workload identity directly in fixtures.
nvx-rs/​src/​host/​process.rs Removes inherited-handle closure and updates spawn documentation.
nvx-rs/​src/​host/​platform/​windows/​tests.rs Adapts retained spawn tests and retires handle-closure coverage.
nvx-rs/​src/​host/​platform/​windows/​spawn.rs Deletes legacy timed termination and annotates CLI-only waiting.
nvx-rs/​src/​host/​platform/​windows/​process.rs Deletes cross-process inherited-handle closure.
nvx-rs/​src/​host/​platform/​inherit.rs Removes generic spawning and descriptor-path APIs; keeps private locking.
nvx-rs/​src/​host/​mod.rs Removes launch and supervisor modules and updates module documentation.
nvx-rs/​src/​host/​config/​tests.rs Checks rendered configuration directly instead of comparing legacy launches.
nvx-rs/​src/​host/​config/​mod.rs Updates legacy comments and annotates a CLI-only check.
nvx-rs/​src/​host/​cli/​store/​tests/​recovery.rs Adapts recovery fixtures to private spawning.
nvx-rs/​src/​host/​cli/​store/​tests/​liveness.rs Adapts liveness fixtures to private spawning.
nvx-rs/​src/​host/​cli/​snapshots/​capture/​tests.rs Uses capture contexts and private spawn fixtures.
nvx-rs/​src/​host/​cli/​sandbox/​state.rs Removes legacy-plan comparisons from documentation.
nvx-rs/​examples/​external-launch.rs Adds a minimal caller-owned launcher and process identity capture.
guest/​common/​init Stops reading obsolete tokens and routes layered roots to nvx-init.
doc/​project-structure.md Documents current init routing and inactive legacy scripts.
doc/​design/​5.1-boot-protocol.md Documents CLI-owned identity and lifecycle tokens.
doc/​design/​4.2-guest-agents-and-workload-model.md Describes nvx-init as the layered-root init.
doc/​acceptance-case-matrix.md Records retired handoff coverage and updated test locations.

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the agents/slim-sl6-0f-cli-command-line branch from de3c4bc to 93469a4 Compare November 12, 2026 09:36
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the agents/slim-sl6-3-old-configs branch from c04cd8a to 604d8da Compare November 12, 2026 09:37
@ppenna Pedro Henrique Penna (ppenna) mentioned this pull request Nov 12, 2026
cli: check the command line that a sandbox launches (SL6.0f) #1526
Merged
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the agents/slim-sl6-0f-cli-command-line branch from 93469a4 to b06d52f Compare November 12, 2026 10:15
Base automatically changed from agents/slim-sl6-0f-cli-command-line to feature/nvx-refactor November 12, 2026 10:32
Pedro Henrique Penna (ppenna) and others added 8 commits November 12, 2026 02:36
@ppenna
examples: launch the external-launch VM with a launcher of its own
7c967b7
The external-launch example handed the command that vm::create prepares
to host::supervisor::spawn_vm, the strict low-level spawn that SL6.1
left public only as a transitional path. SL6.3 deletes that path, and
as SL2.8b designed it, the caller of vm::create supplies its own spawn:
the library keeps no public low-level spawn besides vm::spawn.

The example now starts the VMM with a minimal launcher of its own, on
std::process: it writes the capability into a pipe that it closes to
writers before the spawn, gives the VMM that pipe as its standard input
and the log as its standard output and error, holds the process through
a ProcessRef and Process::open, and kills and reaps it if anything fails
once it runs. It reads the ProcessRef's start time itself, as ProcessRef
defines it: the starttime field of /proc/<pid>/stat on Linux, and the
process's creation time on Windows. So it uses nothing of
host::platform, which SL6.14 makes crate-private, and takes Transport
from host::transport, which re-exports it. Its docs list what it leaves
out of the launch contract of vm::VmmCommand, which a production
launcher adds, as vm::spawn does: it passes no descriptor or handle
besides the standard streams, and refuses a command that allows any; on
Linux it starts the VMM in a process group of its own, but not in a new
session, and leaves the caller's umask; on Windows it starts the VMM
without a console, but with every inheritable handle of the caller and
in no log-named job.

The README's description of the example, and its row in the case
matrix, which stays kept, say so.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
host: delete the prepared launch and its checked-file handoff
313b00b
A PreparedLaunch handed OpenVMM the files that the checks of a plan's
images opened: /proc/self/fd/N on Linux, which the VMM inherited through
the supervisor's allowlist, and on Windows the checked files' final
paths, which their handles held, and which PreparedLaunch::release
closed in the VMM through ProcessHandle::close_inherited. No launch
uses it any more: the CLI's start and run name their images by path in
the VM's configuration, and pass the VMM only the scratch image's claim,
through Prepared::inherit.

So the prepared launch goes: host::sandbox::prepared and PreparedLaunch,
with PreparedLaunch::adapter_arguments, and the checked-file handoff
that only it used: Inherited::proc_path and the crate-private
Process::close_inherited and ProcessHandle::close_inherited of Windows.
The crate-private code that only they used goes too:
move_above_standard_streams on Linux, seal::final_path on Windows, and
the file_mut of CheckedDistro and CheckedScratch, and CheckedDistro's
bound(), whose identity field then went unread. CheckedScratch::claim,
which only the CLI reads now, as it hands the claim to the VMM, is gated
by cli, and the claim's field, which holds the claim whoever reads it,
is allowed to go unread without cli.

The docs say what stays: a launch names its images by path, so what
takes an image's path after its check is what OpenVMM opens, and callers
stage their images in a directory that only their own account can
write, as the docs of distro, scratch and seal require, so that no other
account can replace a checked image. The README's "Checked handoff"
section becomes "Images by path", and the claims of the scratch image
no longer say that the VMM opens /proc/self/fd/N or that a release
closes its copies.

Tests: the handoff's cases retire with it: the 4 cases of
tests/checked_handoff.rs that hand a prepared launch's images to a VMM
fixture, with their launcher fixture and helpers; the 10 unit tests of
host::sandbox::prepared; the Windows platform's
a_child_loses_only_the_inherited_handle_that_is_closed_in_it, the test
of close_inherited; and seal's final_paths_hold_no_nul_whatever_their
_length, the test of final_path. checked_handoff.rs keeps its 2 cases
of the spawn that stays, a wait's exit status and the strict cleanup,
which SL6.3 moves to their owner with the supervisor. The test of the
spawn's allowed descriptors no longer checks proc_path, and the test of
a GPT binding's check no longer checks bound(). The case matrix retires
the doc test of PreparedLaunch and the adapter's scenario
images_replaced_after_the_checks_never_reach_the_vm, and stops naming
the deleted handoff test as coverage of
a_layered_launch_hands_openvmm_the_checked_images.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
host: delete the transitional supervisor path of the spawn
d445918
`host::supervisor` re-exported the low-level spawn of a VMM, `spawn`,
`spawn_vm`, `VmmCommand`, `Launched` and `Inherited`, and
`spawn_command`, for the code that still used them after SL6.1: the
`external-launch` example, which now launches its VMM with a launcher
of its own, and the tests of the spawn in `tests/supervisor.rs` and
`tests/checked_handoff.rs`. `host::vm` spawns VMMs.

The module goes, with what only it made public or used:

- `spawn`, the spawn without the strict log job, `spawn_vm`, its strict
  twin, and `VmmCommand::new`. `vm::spawn` keeps the strict spawn,
  `spawn_vm_with_mode`, which takes their documentation, and builds its
  command whole.
- `Launched::kill_and_wait`, the legacy time-bounded cleanup, with the
  Windows `LaunchedProcess::terminate` that only it called.
  `kill_and_confirm_exit` stays.
- `spawn_command`, which spawned a `std::process::Command` under the
  crate's spawn lock. The tests spawn theirs with `spawn_locked`.

`VmmCommand`, `Launched` and `Inherited` become crate-private. What
only the CLI's one-shot runs use outside the tests,
`Launched::wait_timeout` with its reaping and status helpers, the
Windows `LaunchedProcess::wait_timeout`, and `KILL_TIMEOUT`, carries an
`allow(dead_code)` for builds without the `cli` feature, as do the
spawn lock outside Windows, which only the tests take there, and
`VmmCommand::breakaway_from_job`, which only Windows reads.

Tests move to the owners of the code that they test:

- `tests/supervisor.rs` becomes `tests/process.rs`, with its seven tests
  of `nvx::host::process`, whose processes a fixture of its own starts
  through `std::process` now: `processes_can_be_shared_between_threads`,
  `a_child_that_exits_wakes_its_waiter`,
  `a_process_that_is_not_a_child_wakes_its_waiters`,
  `a_reused_process_id_is_never_signaled`,
  `references_that_name_no_process_are_never_opened`, and on Windows
  `a_process_that_this_user_may_not_query_has_an_unknown_state` and
  `a_process_that_this_user_may_not_terminate_is_waited_for_but_never_signaled`.
- Its four tests of the spawn,
  `working_directory_limits_include_trailing_separators` (Windows),
  `a_restarted_launcher_finds_its_vmm_again_and_ends_it`,
  `vmms_inherit_only_their_streams_and_allowed_descriptors_while_others_spawn`
  and `a_job_that_ends_its_vmm_wakes_the_waiters` (Windows), and the two
  of `tests/checked_handoff.rs`,
  `launched_waits_return_and_retain_the_actual_exit_status` and
  `strict_cleanup_terminates_and_confirms_a_running_child`, move to the
  spawn's unit tests, `src/host/spawn/tests.rs`, which now build on
  Linux and Windows, with one VMM fixture for the two files' fixtures,
  and the launcher fixture. The spawn's Linux tests move to
  `src/host/spawn/tests/linux.rs`, unchanged but for the strict spawn.
- In the unit tests, which run beside hundreds of others, the check that
  a process that `std::process` spawns while VMMs spawn holds none of
  their descriptors looks again until the objects are gone or a second
  passes. The kernel wakes `posix_spawn`'s parent before the child's exec
  closes its close-on-exec descriptors, so for an instant the child's
  table still lists every descriptor of the parent, which the busier
  process made the check see as a leak.
- The tests that spawned through the old paths spawn through
  `spawn_vm_with_mode`, and end their children with
  `kill_and_confirm_exit` or `terminate_and_wait`. The Windows test of a
  log that is no file of a disk volume keeps its refusal by the strict
  spawn and loses the start without a job that only `spawn` made, as
  `a_vmm_whose_log_is_no_file_of_a_disk_volume_is_refused`.
  `the_graph_holds_well_known_dependencies_of_the_sources` loses the
  edge from `supervisor` to `spawn`.

Docs: the README loses the module's row and section; the
`nvx::host::vm` section takes its notes on the umask and the
working-directory limit, and names the spawn's tests. The case matrix's
row of the module's doc test says where its tests went. The public-API
snapshots lose the module.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
host: delete the capture class
2853ff4
`CaptureClass`, the invariant inputs of a template's capture that an
adapter requested, with its canonical encoding and `ClassIdentity`, and
`SnapshotKey::new`, which derived a key from a class and its capture's
manifest, served only the old capture path and the tests. A capture's
key comes from its `CaptureContext`, which `vm::create` prepares and
`finish_capture` reads, through `SnapshotKey::from_capture`.

The class goes, with its identity and its domain, and the import of
`PROCESSOR_COUNTS` that only its check used. The docs of the key, of its
canonical encoding, and of the snapshot module no longer name a class.

Tests:

- The snapshot fixtures `class()` and `network_class()` become
  `context()` and `network_context()`, the contexts of the same
  captures, and build their keys with `from_capture`; the fixtures of
  the capture and restore tests take them.
- The key's tests derive their keys from contexts, through
  `from_capture`, and change the contexts where they changed the class:
  `each_part_of_the_key_changes_it`,
  `a_generations_own_metadata_leaves_the_key_as_it_is`,
  `complete_capture_time_round_trips_without_changing_compatibility_identity`,
  `a_key_holds_what_its_capture_made`,
  `a_capture_that_does_not_match_its_class_is_refused`, which loses the
  case of a network whose policy attaches no NIC, since a context holds
  the NIC itself, `a_class_selects_a_profile_as_openvmm_does`,
  `keys_read_back_from_their_canonical_encoding`,
  `keys_with_the_removed_guest_build_field_are_refused`,
  `a_key_that_holds_its_network_s_lowering_after_its_invariants_is_refused`,
  `keys_of_machines_that_no_manifest_describes_are_refused`, and
  `the_conformance_vectors_decode_and_encode`, which loses the class
  vectors.
- `invalid_classes_are_refused` becomes
  `captures_of_invalid_contexts_are_refused`: the same invalid inputs,
  which `from_capture` refuses with the messages of the context's
  checks.
- Retired with the class: `the_guest_build_is_not_part_of_a_snapshot_key`
  and `each_field_of_a_class_changes_its_identity`, and the class's part
  of `identities_have_a_text_form`.
- `tests/vectors/snapshot-key-v1.txt` loses its `CLASS` vectors; its
  `KEY` vectors do not change.

Docs: the README's snapshot section and the vectors' README describe the
key alone. The public-API snapshots lose the class.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
host: delete the old sandbox plan and launch
11ac217
`SandboxPlan`, the typed plan of a cold layered launch, with its
`SandboxDistro`, `SandboxUpper`, `SandboxNetwork`, `BlockRole` and
persistable form, and `SandboxLaunch` and `SandboxSettings`, the launch
of `nvx-rs sandbox` that made such a plan, served only the old launch
path and the tests: the CLI checks and launches a sandbox through its
`VmConfig`, and checks the command line that it launches since SL6.0f.

They go, with `PLAN_VERSION`, the profile's `KERNEL_COMMAND_LINE_MAX_SIZE`,
`OPENVMM_COMMAND_LINE_RESERVE` and `SANDBOX_COMMAND_LINE_MAX_SIZE`, the
workload limits (`PIDS_MAX_LIMIT` and the settings' checks), and
`options::validate_sandbox_systemd_policy`, the preflight of a
`SandboxLaunch`, whose two checks, `validate_sandbox_entrypoint` and
`DistroBinding::verify`, the CLI calls itself. The boot rendering of
shares goes too: `BootShares`, `boot_shares`, `aggregate_share_tokens`,
`aggregate_command_line_fragment`, `export_command_line_fragment`,
`aggregate_child_name`, `aggregate_child_argument`, `mount_argument`,
and the private `command_line_fragment` and bootstrap-token constants
of `mount`. `plan_mounts`, `plan_mounts_with` and `path_text` stay for

What only the CLI uses now allows `dead_code` without the `cli`
feature, as `spawn` does: `mount::check_distinct_export_roots` and its
re-export beside `HostQueries`, and `config::reject_container_path`.

Tests:

- `host::sandbox`'s own tests retire the plan's and the launch's cases:
  `launch_contract_builds_agent_command_line`,
  `launch_contract_rejects_duplicates_and_reserved_tokens`,
  `launch_settings_are_checked_in_order`,
  `launch_rejects_limits_the_guest_cgroup_cannot_store`,
  `launch_contract_attaches_mount_and_reserves_bootstrap_tokens`,
  `launch_contract_attaches_several_shares_as_an_aggregate`,
  `launch_bounds_shares_by_the_kernel_command_line` and
  `launch_contract_rejects_disk_option_delimiters_and_unbalanced_brackets`,
  whose refusal `config`'s tests and `tests/cli/validation.rs` keep.
  `launch_contract_attaches_a_file_as_an_aggregate_child` becomes
  `file_shares_take_no_policy_paths_or_reserved_targets`, its checks of
  shares without the rendering, and
  `launch_validation_requires_the_layers_and_the_scratch_image` becomes
  `missing_files_are_named_with_their_components_alone`, its check of
  `require_file`. The share checks plan their shares with `plan_mounts`
  and check the plan again as a start does, with
  `check_distinct_export_roots` and `ExportPlan::verify`:
  `launch_validation_rejects_overlapping_or_foreign_host_paths`,
  `shares_that_only_a_verbatim_path_names_are_refused`,
  `launch_validation_rejects_shares_that_came_to_overlap` and
  `launch_validation_requires_plain_mount_directory`. The fixtures
  `exported`, `deny`, `with_export` and `distro` go; `host_text` is
  Windows-only.
- The specification tests retire `aggregate_child_name_known_answer`,
  `launch_arguments_follow_the_openvmm_contract`,
  `accepted_launch_shapes_keep_their_arguments_and_kernel_tokens`,
  `shares_follow_the_openvmm_and_guest_contracts`,
  `launch_settings_follow_the_guest_contract`,
  `caller_parameters_follow_linux_and_guest_rules`,
  `aggregate_child_names_follow_the_restore_contract`,
  `kernel_command_line_stays_within_1024_bytes` and
  `reserved_kernel_tokens_are_always_refused`, which the CLI's tests of
  the command line that it launches cover. `layer_values_are_role_path_uuid`,
  `kernel_token_values_refuse_separators`,
  `the_reproduction_of_microsoft_nvx_723_is_refused` and
  `accepted_values_stay_one_kernel_parameter` keep their checks of
  layers and targets, and `canonical_layer_uuids_reach_the_guest`
  becomes `canonical_layer_uuids_round_trip`.
- The share tests retire `aggregate_child_names_pin_their_targets` and
  `boot_tokens_refuse_what_the_shell_cannot_bind`, and drop the boot
  rendering from `mount_parser_defaults_to_read_only_and_accepts_rw`,
  `mount_parser_accepts_host_paths_with_commas`,
  `mount_owner_defaults_to_vmm_and_forwards_caller`,
  `mount_access_policy_is_validated_and_forwarded` and
  `shares_are_planned_through_the_export_planner`.
- The option tests' preflight calls `validate_sandbox_entrypoint` and
  `DistroBinding::verify`, as the CLI does, in
  `distro_manifest_binds_the_layer`,
  `systemd_entrypoints_and_images_are_refused_independently`,
  `sandbox_allows_non_systemd_sbin_init`,
  `the_entrypoint_check_needs_no_manifest_and_precedes_the_distro_verification`,
  `sandbox_rejects_systemd_from_bound_distro_metadata` and
  `distro_manifests_are_strict_json`. Their shares give the export
  plan's OpenVMM arguments and kernel token, which
  `sandbox_command_shares_a_file` and
  `sandbox_command_attributes_mount_deny_to_the_preceding_mount` check.
- `cold_command_lines_keep_the_old_root_view_and_mapping_values`
  compared a configuration's command line with those of `LaunchSpec`
  and `SandboxPlan`. As
  `cold_command_lines_carry_the_root_the_view_and_the_mapping_count`,
  it checks the line against the configuration: the root's image and
  upper beside its other tokens, the view, and the mapping count.
- `tests/cli/openvmm.rs`'s `two_share_command_line_room` spells the
  tokens that OpenVMM appends for the shares.

Docs: the README's sandbox section and module row, "Images by path",
"Sandbox input contract", which describes the CLI's check of the command
line, and "Specification tests"; the case matrix row that named the
config test; the docs of `layer`, `mount`, the CLI's sandbox state and
the snapshot key. The public-API snapshots lose the deleted items.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
host: delete the old launch
83b4141
`host::launch`, the OpenVMM command line of a managed microVM that a
`LaunchSpec` described, with `VmmLaunch`, the inputs that it shared
with an adapter's launch, served only the old launch path and the
tests: `VmConfig` and `vm::create` render and check every launch, and
the CLI renders the guest's tokens.

The module goes whole: `LaunchSpec` with `check`, `kernel_command_line`,
`openvmm_arguments`, `vmm_launch` and `check_process_command_line`;
`VmmLaunch` with `RESERVE` and `arguments`; `WorkloadIdentity`'s
`DEFAULT` and `select`; `MAX_TIMEOUT`, `DEFAULT_MEMORY_MIB`,
`DEFAULT_HOSTNAME`, `base_command_line`, `kernel_parameters_problem`
and `timeout_problem`; and its re-exports of `host::config`'s
`COMMAND_LINE_BUDGET`, `DEFAULT_GUEST_NETWORK` and Windows command-line
helpers, which stay in `host::config`, as `OPENVMM_COMMAND_LINE_RESERVE`
does for `VmConfig::check_command_line`. `protocol::WORKLOAD_ACCOUNT_TOKEN`,
which only `LaunchSpec` rendered, goes too; the fake OpenVMM spells the
token itself.

What the deletion leaves unused goes with it: `host::sys::effective_ids`,
which only `WorkloadIdentity::select` called. `protocol`'s
`WorkloadIdentity`, which activation payloads carry, was public only
through `host::launch`, so it becomes `pub(crate)`, and `protocol`
re-exports its module only for the CLI and the guest, its remaining
users.

Tests: `host::launch`'s tests retire with it:
`kernel_command_line_sets_the_hostname`,
`arguments_select_the_managed_direct_guest`,
`mappings_add_the_export_and_the_mapping_count`,
`oversized_process_command_lines_are_rejected`,
`launches_may_use_the_reserve_that_provisioning_keeps`,
`every_launch_names_its_own_inputs_alike`,
`the_reserve_of_a_plan_holds_the_rest_of_a_launch_of_inputs_of_max_path`,
`kernel_parameters_are_checked`,
`kernel_parameters_are_read_as_the_kernel_reads_them`,
`reserved_parameters_are_refused_whatever_separates_them`,
`the_kernel_reads_the_hostname_after_accepted_parameters`,
`every_command_line_checks_the_specification`, `timeouts_are_bounded`
and `workloads_that_map_host_paths_take_the_host_identity`. `config`'s
tests keep checking the Windows command-line helpers. The restore
driver's test workload spells the identity that `DEFAULT` named.

Docs: the README loses `host::launch`'s section and module row, and
`host::config`'s part says what the helpers count; the docs of the
reserve and of `boot_arguments` no longer name the old planning. The
public-API snapshots lose the module and the token.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
guest: stop reading OpenVMM's lifecycle tokens in the shell init
3e30b91
The shell `/init` read the tokens that OpenVMM appends for its
`--microvm-lifecycle` and `--microvm-workload-identity` options,
`nvx_lifecycle=`, `nvx_workload_uid=` and `nvx_workload_gid=`, beside
the CLI's own, `nvx_mode=` and `nvx_identity=`, and handed a layered
root whose command line held `nvx_lifecycle=` to the older init agent,
`nvx-init-agent`. Since the old launch paths are gone, no launch of NVX
gives those tokens: the CLI names the lifecycle and the identity with
its own.

The init no longer reads the three tokens, and starts `nvx-init` for
every layered root, whose `nvx_exec=` it no longer runs either, as it
did not for a layered root without the token. A blockless guest takes
its lifecycle from `nvx_mode=` and its workload identity from
`nvx_identity=` alone.

The `workload-identity` and `managed-lifecycle` scenarios start OpenVMM
directly, with its options, which OpenVMM itself checks: they now also
give the CLI's tokens, `nvx_identity=` for each identity, and
`nvx_mode=managed nvx_identity=65534:65534`, so that the guest's init
selects what OpenVMM's options did.

Tests:

- `test_old_lifecycle_tokens_keep_the_old_layered_init` becomes
  `test_old_lifecycle_tokens_no_longer_select_the_old_layered_init`:
  the same layered roots start `nvx-init`.
- `test_old_workload_identity_tokens_name_no_identity` checks that a
  one-shot workload named only by `nvx_workload_uid=` and
  `nvx_workload_gid=` has no identity.
- `test_exec_override_cannot_bypass_the_new_sandbox_init` and
  `test_missing_helpers_or_selected_init_fail_without_fallback` expect
  `nvx-init` for a layered root with `nvx_lifecycle=managed`, and its
  failure when it is missing.
- The scenarios' unit tests,
  `test_workload_identity_scenario_checks_enforcement_and_rejection`
  and `test_managed_lifecycle_runs_the_nvx_rs_test_and_checks_what_it_leaves`,
  check the CLI's tokens on the command line.

Docs: the boot protocol says that `/init` ignores OpenVMM's identity and
lifecycle tokens, the guest-agent design that a layered root runs
`nvx-init`, and the project structure what `init` starts and that it no
longer starts the older sandbox scripts.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
guest: fail closed on OpenVMM's workload identity without nvx_identity
c5d2ee8
Since the shell /init stopped reading OpenVMM's lifecycle and workload
tokens, OpenVMM's --microvm-workload-identity no longer names the
identity of a guest's workload, and a guest ignored it. OpenVMM's
documentation of that option asks the guest to fail closed when it
cannot apply the identity.

So /init fails closed. When the command line has OpenVMM's
nvx_workload_uid= or nvx_workload_gid=, a boot goes on only if
nvx_identity= names the same UID and GID. Otherwise /init stops with
NVX-WORKLOAD-ERROR and status 125 before it starts anything: an
nvx_exec= program, a one-shot or managed workload, the shares, or
nvx-init. It recognizes the two tokens only to refuse a mismatch: it
still takes the identity from nvx_identity= alone, and still ignores
nvx_lifecycle=. NVX's own launches don't change: the CLI and the
library pass no OpenVMM identity, and the scenarios that pass one also
pass the same nvx_identity=. A caller that launches OpenVMM directly
with --microvm-workload-identity adds nvx_identity= with the same
identity to its command line.

Docs: the boot protocol (5.1) says that /init fails closed on OpenVMM's
identity tokens, and the machine model (2.1.2) that NVX's launchers
name the workload identity and lifecycle with tokens of their own,
which the machine profile's tokens no longer select. The case matrix's
row of workload-identity names its new checks.

Tests: GuestInitRoutingTests' test_old_workload_identity_tokens_name_no_identity
becomes test_openvmm_workload_identity_needs_the_same_nvx_identity,
which refuses OpenVMM's identity without nvx_identity=, with its UID
alone, and with another nvx_identity=, on the nvx_exec, one-shot,
managed and sandbox routes, before anything starts, and lets the same
identity boot on. The workload-identity scenario boots twice more, with
OpenVMM's identity and no nvx_identity=, and with an nvx_identity= of
another identity, and requires both to fail closed with the refusal;
its unit tests check those boots, and that a guest that runs either
fails the scenario.

Part of #1122 (SL6.3).

Co-authored-by: Copilot <[email protected]>
@ppenna
Pedro Henrique Penna (ppenna) force-pushed the agents/slim-sl6-3-old-configs branch from 604d8da to c5d2ee8 Compare November 12, 2026 10:43
@ppenna
Pedro Henrique Penna (ppenna) marked this pull request as ready for review November 12, 2026 10:44
@ppenna
Pedro Henrique Penna (ppenna) requested a balanced review from Copilot November 12, 2026 10:44
Copilot started reviewing on behalf of Pedro Henrique Penna (ppenna) November 12, 2026 10:45
View session
Copilot AI reviewed Nov 12, 2026
View reviewed changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues are reported for the legacy API cleanup and migration to host::vm.

No open issues 🎉

Review effort: Balanced

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

Copilot code review Copilot
Copilot review effort
Applies to this pull request for everyone.Learn more about Copilot code review.
Copilot left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@ppenna Pedro Henrique Penna (ppenna)

Labels

feat-nvx-refactor tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@ppenna
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.