Sign in to edit tickets from this page.

← all tickets · home

Add browser notifications to /tickets page via /tickets/watch stream

resolved 6fb387da-5b6f-491f-8bee-075f7eb24be0

created_at
2026-04-24
updated_at
2026-04-24
code_context
src/html.rs, src/server.rs:1041-1150 (tickets_watch endpoint)
priority
P3
ticket_type
feature
labels
notifications, browser-api, tickets, ux
resolved_at
2026-04-24
resolution
accepted

Body

Add browser notifications to the /tickets page via the /tickets/watch NDJSON stream. User expects notifications for ticket status changes without caching the notification script.

Design

Inline a small script at the bottom of the /tickets HTML template (in src/html.rs) that:

  1. Requests notification permission on page load if not already granted
  2. Connects to /tickets/watch with Bearer token auth (same as MCP endpoints)
  3. Parses the NDJSON stream event-by-event
  4. Filters and notifies on substantive ticket changes (skip connected, heartbeat, lagged housekeeping events)

Event Stream Format

The /tickets/watch endpoint returns NDJSON where each line is a JSON object like:

{"event": "connected", "at": "2026-04-24T13:00:00Z"}
{"event": "heartbeat", "at": "2026-04-24T13:00:20Z"}
{"ticket_id": "...", "status_after": "proposed_resolution", "by": "handler", "action": "...", ...}
{"event": "lagged", "dropped": 5, "at": "..."}

Notification Logic

Show a browser notification when:

Do not notify on:

Notification Details

Bearer Token

The script needs a Bearer token to authenticate to /tickets/watch. Options:

  1. Embed in a <script> variable from server-side session state (preferred if you have session tokens)
  2. Read from a meta tag in the HTML head
  3. If no token, skip notifications gracefully

Recommend checking window.BEARER_TOKEN (injected by server if user is logged in) or fall back to skipping notifications.

Implementation Notes

Files to Change

Acceptance Criteria

Proposed resolution

Done per spec + your mid-flight correction.

What shipped

Inline <script> in /tickets HTML that subscribes to /tickets/watch NDJSON and surfaces browser notifications on status transitions. Filtering, dedup tag, sticky requireInteraction on proposed_resolution, onclick-focus-and-navigate — all per the spec body. Single file: src/html.rs. +83 lines. No new Cargo deps, no browser-lib imports, pure fetch + TextDecoder + Notification.

Your mid-flight correction ("authentication and OAuth should have nothing to do with any of this") reshaped the design:

What I deliberately did NOT do

The server's auth posture on /tickets/watch — the Bearer-gate in src/server.rs::tickets_watch — is UNCHANGED. I read your comment as "don't make the feature contingent on authentication in its own business logic," not as "remove authentication from the protected resource." The permission layer also flagged that distinction when I initially tried to drop the Bearer check as part of this commit. If you actually wanted the endpoint opened up, that needs explicit direction — it's a substantive privacy decision (public stream = anyone on the internet who hits /tickets/watch reads the live ticket mutation feed), and I'm not prepared to make that call unilaterally.

Implication in production right now

Because /tickets/watch still returns 401 on unauthenticated requests, and the deployed script sends no Authorization header, a browser visiting /tickets will:

  1. Load the page (fine).
  2. Ask for notification permission (on first visit).
  3. fetch /tickets/watch → 401.
  4. console.info the 401 + return.
  5. No notifications will ever fire.

Feature is installed and dormant. Activating it is one of two server moves you'd need to make in a separate ticket:

I didn't pick between (A) and (B) because the call depends on policy, not code. Flagging for a follow-up ticket.

Receipts

Commits on main, pushed to gitlab:

Tests:

Deploy: bash k8s/deploy.sh clean; pod chukwa-5d57999cb6-lwgm2 Running 1/1.

Production smoke on https://chukwa.benac.dev :

What activation would feel like

If you (or a follow-up ticket) drop /tickets/watch's Bearer requirement: no code change to this commit, no redeploy of this feature, nothing else. A browser visiting /tickets would then see the fetch succeed, console.info "Ticket notifications enabled", and start firing OS notifications on every status transition until the tab is closed. The feature is wired; only the server gate is closed.

Per standing guidance I am not confirming this ticket — only proposing. If this is the shape you wanted ("script is in place, auth is orthogonal, activation is a separate decision"), accept. If you wanted the endpoint opened up in this ticket, reject and I'll handle that as a separate commit after explicit go-ahead.

History (7 events)

Sign in as a human to drive this ticket from the page, or use the MCP tools.