Initial Commit
This commit is contained in:
99
openspec/archive/2026-05-12-websocket-gateway/proposal.md
Normal file
99
openspec/archive/2026-05-12-websocket-gateway/proposal.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# OpenSpec Change: websocket-gateway
|
||||
|
||||
- **Change ID**: websocket-gateway
|
||||
- **Package**: `@suaveplan/websocket-gateway`
|
||||
- **Category**: server (Node-only)
|
||||
- **Target path**: `packages/network/websocket-gateway`
|
||||
- **Status**: PROPOSED
|
||||
- **Date**: 2026-05-11
|
||||
- **Parent**: `network-transport-family` (2026-05-11) — Wave 5
|
||||
- **Migration source**: `../suaveplan/packages/server/websocket-gateway` + `../suaveplan/enterprise/websocket-gateway.md`
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Migrate `@suaveplan/websocket-gateway` into genesis as a server-tier daemon providing **rooms + presence** semantics over WebSocket connections. Pairs with `@suaveplan/network-transport-websockets` ✅ (post-Wave-1 adapter refactor) on the client side. Rooms scope message delivery; presence tracks who is connected to which room; channel multiplexing lets multiple logical streams share one TCP connection.
|
||||
|
||||
---
|
||||
|
||||
## Why Wave 5 (not earlier)
|
||||
|
||||
- Depends on the `network-transport-websockets-adapter` Wave-1 refactor (server-side rooms need the `Transport` contract on the client side).
|
||||
- Server-tier package — bundles with Wave-4 transports, not Wave-3 browser packages.
|
||||
|
||||
---
|
||||
|
||||
## Current-state audit
|
||||
|
||||
Upstream coverage: 97.85% statement.
|
||||
|
||||
Upstream source layout (`../suaveplan/packages/server/websocket-gateway/src/`):
|
||||
|
||||
- `gateway/` — main `WebSocketGateway` daemon
|
||||
- `channel/` — channel multiplexing
|
||||
- `room/` — room semantics (join / leave / broadcast / direct)
|
||||
- `presence/` — presence subsystem (who's in which room)
|
||||
- `types/` — public type surface
|
||||
- `index.ts` — barrel
|
||||
|
||||
---
|
||||
|
||||
## Parity Checklist
|
||||
|
||||
| Capability | Upstream | Migrated | Notes |
|
||||
|---|---|---|---|
|
||||
| `WebSocketGateway` daemon | ✅ | ✅ | |
|
||||
| Room semantics (join/leave/broadcast/direct) | ✅ | ✅ | |
|
||||
| Presence tracking | ✅ | ✅ | |
|
||||
| Channel multiplexing | ✅ | ✅ | |
|
||||
| Plugin wiring via `@suaveplan/api` `definePlugin()` | upstream-required | ⬆️ | Once `@suaveplan/api` lands on genesis (not yet ✅), wire via `definePlugin()`. Until then a standalone `start()`/`stop()` lifecycle. |
|
||||
| JWT auth via `@suaveplan/jwt-tenant` | upstream-required | ⬆️ | Once shipped on genesis. Until then inject `AuthVerifier` callback. |
|
||||
| RBAC/ABAC via `@suaveplan/permissions` | upstream-required | ⬆️ | Same: inject `AuthorizationCheck` callback. |
|
||||
| Rate-limiting via `@suaveplan/rate-limiter` | upstream-required | ⬆️ | Once available. |
|
||||
| Idempotency via `@suaveplan/idempotency` ✅ | upstream-required | ✅ | Wired directly. |
|
||||
| Audit logging via `@suaveplan/audit-logging` | upstream-required | ⬆️ | Once available. Until then `@suaveplan/logger` ✅ with structured fields. |
|
||||
| OTel spans + Prometheus metrics | upstream-required | ⬆️ | Spans `ws_gateway.connect`/`message`/`broadcast`, counters `ws_gateway.rooms_active`, `ws_gateway.presence_updates_total`, histograms `ws_gateway.message_dispatch_ms`. |
|
||||
| `AbortSignal` everywhere | partial | ⬆️ | Threaded through every lifecycle method. |
|
||||
| Retry + circuit breakers via `@suaveplan/retry` ✅ | upstream-required | ✅ | Wired on every outbound integration. |
|
||||
| Health / readiness / liveness | upstream-required | ⬆️ | Inline `/health`, `/ready`, `/live` endpoints until `@suaveplan/health-check` lands. |
|
||||
| Webhooks via `@suaveplan/webhook-client` ✅ | upstream-required | ✅ | Wired for presence-event webhooks. |
|
||||
| Structured errors | 🚫 | ⬆️ | `defineCodes("WS_GATEWAY", [...])`: `ROOM_NOT_FOUND`, `ROOM_FULL`, `CHANNEL_INVALID`, `AUTH_REJECTED`, `RATE_LIMITED`, `INVALID_OPTIONS`. |
|
||||
| Zod boundary validation | partial | ⬆️ | Every public option + every wire frame. |
|
||||
| `export *` barrels | check | ⬆️ | Convert to explicit named exports per §6a. |
|
||||
| Test-runner imports | direct vitest | ⬆️ | Rewrite to `@suaveplan/testing/runner` per §7. |
|
||||
| 100% test coverage | 🚫 (97.85%) | ⬆️ | Bring to 100/100/100/100. |
|
||||
| Integration tests | partial | ⬆️ | Real-server boot via `@suaveplan/testing-integration`; no mocks. |
|
||||
|
||||
---
|
||||
|
||||
## Available workspace deps on genesis
|
||||
|
||||
- `@suaveplan/network-transport-websockets` ⬅ post-Wave-1 (after adapter refactor)
|
||||
- `@suaveplan/idempotency` ✅
|
||||
- `@suaveplan/retry` ✅
|
||||
- `@suaveplan/webhook-client` ✅
|
||||
- `@suaveplan/logger` ✅
|
||||
- `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/timing` ✅
|
||||
- `@suaveplan/testing` + `@suaveplan/testing-integration` ✅
|
||||
- External: `ws` or `bun:websocket` (universal façade) — add to root catalog under `network-server`.
|
||||
|
||||
**Blocking note.** Migration can start once `network-transport-websockets-adapter` ships and (optionally) `@suaveplan/api`, `@suaveplan/jwt-tenant`, `@suaveplan/permissions`, `@suaveplan/rate-limiter`, `@suaveplan/audit-logging`, `@suaveplan/health-check` are on genesis. Auth and rate-limit hooks accept callbacks until those packages land.
|
||||
|
||||
---
|
||||
|
||||
## Acceptance gate
|
||||
|
||||
1. `bunx turbo lint typecheck test --filter=@suaveplan/websocket-gateway` green.
|
||||
2. `bunx turbo test:coverage --filter=@suaveplan/websocket-gateway` 100/100/100/100.
|
||||
3. `bun run docs:check` green.
|
||||
4. Integration test: 3 clients connect via `network-transport-websockets`, join rooms, exchange messages, observe presence events. No mocks.
|
||||
5. `STATUS.md` row flipped.
|
||||
|
||||
---
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Production TLS termination (deployment concern).
|
||||
- Cross-instance gateway clustering (federate via `@suaveplan/network` mesh in a future change).
|
||||
- Persistent room state (separate `websocket-gateway-store-*` package if needed).
|
||||
Reference in New Issue
Block a user