Client (ts/network_ts.ts): one WebSocket per page. Commands queue and go
out one at a time with a client-chosen id; the response is matched on the
echoed id (or to the in-flight request for older servers). 12 s timeout
per request, exponential-backoff reconnect (0.5 s to 10 s), the in-flight
request is retried after a reconnect, and log polls are de-duplicated so
they cannot pile up behind a stalled connection. The old global flag that
silently dropped any request made while another was in flight is gone.
Server (src/webserver.go): the /data/ handler now serves any number of
commands on one connection (it used to break out of its loop after the
first reply without closing the socket, leaving it open and deaf; the old
client papered over that by opening a new socket per request). Connection
closed on exit, request id echoed in the response.
Test: TestWSServesMultipleCommandsPerConnection.
- Provider-controlled strings (channel names, groups, file names, log
lines, in-place mapping edits, client info) are rendered with
textContent instead of innerHTML. PopupContent.description() takes an
explicit isHTML flag that only the static help texts pass.
- Websocket: drop the always-true CheckOrigin so gorilla's same-origin
check applies; read the session token from the HttpOnly cookie sent with
the handshake (the ?Token= query parameter is still accepted for older
clients); the client no longer puts the token in the URL, rewrites the
cookie, or console-logs request/response payloads.
- Session cookie is HttpOnly, SameSite=Strict, Path=/, session-scoped
(expiry stays server side) and is cleared on logout.
- Serving the first-run wizard no longer sets Settings.AuthenticationWEB
to false; the wizard page simply bypasses login while it is active.
- Upgrade failures no longer write a second error response.
- Tests: src/websocket_test.go covers cross-origin refusal, same-origin
and no-Origin clients, missing/unknown/legacy tokens, and cookie flags.
- html/embed.go embeds html/ (pages, css, img, js, video); src/assets.go
serves it, with os.DirFS("html") under -dev. Static assets get an ETag
and Cache-Control: no-cache; HTML pages are still templated (only the
login error message is substituted now).
- Delete the generated src/webUI.go (783 KB base64), src/html-build.go and
cmd/webui-gen; Dockerfile no longer runs a generator.
- Language layer removed: 254 {{.x}} placeholders inlined as English
strings in ts/*.ts and the two auth pages; html/lang/en.json, the
LanguageUI struct and the 'language' setting are gone.
- ts/tsconfig.json + package.json pin typescript 5.9.3; the seven sources
compile (ES2020, global scripts) into one committed html/js/app.js.
Ten unreferenced legacy scripts under html/js/ deleted; all pages load
js/app.js.
- Fix the six type errors that blocked a clean compile, including a real
bug: a missing semicolon in the search shortcut handler made the code
call the result of preventDefault(), so the shortcut threw instead of
focusing the search box.
- /healthz liveness endpoint; Dockerfile healthcheck and README use it.
- Drone: go vet, and a webui-check step that rebuilds the bundle and fails
if the committed app.js is stale.
- README-DEV.md documents build, UI toolchain, -dev, versioning, CI.
Stores `""` to `x-category` when the category is unset, previosuly `"-"` was stored which would append a `<category>` to each `<programme>` for the channel.
fixes#209