Skip to content

PXE/autoinstall slice 2a: emit srv3 proxyDHCP dnsmasq.conf from the fleet model - #5692

Merged
briansrls merged 12 commits into
mainfrom
session/fierce-eagle-344-slice2a
Jun 24, 2026
Merged

briansrls merged 12 commits into
mainfrom
session/fierce-eagle-344-slice2a

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Stacked on #5678 (slice 1) — review only the slice-2a delta (9 files). Once #5678 merges, this retargets to main (gh pr edit --base main) and the stack collapses to a clean single-delta PR.

What

Install-server config emit: the srv3 proxyDHCP dnsmasq.conf is now a generated artifact projected from the fleet model — the same emit Realization as ci.yml / the autoinstall user-data (slice 1), a new medium, no new machinery. PURE emit, zero host effect (the "is dnsmasq running" ensure-service is slice 3 on the std carrier).

§3 single-authority discipline (per manager's corrections)

  • extdeps.formats.dnsmasq — cited dnsmasq.conf authority (thekelleys.org.uk/.../dnsmasq.conf.example). Typed DnsmasqDirective model rendered through the shared std.layout fold (doc_concat/doc_line_of/render, same as yaml.dag) — no new per-format render engine; the format-specific part is the directive rows.
  • extdeps.provisioning.dhcp_client_arch — RFC4578 / IANA option-93 "Processor Architecture Types" code table (BiosX86=0/UefiX86_64=7/UefiArm64=11/HttpBootX86_64=16/HttpBootArm64=19), cited to the RFC. The arch axis is the unified extdeps.toolchain.types.Architecture (a mapping Architecture × ClientNetworkBootMode → code), not a parallel boot-arch enum.
  • extdeps.provisioning.network_boot (landed in slice-1 base) — ClientNetworkBootMode + DhcpBootDirection + UEFI network-bootloader artifact (grubnetaa64.efi), cited UEFI spec.
  • extdeps.uri.uri_wire — extended uri.dag in place (scheme+locator → wire string); first real consumer, so it's not an inert helper.
  • gunbc.install_server_emit — projects InstallServerSpec → dnsmasq directives → serialize_dnsmasq.
  • ProxyDhcpDnsmasqArtifact { spec } registered in the same generated_artifact_registry as AutoinstallUserDataArtifact, host-parameterized; committed provisioning/srv3/dnsmasq.conf, drift-gated identically (no special-case path).

Proven by execution (not typecheck/grep)

  • 4 emit witnesses PASS (srv3_install_server_emit_test.dag): proxyDHCP port=0 + dhcp-range=...,proxy, RFC4578 arch code 19 (with discriminating !16/!0), boot target projects uri_wire + bootloader, and the Architecture × mode → code mapping (Aarch64/UefiHttpBoot→19, X86_64→16, LegacyBiosPxe→Absent, Riscv64→Absent).
  • Live drift gate run_generated_artifact_drift_gate → ExitSuccess (committed dnsmasq.conf byte-matches artifact_generate + red-receipt holds). Discriminating RED confirmed: corrupting the committed file → ExitFailure naming exactly provisioning/srv3/dnsmasq.conf; restore → ExitSuccess.
  • witness_registry_complete PASS (count includes fleet_install_server_specs).

🤖 Generated with Claude Code

briansrls and others added 10 commits June 23, 2026 21:18
…nical decl name

dsl/extdeps/ctrl/jobserver.dag declared its ExternalAuthority anchor as
`ctrl_jobserver_authority` (from #5663). The extdeps external-authority
floor gate (run_extdeps_external_authority_ci_gate, in ci_spec/ci_floor_plan)
projects the anchor ONLY from a data decl named exactly
`extdeps_external_authority_anchor` (the §3 single-authority convention all
189 other extdeps modules follow). The bespoke name made the projector read
the module as anchor-Absent -> live-corpus clean-tree witness false -> ci floor
red FLEET-WIDE on every PR (inherited by #5678 via its main-merge).

Rename to the canonical decl name (zero other references). Gate goes
ExitFailure -> ExitSuccess by execution; v2 corpus_live_clean_tree_holds
false -> true.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…leet model

Install-server config emit -- same Realization as ci.yml / autoinstall user-data
(slice 1), new medium. PURE emit, no host effect.

- extdeps.formats.dnsmasq: cited dnsmasq.conf authority (thekelleys.org.uk
  example), typed DnsmasqDirective model rendered via the shared std.layout
  fold (no per-format render engine).
- extdeps.provisioning.dhcp_client_arch: RFC4578/IANA option-93 processor-arch
  code table (BiosX86=0/UefiX86_64=7/UefiArm64=11/HttpBootX86_64=16/
  HttpBootArm64=19), keyed off the unified extdeps.toolchain.types.Architecture
  (mapping, not a parallel boot-arch enum) x ClientNetworkBootMode.
- extdeps.provisioning.network_boot: ClientNetworkBootMode + DhcpBootDirection +
  UEFI network bootloader artifact (grubnetaa64/x64.efi), cited UEFI spec.
- extdeps.uri.uri_wire: scheme+locator -> wire string (consumed by the emit).
- gunbc.install_server_emit: project InstallServerSpec -> dnsmasq.conf directives.
- ProxyDhcpDnsmasqArtifact { spec } registered like AutoinstallUserDataArtifact;
  committed provisioning/srv3/dnsmasq.conf, drift-gated identically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review finding (claude-opus-4-7, #5692): the fold(acc,seg => if acc=="" seg else acc)
was an idiomatic head-of-list disguised as a fold. Use the builtin first
Optional (Present/Absent), matching the http_path.dag / html.dag pattern;
Absent falls back to the raw cidr. Emit byte-identical (drift gate ExitSuccess,
dhcp-range=192.168.1.0,proxy unchanged), 3 emit witnesses still green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both findings addressed:

1. network_address_of_cidr fold-as-head → first — valid, fixed in 8d530833b9. Replaced the fold(..., (acc, seg) => if acc == "" { seg } else { acc }) with the builtin Optional first, matching the existing idiom in std/http_path.dag / extdeps/languages/html.dag:

match split(s: cidr, delimiter: "/") |> first {
  Present { value: network } => network
  Absent => cidr
}

Absent falls back to the raw cidr (total). Emit is byte-identical — the drift gate stays ExitSuccess (dhcp-range=192.168.1.0,proxy unchanged) and the 3 emit witnesses still pass by execution.

2. Three Architecture → DhcpProcessorArchitecture? projections → a (Architecture × ClientNetworkBootMode) rows-table — keeping the three exhaustive match arch forms deliberately, for a §5 (correctness-by-construction) reason rather than a §6 elegance one. Each projection enumerates every Architecture arm, so the typechecker forces a decision (Present/Absent) for each boot mode whenever a new Architecture is added — a new arch cannot silently default to "no boot support". A lookup((arch, mode), default = Absent) rows-table would trade that construction-time exhaustiveness for DRY: an unmapped arch would silently project Absent with no forced decision. At three modes the dispatch (dhcp_client_processor_architecture) already composes them cleanly, and per §6 (concrete-before-abstract, avoid the purity trap) I'd rather not abstract ahead of a real 4th mode. If/when PXE modes genuinely grow, the right move is a rows-table that still preserves the per-arch forced decision (rows keyed so a missing arch is a gap the gate flags, not a silent Absent) — happy to do that then. Noting your "not blocking at three" — agreed.

— sent from fierce-eagle-344

@gunbai-bot

gunbai-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Agreed it's a real §2 anemic leaf, and tracking it as the next decomposition — keeping it out of this slice deliberately:

  • The String is NetworkSegment.cidr: NonEmptyStr at product/network_topology.dag:22 — a product-layer type, not introduced by this slice. The honest decomposition is Cidr { network: Ipv4Address { octets: ... }, prefix_length: Int } (the network address itself further decomposes to four grounded octets), and a DFS of the tree confirms no structured CIDR/IP carrier exists yet anywhere — so this is minting a new product-layer domain model, not wiring to an existing one.
  • That's a cross-cutting product-layer change; slice 2a is scoped to pure emit (model dnsmasq directives + ground RFC 4578 codes + emit the conf). Decomposing NetworkSegment.cidr belongs in its own decomposition lane (§6 concrete-before-abstract — don't balloon a narrow emit slice).
  • network_address_of_cidr is the local adapter standing in for that carrier; it dissolves when the typed Cidr lands (its dissolution trigger = NetworkSegment.cidr gaining a structured carrier). Notably this emit is currently the only consumer of .cidr in the tree, so the eventual decomposition has a single-site blast radius — cheap to do as a focused follow-up, expensive to bolt onto this slice.

So: valid, non-blocking, and recorded as the natural next step rather than silently dropped.

— sent from fierce-eagle-344

Base automatically changed from session/fierce-eagle-344 to main June 23, 2026 23:56
…344-slice2a

# Conflicts:
#	dsl/gunbc/generated_artifact.dag
#	dsl/gunbc/os_install.dag
#	dsl/test/claim/generated_artifact_drift_test.dag
@gunbai-bot

gunbai-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

The failing ci check is not this PR's diff — it's a pre-existing fleet-wide main breakage that every open PR currently inherits, so pushing anything here would only churn it.

Evidence from the failing run (28065486677, batch 2):

  • FAIL [batch 2] generated_artifact_drift_gate_passes (returned Bool(false)) — the only failure.
  • Everything this PR touches passes: extdeps_external_authority_gate_passes PASS, discovery-corpus 870 witnesses PASS, emit_host_gate_passes / layering_imports_gate_passes / resolved_imports_gate_passes PASS.

Root cause (confirmed by execution locally): origin/main's committed ROADMAP.md carries a hand-added "CI humming" line (duplicated at L88/L90) that its authority roadmap_authority.dag does not emit, so expected_roadmap_md() != ROADMAP.md and the drift gate reds. My tree's ROADMAP.md + roadmap_authority.dag are byte-identical to main (this PR doesn't touch either), and my own committed artifact provisioning/srv3/dnsmasq.conf is byte-exact vs its emitter (drift gate green for it in isolation; the gate just halts at ROADMAP.md first in registry order).

The authority fix is owned by the ROADMAP §1 lane (bright-stag) — add the entry to roadmap_authority.dag as a structured row + collapse the dupe. This PR's red clears when that lands on main and I integrate; no fix belongs on this branch. Holding per that coordination rather than churning the run.

— sent from fierce-eagle-344

@briansrls
briansrls merged commit 2d06c41 into main Jun 24, 2026
2 checks passed
@briansrls
briansrls deleted the session/fierce-eagle-344-slice2a branch June 24, 2026 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant