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).
|
||||
63
openspec/archive/2026-05-12-websocket-gateway/tasks.md
Normal file
63
openspec/archive/2026-05-12-websocket-gateway/tasks.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Tasks — websocket-gateway
|
||||
|
||||
## Phase 1: Scaffold
|
||||
|
||||
- [ ] 1.1 Create `packages/network/websocket-gateway/`, server-tier marker comment.
|
||||
- [ ] 1.2 `package.json` at `0.1.0`, `"engines": { "node": ">=20" }`, NO `browser` field.
|
||||
- [ ] 1.3 Test config via `createTestConfig()`; `tests/dep-graph.test.ts`.
|
||||
- [ ] 1.4 Add `ws` (or commit to `bun:websocket` façade) to root catalog under `network-server`.
|
||||
|
||||
## Phase 2: Types + errors
|
||||
|
||||
- [ ] 2.1 Port `types/` → `src/types/` + sibling `.md`.
|
||||
- [ ] 2.2 `defineCodes("WS_GATEWAY", [...])`: `ROOM_NOT_FOUND`, `ROOM_FULL`, `CHANNEL_INVALID`, `AUTH_REJECTED`, `RATE_LIMITED`, `INVALID_OPTIONS`.
|
||||
- [ ] 2.3 Zod schemas for every public option struct + every wire frame.
|
||||
|
||||
## Phase 3: Core subsystems
|
||||
|
||||
- [ ] 3.1 Port `room/` — join/leave/broadcast/direct.
|
||||
- [ ] 3.2 Port `presence/` — who's in which room.
|
||||
- [ ] 3.3 Port `channel/` — channel multiplexing over one WS connection.
|
||||
- [ ] 3.4 Port `gateway/` — main `WebSocketGateway` daemon.
|
||||
|
||||
## Phase 4: Hooks for unmigrated deps
|
||||
|
||||
- [ ] 4.1 `AuthVerifier` callback (JWT integration deferred until `@suaveplan/jwt-tenant` lands).
|
||||
- [ ] 4.2 `AuthorizationCheck` callback (RBAC integration deferred).
|
||||
- [ ] 4.3 `RateLimitGate` callback (rate-limiter integration deferred).
|
||||
- [ ] 4.4 Replace placeholders with real package wiring as each lands on genesis.
|
||||
|
||||
## Phase 5: Observability + reliability
|
||||
|
||||
- [ ] 5.1 OTel spans `ws_gateway.connect`/`message`/`broadcast`.
|
||||
- [ ] 5.2 Counters `ws_gateway.rooms_active`, `presence_updates_total`.
|
||||
- [ ] 5.3 Histograms `ws_gateway.message_dispatch_ms`.
|
||||
- [ ] 5.4 Retry + circuit breakers via `@suaveplan/retry` on outbound integrations.
|
||||
- [ ] 5.5 Idempotency guard via `@suaveplan/idempotency` on every mutating event.
|
||||
- [ ] 5.6 Webhook delivery via `@suaveplan/webhook-client` on presence events.
|
||||
- [ ] 5.7 Health / readiness / liveness endpoints (inline until `@suaveplan/health-check` lands).
|
||||
|
||||
## Phase 6: Tests + docs
|
||||
|
||||
- [ ] 6.1 Unit tests via `@suaveplan/testing/runner`.
|
||||
- [ ] 6.2 fast-check property tests: room invariants, presence eventual consistency, channel mux fairness.
|
||||
- [ ] 6.3 Integration test via `@suaveplan/testing-integration`: 3-client scenario (rooms + presence + messages), no mocks.
|
||||
- [ ] 6.4 100/100/100/100 coverage gate.
|
||||
- [ ] 6.5 Sibling `.md` per `.ts` impl file.
|
||||
- [ ] 6.6 Root `README.md` with daemon-run + client-pairing examples.
|
||||
|
||||
## Phase 7: Verification
|
||||
|
||||
- [ ] 7.1 `bunx turbo lint typecheck test --filter=@suaveplan/websocket-gateway` green.
|
||||
- [ ] 7.2 `bunx turbo test:coverage --filter=@suaveplan/websocket-gateway` 100/100/100/100.
|
||||
- [ ] 7.3 `bun run docs:check` green.
|
||||
- [ ] 7.4 `MANIFEST.md` regen.
|
||||
- [ ] 7.5 `STATUS.md` row flipped.
|
||||
|
||||
## Pre-archive checklist
|
||||
|
||||
- [ ] Row 1 — Phase 7 green.
|
||||
- [ ] Row 2 — 3-client integration test passes.
|
||||
- [ ] Row 3 — Auth/rate-limit/audit callbacks documented with replacement paths.
|
||||
- [ ] Row 4 — `openspec/specs/websocket-gateway/spec.md` written.
|
||||
- [ ] Row 5 — Folder archived.
|
||||
Reference in New Issue
Block a user