Files
felhom-controller/REPORT.md
T
admin fd40b29119 docs: v0.152.0 REPORT/CONTEXT + fix an async race in TestFabUpload_GCAndIdleTimeout
The fab-upload GC test stat-ed the .part immediately after observing the slot
free, but expireIdleUpload unlinks AFTER releasing the mutex. Passed alone,
failed in the full package once this release's render tests made web heavier.
Not a production defect - a new upload mints a fresh random .part. The test now
waits for the outcome it asserts on the same deadline; red-proofed by removing
the unlink from production.
2026-07-20 13:55:03 +02:00

154 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — v0.152.0 + felhom-samba 1.1.0: mDNS for macOS (S-3), and the connect card stops offering a dead form
**Date:** 2026-07-20 · **Repo:** felhom-controller (v0.151.0 → **v0.152.0**) + **felhom-samba
1.0.0 → 1.1.0** · Trunk, pushed to `main`.
**Origin:** operator report — `smb://FELHOM` still failing from a Mac after v0.151.0; S-3 of
`felhom.eu/documentation/audits/DIAG-sharing-2026-07-20.md`.
## Baselines
| Repo / artifact | start | end |
|---|---|---|
| felhom-controller | `5c105fb`, v0.151.0 live on 9201 | `37e12c8` (+ this docs commit), **v0.152.0** |
| felhom-samba | `1.0.0` | **`1.1.0`**, digest `sha256:1c17c094…` |
| felhom.eu | `a7d9837` | `1d1d60a` |
## The finding that redirected the fix
My earlier conclusion — "macOS no longer does NetBIOS" — **was wrong**, and a packet capture on the
box disproved it. On a bare `smb://FELHOM` from the operator's Mac (`192.168.0.11`):
```
11:18:30.222080 .11:52844 > 192.168.0.255:137 NBNS query, 50 B
name → "FELHOM" + 9 pad + suffix 0x20 (File Server Service — correct for SMB)
11:18:30.222220 .104:137 > .11:52844 NBNS response, 62 B, +140 µs
flags 0x8580 = response, AUTHORITATIVE, RCODE=0 · ANCOUNT 1
TTL 259200 · NB_FLAGS 0x0000 (unique, B-node) · RDATA 192.168.0.104
```
**macOS asked correctly, was answered correctly in 140 microseconds, and never opened a TCP
connection.** It retried once, was answered again, gave up. Sixteen seconds later the same Mac
queried `FELHOM.local` over mDNS and went straight to port 445.
So NetBIOS on macOS feeds legacy browsing, not `smb://` URL resolution: **the bare `smb://<NÉV>`
cannot be made to work from a Mac by any change on our side**, and nmbd — which the R-6/S4b spike
was right to insist on — was never the broken part. It is precisely what serves Windows.
Investigated and dismissed: the box answers **twice** per broadcast (nmbd holds `0.0.0.0:137`,
`<ip>:137` and `<bcast>:137`; a broadcast lands on two). Standard Samba, and a duplicated correct
answer is still a correct answer that macOS declined to use.
### Proven matrix
| Client | Working form | Served by |
|---|---|---|
| Windows | `\\<NÉV>` | nmbd (+ wsdd for the Network view) |
| macOS | **`smb://<NÉV>.local`** | avahi/mDNS — new in 1.1.0 |
| Any | `smb://<IP>` | direct |
## Method — spike before publish (operator's call, and it paid)
avahi was installed by hand into the *running* container and configured, then proven from a second
machine before any image was built. The operator confirmed `smb://FELHOM.local` connects. Only then
was 1.1.0 built. The spike also chose the design: a **static avahi service file** beats smbd's own
`multicast dns register`, because `smb.conf` is bind-mounted READ-ONLY and owned by the controller's
renderer, and a static file additionally publishes `_device-info._tcp`.
## Changes
| File | Change |
|---|---|
| `controller/infra-images/samba/Dockerfile` | `avahi` + `dbus` added; `rm` of packaged service files; header documents the captured NBNS proof and that sidebar discovery is NOT claimed |
| `controller/infra-images/samba/entrypoint.sh` | templates `avahi-daemon.conf` + `_smb._tcp`/`_device-info._tcp` service file **from `FELHOM_SERVER_NAME`**; starts dbus + avahi, both **non-fatal** |
| `controller/internal/infra/infra.go` | `SambaImage` pin → `1.1.0` (`Images()` and the golden bake follow automatically) |
| `controller/internal/web/templates/sharing.html` | Mac line `smb://<NÉV>`**`smb://<NÉV>.local`**; Windows flat name untouched |
| `controller/internal/web/sharing_connect_card_test.go` | assertions updated + new `TestSharingConnectCard_MacLineIsDotLocalNotBareName` |
| `controller/internal/infra/samba_test.go` | tag assertion derives from `SambaImage`; adds an explicit non-`:latest` assertion |
| `controller/internal/web/handler_export_upload_test.go` | async-race fix (below) |
| `CHANGELOG.md`, `controller/README.md`, `REPORT.md` | docs |
## Tests
**23/23 packages green, run twice with `-count=1`.**
Red-proofs, both mutated → FAILED → restored:
| Mutation | Result |
|---|---|
| revert the template's Mac line to the bare `smb://{{.SMBServerName}}` | `TestSharingConnectCard_MacLineIsDotLocalNotBareName` **FAILED** on both the missing `.local` and the present bare form, for both configured names (`FELHOM`, `OTTHON`) |
| delete `os.Remove(job.partPath)` from `expireIdleUpload` | `TestFabUpload_GCAndIdleTimeout` **FAILED**`idle-expired .part must be deleted` |
### Two test bugs found, neither a production defect
1. **`TestRenderSambaCompose` pinned the literal tag `1.0.0`**, so a routine image bump read as a
renderer regression. Now derives from `SambaImage`, plus a separate assertion for what actually
matters — the tag is explicit and never `:latest`.
2. **`TestFabUpload_GCAndIdleTimeout` raced.** `expireIdleUpload` nils the slot, releases the mutex,
and only *then* closes and unlinks the `.part` — so "the slot is free" does not yet mean "the file
is gone", and the test stat-ed immediately. It passed in isolation and failed in the full package
once this release's new render tests made `web` heavier. **Not caused by this change and not a
production bug** (a new upload mints a fresh random `.part`, so the gap is harmless); the test was
asserting an async post-condition synchronously. It now waits on the same 3 s deadline with the
assertion unchanged.
Design gates `template_id_gate` / `emoji_gate` / `native_confirm_gate` / `offbox_rename_gate`: **OK**.
## Build, publish, deploy
```
./controller/scripts/build-samba-image.sh 1.1.0 --push → sha256:1c17c09422be…
smoke test (DooPlex, DEFAULT BRIDGE — never --network host on this host, it would bind 445/5353)
→ smbd · nmbd · wsdd · dbus-daemon · avahi-daemon: running [SMOKETEST.local] (all 5 up)
→ host-name=SMOKETEST, allow-interfaces=eth0, _smb._tcp/445 in the service file
anonymous pull from guest 9201 (no registry creds) → OK
./build.sh 0.152.0 --push → deployed to 9201
```
Live: `felhom-controller:0.152.0 Up (healthy)` · `felhom-samba:1.1.0 Up` — the controller's reconcile
recreated the samba container onto the real image, discarding the hand-patched spike.
## Live validation
**Method: on-the-wire from a second machine (felhom-pve) + endpoint-level for the page.**
```
mDNS from felhom-pve, against the SHIPPED image:
FELHOM.local (A) -> A 192.168.0.104 (from 192.168.0.104)
_smb._tcp (browse) -> PTR FELHOM._smb._tcp.local (from 192.168.0.104)
daemons in felhom-samba:1.1.0: smbd · nmbd · wsdd · dbus-daemon · avahi-daemon: running [FELHOM.local]
GET /sharing -> smb://FELHOM.local smb://192.168.0.104 \\FELHOM
GET /sharing/status ×2 -> phase:"idle", running:true (v0.151.0 contract still holding)
```
Operator, from the Mac: **`smb://FELHOM.local` connects and prompts for credentials.**
## Still open
- **Finder-sidebar discovery — NOT shipped, NOT claimed.** The `_smb._tcp` record is published and
answers browse queries on the wire, but FELHOM did not appear in the operator's Finder sidebar.
That window showed no Network/Bonjour section at all, which points at **Finder Settings → Sidebar
→ Locations** rather than at the box — unverified either way. Next: that setting, and
`dns-sd -B _smb._tcp` on the Mac. Zero-typing discovery was the R-6 spike's original ambition and
is still not demonstrated.
- **Windows was not retested** this session. `\\FELHOM` is served by nmbd, which this release does
not touch, and the capture proves nmbd answers correctly — but no Windows client was exercised.
## Observations — noticed, not acted on
- **The username trap.** macOS prefills the local account name (`Viktor.Nagyfenyvesi`) in the SMB
credential dialog; the household account is `felhom`. The page states this in the password card,
but not next to the connect addresses where the customer is looking at that moment. Worth a
sentence in the connect card — deliberately not added mid-session without a design pass.
- **nmbd's duplicate answer** is harmless here but would look alarming in any future capture. Noted
in the DIAG so the next person does not re-investigate it.
- **The spike left avahi installed by hand** in the old container. It was discarded when the
reconcile recreated the container on 1.1.0 — worth remembering that hand-patching a *managed*
infra container is always temporary by construction, which is a safety property, not a limitation.
- **`dns-sd`/`avahi-browse` were not available** anywhere on the box side, so both the NBNS and mDNS
verifications were done with small hand-written UDP probes run from felhom-pve. That turned out to
be the more valuable method anyway: querying from a *second machine* is what distinguishes "the
daemon answers itself" from "the daemon answers the network", and it is what proved the box
innocent before any code changed.