[ { "date": "2026-09-22", "repo": "svx-web", "hash": "shared-libs-round-3", "type": "change", "summary": "Full shared lib set from callmgr2 (lib/*.js incl. ui_field, auth/lib/*.php incl. html.php); monitor and hover escapers on lib/fmt.js; valid_callsign/require_callsign once in auth/lib.php (node_cmd_api keeps its stricter amateur-format check as the validator argument). Not deployed yet." }, { "date": "2026-09-22", "repo": "svx-web", "hash": "shared-libs-round-2", "type": "change", "summary": "Shared libraries from callmgr2: changelog viewer, pager (monitor/TG monitor/trunks), message helpers, sign-in/register/sign-out transport, one theme.js (lib/theme.js), and PHP auth/lib/http.php + acl.php (JSON, CSRF, rate limit with this site's key namespace, require_privilege). No behaviour change; not deployed yet." }, { "date": "2026-09-22", "repo": "svx-web", "hash": "shared-libs", "type": "change", "summary": "Shared libraries from callmgr2 (copies under lib/ and auth/lib/): lib/api.js (status, lastheard and monitor fetches), lib/fmt.js (fmt2, callsign sort, frequency helpers in the CTCSS view), lib/ui_list.js (list editors, for coming editors), auth/lib/redis.php (Redis connection + batched read). No behaviour change." }, { "date": "2026-08-27", "repo": "svxdr", "hash": "tglist-sole-source", "type": "change", "summary": "FROZEN: the tglist is now the SOLE source of TG name/Location in Lastheard — all fallback removed (locForTG/systemForTG/bridgeIdentity no longer read live astmeta gateway location or nodes[].system). Every talker on a TG shows exactly the tglist name for that TG (blank if absent), so Lastheard is identical on every box. The master list is edited on speed and every box syncs it." }, { "date": "2026-08-27", "repo": "svx-web", "hash": "theme-focus-guard", "type": "fix", "summary": "Mirror of the DMR fix: the morning 'color' theme jump is gone. A theme and the color swatches — the swatch handler then forced 'color' with no user action, overwriting the cookie theme read at boot. Fix: autocomplete=off on the theme select and swatches, plus a user-gesture gate so a restore-fired event before any real interaction is ignored (swatches also require the Color modal to be open). Logged-out cookie behavior unchanged: no cookie -> dark default, saved cookie -> that theme." }, { "date": "2026-08-24", "repo": "svx-web", "hash": "theme-adopt-on-login", "type": "fix", "summary": "Theme now follows your account on login. The account (uuid) profile is the source of truth: signing in applies your saved theme + colours, overriding whatever the pre-paint boot used from the local cookie. Previously the profile was adopted only on a device with no theme cookie yet, so once you had ever picked a theme, logging in on that browser never restored your account theme. Adoption still runs once per page load (a change made later in the session is not clobbered), an account that never saved a theme keeps the cookie/dark boot, anonymous changes save to the cookie only, and logged-in changes save to both the cookie and the profile." }, { "date": "2026-08-22", "repo": "svx-web", "hash": "admin-secret-boundary", "type": "security", "summary": "Reflector/MQTT system secrets are now visible only to Admin L3 — the reflector config already masked KEY/PASSWORD/private values below L3, and that stays. Admin L1 is now strictly read-only: every mutating admin action (cert sign/revoke, node block, service reload/restart, config set/save, MQTT settings) is rejected with 'read_only_admin'. Admin L2 can now edit the reflector config and set secrets blind: secrets show as ******** and, on save, any purely-masked value is restored from the live file so a blind save can never overwrite a real secret with the mask, while a value L2 actually types is written through. A new admin_rank in me.php lets the UI tell L1 from L2 (admin_level collapsed both to 2)." }, { "date": "2026-08-22", "repo": "svx-web", "hash": "theme-colors-array-poison", "type": "fix", "summary": "Theme colour handling hardened (mirror of the DMR fix): colours could be stored as an empty array '[]' instead of an object; all read/write/adopt now funnels through one normaliser that collapses '[]', malformed cookies and stray values to {}, so a bad value can never throw or paint a broken palette, and the save endpoint can no longer emit '[]'." }, { "date": "2026-08-11", "repo": "svx-web", "hash": "theme-color-editor-restored", "type": "feat", "summary": "Color editor restored (🎨 next to the theme selector), now on the fixed CSP-safe engine so it actually works: opens a dialog to pick each part of the Color theme with labelled swatches (Background, Text, Secondary text, Borders, Panel, Accent) + accent quick-picks + reset. Colours are stored in a cookie (svxcolors) for everyone and synced to the account profile when signed in." }, { "date": "2026-08-11", "repo": "svx-web", "hash": "theme-csp-fix-cookie", "type": "fix", "summary": "Theme switch now actually works: the no-flash engine was an inline