v1.0.2
A frontend correctness and security release from a comprehensive multi-agent frontend bug hunt (UI, logic, reactivity, leaks and security), plus a hardening of how the browser authenticates the live-streaming endpoints. The headline item is single-use stream tickets: the session token no longer travels in WebSocket/SSE URLs (where reverse proxies log it). One additive database migration (049_stream_tickets); otherwise a drop-in upgrade.
Security
- Session token no longer placed in WebSocket/SSE URLs: browser
WebSocketandEventSourcecannot send anAuthorizationheader, so the log live-tail (/api/v1/logs/ws), the SIEM events stream (/api/v1/siem/events) and the trace live-tail (/api/v1/traces/stream) previously carried the long-lived session token in the URL query string, where it is logged by proxies and servers. The client now mints a short-lived, single-use stream ticket via an authenticatedPOST /api/v1/stream-ticketsand passes that ticket instead. Tickets live in the relational database (not Redis, so the mechanism is portable across the BullMQ and graphile queue backends), expire in 30s and are consumed on first use. The legacy?token=path still works for backward compatibility - Webhook channel secrets no longer rehydrated into the DOM: editing a notification channel no longer pre-fills the bearer token / basic-auth password inputs with the stored secret; the fields stay empty with a "leave blank to keep current" hint and are only sent when the user types a new value
- OIDC callback strips the session token from the URL after reading it, so it no longer lingers in browser history, the referrer or logs
- Admin pages enforce a client-side admin guard: several admin views (user detail, usage, organization detail) loaded and could mutate data on mount without checking the admin role; they now redirect non-admins, and the admin section layout has a guard of its own
- Removed a debug
console.logthat leaked log message content and api-key metadata to the browser console on the error-detail page
Added
- Global 401 handler: a single fetch interceptor installed at app startup clears local auth state and redirects to the login page (preserving the current path so the user lands back there after signing in) on any authenticated
/api/v1401 that is not an auth endpoint. Previously a revoked or expired session was only detected on a full dashboard remount, so a logged-out user could keep clicking around getting silent failures POST /api/v1/stream-ticketsendpoint andstream_ticketstable (migration 049) backing the stream-ticket auth described above
Fixed
- Stale-response races: overlapping loads triggered by fast filter/pagination changes could let an older in-flight response overwrite fresher results. Added local request-sequence guards on the log search, traces list, error groups, SIEM incidents, monitor detail/list, custom-dashboard panels and alert-preview views
- API client error handling: error-branch
response.json()calls are guarded so a non-JSON error body (reverse-proxy 502/HTML, empty204) no longer throws aSyntaxErrorthat masks the real HTTP failure (auth, admin and exceptions clients) - Locale-stable formatting: user-facing dates and numbers now use explicit
en-USformatting across the status pages, members, project settings, traces, metrics, search and notification-channel views; alert-history timestamps no longer label UTC values as if they were local time - Lifecycle and memory leaks: component store subscriptions are auto-managed, a first-run shortcut-hint
setTimeoutis cleared on unmount, and chart instances are disposed, so navigating away no longer leaves timers, listeners or subscriptions behind - Svelte 5 reactivity and assorted UI fixes: the trace detail page reloads when navigating between traces; the api-key DSN preserves an
http://scheme for non-TLS deployments; the "View Error Group" action navigates with a param the target page actually reads; SigmaSync no longer crashes when a commit hash is absent; the toaster follows the app theme; the delete-organization confirm is disabled while in flight; PII masking rules require a regex or field names; numeric monitor inputs guard againstNaN; and the audit-log resource cell no longer renders a literal escape sequence - ClickHouse: materialized-view backfills now run once instead of on every startup
Notes
- Left intentionally unchanged: storing the session token in
localStorage(a disputed, low-severity finding). Moving it to an httpOnly cookie would trade XSS token-theft for CSRF surface and a full auth-model overhaul without a clear net win; the high-leverage XSS defenses (CSP, output sanitization, auditing the few{@html}sites) are tracked separately