Repository navigation
Description
Parent: #1079, in #1076. Needs: #1091, #1097. Unblocks: #1099, #1104, #1124.
Goal. A cold boot's kernel command line and OpenVMM's arguments come from Runtime and VmConfig alone. The root's tokens carry the overlay mode, the journal policy, the GPT bound and the RAM upper's cap; the caller's command line can't override the tokens that nvx renders (the root's, the view's and nvx_maps), and owns every other token; and a caller can see the mapping table and the native egress rules that its policy lowers to. The new renderer never passes --microvm-lifecycle or --microvm-workload-identity. A caller can check, before anything changes on the host, that a configuration's command line fits Windows' limit, and the helpers that count and check a Windows command line stay public.
Notes.
- Caller-owned guest tokens stay caller-owned. Today's launch path reserves every
nvx_*token; the new renderer reserves only the tokens that it renders, so the CLI and other callers pass their own guest tokens, such asnvx_entrypoint,nvx_argandnvx_share, inBoot.command_line. - A temporary entry point. Until
host::vm::createcalls it (nvx-rs slimming 2.2.1: a VM is created in a private directory, with its restore-ready listener, then spawned #1099), the whole-config renderer is public, documented as temporary.
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.
-
SL2.4a1: The root's kernel tokens carry what
VmConfigsets, and the guest caps a RAM upper.- Objective: The layered-root boot tokens omit configuration that the guest needs to reproduce the requested root. The tokens and parser carry the overlay mode, journal policy, GPT bound and RAM-upper cap, and the guest applies the cap when mounting tmpfs.
- Contents: The root's tokens gain the overlay mode, the journal policy, the GPT bound and the RAM upper's cap, with their parser;
root::assemblemounts a RAM upper withsize=N%. - Scope:
- Extend
nvx-rs/src/protocol/root.rstokens and parsing for both existing image formats, both existing upper kinds, both overlay modes, the journal policy, optional GPT first-partition bound and RAM cap. - Update the shared recorded command-line fixtures so every root-token reader sees the new fields alike.
- Update
nvx-rs/src/guest/root.rsassembly so a RAM upper mounts tmpfs withsize=N%. - Keep
BOOT_CONTRACT_VERSIONunchanged because no released build uses these new tokens.
- Extend
- Not in this PR:
- A new image format, upper kind, overlay mode or journal policy: the tokens cover only the variants already represented by
VmConfig. - Rendering the complete kernel command line from
VmConfig: SL2.4a2 composes the root, view, mapping and caller tokens. - Changing the activation record or restore-time root repair: SL2.5b carries the RAM cap in the record.
- Fallback probing when tokens are absent or malformed: the existing parser remains strict.
- Incrementing the boot contract version: the group issue explicitly keeps it unchanged.
- A new image format, upper kind, overlay mode or journal policy: the tokens cover only the variants already represented by
- Approach: Extend the existing
protocol::rootcodec and fixture rather than adding a second root protocol. Pass the parsed RAM percentage to the current tmpfs mount assize=N%; retain the existing EROFS, GPT, scratch and RAM assembly paths. - Done when:
wire_values_keep_their_literalsnames the added token literals while the boot contract version remains unchanged.every_layout_renders_its_tokens_and_reads_them_backand the recorded-command-line test cover every existing format, upper and overlay combination with the new fields.both_overlay_modes_assemble_on_both_uppers_with_their_own_option_setsobservessize=N%for RAM uppers.a_tmpfs_upper_needs_no_scratch_devicestill passes with the capped tmpfs mount.
- Needs: SL2.3a, in nvx-rs slimming 2.1.1: one value for a VM's configuration #1097.
- Estimate: 120 core lines, 3 counted files. Past 240 core lines, stop and ask before continuing.
-
SL2.4a2: A cold boot's kernel command line comes from
VmConfigalone.- Objective: Cold-boot command lines are assembled by launch-specific code instead of the VM configuration.
VmConfig::kernel_command_linebecomes the single pure renderer for the root, view, mapping count and caller-owned tokens. - Contents:
protocol::view: the view's tokens and their parser.VmConfig::kernel_command_line: the root's tokens, the view's andnvx_maps, thenBoot.command_line. Parity tests compare it with the old rendering, through test-only conversions. - Scope:
- Add
nvx-rs/src/protocol/view.rsfornvx_hostnameandnvx_machine_id, with rendering and strict parsing. - Add
VmConfig::kernel_command_line, ordered as the root tokens, view tokens,nvx_mapswhen an export exists, thenBoot.command_line. - Add the parity conversions in an
implblock inhost/config/tests.rs; add the new view codec's parser cases inprotocol/view/tests.rs. - Render only cold boots, which have
Boot; restores receive their view through the activation record.
- Add
- Not in this PR:
- Rejecting caller tokens that conflict with rendered tokens or
virtfs_*: SL2.4b adds those checks. - Rendering NVX's own guest tokens such as
nvx_entrypoint,nvx_argornvx_share: callers keep those inBoot.command_line. - Rendering OpenVMM process arguments: SL2.4c consumes this kernel command line.
- A generic kernel-command-line builder or quoting grammar: the kernel tokens use the existing
protocol::cmdlinerules. - Changing restore activation records or removing
WorkloadView: SL2.5b handles the record.
- Rejecting caller tokens that conflict with rendered tokens or
- Approach: Reuse the root codec, export mapping count and
protocol::cmdlineparsing conventions. Add one narrow view codec and concatenate the four specified token groups in order; keep compatibility conversions inside the owning module'stestsmodule, not in a production file, instead of retaining a second production renderer. - Done when:
- The
protocol::viewparser round-trips valid hostname and machine-ID tokens and refuses each malformed or duplicate token case. - Parity tests match today's root tokens, view values and
nvx_mapscount through test-only conversions. - A caller's command line appears after all rendered tokens without being otherwise rewritten.
- The
- Needs: SL2.4a1, above; SL2.3b, in nvx-rs slimming 2.1.1: one value for a VM's configuration #1097.
- Estimate: 130 core lines, 3 counted files. Past 260 core lines, stop and ask before continuing.
- Objective: Cold-boot command lines are assembled by launch-specific code instead of the VM configuration.
-
SL2.4b: The caller's command line can't override the tokens that
nvxrenders.- Objective: Caller-supplied boot tokens must not replace the root, view or mapping configuration that
VmConfigrenders. The configuration rejects only those collisions, exposes the exact mapping table behindnvx_mapsand makes the existing map codec directly accessible. - Contents: The refusal of the tokens that
nvxrenders (the root's, the view's andnvx_maps) and ofvirtfs_*inBoot.command_line; the caller owns every other token;VmConfig::mapping_table;COMMAND_LINE_BUDGETmoves fromhost::launchtohost::config.protocol::mapsbecomes a public module, andprotocol's root keeps its re-exports. - Scope:
- Reject the root tokens,
nvx_hostname,nvx_machine_id,nvx_mapsand everyvirtfs_*token inBoot.command_line. - Accept all other caller tokens, including
nvx_entrypoint,nvx_argandnvx_share. - Add
VmConfig::mapping_table()from the configured export, with exactly the entries counted by the renderednvx_mapstoken. - Move
COMMAND_LINE_BUDGETfromnvx-rs/src/host/launch.rstohost::config. - Make
protocol::mapspublic while retaining the existing re-exports fromprotocol.
- Reject the root tokens,
- Not in this PR:
- Rejecting every token whose name starts with
nvx_: callers own the tokens thatVmConfigdoes not render. - Changing the mapping-table wire format, limits or codecs: this PR only exposes the existing module and returns its existing entries.
- Reading mappings from the host or validating mapped paths again:
mapping_table()is a pure projection of the checked export plan. - Rendering OpenVMM arguments or checking the Windows process limit: SL2.4c does both.
- Moving other launch constants or deleting the old launch checks: later migration PRs remove the legacy configuration.
- Rejecting every token whose name starts with
- Approach: Parse
Boot.command_linewith the existing kernel-token reader, normalize names as the kernel does, reject the fixed root, view and mapping names, and reject any normalized name beginningvirtfs_. ReuseExportPlan::guest_table()formapping_table()and expose the existing maps module; do not add a blanket namespace policy or a second mapping representation. - Done when:
- The rewritten kernel-parameter tests refuse every root, view, mapping and
virtfs_*spelling that the kernel treats as the same name. - Tests accept representative caller-owned guest tokens rather than reserving the full
nvx_*namespace. mapping_table()returns exactly the entries counted bynvx_mapswhen an export exists; without an export, the table is empty andnvx_mapsis absent.- Existing users of the root-level map re-exports still compile after
protocol::mapsbecomes public.
- The rewritten kernel-parameter tests refuse every root, view, mapping and
- Needs: SL2.4a2, above.
- Estimate: 150 core lines, 2 counted files. Past 300 core lines, stop and ask before continuing.
- Objective: Caller-supplied boot tokens must not replace the root, view or mapping configuration that
-
SL2.4c: A cold boot's OpenVMM arguments come from
RuntimeandVmConfigalone.- Objective: Cold-boot OpenVMM arguments are spread across legacy launch and plan paths, so callers cannot inspect one configuration-derived result before host changes begin. A temporary whole-configuration renderer and a portable length check derive the arguments from
RuntimeandVmConfigalone. - Contents: Processors, memory, block devices by path, blockless and layered roots, the network's and the export's arguments (internal), the console's attachment, and
LaunchOptions. It never renders--microvm-lifecycleor--microvm-workload-identity. Until SL2.8 calls it, the whole-config renderer is a temporary public entry point, documented as such; SL2.8 makes it internal. The Windows command-line limit stays:PROCESS_COMMAND_LINE_LIMIT,process_command_line_unitsandfit_process_command_linestay public, inhost::config, andVmConfig::check_command_line()(new) renders the configuration's arguments and checks, on every host and before anything changes on it, that they fit with a reserve for the runtime's files and the VM directory's paths, ascheck_adapter_launchdoes for the old plan. - Scope:
- Render processors, memory, kernel command line, block devices by path, blockless and layered roots, network and export arguments, console attachment and every
LaunchOptionsvalue. - Never emit
--microvm-lifecycleor--microvm-workload-identity. - Expose the whole-config renderer temporarily and document that SL2.8 makes it internal when
host::vm::createcalls it. - Move
PROCESS_COMMAND_LINE_LIMIT,process_command_line_unitsandfit_process_command_linefromhost::launchtohost::configwithout narrowing their public use. - Add
VmConfig::check_command_line()to render and check on every host with reserve for the runtime files and VM-directory paths before host state changes.
- Render processors, memory, kernel command line, block devices by path, blockless and layered roots, network and export arguments, console attachment and every
- Not in this PR:
- Opening block devices, resolving final paths, passing file descriptors or guarding the check-to-open interval: this interface passes repository block devices by path.
- Starting OpenVMM, creating a VM directory or allocating endpoints and reports: SL2.8's
createprepares a launch and makes the renderer internal, and SL2.9'sspawnstarts OpenVMM. - Public renderers for the network, export or individual device parts: only the whole-configuration renderer is public temporarily.
- Restore arguments or snapshot compatibility: this renderer covers cold boots from
RuntimeandVmConfig. - Changing policy normalization or exposing native egress rules: SL2.4d is separate.
- Approach: Refactor the existing
LaunchSpec,VmmLaunch, network and export argument assembly into one renderer over the new values. Reuse the current Windows quoting counter and reserve model, and keep part lowerings internal; do not build a command object hierarchy, path-handle layer or host-specific preflight. - Done when:
- Renderer tests cover processors, memory, block devices by path, blockless and layered roots, network, export, both console attachments and every launch-option value.
- No renderer case contains
--microvm-lifecycleor--microvm-workload-identity. VmConfig::check_command_line()accepts a fitting configuration with the reserve and rejects one beyond it with the same result on every host.- The public counting helpers retain their Windows quoting cases, including spaces, quotes, backslashes, empty arguments and non-ASCII text.
- Needs: SL2.4b, above.
- Estimate: 550 core lines, 5 counted files. Past 600 core lines, stop and ask before continuing.
- Objective: Cold-boot OpenVMM arguments are spread across legacy launch and plan paths, so callers cannot inspect one configuration-derived result before host changes begin. A temporary whole-configuration renderer and a portable length check derive the arguments from
-
SL2.4d: A caller can see the native egress rules that its policy lowers to.
- Objective: Callers can construct a
NetworkPolicybut cannot inspect the canonical native allow and deny rules it produces without going through the policy-file compiler. A pure query exposes that existing normalization directly and reports an oversized result as anUnsupportederror. - Contents:
NetworkPolicy::native_egress_rules() -> Result<NativeEgressRules>(new), whereNativeEgressRules { allow, deny }holds the native rules (CIDR,CIDR:PROTOCOL,CIDR:PROTOCOL:PORTorCIDR:PROTOCOL:FIRST-LAST) that the policy's allow and deny rules lower to, from the internal normalization: destinations merged, exceptions subtracted and port ranges merged. Each list holds at mostMAX_RULES; more is anUnsupportederror. It is pure: it reads no policy file and nothing else on the host. The compiler'sMAX_RULES_PER_ACTIONalready aliasesnetwork::MAX_RULES;loweringtakes the limit fromnetworkinstead ofpolicy, so the normalization no longer depends on the compiler. - Scope:
- Add
NetworkPolicy::native_egress_rules() -> Result<NativeEgressRules>inhost::network. - Add
NativeEgressRules { allow, deny }, containing the existing canonicalCIDR, protocol, port and port-range strings for IPv4 and IPv6 rules. - Reuse the internal normalization that merges destinations, subtracts exceptions, merges port ranges and sorts each action.
- Limit each list to
MAX_RULES; return anUnsupportederror when normalization needs more. - Make
host::network::loweringtake its limit fromnetwork::MAX_RULESrather than the policy-file module.
- Add
- Not in this PR:
- Reading JSON or any policy file: the method operates only on the already constructed
NetworkPolicy. - A new rule grammar or normalization algorithm: outputs stay identical to the existing policy compiler's canonical rules.
- Changing OpenVMM network arguments, ingress, host-loopback, forwards or proxy behavior: the query exposes egress allow and deny lowering only.
- Making address parsing or lowering public: callers receive only the two native string lists.
- Host I/O, network probes or rule installation: the method is pure.
- Reading JSON or any policy file: the method operates only on the already constructed
- Approach: Route the public
EgressRulevalues through the current internal parsing and lowering functions, then wrap the two resulting vectors. Move the shared limit dependency downward tohost::network; do not duplicate the compiler, expose its internals or retain a dependency on the policy-file reader. - Done when:
- Existing subtraction and adjacent-or-overlapping range tests pass through
native_egress_rules()with the same canonical strings. - Exactly 256 native rules per allow or deny list are accepted, while 257 are rejected before materializing an oversized result.
- Tests cover destination merging, exception subtraction and port-range merging without reading a file or other host state.
- Existing subtraction and adjacent-or-overlapping range tests pass through
- Needs: SL0.4, in nvx-rs slimming 1.1.1: the public API is checked, and NVX's programs are hidden from it #1091.
- Estimate: 80 core lines, 3 counted files. Past 160 core lines, stop and ask before continuing.
- Objective: Callers can construct a
Tests. SL2.4a1 rewrites protocol::root's wire_values_keep_their_literals, every_layout_renders_its_tokens_and_reads_them_back and every_reader_parses_the_recorded_command_lines_alike for the overlay mode, the journal policy, the GPT bound and the RAM cap, and the_boot_contract_version_names_these_tokens for the new tokens, with BOOT_CONTRACT_VERSION unchanged, and guest::root's both_overlay_modes_assemble_on_both_uppers_with_their_own_option_sets and a_tmpfs_upper_needs_no_scratch_device to show that the tmpfs upper mounts with size=N%. SL2.4a2's parity tests compare the new kernel command line with the old renderers, through test-only conversions: the root's and the view's tokens, and nvx_maps; protocol::view's parser round-trips nvx_hostname and nvx_machine_id, and refuses each malformed token. SL2.4b rewrites host::launch's mappings_add_the_export_and_the_mapping_count, kernel_parameters_are_checked and kernel_parameters_are_read_as_the_kernel_reads_them: the rendered tokens and virtfs_* are refused, a caller's own guest tokens are accepted, and mapping_table() has exactly the entries that nvx_maps counts. SL2.4c rewrites arguments_select_the_managed_direct_guest, and covers processors, memory, block devices by path, blockless and layered roots, the network, the export, both console attachments and each LaunchOptions value; no case renders --microvm-lifecycle or --microvm-workload-identity. SL2.4d keeps the policy normalization's tests, such as test_subtracts_rule_local_cidr_exclusions, test_merges_adjacent_and_overlapping_ranges_of_one_network, test_accepts_exact_256_rule_boundaries and test_rejects_257_rules_before_materializing_them, through native_egress_rules(), with no host I/O. SL2.4c's tests cover VmConfig::check_command_line: a configuration that fits with the reserve, one that doesn't, the same answer on every host, and the counting helpers' quoting.
Done when: every PR above has merged, with dev green.
Activity
esaurez commentedon Nov 10, 2026
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.
SL2.4a1 - merged via pull request 1278.
esaurez/slim-2.1.2-sl2.4a1-20261103atba9b85f8eb1fe65dd699ceaf076177ab9ed6c9ed.feature/nvx-refactorat7afa20575c01be01f3cdf148c90d9d9f6c9bed66; merge commiteb20dbda4bc0d6ce576419b01400f214ec07c9fd.SL2.4a2 - merged via pull request 1312.
esaurez/slim-2.1.2-sl2.4a2-20261106at43716c030c4f4084e9cc06950442a6563eef0f7f.feature/nvx-refactorat489ce50efc93fe253d145557482c6c93e384391b; merge commit09a6f041703c86359243880cdfb3f26d614c5643.SL2.4b - merged via pull request 1332.
esaurez/slim-2.1.2-sl2.4b-20261106at95920a27fb654a849825546f195e105f8ba4fe3f.feature/nvx-refactorat09a6f041703c86359243880cdfb3f26d614c5643; merge commitaa6bb42bc0932e7e861da399df993db6e61ef00a.SL2.4c - merged via pull request 1334.
esaurez/slim-2.1.2-sl2.4c-20261107atd86792ecfdea34dbc9ade4f8dd79d54759055dab.feature/nvx-refactorataa6bb42bc0932e7e861da399df993db6e61ef00a; merge commitfdd642fc705c6ea3846bb2c05400675bbe8e2cec.SL2.4d - merged via pull request 1293.
esaurez/slim-2.1.2-sl2.4d-20261105at059fd784e11059c2822b01becf694f3bdea5729b.feature/nvx-refactorat6224fb7851bc9fc6bda2a4f803fc4f26abc48b96; merge commite08a4b3d466540f2feec4a3c02d23bc8c297867b.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.