Skip to content

nvx-rs slimming 4.3.1: image staging, artifact discovery, the policy-file reader and the mount syntax are private to the CLI #1124

Closed

Description

Parent: #1088, in #1076. Needs: #1098, #1122. Unblocks: #1125, #1126, #1131. No PR of this group merges before the API-ready commit.

Goal. Image staging and artifact discovery become crate-private and cli-gated where they are: host::seal, host::sandbox::{distro, scratch, layer} and host::artifacts, including discovery, Guest and the scratch template's inventory, with the crate root's Artifacts. The policy-file reader first builds public rule values, then it and the --mount syntax become crate-private and cli-gated where they are, and the host::sandbox and host::network::policy modules become crate-private with what remains in them. NVX_OPENVMM and NVX_AUTO_DOWNLOAD keep their meaning, and shared normalization stays public.

Notes.

  • Privatizing counts as a move. Visibility, feature gates, the API snapshot and forced imports have no core lines and no counted file.
  • Integration tests follow visibility. tests/cli.rs, tests/cli/{artifacts, formats, lifecycle}.rs, the policy and mount tests, and any remaining checked-transfer or fake-backed use become unit tests or drive a binary, with the same assertions.

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.4: Image staging and artifact discovery are private to the CLI.

    • Objective: Image staging and artifact discovery are CLI-owned behavior, but their seals, bindings, checked files, artifact inventory and discovery rules are public API of nvx. This PR makes that implementation private to the CLI where it is, without changing image formats, discovery precedence, environment variables, checks or launch behavior.
    • Contents: host::seal, host::sandbox::{distro, scratch, layer} and host::artifacts become crate-private and cli-gated where they are: FileSeal; DistroBinding and the distro policy (PolicyVerdict, PolicyResult, DISTRO_POLICY_REVISION); ScratchBinding and its claim; the checked files CheckedDistro and CheckedScratch; discovery, ArtifactDir, Guest and the scratch template's inventory (Guest::scratch_template_name); and the re-exports that would keep some of them public: the crate root's Artifacts, and host::sandbox's LAYER_ROLES, LayerRole and SandboxLayer. NVX_OPENVMM and NVX_AUTO_DOWNLOAD keep their meaning. The root description keeps the image format and the expected UUID or GUID. The integration tests that use these items become unit tests of their owners or drive the binary, asserting the same behavior. The API snapshot drops the items.
    • Scope:
      • host::seal and host::sandbox::{distro, scratch, layer} become crate-private and cli-gated with their implementations and unit tests, and host::sandbox stops re-exporting LAYER_ROLES, LayerRole and SandboxLayer.
      • host::artifacts discovery, ArtifactDir, Guest and Guest::scratch_template_name become crate-private and cli-gated where they are, and the crate root stops re-exporting Artifacts.
      • The root description continues to own the EROFS or GPT format and the expected filesystem UUID or disk GUID.
      • Repository and release layouts, explicit artifact variables, executable-directory discovery, NVX_OPENVMM and NVX_AUTO_DOWNLOAD keep their current behavior.
      • Integration tests that reach these internals become unit tests of their owners or test through the binary, preserving the same cases.
    • Not in this PR:
      • Image-format, sealing, policy, scratch-claim, artifact-discovery or download behavior changes: this PR only narrows visibility and feature gates.
      • Moving the helpers under host::cli, splitting mixed helpers or adding alias modules.
      • Changing path-only block-device launch behavior or restoring descriptor transfer: those are separate launch decisions.
      • Reworking downloads, installation, archives, GitHub access or update history.
    • Approach: Narrow the modules and items in place, keep them behind cli, and follow the compiler to adjust internal imports. Move each integration-test case beside its owner or drive the CLI binary when behavior crosses modules. Preserve the existing discovery order and image logic, then regenerate the API snapshot and check that its diff removes only these helpers.
    • Done when:
      • Seal, distro, scratch, layer and artifact-discovery tests cover the same successful and refused cases where they now live.
      • The guest artifact inventory includes the same kernel, initramfs, distro files and scratch template for the supported guests.
      • The artifact command still honors NVX_OPENVMM, and download tests still honor NVX_AUTO_DOWNLOAD.
      • The API snapshot lists none of the private image-staging or artifact-discovery items under any path, nvx::Artifacts included.
    • Needs: SL6.3, in nvx-rs slimming 4.2.3: the old configs, the old launch code and bundled are gone #1122; SL6.6a, in nvx-rs slimming 4.2.3: the old configs, the old launch code and bundled are gone #1122.
    • Estimate: 0 core lines (visibility), no counted files.
  2. SL6.7a: The policy-file reader builds public rules.

    • Objective: The policy-file reader currently reaches private network lowering details, which prevents it from becoming private to the CLI cleanly. This PR makes it construct the public rule model and compile through NetworkPolicy::native_egress_rules, preserving the existing JSON language and native output.
    • Contents: The egress compiler parses each JSON rule into the public EgressRule, Destination and PortSelector values, and compiles them through NetworkPolicy::native_egress_rules; it no longer uses address or lowering. Its tests check the same compiled rules.
    • Scope:
      • host::network::policy parses every existing JSON rule into EgressRule, Destination and PortSelector values.
      • The reader builds a NetworkPolicy and obtains allow and deny native rules through NetworkPolicy::native_egress_rules.
      • The existing flat and MXC rule forms, IPv4 and IPv6 destinations, CIDR exclusions, protocol selectors and port ranges remain supported.
      • The current file-size, nesting, rule-budget and native-rule-budget limits remain unchanged.
      • Grammar, model and property tests compare the same compiled native allow and deny rules through the public values.
    • Not in this PR:
      • Making the reader private to the CLI: the following PR narrows its visibility after this dependency change.
      • Changing the policy-file grammar, accepted protocols, limits, diagnostics or canonicalization: existing files must compile the same way.
      • Making address or lowering public, or changing shared normalization: no caller needs either.
      • Adding another rule model or a second native-rule compiler: the public network values already provide the required path.
    • Approach: Replace the reader's direct construction of private lowering inputs with a narrow conversion from its parsed JSON model to the existing public rule values, then call native_egress_rules. Reuse the current JSON reader, validation and normalization tests; do not add a compatibility layer or duplicate the lowerer.
    • Done when:
      • The grammar tests accept and reject the same JSON shapes, encodings, CIDRs, selectors, ports and limits.
      • Model tests show that public rule values represent the same destinations and selectors as the file model.
      • Property tests show that valid policy files compile to the same canonical native allow and deny rules.
      • No policy-file compiler code calls the private address or lowering modules.
    • Needs: SL2.4d, in nvx-rs slimming 2.1.2: the kernel command line and OpenVMM's arguments come from the configuration alone #1098.
    • Estimate: 200 core lines, 2 counted files. Past 400 core lines, stop and ask before continuing.
  3. SL6.7b: The policy-file reader and the mount syntax are private to the CLI.

    • Objective: The egress policy-file reader and --mount syntax are CLI-facing code, but they are public API of nvx. This PR makes them private to the CLI where they are, while preserving policy compilation, mount parsing, export planning and host-path checks.
    • Contents: host::network::policy's reader (compile_policy*, CompiledEgressPolicy, the JSON reader) and the --mount syntax (host::sandbox::mount's parsing and SandboxOptions, with plan_mounts, plan_mounts_with and path_text) become crate-private and cli-gated where they are. The shared normalization stays public. Neither host::sandbox nor host::network::policy keeps anything in the final public API, so both modules become crate-private here: what remains in host::sandbox (its limits and defaults, parse_workload_identity, require_file and the mount types) takes its users' features, host::network::policy's limits go with its reader, and the network lowering takes MAX_RULES directly. Their integration-test users become unit tests of their owners or drive the binary, asserting the same behavior. The API snapshot drops the items.
    • Scope:
      • host::network::policy's JSON reader, compile_policy* functions and CompiledEgressPolicy become crate-private and cli-gated where they are.
      • host::sandbox::mount parsing, SandboxOptions, plan_mounts, plan_mounts_with and path_text become crate-private and cli-gated.
      • Existing mount access, owner, kind, allow, deny and write-path forms continue to produce the same ExportPlan and boot values.
      • Policy-reader, mount-parser, SandboxOptions and host-path integration tests become unit tests or drive the binary.
      • Shared network normalization stays public.
      • The host::sandbox and host::network::policy modules become crate-private: host::sandbox's limits, defaults, parse_workload_identity, require_file and mount types take their users' features; policy's limits go private with its reader; the network lowering uses MAX_RULES directly.
    • Not in this PR:
      • Policy grammar, rule normalization, mount syntax or option-validation behavior changes: this PR only narrows visibility and feature gates.
      • Moving the helpers under host::cli, renaming commands, flags, types or modules, or adding aliases.
      • Redesigning export planning or path rules: their own PRs handle that area.
      • Generalizing mounts for new owners, platforms or path spellings.
    • Approach: Narrow the existing policy reader and mount-syntax items to crate visibility, keep them behind cli, and update internal imports directly. Move each integration-test case beside its owner or test through the CLI binary. Preserve parser structure and shared normalization, then regenerate the API snapshot without introducing a generic parsing framework.
    • Done when:
      • Policy-file grammar, model and property tests pass with the same native rules and failures.
      • --mount tests still cover access, ownership, policy paths, commas, links and reserved targets.
      • SandboxOptions still attributes policy options to the preceding mount and produces the same exports.
      • The API snapshot lists no path under host::sandbox or host::network::policy.
    • Needs: SL6.3, in nvx-rs slimming 4.2.3: the old configs, the old launch code and bundled are gone #1122; SL6.7a, above; SL6.4, above.
    • Estimate: 0 core lines (visibility), no counted files.

Tests. Image, seal, artifact, policy-file and mount tests keep their assertions with their owners. The policy reader compiles the same native rules through EgressRule, Destination and PortSelector. Mount options produce the same exports and host-path checks. Download and artifact commands keep NVX_AUTO_DOWNLOAD and NVX_OPENVMM. Every feature set builds without unused private code, and the API snapshot drops only the privatized items, leaving no path under host::sandbox or host::network::policy.

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

Activity

  1. changed the title [-]nvx-rs slimming 4.3.1: image staging, artifact discovery, the policy-file reader and the mount syntax live in nvx-cli[/-] [+]nvx-rs slimming 4.3.1: image staging, artifact discovery, the policy-file reader and the mount syntax are private to the CLI[/+] 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.

    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. ppenna commented on Nov 12, 2026

    @ppenna
    Contributor

    SL6.4 note: making image staging and artifact discovery CLI-private would leave about 15 groups of items with no caller: Artifacts and the bindings' and checked files' unused accessors, which the CLI never used. Per #1076, leaving code isn't mixed into a privatization group, so a new leaving-code slice, SL6.6b in #1122, deletes them first. SL6.4 stacks on it and stays visibility-only, at 0 core lines.

    host::seal can't be fully cli-gated, because host::snapshot and the Windows platform layer use it internally. Those items take their users' gates, and nothing of host::seal stays public.

  4. 16 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