03 — User Journey (WS / Realtime Module)
- J1 — Login to connected (all personas)
- J2 — Live dashboard update (Org Admin)
- J3 — Notification receipt (Teacher / Student / Parent)
- J4 — Network flap (all personas)
- J5 — Message delivery (planned)
- J6 — Realtime admin debug (proposed)
- Journey rules
Journeys across the connection lifecycle, not screens — the realtime layer's only native moments are connect, event, and reconnect. Source-grounded: handshake (
ws.gateway.ts:35-57), fan-out (ws-bridge.service.ts:16-22), rooms (ws.gateway.ts:50,63-74).
J1 — Login to connected (all personas)
| Step | Actor | System (source) |
|---|---|---|
| 1 | User signs in; REST returns access token | Auth module (token subject/tenant/roles payload) |
| 2 | Client opens socket to /ws with token | namespace: '/ws' (ws.gateway.ts:20-23); token via handshake.auth.token or handshake.query.token (ws.gateway.ts:37-39) |
| 3 | Server verifies token against JWT_ACCESS_SECRET | ws.gateway.ts:42-44 |
| 4 | Server joins socket to tenant:{tenantId} room | ws.gateway.ts:50 |
| 5 | Client shows connected indicator; subscribes to extra rooms if needed | subscribe event (ws.gateway.ts:63-68) |
| 6 | Server begins delivering tenant events | bridge active (ws-bridge.service.ts:23) |
Failure paths: missing token → UnauthorizedException → client.disconnect()
(ws.gateway.ts:40,54-56). Invalid/expired token → same disconnect. The client must
re-drive this journey after any reconnect.
J2 — Live dashboard update (Org Admin)
- Admin has dashboard open on a fee page.
- Cashier marks payment complete →
payments.*domain event emitted (EventBus.emit,events/event-bus.service.ts:11). WsBridge.onAnycatches it (ws-bridge.service.ts:16) →broadcastToTenant(ws.gateway.ts:76) → all admin sockets intenant:{id}.- Client receives envelope
{eventType, occurredAt, payload}(ws-bridge.service.ts:17-21). - Dashboard tile animates the new total without a page reload.
J3 — Notification receipt (Teacher / Student / Parent)
- User is on any module screen.
- Announcement published →
notification.createdevent (dot-namespace convention,API_STANDARDS.md:642-658). - Toast slides in (
m-fast, 00-shared/08), bell badge increments. - User taps → navigates to the detail; list shows the item (reconciled with REST).
J4 — Network flap (all personas)
- WiFi drops. Socket.io client detects ping timeout (server-side heartbeat defaults).
- Client enters reconnecting state; UI shows offline banner (component in 07).
- Backoff retries re-establish the connection (client-side; see 15).
- On reconnect: handshake runs again — token must still be valid (see 14_QA_Checklist.md "auth on reconnect"). If the access token expired, the client refreshes via REST and reopens the socket.
- Missed events are not replayed (fire-and-forget bridge). Client refetches affected lists via REST for eventual consistency — mandatory reconciliation rule (10 §6).
J5 — Message delivery (planned)
- Teacher sends message → Communication module
(planned), delivered via thisWsModule(docs/IMPLEMENTATION_PLAN.md:119). - Recipient sockets receive the message event; thread list updates live.
- Until Communication lands, this journey is a contract placeholder, not a feature.
J6 — Realtime admin debug (proposed)
- IT admin opens Realtime Debug view
(proposed)— 05 §5. - Sees connection health, live event stream, room membership for own tenant.
- Uses it to verify fan-out after a deployment.
Journey rules
- Every reconnect restarts at step 2 of J1 — there is no session resumption in source.
- No journey requires the user to act on the connection itself; failure UX is banner-level (see 06 §1) and non-blocking.