# Realtime WebSocket System ## Architecture PHP (authority) → Redis pub/sub → Node.js relay → WebSocket → Browser - **PHP**: Issues HMAC-signed tokens, checks permissions, publishes events - **Node**: Validates tokens, routes messages, stores last-message. Zero business logic - **Browser**: Connects, subscribes, receives notifications, fetches fresh data via Ajax ## Key Files - `Realtime.php` — Static API: `connection_token()`, `subscribe_token()`, `publish()` - `Realtime_Topic_Abstract.php` — Base class for topic permission checks - `Realtime_Controller.php` — Ajax endpoints for browser token requests - `/system/bin/realtime-server.js` — Node.js WebSocket server - `/system/app/RSpade/Core/Js/Rsx_Realtime.js` — Client manager ## Security Model 1. **Connection token**: HMAC-signed with APP_KEY, contains user_id + site_id + session_id, expires in 60s 2. **Subscribe token**: Per-topic, HMAC-signed, checks `Topic::can_subscribe()` before issuing 3. **Site scoping**: Messages only route to connections with matching site_id 4. **No confidential data**: Messages are notifications only — clients fetch data through Ajax ## Token Format `base64(json_payload).hmac_sha256_hex` Connection: `{user_id, site_id, session_id, exp}` Subscribe: `{topic, filter, site_id, exp}` ## Redis Channels - Pattern: `rsx_rt:{site_id}` - Message: `{topic, data, site_id, ts}` ## Configuration `.env`: ``` REALTIME_ENABLED=false REALTIME_WS_PORT=6200 REALTIME_PUBLIC_URL=ws://localhost:6200 ```