Skip to content

host: write private files through the platform layer (SL6.0d) - #1518

Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
feature/nvx-refactorfrom
agents/slim-sl6-0d-store-helpers
Nov 12, 2026
Merged

Pedro Henrique Penna (ppenna) merged 1 commit into
feature/nvx-refactorfrom
agents/slim-sl6-0d-store-helpers

Conversation

@ppenna

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

Copy link
Copy Markdown
Contributor

Part of #1120 (SL6.0d, "The snapshot and CLI code stop using host::store's file helpers"). Parent #1087, umbrella #1076.

What and why

SL6.1 (#1121) deletes the sandbox store, host::store. Code that stays still writes its private files through the store's file helpers, host::store::files::{write_private, sync_dir, create_new}, and reads through host::store::regular's aliases of open_regular and read_at_most. These callers are finish_capture in host/snapshot/capture.rs, the CLI's sandbox store (host/cli/store/files.rs), and its snapshot store and capture (host/cli/snapshots.rs, host/cli/snapshots/capture.rs). SL6.0a found these uses. #1120's goal is that code which stays stops using what leaves, so this kept-code PR moves the helpers to an owner that stays. Behavior doesn't change. The change is one commit, host: write private files through the platform layer:

  • The three helpers move unchanged to host::platform (host/platform/mod.rs), which already holds the host's file helpers and the strict reads that SL6.0a moved there. write_private, sync_dir and create_new move with private_options and, on Unix, PRIVATE_FILE_MODE (0600), which they share with the store's lock files. All stay crate-private, and a new paragraph of the module doc says what they do.
  • The store re-exports create_new and write_private (pub(crate) use crate::host::platform::{create_new, write_private}; in host/store/files.rs) for its own files, until SL6.1 (host: delete the sandbox store, the instance layer and the supervision (SL6.1) #1520) deletes it. Its open_lock takes the moved options and mode. Nothing in it syncs a directory through sync_dir any more, since host: delete the old clone path (SL6.2b) #1507 and host: delete the template store (SL6.2a) #1513 deleted the old clone path and the template store.
  • The kept callers use host::platform directly. These are finish_capture, the CLI's sandbox store, snapshot store (three sync_dir calls) and capture, and their tests' imports. The same holds for open_regular and read_at_most, which they reached through host::store::regular.
  • Three platform tests cover the moved helpers, which only the store's tests covered so far: a_private_write_replaces_its_file_whole_and_a_failed_one_leaves_no_temporary_file, a_new_private_file_never_takes_the_place_of_an_existing_entry and a_directory_sync_fails_for_a_missing_directory_only_on_unix, in host/platform/tests.rs.
  • The case matrix follows finish_capture's doc test from line 50 to line 48.

A private file is still created with mode 0600 on Unix without following a link, and replaced through a temporary file that a failure removes. Its directory is still synced on Unix only, with the same messages.

Size

Measured against a5921d0b:

  • Core lines: 78, 62 of them in platform/mod.rs: the moved helpers, their imports and the module's new imports. The other 16 are import and re-export lines in the five other files.
  • Counted files: 6: host/platform/mod.rs, host/store/files.rs, host/snapshot/capture.rs, host/cli/store/files.rs, host/cli/snapshots.rs and host/cli/snapshots/capture.rs. The orchestrator approved 6 for Pedro Henrique Penna (@ppenna): the store's re-export keeps it compiling until SL6.1, and a split would be harder to follow.

BOOT_CONTRACT_VERSION and CONTROL_CONTRACT_REVISION don't change, and the public API doesn't change (python scripts/public_api.py passes unchanged).

Not in this PR

Changing what the helpers do; deleting the store or its re-export (SL6.2a and SL6.1); the CLI's own store and lifecycle (SL6.0e, #1519).

Validation

Rebased on a5921d0b, after #1507, #1513, #1501, #1503 and #1523, as 5de1c96d. The rebase drops sync_dir from the store's re-export, which #1513's deletion of the template store left without a user. It resolves finish_capture's matrix row (line 48) beside #1513's host::store (line 104), and platform's module doc beside #1513's edit of it. Its code is then that of SL6.1's stacked copy, 6865582b in #1520, which passed the Linux gates and the microVM scenarios in #1520's validation. On 5de1c96d: cargo fmt --all --check, and Clippy -D warnings with --all-targets --all-features, --lib, --lib --no-default-features and --lib --bins --features cli, and for --target x86_64-unknown-linux-gnu with --all-targets --all-features and --lib, passed on Windows. So did the 257 unit tests of host::{platform, store, snapshot} and host::cli::{snapshots, store} with --all-features, the doc test nvx-rs/src/host/snapshot/capture.rs - host::snapshot::capture::finish_capture (line 48), check_test_layout.py, check_markdown_links.py and SL5.2's matrix check.

The table and the scenarios below ran on 3d52c823, the head before the rebase, with Rust 1.95.0 and NVX_BUNDLE=skip. The checks ran locally on Windows, and in temporary worktrees on nvx-mshv-test (Azure Linux 3, kernel 6.18, linux-mshv, virtual machine) and nvx-kvm-test (Azure Linux 3, kernel 6.6, linux-kvm, virtual machine). The gates are those that local_gates.py --files selects for the change, run from this branch's actions:

Check Windows Linux
cargo fmt --all --check passed
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 passed
Clippy -D warnings for --target x86_64-unknown-linux-gnu: --all-targets --all-features, --lib, --all-targets, --lib --bins --features cli, --lib --no-default-features --features guest passed
cargo check --locked --all-targets --all-features --target aarch64-apple-darwin passed
cargo test --locked --all-features passed passed, on nvx-mshv-test: 104 suites, 2699 tests, 78 ignored
cargo test --locked passed passed, on nvx-mshv-test: 22 suites, 1295 tests, 28 ignored
cargo build --locked --lib --no-default-features, cargo test --locked --lib --no-default-features passed
RUSTDOCFLAGS=-D warnings cargo doc --locked --no-deps --all-features passed
cargo +1.89 check --locked --all-targets --all-features (MSRV) passed
python scripts/public_api.py (both snapshots) passed, unchanged
python scripts/check_test_layout.py, python scripts/check_markdown_links.py passed
The case matrix, with SL5.2's check (check_matrix.py) passed

MicroVM scenarios, with the static musl nvx-rs that CI runs, CI run 43149037772's guest artifacts (5b3fab2c, the same guest inputs) and that run's OpenVMM builds of the pin (14dc4116), with their provenance, on WHP its Windows build, 7abd8c8d, on Windows 11:

Scenarios nvx-kvm-test nvx-mshv-test WHP, locally
The public set: managed-exec-config, sandbox-lifecycle, sandbox-proxy-only, sandbox-ram-upper, sandbox-gpt-layer, vm-lifecycle, snapshot-core and snapshot-tiers passed: 8 passed: 8 passed: 8
managed-lifecycle passed passed

Left to CI: the bundled-artifact check, the guest binaries and the default suites, which this change doesn't reach beyond the scenarios above.

A code-review agent reviewed the whole diff and found no issues. It confirmed that the moved functions keep their logic, modes and messages on every platform, and that no kept snapshot or CLI code still uses host::store's file helpers.

Changes to existing tests (tests-modified)

python scripts/check_test_changes.py --base origin/feature/nvx-refactor reports 13 changes to existing tests, and 3 added tests (above). Each change only imports a moved helper from host::platform, where it imported it from host::store::files, and checks the same things as before:

  • path changes only, as the report says: the helpers SnapshotFixture::new, RestoreFixture::new and RestoreFixture::write_metadata, and the tests snapshot_open_refuses_extra_entries_and_alternate_names, snapshot_open_refuses_files_in_place_of_its_directories, snapshot_open_uses_the_strict_manifest_and_bounded_key_decoders, snapshot_open_refuses_a_key_from_another_manifest_machine, snapshot_description_contents_do_not_affect_opening, snapshot_open_refuses_a_compatible_key_with_another_capture_time and snapshot_open_refuses_captured_network_gateway_and_broadcast_addresses_as_io in host::snapshot::tests; invalid_or_linked_directories_never_publish_or_open in host::cli::snapshots::tests; and capture_helper in host::cli::snapshots::capture::tests;
  • host::snapshot::key::tests::snapshot_open_refuses_other_key_contracts_and_filesystem_tags: its function-local use crate::host::store::files::write_private; becomes use crate::host::platform::write_private;.

No removed or changed test is named in the case matrix.

@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 13 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 helper fn new in host::snapshot::tests, impl SnapshotFixture`` (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1012 nvx-rs/src/host/snapshot/tests.rs:1012
modified helper fn new in host::snapshot::tests, impl RestoreFixture`` (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1473 nvx-rs/src/host/snapshot/tests.rs:1473
modified helper fn write_metadata in host::snapshot::tests, impl RestoreFixture`` (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1550 nvx-rs/src/host/snapshot/tests.rs:1550
modified test fn capture_helper in host::cli::snapshots::capture::tests (only the paths that it names changed) nvx-rs/src/host/cli/snapshots/capture/tests.rs:696 nvx-rs/src/host/cli/snapshots/capture/tests.rs:696
modified test fn invalid_or_linked_directories_never_publish_or_open in host::cli::snapshots::tests (only the paths that it names changed) nvx-rs/src/host/cli/snapshots/tests.rs:128 nvx-rs/src/host/cli/snapshots/tests.rs:128
modified test fn snapshot_open_refuses_other_key_contracts_and_filesystem_tags in host::snapshot::key::tests nvx-rs/src/host/snapshot/key/tests.rs:750 nvx-rs/src/host/snapshot/key/tests.rs:750
modified test fn snapshot_open_refuses_extra_entries_and_alternate_names in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1099 nvx-rs/src/host/snapshot/tests.rs:1099
modified test fn snapshot_open_refuses_files_in_place_of_its_directories in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1129 nvx-rs/src/host/snapshot/tests.rs:1129
modified test fn snapshot_open_uses_the_strict_manifest_and_bounded_key_decoders in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1161 nvx-rs/src/host/snapshot/tests.rs:1161
modified test fn snapshot_open_refuses_a_key_from_another_manifest_machine in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1186 nvx-rs/src/host/snapshot/tests.rs:1186
modified test fn snapshot_description_contents_do_not_affect_opening in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1207 nvx-rs/src/host/snapshot/tests.rs:1207
modified test fn snapshot_open_refuses_a_compatible_key_with_another_capture_time in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1218 nvx-rs/src/host/snapshot/tests.rs:1218
modified test fn snapshot_open_refuses_captured_network_gateway_and_broadcast_addresses_as_io in host::snapshot::tests (only the paths that it names changed) nvx-rs/src/host/snapshot/tests.rs:1879 nvx-rs/src/host/snapshot/tests.rs:1879

Relocated unchanged: 0; added: 3. Compared the merge base a5921d0bb1bd with 5de1c96d8b0e.

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 remain for the private-file helper migration to host::platform.

No open issues 🎉

What changed in this PR

This refactor prepares for removal of the legacy sandbox store by moving private-file helpers into host::platform. Retained snapshot and CLI code uses that layer directly, without changing file behavior or the public API.

Changes:

  • Move private-file creation, atomic replacement, and directory syncing to the platform layer, keeping temporary store re-exports.
  • Update retained callers and tests to use platform helpers directly.
  • Add three platform tests and update the capture doctest’s location in the acceptance matrix.
File Description
nvx-rs/​src/​host/​store/​files.rs Re-exports moved helpers and uses platform-owned lock-file options.
nvx-rs/​src/​host/​snapshot/​tests.rs Switches snapshot fixtures and tests to platform helpers.
nvx-rs/​src/​host/​snapshot/​key/​tests.rs Updates the private-write import.
nvx-rs/​src/​host/​snapshot/​capture.rs Uses platform helpers for reads, writes, and syncing.
nvx-rs/​src/​host/​platform/​tests.rs Adds replacement, creation-refusal, and directory-sync tests.
nvx-rs/​src/​host/​platform/​mod.rs Houses and documents the moved private-file helpers.
nvx-rs/​src/​host/​cli/​store/​files.rs Routes CLI store reads, writes, and syncing through platform.
nvx-rs/​src/​host/​cli/​snapshots/​tests.rs Updates the invalid-key test’s write helper.
nvx-rs/​src/​host/​cli/​snapshots/​capture/​tests.rs Uses platform helpers in the capture fixture.
nvx-rs/​src/​host/​cli/​snapshots/​capture.rs Creates the geometry file through platform.
nvx-rs/​src/​host/​cli/​snapshots.rs Uses platform directory syncing during publication.
doc/​acceptance-case-matrix.md Updates the capture doctest line reference.

Review effort: Balanced

finish_capture, the CLI's sandbox store and the CLI's snapshots write
and sync their files with write_private, sync_dir and create_new from
host::store::files, and read through host::store::regular's aliases of
open_regular and read_at_most, so code that stays depends on the
sandbox store, which SL6.1 deletes.

Move write_private, sync_dir and create_new, with private_options and
PRIVATE_FILE_MODE, which they share with the store's lock files, to
host::platform, which already holds the host's file helpers and the
strict reads that SL6.0a moved there. The store re-exports
create_new and write_private for its own files until SL6.1 deletes
it, and its open_lock takes the moved options and mode; nothing in it
syncs a directory through sync_dir since the template store and the
old clone path left. finish_capture, the CLI's sandbox store,
snapshot store and capture, and their tests use host::platform
directly, also for open_regular and read_at_most. Nothing else
changes: a private file is still created with mode 0600 on Unix
without following a link, replaced through a temporary file that a
failure removes, and its directory synced on Unix alone, with the
same messages.

New platform tests pin the moved helpers: a private write replaces its
file whole, with mode 0600 on Unix, and a failed one leaves no
temporary file; a new private file never takes the place of an
existing entry, nor follows a link on Unix; and a directory sync fails
for a missing directory on Unix alone. The snapshot and CLI snapshot
tests change only their imports.

Part of #1120 (SL6.0d).

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 reported for the private-file helper relocation to the platform layer.

No open issues 🎉

Review effort: Balanced

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