Skip to content

nvx-rs slimming 4.3.4: NVXC, the host's platform layer and the guest's space are private #1127

Closed

Description

Parent: #1088, in #1076. Needs: #1105, #1121, #1123. Unblocks: #1128, #1130, #1131, #1132. No PR of this group merges before the API-ready commit.

Goal. NVXC, the host's platform layer and the guest's space become private where they are. Every NVXC item that protocol re-exports (the frames and their constants, the refusal categories, the EXEC payloads with their codecs, flags and limits, and GuestFeatures) and host::session become crate-private and gated by cli, guest or testing, before v2. host::platform becomes crate-private after its outside users are gone. guest::{root, view, gpt}, the mapper and the apply family become crate-private and guest-gated; the snapshot and public docs stop using the space. MappingTable and the mapping values stay public.

Notes.

  • Integration tests follow visibility. NVXC, platform and space tests that reached public paths become unit tests of their owners or drive a binary.
  • The fake OpenVMM stays hidden. testing::fake_openvmm has only its hidden main public.

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. SL6.12: NVXC is private.

    • Objective: NVXC is NVX's own control protocol: only the CLI, nvx-init, the managed agent and the fake OpenVMM speak it, but its frames, payloads and host session are public API of nvx. Once the old stores and the test adapter are gone, this PR makes it crate-private where it is, before v2 changes it.
    • Contents: NVXC becomes crate-private where it is, gated by the features of its users (cli, guest and testing): every re-export of the protocol root from app, exec and features (the frames: AppFrame, encode_app, decode_app and the APP_* constants; the refusal categories BUSY, CWD_FAILED, INVALID_REQUEST, LAUNCH_FAILED, MAPPING_FAILED, MAPPINGS_INCOMPLETE and UNSUPPORTED_OPERATION, and ExitCategory; the EXEC payloads Workload, WorkloadEnvironment, ExecPayload and GuestExecPayload, with their codecs, their EXEC_* flags and their limits MAX_ARGUMENTS, MAX_ARGUMENT_BYTES, MAX_CWD_BYTES, MAX_GUEST_CWD_BYTES, MAX_ENVIRONMENT, MAX_OUTPUT_BYTES and MAX_TIMEOUT_MS; GuestFeatures), and host::session (ControlSession with send_request and read_response, ExecEvent, and what remains of SessionError and connect), which becomes a private module. protocol::maps, with its own limits, NVXS and the outer records stay public, and protocol's module docs stop presenting NVXC as its public content. The integration tests that use NVXC's items (tests/managed_lifecycle.rs, if the case matrix kept it, and the fake OpenVMM's tests that build EXEC payloads) become unit tests of their owners, or drive a binary. It comes before v2, so v2 is crate-private from its first line.
    • Scope:
      • Every re-export of the protocol root from app and features becomes pub(crate): AppFrame, encode_app, decode_app, every APP_* constant, the refusal categories (BUSY, CWD_FAILED, INVALID_REQUEST, LAUNCH_FAILED, MAPPING_FAILED, MAPPINGS_INCOMPLETE, UNSUPPORTED_OPERATION), ExitCategory and GuestFeatures.
      • So does every re-export from exec: the EXEC payloads and their codecs, the EXEC_* flags, and the limits MAX_ARGUMENTS, MAX_ARGUMENT_BYTES, MAX_CWD_BYTES, MAX_GUEST_CWD_BYTES, MAX_ENVIRONMENT, MAX_OUTPUT_BYTES and MAX_TIMEOUT_MS; the mapping table's limits stay public.
      • host::session becomes a private module: ControlSession with send_request and read_response, ExecEvent, and what remains of SessionError and connect.
      • Each item is gated by the features of the code that uses it (cli, guest or testing), so that no feature set builds unused code.
      • The integration tests that use NVXC's items become unit tests of their owners, or drive a binary, asserting the same behavior.
      • The API snapshot drops the NVXC items, and protocol's module docs stop presenting frames, EXEC payloads and guest features as its public content.
    • Not in this PR:
      • Changing NVXC's frames, payloads, wire values or session behavior: the next protocol version comes in its own PRs.
      • Making the mapping table's codec, NVXS, the outer records, the root, view, export and share codecs, or MAPS_TOKEN private: every init reads them.
      • Moving NVXC into another module or file: it stays where it is.
      • Deleting v1 or FEATURES: a later PR deletes them.
    • Approach: Narrow the visibility of the re-exports and of host::session, then follow the compiler: gate what a feature set leaves unused, and move each integration test that reaches NVXC's internals into its owner's tests module. Regenerate the API snapshot, and check that its diff removes only NVXC items.
    • Done when:
      • NVXC's frame, payload and session tests pass unchanged where they now live.
      • Every feature set that CI builds passes without warnings.
      • The API snapshot lists no item from protocol::{app, exec, features}, constants included, and no host session item; NVXS, the outer records and the mapping table stay listed.
    • Needs: SL6.1, in nvx-rs slimming 4.2.2: the old clone path, template store and sandbox store are gone #1121.
    • Estimate: 0 core lines (visibility), no counted files.
  2. SL6.14: The host's platform layer is private.

    • Objective: host::platform is the host's OS layer, which the library and the CLI use, but it is a public module of nvx. Its public parts moved to host::vm, host::transport and host::runtime with the new interface, and its last outside users are gone, so this PR makes it crate-private where it is.
    • Contents: host::platform becomes a crate-private module where it is: SUPPORTED, create_private_dir, file_identity, process_start_time and any alias that phase 2 left for Transport or probe_hypervisor become pub(crate). Its outside users are gone: the test adapter (SL5.2), the stores' tests (SL6.1) and the NVXC tests (SL6.12); an integration test that still uses it becomes a unit test of its owner. host::vm::create_private_dir, host::transport and host::runtime keep the public forms.
    • Scope:
      • host::platform becomes a private module, and its items (SUPPORTED, create_private_dir, file_identity, process_start_time, and any alias that remains of Transport or probe_hypervisor) become pub(crate).
      • Code that used the old public paths uses the crate paths.
      • An integration test that still uses the platform layer becomes a unit test of its owner, asserting the same thing.
      • The API snapshot drops host::platform.
    • Not in this PR:
      • Changing the platform layer's behavior, or moving or splitting its files.
      • Changing the public forms in host::vm, host::transport or host::runtime.
      • Making other host modules private: their own PRs do that.
    • Approach: Make the module private, change its pub items to pub(crate) as the unreachable_pub lint asks, and follow the compiler. Regenerate the API snapshot, and check that its diff removes only host::platform's items.
    • Done when:
      • The platform layer's tests pass unchanged on Linux and Windows.
      • The API snapshot has no host::platform item on either platform.
      • Every feature set that CI builds passes without warnings.
    • Needs: SL6.12, above.
    • Estimate: 0 core lines (visibility), no counted files.
  3. SL6.13b: The guest's space is private.

    • Objective: The guest's root assembly, view, mapper, GPT helper and activation application are nvx-init's internal reference implementation, not shared library APIs. This PR makes that space private where it is, while leaving the mapping account and values public and removing space use from snapshot and activation documentation.
    • Contents: guest::{root, view, gpt}, the mapper (guest::mappings::mapper with its kernel seam) and the activation's apply family (apply, Applied, RootTemplate, ApplyError, AppliedTeardownError, NetworkError) become crate-private and guest-gated where they are; nvx-init and the managed agent use them there. The docs and examples of snapshot and activation stop using the space and say it is nvx-init's internal reference code. Paths and window_directories stay where they are; the snapshot can use crate-private items. guest::mappings' values and MappingTable stay public. The API snapshot drops the space.
    • Scope:
      • guest::{root, view, gpt} become crate-private and guest-gated where they are.
      • guest::mappings::mapper, including its kernel seam, becomes crate-private; guest::mappings' values and MappingTable stay public.
      • The activation apply family (apply, Applied, RootTemplate, ApplyError, AppliedTeardownError, NetworkError) becomes crate-private and guest-gated.
      • nvx-init and the managed agent continue to use the space at its existing paths.
      • Snapshot and activation docs and examples stop using the space and describe it as nvx-init's internal reference code.
    • Not in this PR:
      • Changing root assembly, overlay, runtime mount, view, mapping, network or activation behavior.
      • Moving or renaming the space modules, Paths or window_directories.
      • Making MappingTable or mapping values private: other space implementations consume those public values.
      • Adding a public space trait, plugin interface or second reference implementation.
      • Cleaning up privileged code or broadening supported roots, filesystems, devices or platforms.
    • Approach: Narrow the existing space modules and apply family to crate visibility, retain their guest gates, and update internal imports directly. Keep the mapper split from the public mapping account at its existing seam. Remove space use from snapshot and activation docs and examples, regenerate the API snapshot, and do not move shared path lookups.
    • Done when:
      • Root assembly, view, mapper, GPT and activation-apply unit tests pass at their existing owners.
      • nvx-init handles EROFS and GPT roots, uppers, views, exports, mappings and restore activation as before.
      • Snapshot and activation docs and examples compile without using the private space.
      • The API snapshot lists no space implementation and still lists MappingTable and the mapping values.
    • Needs: SL6.11b, in nvx-rs slimming 4.2.4: the exec engine, the process modules and the old layered init are gone #1123; SL7.4b, in nvx-rs slimming 2.4.2: activation holds no fence, and a capture is one guest call #1105.
    • Estimate: 0 core lines (visibility), no counted files.

Tests. NVXC's codec and session tests pass in their owner modules; the fake OpenVMM's cases still drive its binary. Platform tests pass on Linux and Windows. The space's unit and privileged tests stay with it. Docs and examples of snapshot and activation compile without the space. Every feature set builds without warnings, and the API snapshot lists none of NVXC, host::platform or the space.

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

Activity

  1. changed the title [-]nvx-rs slimming 4.3.4: the fake VMM, NVXC and the guest's space live in their crates[/-] [+]nvx-rs slimming 4.3.4: NVXC, the host's platform layer and the guest's space are private[/+] on Nov 3, 2026
  2. esaurez commented on Nov 10, 2026

    @esaurez
    ContributorAuthor

    Workstream source/progress checkpoint - 2026-11-10 UTC

    Checked boxes below mean merged scope, not merely an implemented first iteration. Implementation branches are source checkpoints, not automatic qualification, Ready or merge approval. Some starting inputs are frozen/anonymous commits rather than standalone branches; their exact SHAs and known merged producer refs are recorded explicitly.

    • SL6.12 - no completed first-iteration handoff recorded. Inspect any preserved partial/prior work before implementing the issue's scope.

    • SL6.13b - no completed first-iteration handoff recorded. Inspect any preserved partial/prior work before implementing the issue's scope.

    • SL6.14 - no completed first-iteration handoff recorded. Inspect any preserved partial/prior work before implementing the issue's scope.

    The original technical scope remains authoritative, supplemented only by any portable technical clarification in this issue. No machine-specific execution policy is part of this checkpoint.

  3. 28 remaining items

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

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions