8000 feat(minimald): *.localhost hostname registry, startup probe, and registration/deregistration lifecycle · Issue #500 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(minimald): *.localhost hostname registry, startup probe, and registration/deregistration lifecycle #500

Closed

Description

@gominimal-aw-bot

Task

Unit 3 is a single-task unit and collapses per ADR 0028. This task parents directly to tracking issue #478.

Re-scoped 2026-06-23 — DNS mechanism realigned to spec B5 (host-side egress proxy), superseding the systemd-resolved narrowing of #485/#500/#546. The sandbox (hakoniwa) and microVM (libkrun) runtimes have no systemd, and the networking spec (03-spec-networking/networking-with-diagrams.md) never required it: R5 "PTask hostnames in host DNS" → B5 "*.localhost + host-side proxy (or one-time /etc/resolver)", tagged "Needs decision (DNS) — zero-root path exists". Resolution + routing are host-side; the runtimes never resolve anything. PR #546 is held (do-not-merge) pending this re-scope; salvage its in-memory registry, drop its systemd-resolved probe.

repo: gominimal/minimal
spec: docs/specs/03-spec-networking/03-spec-networking.md
requirements: R3.1, R3.2, R3.3, R3.5, R3.6 (R3.4 systemd-resolved probe is removed by this re-scope — replaced by an egress-proxy reachability check; see below)

files in scope:

  • crates/minimald/src/net/dns.rs (salvage from feat(minimald): Unit 3 DNS — B5 host-side egress proxy + .min.internal hostname registry #546) — in-memory hostname registry; register(session_name, host_id) / deregister(session_name) with structured tracing events (R3.5); hostname format <session-name>.<host-id>.min.internal (TLD decided 2026-06-23 — Mike's preference; under B5 the TLD is a free label since the proxy routes by Host: header, so .min.internal is semantically honest for internal PTask services and the .localhost loopback-fallback is not relied on); register HostNet PTasks → 127.0.0.1, OwnIp PTasks → the gvproxy switch IP (R3.6). Remove the resolver write path (systemd-resolved D-Bus / resolvectl) — no host resolver is written. OwnIp switch-IP registration depends on the feat(minimald,sandbox2): wire minimald::net switch into the live OwnIp session-launch path (R1.5) #542 live-switch wiring (now merged via feat(minimald,sandbox2): wire net switch into live OwnIp launch path #547).
  • crates/minimald/src/net/proxy.rs (new) — the B5 host-side egress proxy. A forward/CONNECT proxy that routes a request by its Host: header (or CONNECT authority) to the target PTask's address via the registry: HostNet → 127.0.0.1:<port>, OwnIp → the PTask switch IP through the gvproxy switch (reuse the feat(minvmd): implement DM1 gvproxy tap relay for OwnIp PTasks #540 relay path). The host resolver is never consulted — *.min.internal is an opaque label the proxy maps internally, so the no-systemd runtimes and the TLD choice are both irrelevant to correctness. Clients reach the proxy via proxy-env / PAC (HTTP(S)_PROXY), the zero-root cross-platform path the spec asserts ("zero-root path exists"); /etc/resolver is the macOS root-write alternative, not implemented here.
  • crates/minimald/src/lib.rs (or main.rs) — replace the systemd-resolved startup probe with an egress-proxy reachability check: on daemon start, bind the proxy listener; on bind failure → tracing::warn!(component = "dns-proxy", status = "unavailable", remedy = "<port in use / set HTTP_PROXY>"). (Supersedes R3.4's systemd-resolved warn.)
  • crates/minimald/src/session.rs — call dns::register at session launch (HostNet + OwnIp), dns::deregister on exit.
  • (deferred) crates/minimal2/src/client.rs hostname/TCP connect (UC2c, R3.2) — UDS-only client; TCP/hostname transport belongs with the DM5 network-listener work in Unit 4.
  • docs/specs/03-spec-networking/03-spec-networking.md — amend R3.1 hostname format to <session-name>.<host-id>.min.internal; close Open Question 1 with the B5 host-side-egress-proxy decision (proxy routes by Host:/authority; resolution stays host-side; systemd not required), explicitly superseding spike spike: DNS hostname registration works rootlessly on target Linux distributions #485's systemd-resolved finding.

proof artifacts:

  • Test: registry/proxy routing contract. Register a HostNet PTask "myservice"/host-id "dev"; drive a request with Host: myservice.dev.min.internal through the proxy and assert it routes to the registered target. After deregister, assert the proxy returns a not-found (no stale route). No getaddrinfo/host-resolver dependency — asserts the proxy contract directly. Fails on base (no registry/proxy).
  • Test: OwnIp routing — a registered OwnIp PTask routes through the gvproxy switch relay to its switch IP (may reuse / extend the feat(minvmd): implement DM1 gvproxy tap relay for OwnIp PTasks #540 relay test; the privileged netns leg defers to ci-netns.yml). Fails on base.
  • Test: proxy-listener bind-failure emits the component = "dns-proxy" tracing::warn! (supersedes the R3.4 systemd-resolved probe test). Fails on base.

verification:

  • cargo build --locked
  • cargo test -p minimald --locked
  • cargo fmt --all -- --check
  • cargo clippy -p minimald --all-targets -- -D warnings

depends on:

Related to #478

Generated by sdd-triage-materialize for issue #478 · ◷

Activity

  1. gominimal-aw-bot commented on Jun 22, 2026

    @gominimal-aw-bot
    ContributorAuthor

    /execute

  2. norrietaylor commented on Jun 23, 2026

    @norrietaylor
    Member

    /execute

  3. gominimal-aw-bot commented on Jun 23, 2026

    @gominimal-aw-bot
    ContributorAuthor

    /execute

  4. gominimal-aw-bot commented on Jun 23, 2026

    @gominimal-aw-bot
    ContributorAuthor

    Blocked — needs a maintainer decision on three load-bearing points before I can implement at confidence.

    I read the task scope, the *.localhost decision from spike #485 (merged as PR #487), the existing crates/minimald/src/net/ (from #496), crates/minimald/src/session.rs, and crates/minimal2/src/client.rs. The in-memory registry (R3.5) and the systemd-resolved startup probe (R3.4, = proof artifact 2) are straightforward. But three parts of the task can't be implemented faithfully as written:

    1. Proof artifact 1 contradicts the *.localhost mechanism the task adopts.
    It asserts getaddrinfo("myservice.dev.localhost") returns 127.0.0.1 while an OwnIp PTask runs, then NXDOMAIN after it exits. But spike #485's finding (which this task adopts) is *.localhost + host-side proxy: systemd-resolved synthesizes every *.localhost name to 127.0.0.1 statically, independent of any PTask lifecycle. So:

    • "returns 127.0.0.1 while running" passes against an empty PR — systemd-resolved answers it with no minimald involvement, i.e. a health check, not a proof (empty-PR rule); and
    • "NXDOMAIN after exit" can never be observed where systemd-resolved is active — *.localhost is never NXDOMAIN.

    This artifact assumes minimald serves a dynamic zone whose records appear/withdraw with the PTask — the *.min.local design the task is explicitly moving away from. The two are mutually exclusive.
    Decision: (a) keep *.localhost + host-side proxy and rewrite proof artifact 1 to assert the registry/proxy contract directly (register → entry present + proxy routes by Host header; deregister → entry gone), or (b) keep a dynamic getaddrinfo-lifecycle proof and revert to a minimald-served zone (not *.localhost). I won't pick this silently — it determines the whole DNS mechanism.

    2. OwnIp registration "to the gvproxy switch IP at session launch" has no switch IP to register against in minimald.
    GvproxySwitch::attach() (the R1.5 attach that yields a PTask's 100.64.x.y) is never called from the native-Linux minimald session path — session.rs/server.rs only forward network_mode into the sandbox; the OwnIp switch wiring from #496/#522 lives in minvmd (the VM path). So at session.rs launch there is no per-PTask switch IP to pass to dns::register for an OwnIp PTask. HostNet → 127.0.0.1 I can do today.
    Decision: scope session.rs registration to HostNet only for now (leaving OwnIp registration to follow the switch-into-minimald-session wiring), or register OwnIp at 127.0.0.1 too per R3.3's published-port model (which contradicts the task's explicit "switch IP" wording), or is the switch-into-session wiring expected here?

    3. minimal2 client "accept a .localhost hostname in addition to an IP" — the client has no IP/TCP path.
    Client::connect and resolve_socket_path are UDS-only (tokio::net::UnixStream). There is no IP-based connect to add a hostname alternative to; UC2c/R3.2 (a network-accessible DM5 minimald) presupposes a TCP transport this crate doesn't have yet.
    Decision: is a TCP/hostname client transport in scope for #500, or does R3.2/UC2c belong with the DM5 network-listener work (Unit 4)?

    I have not opened a PR (a declared proof artifact that can't pass is a hand-off, not a partial PR). The clearly-sound parts — the in-memory dns.rs registry with R3.5 structured tracing, the R3.4 systemd-resolved startup probe (matches proof artifact 2 exactly), and the spec amendment closing Open Question 1 with the #485 finding — I can land immediately once the three decisions above are made. Clear needs-human with guidance and I'll resume.

    Side note (independent of this task): the spike finding doc docs/spikes/2026-06-20-dns-hostname-mechanism.md that PR #487 merged is absent from the current main working tree — worth a look.

    Generated by sdd-execute (opus tier) for issue #500 · ◷

  5. 1 remaining item

  6. norrietaylor commented on Jun 23, 2026

    @norrietaylor
    Member

    Maintainer decisions (re-scope approved) — resume on this:

    1. Proof mechanism: keep *.localhost + host-side proxy (spike spike: DNS hostname registration works rootlessly on target Linux distributions #485). Proof artifact 1 is rewritten to assert the registry/proxy contract (register → entry present + proxy routes by Host: header; deregister → gone), not a getaddrinfo lifecycle, which *.localhost's static synthesis makes unobservable.
    2. OwnIp registration: scope session.rs registration to HostNet only for now. OwnIp registration to the switch IP is deferred to feat(minimald,sandbox2): wire minimald::net switch into the live OwnIp session-launch path (R1.5) #542 (the switch-into-minimald-session wiring); resume that part once feat(minimald,sandbox2): wire minimald::net switch into the live OwnIp session-launch path (R1.5) #542 lands.
    3. TCP/hostname client (R3.2/UC2c): out of scope for feat(minimald): *.localhost hostname registry, startup probe, and registration/deregistration lifecycle #500 — deferred to Unit 4 (the DM5 network-listener work); the client stays UDS-only here.

    Land now: the in-memory dns.rs registry (R3.5), the systemd-resolved startup probe (R3.4), the HostNet registration path, and the spec amendment (R3.1 *.localhost, close Open Question 1). The body is updated to match. Separately, I'm recovering the missing docs/spikes/2026-06-20-dns-hostname-mechanism.md.

  7. removed
    needs-humanAn agent handed off; a human must act, then clear this label. Set by defer and handoffs.
    on Jun 23, 2026
  8. gominimal-aw-bot commented on Jun 23, 2026

    @gominimal-aw-bot
    ContributorAuthor

    The sdd-spec agent run failed before it could post a spec, a comment, or any lifecycle update — the failure was not classified by the conclusion job (e.g. the agent step itself crashed). Applying needs-human so this is visible and recoverable. A human should investigate the failed run and, once ready, clear the needs-human label to re-run the spec agent on this tracking issue. Failed run: https://github.com/gominimal/minimal/actions/runs/28032382361

  9. added
    needs-humanAn agent handed off; a human must act, then clear this label. Set by defer and handoffs.
    on Jun 23, 2026
  10. removed
    needs-humanAn agent handed off; a human must act, then clear this label. Set by defer and handoffs.
    on Jun 23, 2026
  11. gominimal-aw-bot commented on Jun 23, 2026

    @gominimal-aw-bot
    ContributorAuthor

    This is sdd-spec. Issue #500 is a task sub-issue parented directly to tracking issue #478 and currently carries sdd:in-progress — this is sdd-execute's domain, not sdd-spec's. The previous bot comment's guidance (clear

    Generated by sdd-spec for issue #500 · ◷

  12. gominimal-aw-bot commented on Jun 23, 2026

    @gominimal-aw-bot
    ContributorAuthor

    Pull request created: #546

    Generated by sdd-execute (opus tier)

  13. added a commit that references this issue on Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0