Skip to content

nvx-rs: build every feature set, compile the documented examples, and give every old test a fate (SL5.1a) - #1488

Merged
Pedro Henrique Penna (ppenna) merged 5 commits into
feature/nvx-refactorfrom
agents/slim-sl5-1a-feature-sets
Nov 11, 2026
Merged

Pedro Henrique Penna (ppenna) merged 5 commits into
feature/nvx-refactorfrom
agents/slim-sl5-1a-feature-sets

Conversation

@ppenna

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

Copy link
Copy Markdown
Contributor

Part of #1118 (SL5.1a, "Every feature set builds, the documented examples compile, and every old test has a fate"). Parent #1086, umbrella #1076.

What and why

NVX deletes its runtime adapter, tests/runtime-adapter, in SL5.2 (#1119), once the acceptance that replaces it passes. Before then, the public surface needs coverage that doesn't depend on the adapter, and every test that the deletion removes needs a recorded fate. This PR adds the one feature-set build that CI lacked, compiled examples of the documented workflows, a security checklist, and the case matrix:

  • Every feature set builds. CI built nvx with all features, with host (the default), without default features, with cli and testing alone, and with guest alone in the musl check of the guest binaries, but never with serde alone. The Lint step of check-nvx-rs now also runs cargo clippy --locked --lib --no-default-features --features serde -- -D warnings, so code that only serde's users reach can't hide behind host, which enables serde. doc/ci.md, doc/contribute.md and the README's Testing section list the feature sets that CI checks.
  • The documented examples compile. Two compile-only examples use the public API alone, and nothing runs them. Cargo builds each with the feature that it needs, so Clippy's runs of all targets compile them.
    • nvx-rs/examples/host-workflows.rs: a cold boot, with what the caller saves; a capture, finished with the proof of the VM's exit, whose three entries move into the caller's snapshot directory; a restore with vm::create(.., Some(snapshot), ..), which drives RestoreMachine through ReadyListener::receive, session::connect and ControlSession::attach to the guest's Ready, under the snapshot's lock and view as vm::create documents them; finding a VM again after the caller restarts; and a stop. A failed capture or restore ends its VM, or returns it in an Unstopped error when its exit isn't verified, since vm::stop leaves the caller that VM's process.
    • nvx-rs/examples/guest-workflows.rs, for Linux guests: the time daemon, the control session, a capture with each disposition, the activation of a restore, and the mapping table. It leaves the guest's space to its caller, and says what a real init adds to its simpler loop: the activation's deadline, and what its session received while it applied a record.
    • The space's steps compile in nvx-init instead, in guest::init::boot::tests::the_reference_space_steps_compile: a cold boot, the mapping table and a restore, as nvx-init takes them, in closures that the test compiles and never runs, since they would mount over the test host's root.
  • The security checklist. nvx-rs/tests/security_checklist.rs checks, through the public API alone and without a VM, the security requirements that the docs of filesystem, vm and snapshot state: the path rules (an export's guest targets, a read-only path inside a writable one, and, on Windows, the refused caller owner); the stability of exported objects, which a start checks again; the image checks, a replaced staged image and a claimed scratch image, in directories that only the caller's account can write; a private VM directory, never restricted in place, and a launch's new private log, which keeps every entry that it didn't create; a snapshot's strict directory; and the launch's liveness, endpoint-owner and recovery claims: a saved VM runs until its process exits, another runtime is refused without a signal, and a reattachment refuses an endpoint that another process serves, keeping the VM and the saved values. An idle copy of the test binary stands in for a VM's process. The restore's own requirements, SL2.16's view, lock and listener, need a captured snapshot, so the unit tests of vm, snapshot and restore keep checking them; the docs after SL2.16 add no requirement that the public API can check without one.
  • The case matrix. doc/acceptance-case-matrix.md gives 478 tests one fate each, kept, rewritten or retired, by name: the 157 scenarios of scenarios.txt (the 154 of the adapter's stage, the two that dev added, and the Linux-only restore exclusion), the adapter's 166 other tests, the 52 microVM scenarios, 69 cases of CI (the steps of its workflows and actions that check something, and the Python tests of its wiring that name the adapter), and 34 cases of the docs (the 32 doctests, the README's example and external-launch). A rewritten test names the existing tests that cover it, among them SL2.16's and SL4.3's, or the slice that adds them, SL5.1b or SL5.1c; a retired one says what leaves NVX. A script outside the repository generated the matrix from the manifests and checked that each named Rust test, microVM scenario, Python test class and path exists.
  • Index. The README's documentation index and doc/project-structure.md list the matrix, the examples and the checklist.

A deliberate coverage change: three dependency tests retire

Three tests of tests/runtime-adapter/tests/independent_build.rs checked the dependency graph of the adapter's configurations of nvx:

  • the_protocol_only_configuration_depends_on_nvx_alone_without_features: the protocol-only configuration pulls in nvx alone, without features;
  • the_host_only_configuration_enables_the_host_side_of_nvx_alone: the host-only configuration enables host, and not guest;
  • the_guest_only_configuration_pulls_in_no_host_or_tokio_dependency: the guest-only configuration, for musl, enables guest alone, and pulls in no Tokio and none of the dependencies that only nvx's host side declares.

The matrix retires them, deliberately. #1086 replaces the adapter's per-feature build checks with "CI builds each feature set", which this PR completes, and SL5.1a's "Not in this PR" excludes new coverage categories, so no replacement is in scope. Once the adapter goes, CI still builds nvx with each feature set alone, warnings denied, but no test checks which dependencies a feature set pulls in. A check of nvx's feature graph, for example over cargo metadata, would be a follow-up.

The examples are documentation

The two examples hold 388 lines of code (296 in host-workflows.rs, 92 in guest-workflows.rs). This PR counts them as documentation, as the slice's estimate, "50 core lines (CI), 2 counted files", implies: they are compiled documentation of the public API that nothing calls, and #1076's acceptance names them beside the docs ("CI builds each feature set and compiles the documented examples").

Size

Measured against feature/nvx-refactor a53a2626: 10 core lines (stop 100) in 2 counted files: .github/actions/check-nvx-rs/action.yml 2 and nvx-rs/Cargo.toml 8. The rest is tests (nvx-rs/tests/security_checklist.rs and nvx-rs/src/guest/init/boot/tests.rs), the examples, counted as documentation, and docs.

Commits

  1. ci: lint nvx with the serde feature alone (Enrique Saurez (@esaurez))
  2. guest: compile the reference space's steps in nvx-init
  3. nvx-rs: compile the documented host and guest workflows
  4. nvx-rs: check the documented security requirements through the API (Enrique Saurez (@esaurez))
  5. doc: give each adapter, CI and docs test a fate

Enrique Saurez (@esaurez)'s first implementation is esaurez/slim-4.1.1-sl5.1a-private-20261108 (547101c9, the checkpoint on #1118). This branch keeps his authorship of the serde lint and the checklist, and credits him as co-author of the rest, which it reworks onto the merged SL2.16 (#1470) and SL4.3 (#1476).

Not in this PR

Smoke tests on real VMs, which SL5.1b and SL5.1c add; deleting the adapter, its runner or its gates, which SL5.2 (#1119) does; a new test framework or runner; the guest's space as public API; a check of the dependencies that each feature set pulls in (above). No production code changes, and the public API snapshots don't change.

Validation

With this branch's check-nvx-rs and check-quality commands (in nvx-rs/, NVX_BUNDLE=skip): on Linux on the head 05cd1d2d (on ac3bbefb), and on Windows on the earlier head b5fd0431 (on a53a2626), which differs only in its base and in the review fix of guest-workflows.rs, whose changed code builds only for Linux. On 05cd1d2d, Windows also passed the Clippy runs of all targets with all features and of serde alone, the checklist (11 passed, 1 ignored) and the Markdown links.

Check Windows (local) Linux (nvx-kvm-test, KVM)
cargo fmt --all --check passed passed
cargo clippy --locked ... -- -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 passed, all six passed, all six
cargo test --locked --features host --test security_checklist 11 passed, 1 ignored (the idle stand-in) 10 passed, 1 ignored (no Windows-only test)
cargo test --locked --all-features --lib the_reference_space_steps_compile Linux only passed
RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --all-features passed on the previous head 74a58def; only the examples and Markdown docs changed since passed
cargo +1.89 check --locked --all-targets --all-features passed passed
cargo check --locked --all-targets --all-features --target aarch64-apple-darwin passed
python3 scripts/public_api.py passed, no change
python3 scripts/nvx.py check-guest-binaries the musl Clippy of all targets with guest alone, which compiles guest-workflows, passed; the musl tests: 1117 passed and 26 failed, the same 26 guest:: tests that fail at the base a53a2626 on that host (a process-group kill returns EINVAL, os error 22)
scripts/check_test_layout.py, scripts/check_markdown_links.py passed passed
python -m unittest test_nvx_tools.CiConfigurationTests, which reads check-nvx-rs 94 passed, 6 skipped

cargo test --doc --all-features -- --list lists the 32 doctests that the matrix names. The branch rebased onto ac3bbefb without conflicts, and the matrix's checks pass there and leave it unchanged: no test, scenario, CI step or doctest that it names moved.

No microVM scenario ran: no runtime path changes. Left to CI: the full test suites on Linux and Windows, the bundling test, the runtime adapter's configurations, the guest binaries' build and integration tests, the full Python suites, and the microVM, adapter and benchmark lanes.

Changes to existing tests

python3 scripts/check_test_changes.py --base origin/feature/nvx-refactor lists no change to an existing test, and 28 added items: the checklist's 12 tests (one Windows-only, and the ignored idle stand-in) with their helpers, and the space's test. No existing test changes or goes; the matrix gives each test of the adapter, of CI and of the docs its fate before SL5.2 deletes the adapter.

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.

🟡 Changes recommended

The completion timestamp is sampled before assembly, allowing work that crosses the activation deadline to transition to Ready and be sent to the host.

1 open issue
What changed in this PR

This PR prepares NVX to replace its runtime adapter with independent acceptance coverage. It adds the missing feature-set check, compiled workflow examples, security checks, and a test-disposition matrix before the adapter’s later removal.

Changes:

  • Add warnings-denied Clippy coverage for serde alone.
  • Compile host, guest, and private guest-space workflows, and add public-API security checklist tests.
  • Record dispositions for 478 existing cases and update documentation indexes.
File Description
README.md Link the acceptance case matrix.
nvx-rs/​tests/​security_checklist.rs Add public-API security checks without running VMs.
nvx-rs/​src/​guest/​init/​boot/​tests.rs Compile reference guest-space steps without executing them.
nvx-rs/​README.md Document the checklist, examples, matrix, and feature checks.
nvx-rs/​examples/​host-workflows.rs Demonstrate host lifecycle, capture, and restore workflows.
nvx-rs/​examples/​guest-workflows.rs Demonstrate guest capture, activation, and mapping workflows.
nvx-rs/​Cargo.toml Register feature-gated workflow examples.
doc/​project-structure.md Index the new examples, checklist, and matrix.
doc/​contribute.md Include the serde-only validation gate.
doc/​ci.md Explain feature-set and example compilation coverage.
doc/​acceptance-case-matrix.md Assign existing cases kept, rewritten, or retired dispositions.
.github/​actions/​check-nvx-rs/​action.yml Add the serde-only Clippy command.

Review effort: Balanced

Comment thread nvx-rs/examples/guest-workflows.rs Resolved
Enrique Saurez and others added 2 commits November 11, 2026 13:27
CI built nvx with warnings denied with all features, with its default
features (host), without default features, with cli and testing alone,
and, in the musl check of the guest binaries, with guest alone, but
never with serde alone, the one feature set that the slimming plan
names and CI didn't build. Code that only serde's own users reach could
therefore hide behind the host feature, which enables serde.

The Lint step of check-nvx-rs now runs Clippy on the library with
--no-default-features --features serde, warnings denied, beside the
other feature sets, and its comment, the README's Testing section,
doc/ci.md and doc/contribute.md say which feature sets CI checks.

Evidence: cargo clippy --locked --lib --no-default-features --features
serde -- -D warnings passes on Windows and on Linux (nvx-kvm-test).

Part of #1118 (SL5.1a).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The guest's space, the root and its upper, its runtime file systems,
the view, the host export and its mappings, and the VM's one switch, is
nvx-init's own code, which NVX's reference space implements privately:
no public example can show its steps, and the guest-agent guidelines
are to quote them from a unit test of the private space.

A unit test of nvx-init's boot now holds those steps as nvx-init takes
them, for a cold boot, for the host's mapping table after Ready, and for
a restore, in closures that it compiles and never runs, since they would
mount over and switch the test host's root. The test fails to compile
when the space's interface changes under the quoted steps.

Evidence: the guest-only musl tests pass on nvx-kvm-test with the new
test, which compiles and passes; the 26 tests of that run that fail
there fail the same way at the base revision, 5947e4e, with EOPNOTSUPP
from that host's kernel.

Part of #1118 (SL5.1a).

Co-authored-by: Enrique Saurez <esaurez@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ppenna
Pedro Henrique Penna (ppenna) marked this pull request as ready for review November 11, 2026 21:29
The documented workflows of nvx's public API had no compiled example
besides external-launch, which runs one cold boot, or a restore up to
its restore-ready event, through a launcher of the caller's own. The
library's guide and the guest-agent guidelines, which come later, are
to link compiled examples of the rest.

Two compile-only examples now cover them through the public API alone,
and nothing calls their functions. host-workflows boots a VM cold and
returns what its caller saves; captures a snapshot, finishes it with the
proof of the VM's exit, and moves its three entries into an empty
directory of the caller's; restores a snapshot and drives the restore's
machine to its guest's Ready, through the restore-ready event and a
control session that only the VM's own process may send and serve; ends
the VM of a failed capture or restore, or returns it to its caller in an
Unstopped error when its exit isn't verified, since vm::stop leaves the
caller such a VM's process; finds a VM again after its caller
restarted, and terminates one of another runtime; and stops a VM after
a grace period. guest-workflows, for Linux guests, starts the time
daemon, attaches the control session, captures the VM with each
disposition of a capture, activates a restore, and applies the host's
mapping table; it leaves the guest's space to its caller, as nvx-init's
space is its own, and says what a real init adds to its simpler loop:
the activation's deadline, and what the session received while the
init applied a record. Cargo builds each with the feature that it
needs, so CI's Clippy runs of all targets compile them, guest-workflows
in the musl check of the guest binaries. The project structure lists
the examples.

Evidence: cargo clippy --all-targets --all-features -D warnings passes
on Windows and on Linux, and nvx.py check-guest-binaries's Clippy run
compiles guest-workflows with guest alone on Linux.

Part of #1118 (SL5.1a).

Co-authored-by: Enrique Saurez <esaurez@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The runtime adapter, which NVX deletes once its replacement passes,
checked the security requirements of the host's documentation through
the public API, among its scenarios on real VMs. Nothing else did so
without the adapter.

nvx-rs/tests/security_checklist.rs now checks each of them through the
public API, without a VM: an export refuses guest targets that are not
canonical or that a root reserves, and a read-only path inside a
writable directory; it checks an exported object that a workload could
move again before a start; a staged image that was replaced fails its
check, and a scratch image is claimed by one launch and checked again
after a release; a VM's directory is private and never restricted in
place; a launch takes a new private log and keeps every entry that it
didn't create; a snapshot opens only from a snapshot directory; a saved
VM runs until its process exits, and another runtime is refused without
a signal; and a reattachment refuses an endpoint that another process
serves, keeping the VM and the saved values. An idle copy of the test
binary stands in for a VM's process. The checks that NVX makes of a
restore need a captured snapshot, so the unit tests of vm, snapshot and
restore keep checking them, as the README says. The project structure
lists the checklist among nvx-rs's tests.

Evidence: the checklist passes on Windows and on Linux (nvx-kvm-test).

Part of #1118 (SL5.1a).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NVX deletes its runtime adapter once the acceptance that replaces it
passes, and its deletion is to point each test that it removes to a
fate, which nothing recorded.

doc/acceptance-case-matrix.md now gives each test one fate, kept,
rewritten or retired, by name: the 157 scenarios of the adapter's
scenarios.txt, the 154 of its stage, the two that dev added and the
Linux-only restore exclusion; the adapter's 166 other tests; the 52
microVM scenarios; CI's steps that check something, and the Python
tests of CI's wiring that name the adapter; and the code of the docs
that rustdoc compiles. A rewritten test names the tests that cover it
without the adapter, which exist, among them those of SL2.16's restore
and SL4.3's restore driver, or the later slices that add them, SL5.1b
and SL5.1c; a retired one says what leaves NVX. Every named test exists
where the matrix was added. The adapter's checks of the features and
dependencies that its own configurations select of nvx retire with it:
CI builds each feature set alone, but no test checks the dependencies
that one pulls in. The README's documentation index and the project
structure list the matrix.

Part of #1118 (SL5.1a).

Co-authored-by: Enrique Saurez <esaurez@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 are identified for the acceptance-coverage and validation-documentation changes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants