WebSockets
The Cloud Backend runs two WebSocket hubs for real-time push updates to the Cloud SPA:
| Path | Purpose |
|---|---|
/api/ws/security | Security alert feed, investigation events |
/api/ws/vpn | VPN session status updates |
Connection and auth
Section titled “Connection and auth”sequenceDiagram
participant SPA as Cloud SPA
participant API as Cloud Backend
participant Hub as WebSocket Hub
SPA->>API: WS upgrade GET /api/ws/security?token=<access_jwt>
API->>API: Validate JWT from query param
API->>API: Extract tenant_id, user_id
API->>Hub: Register connection { conn, tenant_id, user_id }
API-->>SPA: 101 Switching Protocols
Note over SPA,Hub: Connection open
API->>Hub: Broadcast event to tenant_id connections
Hub-->>SPA: WS message frame
SPA->>API: WS close frame
API->>Hub: Deregister connection
Authentication uses the JWT as a query parameter (?token=), not in headers. This is because the WebSocket API in browsers does not allow custom headers during the upgrade handshake. The ALLOW_ORIGINS env var is checked against the Origin header on the upgrade request.
Hub architecture
Section titled “Hub architecture”The WebSocket hub lives in Backend/internal/websocket/hub.go. It maintains a concurrent map of:
tenant_id → []connectionBroadcasting works by looking up all connections for a given tenant_id and writing the event to each. Closed connections are cleaned up automatically.
Security alert broadcast
Section titled “Security alert broadcast”When a security alert arrives (via webhook ingest, Ingestor event, or internal generation):
sequenceDiagram
participant Source as Alert source (Ingestor / webhook / job)
participant SecurityDomain as security domain
participant SQL as Azure SQL
participant Hub as WebSocket Hub
participant SPA as Cloud SPA
Source->>SecurityDomain: New alert payload
SecurityDomain->>SQL: INSERT security_alerts
SecurityDomain->>Hub: Broadcast({ type: "alert", data: alert })
Hub-->>SPA: WS message (all tenant connections)
SPA->>SPA: Update alert inbox in UI (TanStack Query invalidation)
VPN session updates
Section titled “VPN session updates”The VPN hub broadcasts session state changes (connecting, connected, disconnected, error) to all SPAs open for the tenant. This allows multiple users to monitor VPN sessions in real-time without polling.
Frontend integration
Section titled “Frontend integration”| Store | File |
|---|---|
| WebSocket state | Frontend/lib/stores/wsStore.ts |
| Security WS client | Frontend/lib/ws/securityWs.ts |
| VPN WS client | Frontend/lib/ws/vpnWs.ts |
The Zustand wsStore tracks connection state (connecting | open | closed) and exposes methods to subscribe to events. TanStack Query cache is invalidated when relevant WS events arrive.
Investigation terminal
Section titled “Investigation terminal”The Security module includes an investigation terminal (xterm.js in the SPA) that executes tools through VPN gateway connections. Tool execution results stream back via the /api/ws/security connection as incremental message frames.
CORS / Origin check
Section titled “CORS / Origin check”The backend checks the Origin header on WS upgrade against ALLOW_ORIGINS. In production:
ALLOW_ORIGINS=https://cloud.monozu.ioIn local dev:
ALLOW_ORIGINS=http://localhost:3000,http://127.0.0.1:3000