v0.152.0 + felhom-samba 1.1.0 — mDNS for macOS, and the card stops offering a dead form
Capture on the box disproved the first theory: macOS DOES send a correct NBNS query for <NAME><20> and nmbd DOES answer it correctly in 140us (flags 0x8580, RCODE=0, right address) - macOS just never acts on it. NetBIOS there feeds legacy browsing, not smb:// URL resolution, so the bare name can never work on a Mac and nmbd was never the broken part. felhom-samba 1.1.0 adds avahi + dbus, with avahi-daemon.conf and the _smb._tcp service file templated from FELHOM_SERVER_NAME so a rename re-advertises. Both daemons are non-fatal on failure - a discovery gap must not become an outage. v0.151.0's card offered smb://<NAME> for Mac, which is exactly the dead form; now smb://<NAME>.local. Windows keeps the flat \\<NAME>, which nmbd serves correctly. Red-proofed both directions. NOT claimed: Finder-sidebar discovery - published and answering on the wire, but not observed working on the test Mac. Recorded OPEN. TestRenderSambaCompose pinned the literal 1.0.0 tag, so an image bump read as a renderer regression; now derives from SambaImage and asserts non-:latest.
This commit is contained in:
@@ -27,7 +27,7 @@ const (
|
||||
FileBrowserImage = "gtstef/filebrowser:1.3.3-stable"
|
||||
// SambaImage is our own pinned LAN-sharing image (R-7 slice 1). Built by
|
||||
// controller/scripts/build-samba-image.sh from controller/infra-images/samba/. NEVER :latest.
|
||||
SambaImage = "gitea.dooplex.hu/admin/felhom-samba:1.0.0"
|
||||
SambaImage = "gitea.dooplex.hu/admin/felhom-samba:1.1.0"
|
||||
)
|
||||
|
||||
// Images returns every controller-managed infra image, derived from the pins above so there is
|
||||
|
||||
@@ -77,7 +77,7 @@ func TestRenderSambaCompose(t *testing.T) {
|
||||
got := RenderSambaCompose(sampleSambaData())
|
||||
for _, want := range []string{
|
||||
"network_mode: host",
|
||||
"image: gitea.dooplex.hu/admin/felhom-samba:1.0.0",
|
||||
"image: " + SambaImage,
|
||||
"- ./smb.conf:/etc/samba/smb.conf:ro",
|
||||
"- samba-passdb:/var/lib/samba",
|
||||
"FELHOM_SERVER_NAME=FELHOM",
|
||||
@@ -87,6 +87,13 @@ func TestRenderSambaCompose(t *testing.T) {
|
||||
t.Errorf("compose missing %q\n%s", want, got)
|
||||
}
|
||||
}
|
||||
// The tag must be EXPLICIT — a floating :latest breaks reproducible pins and is the thing the
|
||||
// constant exists to prevent. Asserted on the constant's shape, so an image bump is a one-line
|
||||
// change in infra.go and never a test edit.
|
||||
if strings.HasSuffix(SambaImage, ":latest") || !strings.Contains(SambaImage, ":") {
|
||||
t.Errorf("SambaImage %q must carry an explicit non-latest tag", SambaImage)
|
||||
}
|
||||
|
||||
// Read-only share → :ro bind (red-proof target: drop the :ro in the renderer and this fails).
|
||||
roBind := "- /mnt/felhom-drives/media/filmek:/mnt/felhom-drives/media/filmek:ro"
|
||||
if !strings.Contains(got, roBind) {
|
||||
|
||||
@@ -37,10 +37,10 @@ func TestSharingConnectCard_ShowsNameAndDirectAddress(t *testing.T) {
|
||||
|
||||
body := getPage(t, s, "/sharing").Body.String()
|
||||
for _, want := range []string{
|
||||
"Csatlakoz", // the card heading (ASCII-safe substring)
|
||||
`\\FELHOM`, // Windows form
|
||||
"smb://FELHOM", // Mac form
|
||||
"smb://192.0.2.10", // the fallback that did not exist before
|
||||
"Csatlakoz", // the card heading (ASCII-safe substring)
|
||||
`\\FELHOM`, // Windows form
|
||||
"smb://FELHOM.local", // Mac form — .local is load-bearing, see the regression test below
|
||||
"smb://192.0.2.10", // the fallback that did not exist before
|
||||
} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("page missing %q", want)
|
||||
@@ -83,7 +83,7 @@ func TestSharingConnectCard_NoAddressOmitsTheLine(t *testing.T) {
|
||||
s, _ := connectCardServer(t, "FELHOM", "")
|
||||
|
||||
body := getPage(t, s, "/sharing").Body.String()
|
||||
if !strings.Contains(body, "smb://FELHOM") {
|
||||
if !strings.Contains(body, "smb://FELHOM.local") {
|
||||
t.Error("name lines must remain when no address can be derived")
|
||||
}
|
||||
if strings.Contains(body, "smb://\n") || strings.Contains(body, "smb://<") || strings.Contains(body, "smb://</span>") {
|
||||
@@ -100,7 +100,7 @@ func TestSharingConnectCard_UsesConfiguredName(t *testing.T) {
|
||||
s, _ := connectCardServer(t, "OTTHON", "192.0.2.10")
|
||||
|
||||
body := getPage(t, s, "/sharing").Body.String()
|
||||
if !strings.Contains(body, "smb://OTTHON") || !strings.Contains(body, `\\OTTHON`) {
|
||||
if !strings.Contains(body, "smb://OTTHON.local") || !strings.Contains(body, `\\OTTHON`) {
|
||||
t.Error("the configured server name is not on the page")
|
||||
}
|
||||
if strings.Contains(body, "FELHOM") {
|
||||
@@ -144,7 +144,38 @@ func TestSharingConnectCard_UnsetNameFallsBackToEffective(t *testing.T) {
|
||||
if want == "" {
|
||||
t.Skip("no product default server name to assert")
|
||||
}
|
||||
if body := getPage(t, s, "/sharing").Body.String(); !strings.Contains(body, "smb://"+want) {
|
||||
if body := getPage(t, s, "/sharing").Body.String(); !strings.Contains(body, "smb://"+want+".local") {
|
||||
t.Errorf("effective default name %q not rendered", want)
|
||||
}
|
||||
}
|
||||
|
||||
// REGRESSION (v0.152.0) — the Mac line must offer `smb://<NEV>.local`, never the bare name.
|
||||
//
|
||||
// v0.151.0 shipped `smb://FELHOM`, which is the ONE form that provably cannot work on a Mac.
|
||||
// Captured live 2026-07-20: macOS broadcasts a correct NBNS query for FELHOM<20>, the box answers
|
||||
// in 140us with a textbook positive response (flags 0x8580, RCODE=0, the right address), and macOS
|
||||
// never opens a TCP connection — NetBIOS feeds legacy browsing there, not smb:// URL resolution.
|
||||
// Sixteen seconds later the same Mac connected via `smb://FELHOM.local` on the first try. So this
|
||||
// is not a choice between two working spellings: the bare form is a dead end the page was actively
|
||||
// sending customers down.
|
||||
func TestSharingConnectCard_MacLineIsDotLocalNotBareName(t *testing.T) {
|
||||
for _, name := range []string{"FELHOM", "OTTHON"} {
|
||||
s, _ := connectCardServer(t, name, "192.0.2.10")
|
||||
body := getPage(t, s, "/sharing").Body.String()
|
||||
|
||||
if !strings.Contains(body, "smb://"+name+".local") {
|
||||
t.Errorf("%s: the Mac line must offer smb://%s.local", name, name)
|
||||
}
|
||||
// Anchored on the closing tag, so `smb://FELHOM.local</span>` cannot satisfy this by accident.
|
||||
if strings.Contains(body, "smb://"+name+"</span>") {
|
||||
t.Errorf("%s: the page still offers the bare smb://%s — macOS cannot resolve it", name, name)
|
||||
}
|
||||
// Windows is served by nmbd and is proven working: fixing the Mac must not touch it.
|
||||
if !strings.Contains(body, `\\`+name) {
|
||||
t.Errorf("%s: the Windows flat-name form went missing", name)
|
||||
}
|
||||
if strings.Contains(body, `\\`+name+".local") {
|
||||
t.Errorf("%s: the Windows line gained .local — that is the Mac's mechanism, not nmbd's", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</div>
|
||||
<div class="form-hint">
|
||||
Mac: Finder → Ugrás → Csatlakozás a szerverhez:
|
||||
<span class="mono">smb://{{.SMBServerName}}</span>
|
||||
<span class="mono">smb://{{.SMBServerName}}.local</span>
|
||||
</div>
|
||||
{{if .SMBDirectAddress}}
|
||||
<div class="form-hint">
|
||||
|
||||
Reference in New Issue
Block a user