From bb338140c797e7894d457ba044cb8c9d42d9a07a Mon Sep 17 00:00:00 2001 From: Gustavo Bertoi Date: Mon, 29 Jun 2026 13:06:16 -0300 Subject: [PATCH] =?UTF-8?q?feat(doctor):=20X6=20(part)=20=E2=80=94=20dns?= =?UTF-8?q?=20/etc/hosts=20probe=20(spec=2005/13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the doctor matrix with a best-effort `dns (/etc/hosts)` probe: when the current dir is a workspace with a configured Caddy proxy, it diffs the proxy route hosts against the marker-fenced /etc/hosts block (dns.Missing) and warns with `sudo devstack dns setup` when any are absent. Non-fatal (local routing is opt-in); skipped entirely outside a proxy workspace. Pairs with the trust probe to complete the M5 self-verification in doctor; the shared-ledger probe + safe --fix remain for the rest of X6. Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/cli/doctor.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/internal/cli/doctor.go b/internal/cli/doctor.go index 3ad6792..4206930 100644 --- a/internal/cli/doctor.go +++ b/internal/cli/doctor.go @@ -7,7 +7,10 @@ import ( "github.com/spf13/cobra" + "github.com/open-source-cloud/devstack/internal/config" + "github.com/open-source-cloud/devstack/internal/dns" "github.com/open-source-cloud/devstack/internal/docker" + "github.com/open-source-cloud/devstack/internal/proxy" "github.com/open-source-cloud/devstack/internal/state" "github.com/open-source-cloud/devstack/internal/trust" "github.com/open-source-cloud/devstack/internal/xdg" @@ -135,6 +138,26 @@ func runDoctor(cmd *cobra.Command) []docker.Check { checks = append(checks, docker.Check{Name: "state ledger", Status: docker.StatusOK, Detail: fmt.Sprintf("schema v%d @ %s", v, ctxName)}) } + // DNS entries for *.localhost (spec 05) — best-effort, only when the current + // dir is a workspace with a configured proxy. Never fatal (opt-in). + if m, err := config.Load(cwd); err == nil && proxy.Enabled(m) { + var hosts []string + for _, r := range proxy.BuildRoutes(m) { + hosts = append(hosts, r.Host) + } + if missing, err := dns.Missing(dns.DefaultHostsPath, hosts); err == nil { + if len(missing) == 0 { + checks = append(checks, docker.Check{Name: "dns (/etc/hosts)", Status: docker.StatusOK, Detail: fmt.Sprintf("%d *.localhost host(s) resolved", len(hosts))}) + } else { + checks = append(checks, docker.Check{ + Name: "dns (/etc/hosts)", Status: docker.StatusWarn, + Detail: fmt.Sprintf("%d of %d *.localhost host(s) missing", len(missing), len(hosts)), + Remediation: "run `sudo devstack dns setup`", + }) + } + } + } + // Local-CA trust (spec 05) — opt-in, so never fatal: report readiness as a // warning with the exact remediation when not fully set up. ts := trust.New().Status(ctx)