Skip to content

nvx-rs slimming 1.1.3: the guest's and the host's OS layers live in nvx-sys #1093

Closed as not planned

Description

Parent: #1077, in #1076. Needs: #1092. Unblocks: #1094, #1095, #1096, #1097, #1099, #1104, #1106, #1108, #1120, #1132.

Goal. The OS layers that nvx and NVX's other crates share move into nvx-sys, by git mv: the old error type, the guest's sys, parse, status and kernel_text, and the host's sys and the low-level parts of platform (common, Linux, Windows, and the fallback for unsupported hosts). nvx aliases the old paths, so its callers don't change, and keeps its public facades, such as Transport and probe_hypervisor. Six PRs keep each move dependency-closed. The OS layers have 687 pub(crate) lines; only the items that nvx uses across the new boundary, and the host items that the cli feature gated, become public.

Notes.

  • nvx-sys is published before nvx, with no stability guarantee. The owners publish its first version by hand, then add its trusted publisher.
  • nvx-sys uses nothing from nvx. The links back are cut as the code moves: comments, LaunchStage, Command, Hypervisor and FileSeal. nvx-sys has no cli feature, so the items that it gated become public.
  • The host OS layer moves after nvx-rs: move the host modules' tests out of their sources #1197. SL0.3c and SL0.3d edit nvx-rs/src/host/, which nvx-rs: move the host modules' tests out of their sources #1197 edits too as it moves the host modules' tests out of their sources, so they start from, or rebase onto, a dev that contains it. The PRs before them don't touch the host. The guest OS layer's tests and test helpers are already in tests modules (nvx-rs: move the guest modules' tests out of their sources #1196): each module moves with its tests.rs or tests/, and the helpers that guest::sys::tests shares with nvx's tests move behind nvx-sys's test-support feature.

PRs, in order. Each PR has one goal, leaves dev green, and names in its description each old test of its area as kept, rewritten or retired, with each change that check_test_changes.py reports. Its tests follow the repository's test layout: a module's unit tests, and the code that only they use, sit in its tests.rs or tests/ and move with it. The estimates count core lines (code, not comments, docs or tests) and counted files; each PR records its measured values. Each PR does what its Scope says and no more: a case, input or layout that its Scope doesn't name, and whatever "Not in this PR" lists, is out of scope. Address every review comment within the scope, and ask before acting on one that asks for more. A PR whose measured core lines pass the stop that its Estimate names (twice the estimate, at most 600) stops and asks before continuing.

  1. SL0.3a1: The old error type lives in nvx-sys.

    • Objective: The shared error type must be available to nvx-sys before the OS modules move there. Moving it first lets nvx depend on and re-export the new crate without changing callers, while publishing places nvx-sys before its dependent.
    • Contents: git mv of error.rs, which nvx re-exports until SL6.8c, so callers don't change; nvx depends on nvx-sys, which the publishing list now publishes before it; the owners publish its first version by hand, then add its trusted publisher. The README's error table and its test follow.
    • Scope:
      • git mv of nvx-rs/src/error.rs and nvx-rs/src/error/tests.rs to crates/nvx-sys/src/error.rs and crates/nvx-sys/src/error/tests.rs, plus the module wiring and visibility edits the crate boundary requires.
      • nvx depends on nvx-sys and re-exports Error, ErrorCode, ErrorKind and Result at their existing paths until SL6.8c.
      • The publisher's ordered crate list places nvx-sys before nvx; owners publish its first version from the final reviewed source and configure its trusted publisher before the PR is marked ready or queued. This is a promotion prerequisite, not a local-build, draft-review or completion-CI prerequisite, and does not authorize publication by the implementation worker.
      • The ErrorKind and error-code tables move from nvx-rs/README.md to crates/nvx-sys/README.md with the existing table test; nvx documentation links to their new owner, and repository links and checks follow it.
      • The protocol-only adapter still depends directly on nvx without features. Its expected graph now includes nvx-sys and that crate's existing Unix dependencies, including nix; update the dependency assertions and documentation without enabling nvx features or adding a new nix feature gate.
    • Not in this PR:
      • Changing error variants, codes, messages, conversions or formatting: this PR moves the existing type.
      • Replacing the crate-wide error with domain errors: SL2.1 and SL6.8c perform that API redesign.
      • Moving any guest, host or time OS module: later PRs in this group move those dependency-closed slices.
      • General publishing redesign beyond adding nvx-sys to the existing order: nvx-rs slimming 1.1.1: the public API is checked, and NVX's programs are hidden from it #1091 supplies workspace publishing.
    • Approach: Move the existing file intact, expose only what its new crate and the existing nvx re-export require, and point nvx at it. Reuse the workspace publisher's ordered crate list; do not introduce a second error implementation, compatibility wrapper or publishing path.
    • Done when:
      • The moved error tests pass in nvx-sys, and nvx re-exports Error, ErrorCode, ErrorKind and Result at their existing paths.
      • The moved README error-table check reads the canonical tables in nvx-sys's own README, so the crate's tests remain independently packageable; nvx documentation links to that location.
      • The protocol-only dependency checks explicitly verify the adapter's nvx dependency, nvx's nvx-sys dependency and the absence of nvx features, with the expected Unix shared-OS dependencies accounted for.
      • Publishing plans nvx-sys before nvx; owners complete the first nvx-sys publication and trusted-publisher setup before ready/queue promotion.
    • Needs: SL0.2a, in nvx-rs slimming 1.1.2: one Cargo workspace, and the new crates' empty shells #1092.
    • Estimate: 50 core lines, 4 counted files. Past 100 core lines, stop and ask before continuing.
  2. SL0.3a0: The guest's descriptor primitives live in nvx-sys.

    • Objective: Most guest OS modules depend on the descriptor and socket primitives, so those primitives must cross the crate boundary first. After this move, later guest slices can depend only on code already in nvx-sys, while existing nvx modules keep their old local paths.
    • Contents: git mv of guest::sys::{fd, socket}, which most of the other OS modules use, with nvx-sys's module and re-export spine; nvx aliases the old paths. Their apparent links back to guest::spawn are comments. The descriptor code's real dependency on kernel::NULL_DEVICE is cut by moving that one constant's definition into fd and re-exporting it from its old kernel path; the rest of kernel stays for SL0.3a2. EntryChild and LaunchStage stay out of this slice.
    • Scope:
      • git mv of nvx-rs/src/guest/sys/fd.rs and socket.rs into the guest OS module under crates/nvx-sys/src/.
      • The nvx-sys guest module and re-export spine needed by these two files, with nvx aliases for their former guest::sys paths.
      • Only import, module-path and visibility edits forced by the new crate boundary.
      • Move the single NULL_DEVICE definition and its documentation into fd; nvx's kernel re-exports it, so existing callers keep their paths. Do not duplicate the constant or move the rest of the kernel module.
      • fd/tests.rs and socket/tests.rs move with their modules. The helpers in fd/tests.rs become fd/test_support.rs, behind nvx-sys's test-support feature, rather than exposing a cfg(test) module across crates. The socket tests keep their three cases; create_fifo, set_descriptor_limit and is_sealed_immutable remain available to nvx tests through its versioned nvx-sys development dependency.
      • Minimal wiring in the existing guest-binary musl check and its command-selection tests retains the moved socket tests and linting on musl as well as the Linux workspace. Keep the existing nvx guest checks; do not replace or weaken them.
    • Not in this PR:
      • guest::sys::entry, guest::sys::spawn, EntryChild or LaunchStage: their real higher-level dependencies keep them for SL0.3b.
      • Moving other guest::sys modules, even when they use descriptors: SL0.3a2 moves that dependency-closed set.
      • Changing descriptor ownership, buffering, socket semantics or error handling: no caller needs new behavior.
      • Renaming types, functions or modules, except the specified test-helper file change, or cleaning up their APIs and documentation beyond path fixes.
    • Approach: Use git mv, preserve the two files' implementation and tests, and add the smallest module and alias wiring that makes both crates compile. Treat references to guest::spawn in comments as documentation fixes, not dependencies; do not extract a descriptor abstraction or redesign the wrappers.
    • Done when:
      • The socket tests still cover unconnected datagrams, inherited IPv4 datagram descriptors and an address already in use.
      • Those socket tests run through the existing local/CI guest musl gate as well as the Linux workspace; moving crates does not drop that coverage.
      • NULL_DEVICE has one definition, and retained kernel callers continue through their old path.
      • nvx code using the old local guest OS paths compiles without caller edits.
    • Needs: SL0.3a1, above.
    • Estimate: 100 core lines, about 11 counted files including the module spine and musl gate wiring. Past 200 core lines, stop and ask before continuing.
  3. SL0.3a2: The guest's base OS helpers live in nvx-sys.

    • Objective: The dependency-closed base of the guest OS layer must move behind nvx-sys before entry and spawn can follow. The move preserves existing guest behavior and paths while exposing only the items that nvx must use across the new crate boundary.
    • Contents: git mv of guest::{parse, status, kernel_text} and of the other guest::sys modules but entry and spawn (clock, discipline, filesystem, ioctl, kernel, mapping, msr, poll, port, process, rooted, scheduler, secret, signal, sock_diag, terminal, timer and x86), which fd makes dependency-closed. The port and signal tests that use guest::spawn::Command, guest::process::Child or the managed agent's isolate_process_test move to nvx, beside those owners, or are rewritten on nvx-sys's own helpers. Their pub(crate) and pub(super) items that nvx uses become pub; nvx aliases the old paths, so callers don't change. Test helpers that cross the new boundary sit behind nvx-sys's test-support feature, used as a dev-dependency, or the tests move to the owner of the higher-level behavior; no cfg(test) item crosses a crate. They carry what dev added to them since the baseline: signals through a pidfd or to a process group, the rooted open's retry of openat2's EAGAIN, and the clock discipline's held host correction.
    • Scope:
      • git mv of guest::{parse,status,kernel_text} and guest::sys::{clock,discipline,filesystem,ioctl,kernel,mapping,msr,poll,port,process,rooted,scheduler,secret,signal,sock_diag,terminal,timer,x86} into crates/nvx-sys/src/.
      • nvx aliases the former guest paths; only cross-crate users change imports, and only their required pub(crate) or pub(super) items become public.
      • The parent-level args, c_string and errno_of definitions follow their moved consumers into nvx-sys, with aliases at their old nvx paths; the existing errno_of test follows its definition.
      • The existing tests.rs files under the listed module paths move with their owners, except higher-level port and signal tests using guest::spawn::Command, guest::process::Child or the managed agent's isolator; those stay in nvx or use nvx-sys helpers.
      • Only helpers shared by moved code and retained nvx tests cross into nvx-sys behind test-support: process isolation and status, path and umask helpers, signal helpers, diagnostic encoders and PortBackend, including shared status-command-line and child-process fixtures. Helpers with no moved consumer, such as Failing, stay with their existing nvx owner. Tests using the helpers inside nvx-sys retain access without requiring a downstream test build.
      • The moved behavior includes pidfd and process-group signals, openat2 EAGAIN retries, and held host-clock correction.
    • Not in this PR:
      • guest::sys::{entry,spawn}: SL0.3b first cuts their dependencies on LaunchStage and Command.
      • Rewriting port, signal or process tests around a new general test framework: move them to their behavior's owner or use the existing low-level helpers.
      • Making the whole guest OS layer public: only existing cross-crate uses and declared test support cross the boundary.
      • Behavior changes, type or function renames, parser redesigns, portability work or cleanup unrelated to the move.
    • Approach: Move the listed modules in place and preserve their implementations. Fix module paths and raise visibility item by item from actual nvx compile errors. Keep higher-level tests beside their owners, and expose narrowly reusable test helpers through test-support; do not create a new OS facade, parser or test harness.
    • Done when:
      • Every old test in the moved modules is recorded as moved, rewritten or retained in nvx, with port and signal tests kept beside any higher-level dependency they exercise.
      • Tests cover pidfd and process-group signaling, rooted-open retry after EAGAIN, and held host-clock correction.
      • nvx compiles through aliases at the old guest paths, and no cfg(test) item crosses the crate boundary.
    • Needs: SL0.3a0, above.
    • Sizing: The initial estimate was 250 core lines and 5 counted files. Current preparation projects about 600-680 core lines and 25-30 counted files, including necessary visibility and shared test-support wiring. These are advisory targets, not correctness or approval gates. Measure and explain the actual cohesive move; do not reduce coverage, code-golf or reslice solely to satisfy a numeric threshold.
  4. SL0.3b: The whole guest OS layer lives in nvx-sys.

    • Objective: The final guest OS modules cannot move while they name nvx launch types. Cutting those links and moving entry and spawn completes the guest OS layer in nvx-sys, with no dependency back from nvx-sys to nvx.
    • Contents: git mv of guest::sys::{entry, spawn}. Their links back to guest::{entry, spawn} (LaunchStage, Command) are cut, so nvx-sys uses nothing from nvx. The spawn tests that use the managed agent's isolate_process_test move to nvx, beside that owner, or are rewritten on nvx-sys's own subprocess helper.
    • Scope:
      • git mv of entry.rs, entry/tests.rs, spawn.rs and spawn/tests.rs into the guest OS module under crates/nvx-sys/src/, and move both production files' allowlist seam entries to their new paths.
      • Replace their dependencies on guest::spawn::LaunchStage and guest::spawn::Command with low-level inputs and results owned by nvx-sys; the nvx layer adapts them.
      • Only import, visibility and alias edits required to keep existing nvx callers at their old paths.
      • Simulation, the capability constants and holds_capability move behind nvx-sys's test-support feature for retained nvx tests; spawn tests using the managed agent's isolator stay in nvx beside that owner or use an nvx-sys subprocess helper.
    • Not in this PR:
      • Redesigning the public guest Command, LaunchStage or spawn APIs: they stay owned by nvx.
      • Changing child setup order, credentials, working directories, mount behavior, descriptor inheritance or failure reporting.
      • Building a reusable process framework or a general subprocess-test library: only the existing tests need isolation.
      • Moving guest modules outside entry and spawn: SL0.3a0 and SL0.3a2 own those moves.
    • Approach: Separate the low-level child operations from the nvx types at the existing call boundary, then move both files with git mv. Add only narrow adapters in nvx, and keep test isolation local to the crate that owns each test; do not redesign spawning or duplicate the implementation.
    • Done when:
      • The entry and spawn tests retain today's child setup, execution and failure-stage behavior.
      • Tests that require the managed agent's isolator remain in nvx or run through a local nvx-sys subprocess helper.
      • Neither normal nor test code in nvx-sys imports nvx, and existing nvx guest callers keep their paths.
    • Needs: SL0.3a2, above.
    • Estimate: 300 core lines, 4 counted files. Past 600 core lines, stop and ask before continuing.
  5. SL0.3c: The host's OS helpers live in nvx-sys, on Linux.

    • Objective: The host's common, Linux and unsupported-host primitives must be shared without moving nvx's public host facades. After this move, nvx-sys owns the low-level host operations, while Transport, its stream wrappers and probe_hypervisor remain available from nvx.
    • Contents: git mv of host::sys, and of host::platform's common, Linux and unsupported-host parts (inherit, other, and the linux directory: mod, endpoint, identity, log_claim, private, process and spawn, with its tests). Transport, its implementations for the platform's streams (as wrappers over public low-level stream operations) and probe_hypervisor stay in nvx; the links back (Hypervisor, and FileSeal, its test use included) are cut. Their cfg(feature = "cli") gates go: nvx-sys has no cli feature, and the items it gated become public. The read counters and the spawn's umask rule, which dev added, move with them.
    • Scope:
      • git mv of host/sys and host/platform/{inherit,other,linux} into nvx-sys, splitting host/platform/mod.rs so that Transport, probe_hypervisor, their wrapper tests and host/platform/tests.rs stay in nvx; host/sys/tests.rs, host/sys/process/tests.rs and the Linux platform's tests.rs files move.
      • Expose the spawn-descriptor, umask, identity, ownership and store-directory helpers that retained nvx tests use through nvx-sys's test-support feature; cut Hypervisor and FileSeal links, keeping or rewriting the FileSeal-dependent test in nvx.
      • Transport, Linux stream implementations as nvx wrappers over public low-level stream operations, and probe_hypervisor stay in nvx.
      • Remove cfg(feature = "cli") from moved items and make those items public because nvx-sys has no cli feature.
      • Preserve Linux read counters, restore-ready socket permissions under restrictive umasks, and the unsupported-host implementation.
    • Not in this PR:
      • Moving the Windows platform directory: SL0.3d moves and tests that platform separately.
      • Moving or redesigning Transport, probe_hypervisor, Hypervisor or FileSeal: they are nvx facades and types.
      • Adding support for another host platform: Linux and Windows are supported, and the existing fallback reports other hosts unavailable.
      • Changing process, endpoint, identity, log-claim or spawn behavior, or cleaning up their APIs beyond forced boundary edits.
    • Approach: Move the existing common, Linux and fallback files with git mv. Extract only the low-level stream operations needed by thin nvx Transport wrappers, replace Hypervisor and FileSeal links with primitive inputs, and remove obsolete feature gates; do not create a new transport hierarchy or platform abstraction.
    • Done when:
      • Existing low-level and retained higher-level tests still cover wait timing, restore-ready socket permissions under a restrictive umask, closed-before-accept behavior, unread transport counts, process read counters and log-claim identity checks.
      • The FileSeal-dependent test remains with nvx or is rewritten without crossing the crate boundary.
      • Transport and probe_hypervisor remain at their existing nvx paths, and unsupported hosts still compile and report unavailable.
      • The moved host code has no cli feature gates and no dependency on nvx.
    • Needs: SL0.3a1, above.
    • Estimate: 300 core lines, 5 counted files. Past 600 core lines, stop and ask before continuing.
  6. SL0.3d: The host's OS helpers live in nvx-sys, on Windows.

    • Objective: Windows needs the same host OS ownership as Linux without broadening the move into a platform redesign. The Windows primitives and their low-level tests move to nvx-sys, while higher-level tests stay with their owners and nvx retains its existing public facades.
    • Contents: git mv of the Windows part of host::platform, now the windows directory (about 1.9K core lines in eight files, and 65 pub(crate) items). Its cfg(feature = "cli") gates go, as in SL0.3c. CI's Windows jobs run nvx-sys's tests. It carries the per-log job objects and the log claim's identity checks that dev added.
    • Scope:
      • git mv of the Windows endpoint, identity, interrupt, log_claim, private, process, spawn and module files, with windows/tests.rs and windows/private/tests.rs, into crates/nvx-sys/src/; supervisor and store tests stay in nvx and use set_access through nvx-sys's test-support feature.
      • Remove the moved code's cfg(feature = "cli") gates and make the formerly gated items public for existing cross-crate callers.
      • Preserve per-log job objects, log-claim identity checks, named-pipe operations, process identity and handle inheritance behavior.
      • Update Windows CI jobs to run nvx-sys tests, and move the allowlist seam entry for host/platform/windows/spawn.rs to its new path.
    • Not in this PR:
      • Redesigning Windows process launch, job ownership, named pipes, security descriptors or handle inheritance: this is a move.
      • Changing Transport or probe_hypervisor, which remain nvx facades over the moved primitives.
      • Adding Windows behavior not present in the moved modules or making Linux and Windows implementations structurally identical.
      • Renaming public or private items, reorganizing the Windows directory further, or performing unrelated cleanup.
    • Approach: Move the Windows files and low-level tests together, keeping higher-level tests beside their owners. Adjust imports and visibility only where the crate boundary requires it, and remove feature gates that the destination crate cannot express. Keep the existing operating-system calls and test fixtures; do not wrap them in a new cross-platform framework.
    • Done when:
      • nvx-sys and retained nvx Windows tests together cover endpoint I/O, process identity, spawn handle inheritance and per-log job-object lifetime.
      • Log-claim tests still reject a changed file identity and track the job associated with the opened log.
      • Windows CI builds and runs the nvx-sys test target.
      • Existing nvx host callers continue through their current facades without behavior changes.
    • Needs: SL0.3c, above.
    • Estimate: 200 core lines, 5 counted files. Past 400 core lines, stop and ask before continuing.

Tests. Each PR keeps, rewrites or retires the tests of its area, by name; tests move with a module that owns their behavior. A test that uses code staying in nvx doesn't move with its module: the port and signal tests that use guest::spawn::Command, guest::process::Child or the managed agent's isolate_process_test move to nvx or are rewritten on nvx-sys's own helpers, and so do the spawn tests that use the agent's isolate_process_test; the platform test that uses FileSeal moves to nvx, beside the seal, or is rewritten without it; and the tests of Transport's implementations test nvx's wrappers. Test helpers that cross the new boundary sit behind nvx-sys's test-support feature, used as a dev-dependency; no cfg(test) item crosses a crate. CI's Windows jobs run nvx-sys's tests. The README's error table and its test follow the error type.

Done when: every PR above has merged, with dev green.

Activity

  1. esaurez commented on Nov 3, 2026

    @esaurez
    ContributorAuthor

    Closing as not planned: the plan in #1076 changed. nvx stays the only crate, with no Cargo workspace and no new crates. NVX's own programs, its control protocol and the OS layers stay in nvx, private to it, and CI checks the public API against committed snapshots (#1091). The guest's and the host's OS layers stay where they are, private to nvx. Their one public part, host::platform, becomes private in #1127.

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

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions