diff --git a/CHANGELOG.md b/CHANGELOG.md index cd06d73..090b53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,50 @@ ## Changelog +### v0.151.0 — the Megosztás page stops reloading, and says how to connect (2026-07-20) + +Closes **S-1**, **S-2**, **S-5** and the core of **S-4** from +`felhom.eu/documentation/audits/DIAG-sharing-2026-07-20.md`. + +**S-1 — `/sharing` reload-looped about once a second, for every customer with sharing enabled.** +`GET /sharing/status` carries two things that mean different things to the client: `phase` (the +ensure JOB — the page answers a terminal `running` with a one-shot `location.reload()`, because the +„Állapot" badge is server-rendered) and `running` (the service LEVEL, straight from the liveness +probe). v0.147.0 coerced `idle`→`running` on the PHASE channel so that a missing job could never +contradict a live container. That duty was real, but it belongs to — and was already discharged by — +the `running` field beside it; on the phase channel the same value reads as a fresh success edge. The +poll's `tick()` runs synchronously at script end, so the FIRST poll of every steady-state page load +reported a terminal job that had never run, scheduled a reload 1.2s later, and the new page did it +again. The coercion is gone: no job, no edge. The defensive intent it was written for is now pinned +by its own named regression test on the `running` field. + +**S-4 (core) — a REAL bring-up is now reported exactly once.** Without this the loop would return +after every future image update: the finished job outlives the reload it triggered, so the next page +load found `phase:"running"` waiting for it. `consumeIfRunning` serves a terminal `running` once and +clears it — and only while the single-flight slot is free, since the job goroutine sets the phase +before its deferred `release()` and eating it in that window would lose the success the customer is +waiting on. `failed` and `needs_password` stay sticky (their client path stops the timer and shows a +card with NO reload, so stickiness is informative and cannot loop), and in-flight phases are never +consumed. Accepted cost, stated rather than hidden: with two tabs open during a bring-up only the +first gets the success banner — both still show the true state, which comes from the level channel. +The unified async-job feedback layer remains the ROADMAP item; this is the minimal contract fix. + +**S-2 + S-5 — the page now names both ways in.** It had only ever shown the configured NetBIOS name, +so a customer whose network fails to resolve it had no fallback but a guess — and the guess that +produced the diagnosis was the Proxmox HOST's address, which never ran smbd. New +„Csatlakozás a megosztáshoz" card: the Windows form, the Mac form, and the direct `smb://`. +The address comes from `stacks.SambaLANAddress()`, which reads the guest's netns through the SAMBA +container (`network_mode: host`) — the controller is on a docker bridge and would answer `172.x`, +the same trap `setup.DetectLocalIPs` needs `HOST_IP` for. Reading it there also makes it the right +kind of true: it is the address smbd is bound to, not merely one the box owns. **Derived per render +and cached nowhere** — the guest holds it by DHCP, so a stored copy eventually misdirects people +(S-5) — and an underivable address omits the line, because no address beats a wrong address. + +`sharing.html`'s `