Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
# OpenSpec Change: enterprise-api-plugin-sse
- **Change ID**: enterprise-api-plugin-sse
- **Package**: `@suaveplan/api-plugin-sse`
- **Category**: api/data
- **Target path**: `api/data/api-plugin-sse`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/api-plugin-sse.md`
---
## Summary
Deliver `@suaveplan/api-plugin-sse` on the genesis branch from scratch at enterprise quality. Server-Sent Events plugin: per-client event streams keyed by user/topic, fan-out from `@suaveplan/events` bus to connected clients, heartbeat keepalive, backpressure via bounded send queues, auth-gated connections, connection lifecycle tracking. Routes under `/sse`. Events: `sse:client:connected`, `sse:client:disconnected`. Used by analytics dashboard, notifications, real-time feeds.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/api` (`workspace:^`) | `definePlugin` |
| `@suaveplan/api-shared` (`workspace:^`) | Helpers |
| `@suaveplan/api-plugin-auth` (`workspace:^`) | `requireAuth` |
| `@suaveplan/events` (`workspace:^`) | Bus subscriptions for fan-out |
| `@suaveplan/error` (`workspace:^`) | `SseError` hierarchy |
| `@suaveplan/rate-limiter` (`workspace:^`) | Connection rate limits |
| `hono` (`catalog:server`) | SSE helpers |
| `zod` (`catalog:forms`) | Schemas |
| `@opentelemetry/api` | OTel |
---
## Public API surface
```ts
function createSsePlugin(config?: SsePluginConfig): PluginDescriptor
// Registered service:
interface SseService {
publish(topic: string, event: SseEvent): void
broadcast(event: SseEvent): void
connectionCount(): number
getTopicConnectionCount(topic: string): number
}
interface SseEvent { type: string; data: unknown; id?: string }
interface SsePluginConfig { heartbeatIntervalMs?: number; sendQueueSize?: number; allowedOrigins?: string[] }
```
### Error codes
```ts
type SseErrorCode =
| "SSE_TOO_MANY_CONNECTIONS"
| "SSE_AUTH_FAILED"
| "SSE_TOPIC_INVALID"
```
---
## File layout
```text
api/data/api-plugin-sse/
package.json tsconfig.json vitest.config.ts
src/
index.ts events.ts types/ errors/
core/connection-manager/ core/heartbeat/
services/sse/
routes/sse/
tests/integration.test.ts
```
---
## Impact
Prerequisites: `@suaveplan/api`, `@suaveplan/api-plugin-auth`, `@suaveplan/events`, `@suaveplan/rate-limiter`.

View File

@@ -0,0 +1,59 @@
# 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/`.