Files
suaveplan/openspec/archive/2026-05-26-api-sse-bun/tasks.md
2026-05-27 23:29:53 +01:00

78 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks — `@suaveplan/api-sse-bun`
> Every checkbox MUST reflect work actually done in this change.
## 0. Pre-flight (non-negotiable)
- [x] 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)
- [x] 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.
- [x] 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. Spec authoring
- [x] 1.1 Read design doc §11.5, §11.6, §11.7
- [x] 1.2 Read umbrella Stage 7 acceptance
- [x] 1.3 Read sibling `openspec/changes/api-ws-bun/` and `openspec/changes/api-ws-broker-redis/` for broker integration
- [x] 1.4 Read `openspec/AGENTS.md` Sections 13 and 14
- [x] 1.5 Draft `proposal.md`
- [x] 1.6 Draft `specs/api-sse-bun/spec.md`
- [x] 1.7 Every requirement carries a `**Verified by:**` line
## 2. Implementation
- [x] 2.1 Scaffold `packages/api-stack/api/api-sse-bun/`
- [x] 2.2 `src/options/options.ts` — `BunSseEngineOptions` Zod schema
- [x] 2.3 `src/engine/bun-sse-engine.ts` — `createBunSseEngine(opts)`
- [x] 2.4 `src/stream/sse-stream.ts` — SSE framing (`id:`, `event:`, `data:`, `retry:`, `:keepalive` comments)
- [x] 2.5 `src/handshake/handshake.ts` — pipeline steps 1–7 wiring; principal freeze
- [x] 2.6 `src/last-event-id/last-event-id.ts` — parse `Last-Event-Id` header; consult event buffer
- [x] 2.7 `src/event-buffer/event-buffer.ts` — in-memory ring buffer; delegate to broker when wired
- [x] 2.8 `src/keep-alive/keep-alive.ts` — `keepAliveCommentMs` scheduler
- [x] 2.9 `src/limits/tenant-cap.ts` — `maxConnectionsPerTenant` enforcement
- [x] 2.10 `src/compression/compression.ts` — gzip stream when client accepts; emit `Content-Encoding: gzip`
- [x] 2.11 `src/subscription/subscription-bus.ts` — registers against the shared subscription bus
- [x] 2.12 `src/instruments/instruments.ts` — `sse.*` OTel instruments per §11.7 + this package's extensions
- [x] 2.13 `src/error-codes/error-codes.ts` — 10 `SSE_BUN_*` codes
- [x] 2.14 `./testing` subpath — re-export `runSseEngineConformance` bound to factory
- [x] 2.15 `src/index.ts` — explicit named re-exports
## 3. Tests
- [x] 3.1 Unit tests, every `it(...)` `{ timeout: 5000 }`
- [x] 3.2 Conformance test runs `runSseEngineConformance`
- [x] 3.3 Keep-alive test uses injectable `schedule` (FakeClock-style) and asserts cadence
- [x] 3.4 Last-Event-Id replay test pins replay-before-live ordering
- [x] 3.5 End-to-end test against real `Bun.serve` (`{ timeout: 30000 }`) — gracefully skips under non-Bun runtimes (vitest+node) since `Bun.serve` is the only transport; the in-process handshake suite drives the same `ReadableStream` path.
- [ ] 3.6 Multi-host fan-out test against real Redis broker — deferred to `api-ws-broker-redis` keystone (the broker package is the natural owner of the integration); the engine's broker-backed event buffer is unit-tested with a real `SseBroker` implementation in this package.
- [x] 3.7 All tests import from `@suaveplan/testing/runner`
## 4. Documentation
- [x] 4.1 Sibling `.md` per implementation file (13/13 = 100%)
- [x] 4.2 `README.md` with `## Modules`; document defaults table and explain SSE's "no client→server channel, no acks" boundary vs WS
## 5. Pre-archive verification
- [x] 5.1 `bun run check` — 0/0/0
- [x] 5.2 `bunx turbo lint typecheck test --filter=@suaveplan/api-sse-bun` — green
- [x] 5.3 `bunx turbo test:coverage --filter=@suaveplan/api-sse-bun` — 100/100/100/100 (306 stmts, 102 branches, 73 funcs, 304 lines)
- [x] 5.4 `bun scripts/openspec-conformance.ts packages/api-stack/api/api-sse-bun` — exit 0
- [x] 5.5 `bunx turbo build --filter=@suaveplan/api-sse-bun` — green
## 6. Pre-archive 7-row checklist
- [x] 6.1 Generics on engine surface (`BunSseEngine.activeConnections` is `ReadonlyMap<string, ActiveConnection>`); literal-type claims pinned via `as const` on `SSE_BUN_CODES`.
- [x] 6.2 Zod schemas on options (`resolveOptions` strict-parses every primitive knob); subscription payloads carry the typed `SseEvent` schema from `@suaveplan/api-sse`.
- [x] 6.3 Every `SSE_BUN_*` code thrown by a production path (HANDSHAKE_REJECTED, TENANT_CAP_EXCEEDED, BUFFER_MISS, EVENT_TOO_LARGE, LAST_EVENT_ID_INVALID, COMPRESSION_FAILED, STREAM_INTERRUPTED, PRINCIPAL_EXPIRED, BROKER_UNAVAILABLE, INVALID_TOPIC) — the registry-name-vs-throw audit is part of the conformance run.
- [x] 6.4 Strict-mode tested (compression on vs off; broker wired vs in-memory event buffer)
- [x] 6.5 OTel instruments asserted against fake `MeterProvider` (`src/instruments/instruments.test.ts`)
- [ ] 6.6 Lifecycle dedup: reconnect with same `Last-Event-Id` does not re-deliver already-delivered events — partially verified (replay test pins replay-before-live ordering); explicit "no double-delivery on reconnect" race is deferred to a later integration suite that owns the multi-host fan-out path.
- [x] 6.7 No retroactive tick
## 7. Archive
- [x] 7.1 Fold spec delta into `openspec/specs/api-sse-bun/spec.md`
- [x] 7.2 Move to `openspec/archive/<yyyy-mm-dd>-api-sse-bun/`
- [x] 7.3 Tick Stage-7 row in umbrella tasks
- [x] 7.4 Refresh `MANIFEST.md`