Files
d4d6f486ea fix(zap): mDNS opt-in (--mdns, ZAP_MDNS); hanzoai/tasks v1.53.2 so its ZAP clients stop listening (#54)
* fix(zap): make mDNS discovery opt-in

With ZAP on a non-loopback address, plugins/zap still ran mDNS unless
--no-mdns was passed: it announced _hanzo-base._tcp on the LAN, and
handlePeerEvent dialled any peer that announced it back. Hanzo nodes
reach each other through explicit peers, so discovery is now off unless
--mdns or ZAP_MDNS asks for it, and never on loopback. --no-mdns still
forces it off, so v1.5.93 configs keep their meaning.

Every other ZAP node in the repo already sets NoDiscovery.

Co-Authored-By: Claude Opus 5 <[email protected]>

* fix(tasks): take hanzoai/tasks v1.53.2, whose ZAP clients do not listen

plugins/tasks dials a Tasks server through hanzoai/tasks' SDK client.
At v1.52.9 that client, like pkg/tasks', started its node on Port 0,
listening on every interface, before dialling out. v1.53.2 dials
without starting a listener (hanzoai/tasks b4a8209c). zap-proto/zip
moves to v1.36.9 with it.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-10 21:12:42 -07:00

93 lines
2.9 KiB
Go

package zap
import "testing"
// DefaultConfig is the operator's whole interface to this transport: a port, an
// address, an mDNS switch and an off-switch. All four are read from the
// environment, so all four are pinned here.
func TestDefaultConfig(t *testing.T) {
t.Run("defaults when nothing is set", func(t *testing.T) {
t.Setenv("ZAP_PORT", "")
t.Setenv("ZAP_DISABLED", "")
t.Setenv("ZAP_ADDR", "")
t.Setenv("ZAP_MDNS", "")
c := DefaultConfig()
if c.Port != 9999 {
t.Fatalf("Port = %d, want 9999", c.Port)
}
if c.Address != "" {
t.Fatalf("Address = %q, want empty — the node follows the HTTP host unless told", c.Address)
}
if c.MDNS || c.NoMDNS {
t.Fatalf("MDNS = %v, NoMDNS = %v — with nothing set, discovery is simply off", c.MDNS, c.NoMDNS)
}
if c.ServiceType != "_hanzo-base._tcp" {
t.Fatalf("ServiceType = %q", c.ServiceType)
}
if !c.Enabled {
t.Fatal("Enabled = false — the transport is on unless disabled")
}
if c.NodeID == "" {
t.Fatal("NodeID is empty — a node with no id identifies no peer")
}
})
t.Run("ZAP_PORT is honoured", func(t *testing.T) {
t.Setenv("ZAP_PORT", "4242")
if got := DefaultConfig().Port; got != 4242 {
t.Fatalf("Port = %d, want 4242", got)
}
})
t.Run("ZAP_ADDR is honoured", func(t *testing.T) {
t.Setenv("ZAP_ADDR", "127.0.0.1:19652")
if got := DefaultConfig().Address; got != "127.0.0.1:19652" {
t.Fatalf("Address = %q, want 127.0.0.1:19652", got)
}
})
// mDNS is opt-in, and asking takes every spelling of true.
for _, raw := range []string{"true", "TRUE", "1", "t"} {
t.Run("ZAP_MDNS="+raw+" turns mDNS on", func(t *testing.T) {
t.Setenv("ZAP_MDNS", raw)
if !DefaultConfig().MDNS {
t.Fatalf("ZAP_MDNS=%q left mDNS off", raw)
}
})
}
for _, raw := range []string{"false", "0", "", "nonsense"} {
t.Run("ZAP_MDNS="+raw+" leaves it off", func(t *testing.T) {
t.Setenv("ZAP_MDNS", raw)
if DefaultConfig().MDNS {
t.Fatalf("ZAP_MDNS=%q turned mDNS on", raw)
}
})
}
t.Run("an unreadable ZAP_PORT keeps the default", func(t *testing.T) {
t.Setenv("ZAP_PORT", "not-a-port")
if got := DefaultConfig().Port; got != 9999 {
t.Fatalf("Port = %d, want 9999 — garbage must not silently bind elsewhere", got)
}
})
// The off-switch takes every spelling of true, which is the point of routing
// it through osutils.Bool: `ZAP_DISABLED=1` used to leave the listener up.
for _, raw := range []string{"true", "TRUE", "True", "1", "t"} {
t.Run("ZAP_DISABLED="+raw+" disables", func(t *testing.T) {
t.Setenv("ZAP_DISABLED", raw)
if DefaultConfig().Enabled {
t.Fatalf("ZAP_DISABLED=%q left the transport enabled", raw)
}
})
}
for _, raw := range []string{"false", "0", "f", "", "nonsense"} {
t.Run("ZAP_DISABLED="+raw+" leaves it on", func(t *testing.T) {
t.Setenv("ZAP_DISABLED", raw)
if !DefaultConfig().Enabled {
t.Fatalf("ZAP_DISABLED=%q disabled the transport", raw)
}
})
}
}