Files
2026-05-27 23:29:53 +01:00

3.0 KiB

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<clientId, SseConnection> 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/.