SSE caseload filtering (op-infra Step 9 follow-up)
Context
Op-infra Step 9 shipped SSE infrastructure on canopy-web (single AMQP queue + tokio broadcast + browser EventSource). The htmx-sse extension half closed in MR !188 (2026-05-04). One scope item remains: caseload filtering.
Caseload-based filtering (plan §9.2)
The plan calls for filtering by the worker's assigned caseload. Today the SSE handler broadcasts every routing-key-matched event to every connected worker. This is fine for a small worker pool, but at scale it leaks events about cases the worker isn't responsible for.
Blocker: there is no caseload-membership store yet. Adding one is a larger design (per-worker assignment model, supervisor reassignment workflow, ownership transitions) outside Step 9's scope.
When that lands, the SSE handler reads the worker's caseload from session and filters envelope payloads server-side before sending to the per-connection receiver. The broadcast hub stays single-shard.
Acceptance criteria
- Caseload-filtering: handler reads worker's caseload from session, filters envelope payloads before send. Gated on broader case-management work.
Resolved sub-items
htmx-sse extension wiring— closed in MR !188 (2026-05-04). `htmx-sse.min.js` v2.2.4 vendored under `services/canopy-web/static/vendor/`. Base template uses ``. Hand-rolled `EventSource` IIFE in `canopy-web.js` retired (zero consumers). Page templates can now use `sse-swap="event_name"` for HTML fragments or `hx-trigger="sse:event_name from:body"` for fetch-on-notify (the right pattern for our JSON envelopes).Notice/appeal publishers wired— these were ALREADY published when Step 9 shipped. `notice.generated` / `appeal.filed` are bound by the SSE allowlist.- `assignment.created` remains forward-compat — there is no canopy-assignments service yet (post-UAT).
Source
Op-infra plan Step 9 implementation (MR !154 (merged)). Scope reduced 2026-05-01 (publishers verified extant) and 2026-05-04 (htmx-sse extension closed).