WebSocket API
The backend does not handle WebSocket connections directly; it only mints the JWT a client presents to open a real-time connection. The active system is Supabase Realtime, exposed through a single endpoint — POST /websocket/token, documented below.
An earlier Cloudflare office-router Worker design (Durable Objects + an RS256 handshake token) was implemented but never routed. Its backend service (
internal/platform/cloudflare/auth/, handlerGenerateDOUrl) was removed in a dead-code purge (qubital-backend #4) and does not reflect any current code. See that PR and the git history if you need the details.
Supabase Realtime token
The backend mints a short-lived HS256 JWT that the client presents to authenticate its Supabase Realtime subscription. The response is { token, expiresAt }. See Chat for how the frontend mints and uses it, and Supabase Realtime for the service.
| Field | Value |
|---|---|
| Endpoint | POST /websocket/token |
| Algorithm | HS256 |
| Signing key | SUPABASE_JWT_SECRET env var |
| Issuer | qubital-backend (hardcoded) |
| Audience | authenticated (Supabase RLS requirement) |
| TTL | 3600 seconds |
Roadmap: the realtime transport is slated to move from Supabase Realtime to Centrifugo. The
POST /websocket/token → { token, expiresAt }contract is intended to stay stable across that swap, so it is the seam the frontend integrates against.
Related
- Chat — how the frontend mints and uses the token
- Supabase Realtime — the realtime service
- Configuration —
SUPABASE_JWT_SECRET