Skip to content

protocol: make NVXC private to nvx (SL6.12) - #1525

Merged
Pedro Henrique Penna (ppenna) merged 4 commits into
feature/nvx-refactorfrom
agents/slim-sl6-12-nvxc-private
Nov 12, 2026
Merged

Pedro Henrique Penna (ppenna) merged 4 commits into
feature/nvx-refactorfrom
agents/slim-sl6-12-nvxc-private

Conversation

@ppenna

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

Copy link
Copy Markdown
Contributor

Part of #1127 (SL6.12, "NVXC is private"). Parent #1088, umbrella #1076.

It needs no other PR: no item that stays public exposes an NVXC type (nvx::exec and guest::{exec, spawn, process, cgroup, entry} use none), so neither #1506 (SL6.11a) nor SL6.11b has to come first.

What and why

NVXC is NVX's own control protocol, and only NVX's programs speak it: the CLI with its restore driver, nvx-init and the managed agent, and the fake OpenVMM. Yet nvx::protocol re-exported its frames, refusal categories, EXEC payloads, limits and GuestFeatures, and nvx::host::session its host session, as public API of nvx. As SL6.12's Scope says, this PR makes them crate-private where they are, gated by the features of their users, before v2 changes NVXC. No frame, payload, wire value or session behavior changes, nothing moves to another module or file, and v1 and FEATURES stay.

  • host::session is private to the CLI (host: make the control session private to the CLI). It becomes #[cfg(feature = "cli")] pub(crate) mod session, and its items pub(crate): ControlSession with send_request and read_response, ExecEvent, SessionError and connect. It is crate-visible rather than private to host because the managed agent's loopback test drives it. APP_CAPTURE and encode_capture_payload, which only the session's capture sends, follow it from host to cli.

  • NVXC is crate-private (protocol: make NVXC private to the programs that speak it). Every item of protocol::{app, exec, features} becomes pub(crate), and each item and re-export is gated by the features of the code that uses it, so that no feature set builds an item that it doesn't use. Below, guest is all(feature = "guest", target_os = "linux", target_arch = "x86_64"), where the managed agent builds.

    • cli: the host's encoders, Workload, WorkloadEnvironment and encode_exec_payload, encode_capture_payload and encode_activate_payload.
    • guest: the guest's decoders, AppFrame, GuestExecPayload with decode_guest_exec_payload, decode_capture_payload and decode_activate_payload.
    • testing: the fake OpenVMM's decoder, ExecPayload with decode_exec_payload.
    • cli or testing: ExitCategory. testing or guest: the refusal categories BUSY, CWD_FAILED, INVALID_REQUEST, LAUNCH_FAILED and MAPPINGS_INCOMPLETE. cli or guest: APP_CAPTURE, APP_ACTIVATE and the re-export of APP_HEADER_LEN.
    • any of the three: the frames' codec, encode_app and decode_app, the other APP_* kinds, MAPPING_FAILED, UNSUPPORTED_OPERATION, MAX_OUTPUT_BYTES, GuestFeatures, and the exec and features modules.

    protocol no longer re-exports what only the codec itself reads: APP_MAGIC, APP_VERSION, the EXEC_* flags and the other limits. protocol::exec is crate-visible, for the CLI session's tests that read the EXEC flags. The capture and activate messages, whose expect(dead_code) hooks covered the builds without their users, take the same gates, so protocol/app.rs holds no test hook any more.

  • What no feature set uses moves into protocol's tests, as the orchestrator decided for Pedro Henrique Penna (@ppenna): GuestFeatures::{REQUIRED, contains}, MAX_CWD_BYTES and MAX_TIMEOUT_MS, with their values unchanged, since only those tests read them.

  • The public callers that used NVXC speak for themselves.

    • examples: connect to VMs through the public transport: host-workflows' capture and restore connect with transport::connect_verified, attach with HostConnection::attach, and hand that connection to their callbacks, on which a caller speaks its own protocol with its guest. failed() classifies an nvx::Error as it classified the session's errors. external-launch connects to its boot console the same way.
    • tests: encode the VM lifecycle's PING and STOP frames in the test: tests/vm_lifecycle.rs stays a public-API integration test, as the orchestrator decided. It encodes the empty PING and STOP frames that it sends and the READY and STOPPED acknowledgements that it expects, as tests/vectors/nvxc-v1.txt pins them, and compares each answer with the whole frame. Its comment says why: nvx carries whatever protocol a caller speaks with its guest over the HostConnection, and leaves the protocol to the caller.
  • tests/managed_lifecycle.rs becomes a unit test of its owner, host::session::tests::managed_lifecycle in nvx-rs/src/host/session/tests/managed_lifecycle.rs, moved with git mv. Only its imports (crate:: paths), its cfg (now its module declaration's) and three refusal categories, which it now spells because the cli feature alone doesn't build the guest's constants, change. The managed-lifecycle scenario runs it with cargo test --features cli --lib -- --ignored --nocapture --exact host::session::tests::managed_lifecycle::a_managed_guest_runs_request_scoped_workloads_until_it_stops.

  • The public-API snapshots drop 129 items on each platform, and add none: 93 of NVXC and 36 of host::session. NVXS, the outer records, protocol::maps with its limits, MAPS_TOKEN and MappingTable stay listed.

  • Docs. protocol's module docs, the crate's and host's rustdoc and nvx-rs/README.md (the nvx::protocol row and section; the nvx::host::platform, report row and section, which lose the session; the transport, loopback-test and managed-lifecycle-test text) stop presenting NVXC and the session as public API. doc/usage.md, doc/ci.md, doc/contribute.md, doc/adversarial-testing.md and doc/project-structure.md name the managed lifecycle test where it now lives. fake_openvmm's and maps' docs no longer link NVXC items.

  • The case matrix stays true. The managed-lifecycle scenario's row, kept, says where its test now lives and how the scenario runs it. The two rows that name nvx-rs/src/lib.rs - (line 61) as coverage name (line 62), where the crate docs' doc test now starts. No inventoried test is added or removed, so no count changes, and SL5.2's check_matrix.py passes.

Seams

Five methods of ControlSession keep #[cfg_attr(not(test), expect(dead_code, reason = "..."))], as #1076's rules allow, since the CLI's own session sends PING, FEATURES, EXEC and STOP through send_request and read_response:

Method Reason Later caller
ping SL4.4c's host paths ping the guest through the session SL4.4c (#1128)
start_exec SL4.4c's sandbox exec and run start workloads through it SL4.4c (#1128)
cancel_exec SL4.4c's sandbox exec and run cancel through it on Ctrl-C SL4.4c (#1128)
stop SL4.4c's sandbox exec and run stop the guest through it SL4.4c (#1128)
features no host path sends FEATURES here, and SL4.4d deletes it none; SL4.4d (#1129) deletes it

scripts/test-layout-allowlist.json: nvx-rs/src/host/session.rs goes from 1 seam (capture's hook, which goes) to these 5, and the entry of nvx-rs/src/protocol/app.rs (6) goes, since gates replace its hooks.

Size

Measured: 0 core lines and 0 counted files, as the Estimate says. Every edit of production Rust (protocol/{app,exec,features,mod,maps}.rs, host/{session,mod}.rs, guest/managed_agent/dispatch.rs, testing/fake_openvmm.rs, lib.rs) makes items crate-private, gates them by the features of their users, adds the imports and expect(dead_code) hooks that this forces, or edits docs; a script that lists the added lines of these files outside comments and attributes finds only pub(crate) items, use lines, re-export lists and rustfmt's rewrapping of two declarations. Moving the four items that only tests read into protocol/tests.rs is the test gate's equivalent. The examples count as docs (as in #1488 and #1508), scripts/nvx_tools/microvm_tests.py and sandbox_lifecycle_tests.py drive the microVM scenarios, which check_test_changes.py classifies as end-to-end tests, and scripts/test-layout-allowlist.json is test policy.

Judgment calls, approved by the orchestrator for Pedro Henrique Penna (@ppenna)

  • Test gates (option A): each test is gated by the features of the code that it tests, with its body unchanged, rather than cfg(any(test, ...)) hooks on about 75 production items. Every test still runs in Linux's all-features cargo test. The guest decoders' tests leave the Windows build, and the dispatch tests leave the musl guest job, since that code is guest-only or cli-only.
  • tests/vm_lifecycle.rs stays a public-API integration test that encodes its own PING and STOP frames.
  • The managed-lifecycle scenario runs the moved test with cargo test --features cli --lib -- --ignored --exact <path>.
  • The five session hooks above.
  • GuestFeatures::{REQUIRED, contains}, MAX_CWD_BYTES and MAX_TIMEOUT_MS move into protocol/tests.rs.

Validation

The gates that local_gates.py --files selects, run from this branch's own action definitions, with Rust 1.95.0 and NVX_BUNDLE=skip:

Where Check Result
Windows cargo fmt --all --check passed
Windows cargo clippy --locked -- -D warnings with --all-targets --all-features, --lib, --lib --no-default-features, serde alone, --lib --bins --features cli, --lib --bins --no-default-features --features testing passed
Windows cargo clippy --all-targets -- -D warnings for the x86_64-unknown-linux-gnu target with all features, and for x86_64-unknown-linux-musl with --no-default-features --features guest, on each of the four commits (git rebase -x) passed
Windows cargo test --locked --all-features / cargo test --locked / cargo build --locked --lib --no-default-features / cargo test --locked --lib --no-default-features 1352 / 921 / built / 246 passed, 0 failed
Windows RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --all-features; cargo +1.89 check --locked --all-targets --all-features passed
Windows python scripts/public_api.py (both snapshots) passed; the diff drops 129 items per platform, all of NVXC or host::session
Windows cargo check --all-targets --all-features --target aarch64-apple-darwin passed
Windows check_test_layout.py, check_markdown_links.py, ruff check, ruff format --check, compileall, pyright (Linux and Windows) passed
Windows validate-nvx's python -m unittest scripts/test_*.py ..., test_adversarial.py, test_hosts.py, nvx.py test-microvm --help passed: 1824 tests (73 skipped), 84 (11 skipped) and 4; --help works
Windows SL5.2's check_matrix.py against 99d2022085f passed
Linux/MSHV (nvx-mshv-test, kernel 6.18) cargo clippy --locked --all-targets -- -D warnings with all features, the defaults, no features, serde, cli, testing, guest, the defaults with guest, cli,guest, testing,guest and cli,testing passed
Linux/MSHV cargo test --locked: --all-features, the defaults, --lib --no-default-features, --lib --features cli, --lib --no-default-features --features testing, --lib --no-default-features --features guest 2359 / 909 / 246 / 1125 / 274 / 1124 passed, 0 failed
Linux/MSHV cargo doc with -D warnings; cargo +1.89 check --all-targets --all-features; the bundled-artifacts test passed (21 bundling tests)
Linux/MSHV nvx.py check-guest-binaries --toolchain 1.95.0, build-guest-binaries, test-guest-binaries (musl) passed
Linux/KVM (nvx-kvm-test) NVX_AUTO_DOWNLOAD=0 nvx.py test-microvm --backend kvm --scenario managed-lifecycle --scenario vm-lifecycle, with the guest kernel, Alpine initramfs, Ubuntu layer, scratch template and OpenVMM (14dc4116, SHA-256 checked against its provenance) of CI run 43153762018 at 07c508c7, which no guest, protocol or OpenVMM change separates from this base; its guest binaries are the base's, since this PR changes only the visibility and gates of the guest's code, which the musl rows check passed: the moved test (1 passed, 1135 filtered out) and a_cold_vm_is_reattached_from_saved_values_and_stopped

After #1520 merged, the branch was rebased with git rebase --onto origin/feature/nvx-refactor 5bffcd7f onto baf560d1, without conflicts, and git range-diff shows its four commits unchanged. Rerun on the rebased head, everything passed: on Windows, cargo fmt --check, cargo clippy --all-targets -- -D warnings with all features, the defaults, no features, serde, cli, testing and cli,testing, and for the Linux gnu (all features) and musl (guest) targets; cargo test --lib with all features, the defaults, cli and no features (1168 / 853 / 1139 / 246 passed); public_api.py, check_matrix.py and check_test_layout.py; and the whole Linux/MSHV matrix above (all features: 2360 passed). check_test_changes.py reports the same changes.

A code-review subagent reviewed the whole diff and found no significant issues. Left to CI: the WHP microVM scenarios (this PR changes no Windows runtime path), the rest of the microVM matrix, benchmarks, and Specula's CI wiring test, which imports fcntl, so runs only on Linux, and which this PR doesn't touch.

Changes to existing tests

python scripts/check_test_changes.py --base origin/feature/nvx-refactor reports 342 changes to existing tests, 21 added test items, and none relocated unchanged; this PR carries the tests-modified label. Each change and its reason:

  • Gates, bodies unchanged (option A). Each test that reaches a now-gated item takes the gate of the code that it tests (guest as above):

    Test module Gate Items Why
    guest::managed_agent::dispatch::tests, with ::runtime cli, on mod tests in dispatch.rs 134 they drive the agent with the host's EXEC encoder
    helpers that only those tests use: guest::managed_agent::tests::PROCESS_TEST_LOCK; guest::managed_agent::seam::tests::{TestSystem::with_direct, start_as_privileged, start_with_failing_credentials}; guest::sys::spawn::tests::{CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_SETGID, CAP_SETUID} and their re-export in guest::sys::tests cli 8 unused where the dispatch tests aren't built
    guest::managed_agent::tests::loopback, with ::tests cli (was host) 31 its host is the session
    host::session::tests the module's cli 44 they test the session
    host::session::tests::exec_sends_the_working_directory_and_reports_its_refusal also testing or guest 1 it reads CWD_FAILED
    host::session::tests::features_report_what_the_guest_provides also guest 1 it reads the guest agents' feature sets
    host::session::tests::managed_lifecycle (moved from tests/managed_lifecycle.rs) the module's cli, and any(target_os = "linux", windows) from the old file's inner cfg 24 it drives the session
    host::restore::tests::live_init cli 23 it attaches to the restored init through the session
    host::transport::tests: verified_and_legacy_connections_wait_for_the_owned_endpoint_and_keep_nat, another_process_serving_the_endpoint_is_refused, the helper exchange cli 3 they compare connect_verified with the session's connect
    host::cli::session::tests: features_of_a_guest_that_predates_them_are_none, protocol_violations_keep_the_messages_of_python testing or guest 2 they read the guest's constants
    testing::fake_openvmm::tests::the_current_guest_advertises_every_required_feature cli and guest 1 it reads GuestFeatures::REQUIRED and the guest agents' sets
    protocol::tests the gates of the codecs that each test checks, below 43

    The imports of guest::sys::tests, host::cli::session::tests, host::transport::tests and protocol::tests split along the same gates. protocol::tests, by gate:

    • cli: exec_payload_distinguishes_explicit_environments, exec_payload_enforces_agent_limits, helpers program, strings;
    • cli, testing or guest: decoders_reject_malformed_input, exec_limits_support_linux_paths, frames_match_their_vectors, guest_maps_decoder_accepts_non_utf8_linux_paths, host_maps_encoding_round_trips_through_the_guest_decoder, maps_payloads_are_split_to_fit_the_limit, maps_payloads_enforce_agent_limits, record_definitions_keep_their_wire_values, helper frame_kind (they read NVXC's header, kinds or limits);
    • cli and testing: exec_payload_carries_every_32_bit_timeout, exec_payload_carries_the_working_directory_natively, exec_requests_are_refused_where_the_guest_agent_refuses_them, exit_categories_match_the_guest_agent, feature_definitions_keep_their_wire_values, features_match_their_vectors, guest_features_use_distinct_bits, layered_sandboxes_need_per_execution_environments_and_mapping_tables, helper extended;
    • guest: activate_requests_refuse_truncated_or_malformed_payloads, capture_requests_refuse_unknown_or_mis_sized_flags, guest_exec_decoder_accepts_what_the_c_agent_accepted, guest_exec_decoder_refuses_what_the_c_agent_refused, helper raw_extended;
    • guest and testing: both_agent_modes_announce_the_host_mapping_table, decoders_never_panic, exec_decoders_refuse_strings_with_the_same_messages, guest_exec_decoder_accepts_linux_bytes_and_the_c_cwd_boundary, the_guest_decodes_every_exec_payload_that_the_host_decodes, helper near_vectors, the proptest! block;
    • cli and guest: activate_requests_round_trip_records_and_workload_identity, activate_workload_ids_match_guest_credential_bounds, capture_requests_round_trip_both_kill_flags, host_exec_encoding_round_trips_through_the_guest_decoder, the_host_requires_every_feature;
    • cli, guest and testing: exec_payloads_match_their_vectors, guest_features_report_what_a_guest_lacks;
    • testing or guest: exec_extension_keeps_its_wire_values, host_mapping_table_keeps_its_wire_values.
  • Rewritten: tests/vm_lifecycle.rs's acknowledged helper, its imports and a_cold_vm_is_reattached_from_saved_values_and_stopped encode the frames themselves, as above; the vm-lifecycle scenario passes.

  • Moved: tests/managed_lifecycle.rs to host::session::tests::managed_lifecycle (its inner attributes and imports are reported removed), with its imports and three spelled refusal categories; the managed-lifecycle scenario passes.

  • End-to-end: scripts/nvx_tools/microvm_tests.py's MANAGED_LIFECYCLE_TEST and managed_lifecycle_test_command name the moved test and run it with --features cli --lib -- --ignored --nocapture --exact, and scripts/test_microvm_tests.py's test_managed_lifecycle_runs_the_nvx_rs_test_and_checks_what_it_leaves, test_managed_lifecycle_requires_cargo and test_managed_lifecycle_fails_with_the_test_and_with_the_report expect that command.

  • Removed hooks: the test hooks of protocol::app's APP_CAPTURE, APP_ACTIVATE, encode_capture_payload, decode_capture_payload, encode_activate_payload and decode_activate_payload, and of ControlSession::capture, give way to gates.

  • Test policy: the allowlist loosens nvx-rs/src/host/session.rs from 1 to 5 seams (Seams, above) and drops nvx-rs/src/protocol/app.rs.

  • Added: the 21 added items include the moved test's module declaration, vm_lifecycle's frame constants and encoder, managed_lifecycle's refusal categories, the items that moved into protocol's tests, and the imports that split by gate.

No test is retired.

@ppenna Pedro Henrique Penna (ppenna) added tests-modified Changes existing tests, test data, or test wiring feat-nvx-refactor labels Nov 12, 2026
@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 342 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 guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1
modified attributes the inner attributes of guest::managed_agent::dispatch::tests::runtime (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests/runtime.rs:1 nvx-rs/src/guest/managed_agent/dispatch/tests/runtime.rs:1
modified attributes the inner attributes of guest::managed_agent::tests::loopback (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and feature = "host" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/tests/loopback.rs:1 nvx-rs/src/guest/managed_agent/tests/loopback.rs:1
modified attributes the inner attributes of guest::managed_agent::tests::loopback::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and feature = "host" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/tests/loopback/tests.rs:1 nvx-rs/src/guest/managed_agent/tests/loopback/tests.rs:1
modified attributes the inner attributes of host::restore::tests::live_init (it now compiles where any ( target_os = "linux" , windows ) and feature = "cli" and feature = "host" and test hold, not where any ( target_os = "linux" , windows ) and feature = "host" and test did) nvx-rs/src/host/restore/tests/live_init.rs:1 nvx-rs/src/host/restore/tests/live_init.rs:1
modified attributes the inner attributes of host::session::tests (it now compiles where feature = "cli" and feature = "host" and test hold, not where feature = "host" and test did) nvx-rs/src/host/session/tests.rs:1 nvx-rs/src/host/session/tests.rs:1
modified helper const INSTANCE in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:26 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:26
modified helper struct Response in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:29 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:29
modified helper struct Harness in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:36 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:36
modified helper impl Harness in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:44 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:44
modified helper fn new in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:45 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:45
modified helper fn with_system in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:49 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:49
modified helper fn in_sandbox in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:57 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:57
modified helper fn spawn in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:64 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:64
modified helper fn spawn_at in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:71 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:71
modified helper fn spawn_with in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:77 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:77
modified helper fn spawn_with_capture in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:81 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:81
modified helper fn reset in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:111 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:111
modified helper fn request in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:126 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:126
modified helper fn request_all in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:132 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:132
modified helper fn send in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:138 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:138
modified helper fn next_response in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:163 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:163
modified helper fn responses in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:180 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:180
modified helper fn stop in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:195 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:195
modified helper fn fail in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:211 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:211
modified helper fn close in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:219 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:219
modified helper fn read_outer in guest::managed_agent::dispatch::tests, impl Harness`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:227 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:227
modified helper fn read_outer in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:232 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:232
modified helper fn response in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:243 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:243
modified helper fn stdout_from in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:252 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:252
modified helper fn exec_payload in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:266 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:266
modified helper fn maps_payload in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:276 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:276
modified helper fn assert_environment_failure in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:290 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:290
modified helper fn running_restored_workload in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:581 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:581
modified helper fn sandbox_root in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:762 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:762
modified helper fn spawn_sandbox in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1031 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1031
modified helper fn sandbox_system in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1041 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1041
modified helper type TestResult in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1313 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1313
modified helper fn workload_payload in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1317 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1317
modified helper fn utf8 in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1327 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1327
modified helper struct Unsearchable in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1335 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1335
modified helper impl Unsearchable in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1337 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1337
modified helper fn new in guest::managed_agent::dispatch::tests, impl Unsearchable`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1339 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1339
modified helper impl Drop for Unsearchable in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1349 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1349
modified helper fn drop in guest::managed_agent::dispatch::tests, impl Drop for Unsearchable`` (it now compiles where feature = "cli" and `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` hold, not where `feature = "guest"` and `target_arch = "x86_64"` and `target_os = "linux"` and `test` did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1350 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1350
modified helper fn start_with_real_credentials in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1368 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1368
modified helper fn start_after_pending_statuses_are_collected in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1374 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1374
modified helper fn start_with_failed_pidfd_and_cleanup in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1428 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:1428
modified helper fn lost_status_harness in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:2016 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:2016
modified helper fn lost_status_diagnostics in guest::managed_agent::dispatch::tests (it now compiles where feature = "cli" and feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "guest" and target_arch = "x86_64" and target_os = "linux" and test did) nvx-rs/src/guest/managed_agent/dispatch/tests.rs:2029 nvx-rs/src/guest/managed_agent/dispatch/tests.rs:2029

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

End-to-end tests

Change What Before After
modified helper assignment MANAGED_LIFECYCLE_TEST in scripts/nvx_tools/microvm_tests.py scripts/nvx_tools/microvm_tests.py:1363 scripts/nvx_tools/microvm_tests.py:1365
modified helper def managed_lifecycle_test_command in scripts/nvx_tools/microvm_tests.py scripts/nvx_tools/microvm_tests.py:1383 scripts/nvx_tools/microvm_tests.py:1388

Test doubles

Change What Before After
modified test fn the_current_guest_advertises_every_required_feature in testing::fake_openvmm::tests (moved, and it now compiles where feature = "cli" and feature = "guest" and feature = "testing" and target_arch = "x86_64" and target_os = "linux" and test hold, not where feature = "testing" and test did) nvx-rs/src/testing/fake_openvmm/tests.rs:24 nvx-rs/src/testing/fake_openvmm/tests.rs:30

Test policy

Change What Before After
loosened allowlist entry nvx-rs/src/host/session.rs (the seams allow 5 test hooks, up from 1) scripts/test-layout-allowlist.json

Relocated unchanged: 0; added: 21. Compared the merge base d58c687f06f6 with 0e927f7865af.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 were identified for the NVXC and host-session visibility changes.

No open issues 🎉

What changed in this PR

This PR implements SL6.12 of the library-slimming workstream: NVXC and its host session become crate-private before the protocol’s v2 changes. Public NVXS transport and mapping codecs remain available, with no wire-format or session-behavior changes.

Changes:

  • Restricts NVXC items to crate visibility and gates them by their CLI, guest, or testing users.
  • Moves managed-lifecycle coverage into session unit tests and adapts public examples and VM lifecycle tests to use transport directly.
  • Updates API snapshots, documentation, test commands, and the acceptance matrix to reflect the private boundary.
File Description
scripts/​test-layout-allowlist.json Updates allowances for remaining session hooks.
scripts/​test_microvm_tests.py Checks the moved test’s Cargo command and diagnostics.
scripts/​nvx_tools/​sandbox_lifecycle_tests.py Updates the lifecycle test path in documentation.
scripts/​nvx_tools/​microvm_tests.py Runs the managed-lifecycle unit test with cli.
nvx-rs/​tests/​vm_lifecycle.rs Encodes lifecycle frames locally through public transport.
nvx-rs/​src/​testing/​fake_openvmm/​tests.rs Gates feature assertions by their dependencies.
nvx-rs/​src/​testing/​fake_openvmm.rs Removes a rustdoc link to a private type.
nvx-rs/​src/​protocol/​tests.rs Gates codec tests and houses test-only definitions.
nvx-rs/​src/​protocol/​mod.rs Makes NVXC exports private and feature-gated.
nvx-rs/​src/​protocol/​maps.rs Describes NVXC without linking private constants.
nvx-rs/​src/​protocol/​features.rs Privatizes and gates guest feature definitions.
nvx-rs/​src/​protocol/​exec.rs Privatizes and gates EXEC payloads and codecs.
nvx-rs/​src/​protocol/​app.rs Privatizes and gates application frames and payload helpers.
nvx-rs/​src/​lib.rs Documents the public transport/private NVXC boundary.
nvx-rs/​src/​host/​transport/​tests.rs Gates tests that compare transport with the private session.
nvx-rs/​src/​host/​session/​tests/​managed_lifecycle.rs Houses the moved lifecycle test with crate-local imports.
nvx-rs/​src/​host/​session/​tests.rs Registers the moved test and gates feature-dependent cases.
nvx-rs/​src/​host/​session.rs Makes session APIs crate-private and marks retained hooks.
nvx-rs/​src/​host/​restore/​tests.rs Gates live session tests behind cli.
nvx-rs/​src/​host/​mod.rs Makes the session module crate-private and CLI-only.
nvx-rs/​src/​host/​cli/​session/​tests.rs Adjusts private imports and feature-dependent test gates.
nvx-rs/​src/​guest/​sys/​tests.rs Gates re-exports used by dispatch tests.
nvx-rs/​src/​guest/​sys/​spawn/​tests.rs Gates capability constants used by dispatch tests.
nvx-rs/​src/​guest/​managed_agent/​tests.rs Gates the loopback harness and shared test lock.
nvx-rs/​src/​guest/​managed_agent/​seam/​tests.rs Gates helpers used by CLI-dependent guest tests.
nvx-rs/​src/​guest/​managed_agent/​dispatch.rs Requires cli for tests using the host encoder.
nvx-rs/​README.md Updates module descriptions and lifecycle-test documentation.
nvx-rs/​public-api/​windows.txt Removes NVXC and host-session API entries.
nvx-rs/​public-api/​linux.txt Removes NVXC and host-session API entries.
nvx-rs/​examples/​host-workflows.rs Uses public connections and classifies transport errors.
nvx-rs/​examples/​external-launch.rs Connects to the console through public transport.
doc/​usage.md Documents the relocated lifecycle unit test.
doc/​project-structure.md Removes managed lifecycle from the integration-test listing.
doc/​contribute.md Updates the managed-lifecycle test location.
doc/​ci.md Documents the unit-test path and required feature.
doc/​adversarial-testing.md Updates lifecycle test naming and prebuild command.
doc/​acceptance-case-matrix.md Tracks the moved test and shifted doctest location.

Review effort: Balanced

Base automatically changed from agents/slim-sl6-1-sandbox-store to feature/nvx-refactor November 12, 2026 08:12
host-workflows' capture and restore asked their guest for a snapshot
and activated a restore through ControlSession, the host's session of
NVXC, NVX's own control protocol, which they reached at its public
path, nvx::host::session, with session::connect. external-launch also
connected to the boot console of its VM with session::connect. The
examples say that a caller speaks its own protocol with its guest, and
SL6.12 (#1127) makes NVXC and the host's session private to nvx: a
caller of the library connects through the transport that nvx gives
every caller.

host-workflows' capture and restore now connect with
transport::connect_verified, which checks that the VM's own process
serves the endpoint, and attach with HostConnection::attach, the
host's role of the NVXS session. The callbacks take that connection,
on which the caller sends and receives its own protocol's messages,
and fail with nvx::Error. failed() classifies a connection's failure
as the restore expects it, as it did the session's: a VM that exited;
a lost connection, whose broker closed or reset the session, whose
stream ended inside a record, or whose transport broke; an expired
deadline; an endpoint that another process serves; a malformed
exchange; or I/O. external-launch connects to its boot console with
transport::connect_verified and the VM process's reference, which
session::connect built from the same process ID and start time and
the host's boot.

Evidence: cargo clippy --all-targets --all-features -- -D warnings
compiles both examples on Windows.

Part of #1127 (SL6.12).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tests/vm_lifecycle.rs drives a cold VM through the public API alone,
and asks its guest, nvx-init, whether it is ready and to end the VM in
the guest's protocol, NVXC, whose frames it built and read with
nvx::protocol::{encode_app, decode_app} and the APP_* kinds. SL6.12
(#1127) makes NVXC private to nvx, as NVX's own protocol, so a caller
of the public API that runs nvx-init speaks NVXC on its own, over the
HostConnection that vm::reattach returns, as this test's caller does.

The test now encodes the empty NVXC frames that it sends, PING and
STOP, and the acknowledgements that it expects, READY and STOPPED,
itself: the magic, the version, the kind, zero flags, the request's
ID, a zero status, and a zero length, as tests/vectors/nvxc-v1.txt
pins them. It compares each answer with the whole acknowledgement
frame, which checks the magic, version, flags, kind, request ID,
status and empty payload that decode_app and its assertion checked.
It stays a test of the public API, which the case matrix's vm-lifecycle
row names, so the scenario that runs it is unchanged.

Evidence: cargo clippy --test vm_lifecycle -- -D warnings passes on
Windows; the frame matches the NVXC PING frame of the DATA_PING record
in tests/vectors/nvxc-v1.txt.

Part of #1127 (SL6.12).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nvx::host::session, the host's session of NVXC, NVX's own control
protocol, was public API of nvx, though only NVX's programs use it: the
CLI, with the sessions of nvx-rs sandbox and its snapshot capture, and
the restore driver, which the cli feature builds. SL6.12 (#1127) makes
it private where it is, before NVXC v2 changes it.

The module becomes crate-private and cli-gated, and its items
pub(crate). The CLI's own session sends PING, FEATURES, EXEC and STOP
through send_request and read_response, so nothing in NVX calls the
session's ping, features, start_exec, cancel_exec or stop any more.
They keep cfg_attr(not(test), expect(dead_code)) hooks, which name
SL4.4c, whose sandbox exec and run ping, exec, cancel and stop through
the session, and, for features, SL4.4d, which deletes FEATURES; the
allowlist's seams of session.rs go from 1 to 5. capture's hook and
activate's cfg go, since the module is the CLI's alone, and APP_CAPTURE
and encode_capture_payload, which only the session's capture sends,
follow it from host to cli.

tests/managed_lifecycle.rs, which drove the managed lifecycle of a real
guest through nvx::host::session, moves with git mv to the session's
tests, as host::session::tests::managed_lifecycle, unchanged but for its
imports, which use crate paths, and its cfg, which its module
declaration holds. The managed-lifecycle scenario runs it with
`cargo test --features cli --lib -- --ignored --exact` and its path.
The tests that reach the session from outside it follow its gate: two
transport tests, which compare connect_verified with the session's
legacy connect, with their exchange helper; the live restored-init
tests of host::restore; and the managed agent's loopback test, whose
host is the session.

The public-API snapshots drop host::session's items, and only those.
The README and the docs describe the session as private, and the
managed-lifecycle test where it now lives.

Evidence, on Windows with Rust 1.95.0: cargo clippy -D warnings passes
for --all-targets --all-features, --lib, --lib --no-default-features,
serde alone, --lib --bins with cli, and with testing alone, and for
x86_64-unknown-linux-gnu --all-targets --all-features and
x86_64-unknown-linux-musl with guest alone and --all-targets;
cargo doc -D warnings, public_api.py and check_test_layout.py pass;
cargo test --all-features --lib passes for host::session,
host::transport, host::restore, host::cli::session,
host::cli::snapshots and host::restore_driver (110 passed, 4 ignored),
and cargo test --lib passes for host::transport and host::restore with
the default features; python -m unittest test_microvm_tests -k
managed_lifecycle passes.

Part of #1127 (SL6.12).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nvx::protocol re-exported NVXC, NVX's own control protocol, as public
API of nvx: its application frames (AppFrame, encode_app, decode_app
and the APP_* kinds), the refusal categories and ExitCategory, the EXEC
payloads with their codecs, flags and limits, and GuestFeatures. Only
NVX's programs speak NVXC: the CLI and its restore driver, nvx-init and
the managed agent, and the fake OpenVMM. SL6.12 (#1127) makes it
crate-private where it is, before NVXC v2 changes it.

Every NVXC item becomes pub(crate) and is gated by the features of the
code that uses it, so that no feature set builds an item that it does
not use: cli for the host's encoders and checks, guest on Linux x86-64
for the guest's decoders and the managed agent, and testing for the
fake OpenVMM's decoder. The exec and features modules compile with any
of them. protocol re-exports each item under the gate of its users,
and no longer re-exports what only the codec itself reads. The capture
and activate messages, whose expect(dead_code) hooks covered the
builds without their users, take the same gates, so app.rs holds no
test hook any more and its allowlist entry goes. GuestFeatures's
REQUIRED and contains, MAX_CWD_BYTES and MAX_TIMEOUT_MS, which no
feature set uses, move into protocol's tests, which alone read them.
protocol::exec is crate-visible, for the CLI session's tests that read
the EXEC flags.

The tests of NVXC are gated by the features of the code that they
test, with their bodies unchanged, so that every build compiles them
where their code is built, and every one of them runs in the
all-features tests on Linux: protocol's NVXC tests take the gates of
the codecs that they check; the managed agent's dispatch tests, which
drive the agent with the host's EXEC encoder, and the test helpers that
only they use, take cli; and tests of the host's session, the CLI's
session and the fake OpenVMM that use a guest or testing constant take
that feature. The managed lifecycle test spells the three refusal
categories that it expects, since the cli feature alone, with which its
scenario runs it, does not build the guest's constants.

The public-API snapshots drop the 93 NVXC items of each platform, and
only those: NVXS, the outer records and the mapping table's payloads
and tokens stay. protocol's docs, the crate's, the README and the
items that linked NVXC no longer present it as public API.

Part of #1127 (SL6.12).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants