# Tasks: enterprise-websocket-gateway **Change ID**: enterprise-websocket-gateway **Package**: `@suaveplan/websocket-gateway` **Target path**: `api/framework/websocket-gateway` **Prerequisite packages on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`, `@suaveplan/events`, `@suaveplan/rate-limiter`, `@suaveplan/api` --- ## 1. Scaffold - [x] Create `api/framework/websocket-gateway/` with all subdirs per layout. - [x] `package.json` v0.0.0, `"sideEffects": false`, subpath exports. - [x] `tsconfig.json` extending `library-node.json`. - [x] `vitest.config.ts` via `createTestConfig()`. - [x] Scripts: `lint`, `typecheck`, `test`, `test:coverage`, `build`, `docs:check`, `bench`. --- ## 2. Types and errors - [x] `src/types/common.ts` — all interfaces and types listed in proposal. - [x] `src/types/common.md` (≥200 words, both examples). - [x] `src/errors/ws-errors.ts` — 6-code union, metadata, `registerWsGatewayErrorCodes()`. - [x] `ws-errors.test.ts` and `ws-errors.md`. --- ## 3. Connection - [x] `WsConnection` class: `id` (UUID), `userId`, `tenantId`, `topics: Set`, outbound `sendQueue` (bounded ring buffer of size `sendQueueSize`). - [x] `subscribe(topic)` / `unsubscribe(topic)`. - [x] `send(message)` — enqueue; drop oldest + increment `ws.queue_drops_total` if full. - [x] `close()` — flush queue, call `ws.close()`. - [x] `connection.test.ts`: subscribe/unsubscribe, send queued, queue-full drops oldest, close flushes. - [x] `connection.md`. --- ## 4. Heartbeat - [x] `HeartbeatManager`: sends ping every `heartbeatIntervalMs`; schedules `pingTimeoutMs` deadline per connection; on pong received, cancel deadline; on deadline exceeded, close connection. - [x] Injectable `Clock` for testability. - [x] `heartbeat.test.ts`: pong received cancels deadline, deadline exceeded closes connection. - [x] `heartbeat.md`. --- ## 5. WS Router - [x] `WsRouter`: registers `on(type: string, handler: WsMessageHandler)` handlers; routes inbound messages by `message.type`. - [x] `WsMessageEnvelopeSchema` (Zod) validates every inbound message; invalid → `WsGatewayError(WS_INVALID_MESSAGE)`. - [x] `ws-router.test.ts`: known type routed, unknown type → error, invalid envelope → error. - [x] `ws-router.md`. --- ## 6. Gateway - [x] `createWebSocketGateway(options)`: - Maintains `connections: Map`. - `handleUpgrade(app, path)` — registers Hono WebSocket route. - On connect: auth via `options.authenticate`; max-connections check; create `WsConnection`; start heartbeat; emit `ws:connected` event. - On message: rate-limit check; validate + route via `WsRouter`. - On disconnect: remove from map; stop heartbeat; emit `ws:disconnected` event. - `publish(topic, message)` — fan out to all connections subscribed to topic. - `broadcast(message)` — fan out to all connections. - `close()` — close all connections gracefully. - [x] OTel: `ws.connections_active` gauge updated on connect/disconnect; counters + histograms on message receive/send. - [x] `gateway.test.ts` (≤500 lines): connect + auth, auth failure closes ws, max-connections rejects, publish to topic, broadcast, rate-limited message dropped. - [x] `gateway.md`. --- ## 7. Hono adapter - [x] `createHonoWsAdapter(gateway: WebSocketGateway): (app: HonoApp, path: string) => void` — wraps Hono `upgradeWebSocket`; bridges native ws events to gateway lifecycle. - [x] `hono-ws-adapter.test.ts`: upgrade handled, message forwarded. - [x] `hono-ws-adapter.md`. --- ## 8. Benchmarks (`src/__benchmarks__/ws-gateway.bench.ts`) - [x] `ws_message_routing`: route 10 000 messages through `WsRouter` with 5 registered handlers. - [x] `ws_publish_100_connections`: `publish()` to a topic with 100 subscribers. --- ## 9. Integration tests (`tests/integration.test.ts`) - [x] Start a real Hono server + WebSocket gateway; connect N clients; send messages; assert routing + heartbeat + disconnect. --- ## 10. Docs and publish - [x] All co-located `.md` files (≥200 words, both examples, API reference). - [x] Root `README.md`. - [x] `bunx turbo lint typecheck test --filter=@suaveplan/websocket-gateway` — green. - [x] `bunx turbo test:coverage --filter=@suaveplan/websocket-gateway` — 100%. - [x] `bun scripts/publish.ts --package @suaveplan/websocket-gateway`. - [x] Archive → `openspec/archive/2026-04-24-enterprise-websocket-gateway/`.