/ws/eaas/v1
EaaS event stream (WebSocket, first-frame auth)
WebSocket twin of the GET /api/v1/events JSON/SSE face (registered by the IM
bootstrap in-process; the upgrade branch mirrors /ws). JSON text frames, one object
per frame. There is NO ?token= channel — the credential rides the first frame.
Credential = the project machine key (sk-eaas-…) ONLY. The WS auth face resolves
through the EaaS key table (resolveEaasToken); a platform key (sk-prismer-*), a
principal session token (ps-eaas-…) or a JWT fails the shape gate with 401 → close
4401 (reasons are not distinguished). Operator-human and principal event streams use
the SSE representation of GET /api/v1/events instead (header credentials; the
principal subscription there is pinned to the session-bound environment).
Client → server frames:
{type:'auth', token:' — REQUIRED first frame; any other frame
before auth closes 4401.
{type:'subscribe', environmentIds?:string[], projectIds?:string[], cursor?:'N'} —
cursor is a decimal seq string (0 start). Multiple subscribe frames are allowed
and are serialized per connection.
Server → client frames:
{type:'authorized', lastSeq:'N'} — auth ok (lastSeq = tenant stream head, the
scan-position anchor).
{type:'subscribed', cursor:'N'} — subscription accepted; the start position is
acknowledged BEFORE any replay frame.
{type:'event', event:{…envelope}} — replay (durable) and live (incl. ephemeral)
share this shape; there is no terminal EOF.
{type:'eaas.resync', lastSeq:'N'} — the requested cursor is no longer serviceable
(beyond the head or below the durable prune watermark), followed by close 4409.
{type:'error', message} — recoverable frame-level error (connection stays open).
Close codes (RFC6455 app-defined 4xxx): 4400 frame is not JSON · 4401
unauthenticated / malformed / invalid / revoked key / missing events:read (also used
when a non-auth frame arrives first — the reason is not distinguished to avoid leaking
key state; revocation is re-checked every 60s and a transient store error skips that
round rather than killing healthy connections) · 4403 caps exceeded (10
connections per keyId, 50 subscriptions per connection) or slow consumer (>1MB
outbound buffer) · 4404 FF_EAAS_ENABLED off (also enforced mid-connection: the
flag being turned off closes existing streams) · 4409 cursor expired → resync
from an authorized snapshot.
Delivery is at-least-once; filter-induced seq gaps are never back-filled — resume
only from the server's cursor.