Skip to content

nvx-rs slimming 4.3.2: path rules are private to the CLI, and the export holds paths only #1125

Closed

Description

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

Goal. The export planner, verify's host rechecks and host::paths become crate-private and cli-gated where they are, and the crate root stops re-exporting resolve_guest_path; guest_path stays public. The CLI owns PlannedExport { description, pins }, persists both and checks the pins before passing the description to the public export API. ExportPlan then holds paths only, and nvx documents what the caller keeps stable.

Notes.

  • Privatizing counts as a move. No file split or relocation is needed.

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.5a2: Path rules are private to the CLI.

    • Objective: Path resolution, protected-path policy, aliases and host rechecks are CLI policy, not shared export-description behavior, but their planner is public API of nvx. This PR makes those rules private to the CLI where they are, while retaining identity pins and the pre-launch recheck.
    • Contents: The planner (plan, ExportRequest, Mapping, Target, PathList, resolve_guest_path), verify's host rechecks and host::paths become crate-private and cli-gated where they are; the crate root stops re-exporting resolve_guest_path, and keeps guest_path, the public path convention. The CLI keeps the identity pins and the pre-launch recheck. Their integration-test users become unit tests of their owners or drive the binary, asserting the same rules. The API snapshot drops the items.
    • Scope:
      • The planner containing plan, ExportRequest, Mapping, Target, PathList and resolve_guest_path becomes crate-private and cli-gated where it is; the crate root stops re-exporting resolve_guest_path, and its guest_path re-export stays.
      • verify's host rechecks and host::paths remain at their paths and become private to the CLI.
      • Existing canonicalization, protected and reserved targets, allow, deny and write-path rules, aliases and OpenVMM limits remain unchanged.
      • The CLI continues to record file identities for movable objects and refuses changed or uninspectable pins before launch.
      • Integration-test cases for planning, guest-path resolution and host rechecks become unit tests or drive the binary.
    • Not in this PR:
      • Removing identities from ExportPlan or introducing PlannedExport: the next representation change does that.
      • Changing path-policy semantics, platform-specific identity checks, error text or accepted path spellings.
      • Adding path discovery, globbing, symbolic-link policy matrices or configurable protected targets.
      • Moving the helpers under host::cli, renaming planner types or adding an alias module.
    • Approach: Narrow the existing planner, verifier and path helpers to crate visibility and gate them with cli. Update internal imports directly, keep the identity pins and pre-launch recheck in place, and move integration-test cases beside their owners or through the binary. Regenerate the API snapshot without adding a trait or compatibility facade.
    • Done when:
      • Planner tests cover the existing mapping, protected-path, policy-path, alias, volume and OpenVMM-limit cases.
      • resolve_guest_path still canonicalizes the supported aliases and refuses paths named only by a verbatim spelling.
      • Changed and uninspectable file identities are refused before launch with the same reasons.
      • The API snapshot lists none of the private planner, verifier or path-rule items, at the crate root included; guest_path stays listed in host::filesystem and at the root.
    • Needs: SL6.3, in nvx-rs slimming 4.2.3: the old configs, the old launch code and bundled are gone #1122; SL6.4, in nvx-rs slimming 4.3.1: image staging, artifact discovery, the policy-file reader and the mount syntax are private to the CLI #1124; SL6.7b, in nvx-rs slimming 4.3.1: image staging, artifact discovery, the policy-file reader and the mount syntax are private to the CLI #1124.
    • Estimate: 0 core lines (visibility), no counted files.
  2. SL6.5b: The export holds paths only.

    • Objective: ExportPlan currently combines a path description with host identities that only the CLI's reusable store needs. This PR leaves paths in the shared description while the CLI persists and verifies a PlannedExport containing the description and its pins.
    • Contents: The CLI owns PlannedExport { description: ExportPlan, pins }: its store persists both, and its verifier checks the pins before it passes the description to nvx; the planner and verifier, private to the CLI since SL6.5a2, and their callers change together. nvx removes FileIdentity, ExportChild::denied_identities, Bind::identity and their rules from ExportPlan and its check, documents what the caller keeps stable, and makes ExportPlan::{openvmm_arguments, kernel_token} internal.
    • Scope:
      • The CLI owns PlannedExport { description: ExportPlan, pins }, and its store persists both fields.
      • The private planner produces the description and pins together, and the CLI verifies pins before passing the description to nvx.
      • FileIdentity, ExportChild::denied_identities, Bind::identity and their structural rules are removed from ExportPlan.
      • ExportPlan::check remains structural and runs without identity data.
      • host::filesystem documents which exported paths a caller keeps stable, and ExportPlan::{openvmm_arguments, kernel_token} become internal.
    • Not in this PR:
      • Changing path planning, protected targets, alias resolution or which objects the CLI pins: the private path rules already establish those cases.
      • Adding optional identities back to ExportPlan or a movable-object API: shared descriptions hold paths only.
      • Defending against a malicious host or control process: the caller owns path stability under the documented model.
      • Changing export wire formats, guest mappings or OpenVMM argument meanings.
      • Designing a generic persistence framework for plans and pins: the existing CLI store is the only caller.
    • Approach: Introduce the small CLI wrapper at the planner and store boundary, move existing identity vectors into its pins, and update the private planner, verifier and callers together. Delete identity fields and checks from the shared types, keep structural validation in place, and document the caller contract instead of adding optional fields or callbacks.
    • Done when:
      • The CLI stores and reloads an export description with its pins.
      • A changed or uninspectable pin is refused before the CLI passes the description to nvx.
      • ExportPlan::check tests pass without constructing identity data and still reject the same structural errors.
      • Export lowering produces the same OpenVMM arguments, kernel token and guest mapping table.
      • The public docs state the launch race, writable-part recheck and durable-denial responsibilities.
    • Needs: SL6.5a2, above.
    • Estimate: 250 core lines, 4 counted files. Past 500 core lines, stop and ask before continuing.

Tests. Filesystem tests split by visibility: public structure, lowering and guest_path tests remain public-API tests; planner, resolve_guest_path, host recheck and path-rule tests become unit tests of their owners. A changed or uninspectable pin is still refused before launch. Once identity data goes, ExportPlan::check runs without it. The API snapshot drops only the privatized path rules.

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

Activity

  1. changed the title [-]nvx-rs slimming 4.3.2: path rules live in nvx-cli, and the export holds paths only[/-] [+]nvx-rs slimming 4.3.2: path rules are private to the CLI, and the export holds paths only[/+] 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.5a2 - no completed first-iteration handoff recorded. Inspect any preserved partial/prior work before implementing the issue's scope.

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

    @ppenna
    Contributor

    SL6.5a2 note: resolve_guest_path is deleted rather than made private. No NVX program calls it, so SL6.6d (#1122, #1122 (comment)) deletes it, with Target::Convention, Mapping::convention, ExportRequest::new and PathList::EMPTY, before SL6.5a2.

    That makes one of SL6.5a2's Done-when items moot: "resolve_guest_path still canonicalizes the supported aliases and refuses paths named only by a verbatim spelling". The planner's own tests keep that behavior covered: spellings_of_one_object_share_its_guest_path checks alias canonicalization, and paths_that_only_a_verbatim_path_names_are_refused checks the verbatim refusal. SL6.6d keeps a planner test for each alias case that resolve_guest_path's test covered.

    Everything else in SL6.5a2's Scope is unchanged.

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