# Tasks: enterprise-api-plugin-sse **Change ID**: enterprise-api-plugin-sse **Package**: `@suaveplan/api-plugin-sse` **Target path**: `api/data/api-plugin-sse` **Prerequisite packages on Verdaccio**: `@suaveplan/api`, `@suaveplan/api-shared`, `@suaveplan/api-plugin-auth`, `@suaveplan/events`, `@suaveplan/rate-limiter`, `@suaveplan/error` --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold + types + errors + events - [ ] Create directory; `package.json` v0.0.0; standard tooling. - [ ] Types: `SseEvent`, `SseConnection`, `SsePluginConfig` (Zod). - [ ] Errors: 3-code union + registration. Test + doc. - [ ] Events: `SsePluginEventMap` (sse:client:connected, sse:client:disconnected). --- ## 2. Connection manager - [ ] `ConnectionManager`: `Map` keyed by `userId:topic`. On connect: auth check, rate-limit, max-connections check; create connection; start heartbeat. On disconnect: remove + emit event. - [ ] Heartbeat: send `event: ping` every `heartbeatIntervalMs` (default 30 s); connection dropped if client disconnects. - [ ] Backpressure: bounded send queue per connection; drop oldest on full. - [ ] `connection-manager.test.ts` + `connection-manager.md`. --- ## 3. SseService - [ ] `publish(topic, event)` — fan out to all connections subscribed to `topic`; encode as SSE wire format (`data: ...\n\n`). - [ ] `broadcast(event)` — fan out to all connections. - [ ] `connectionCount()`, `getTopicConnectionCount(topic)`. - [ ] Subscribe to `@suaveplan/events` bus topics in `onInit`; forward to matching SSE connections. - [ ] OTel gauge `sse.connections_active`; counter `sse.events_sent_total`. - [ ] `sse.service.test.ts` + `sse.service.md`. --- ## 4. Routes - [ ] `GET /sse/stream?topic=...` — `requireAuth`; returns SSE stream (Hono `streamSSE`). Rate-limited on connections. - [ ] `GET /sse/stats` — admin; returns connection counts. - [ ] Route `.test.ts` + `.md`. --- ## 5. Plugin factory + integration tests + publish - [ ] `createSsePlugin`: `definePlugin`, `dependencies: ["auth"]`; subscribe to bus in `onInit`; detach in `onClose`. - [ ] Integration: connect client → publish event via bus → received by SSE stream. - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-sse` — green; 100% coverage. - [ ] `bun scripts/publish.ts --package @suaveplan/api-plugin-sse`. - [ ] Archive → `openspec/archive/2026-04-24-enterprise-api-plugin-sse/`.