10 — Interaction Specification (WS / Realtime Module)
- 1. Connection lifecycle interactions
- 2. Live-update interactions
- 3. Toast queueing rules
- 4. Navigation from events
- 5. Ordering & dedup semantics
- 6. Offline / reconnect interactions
- 7. Keyboard / adaptive interactions
- 8. Analytics events (proposed)
Precise interaction rules for the realtime layer. Motion/animation tokens come from 00-shared/08; accessibility baseline from 00-shared/09. Analytics
(proposed).
1. Connection lifecycle interactions
| Trigger | Interaction |
|---|---|
| App start | silent connecting; no UI until connected or first failure |
| Connected | nothing visible (dot green, no animation) |
| Reconnect attempt #1..n | pulsing dot only; after n=1 show banner (06 §1.2) |
| Offline (> 30 s) | banner + "Retry now"; background backoff continues |
| error-auth | banner "Session expired — reconnecting"; client refreshes token then reconnects; on refresh failure → app sign-out with snackbar |
| Manual retry | cancels backoff timer, immediate connect attempt, m-fast state change |
All transitions announce via live region (00-shared/09); none block user input.
2. Live-update interactions
| Rule | Detail |
|---|---|
| Non-interruption | events never steal focus, move the caret, or reorder mid-edit — defer via AppLiveList (06 §3, 09 §4) |
| Row flash | matching row gets a 400 ms highlight (m-fast ease-out) then settles |
| Insert | only at list head or by current sort; never while pull-to-refresh is active |
| Aggregation | dashboard tiles animate delta (m-fast); total recomputed locally, no refetch |
| Pull-to-refresh | always available; forces REST refetch even when connected (source of truth) |
| Toast tap | navigate to target; bell badge decrements only via list-open reset (09 §3) |
3. Toast queueing rules
- Max 1 visible toast; others queue FIFO; queue cap 5 (drop oldest, keep badge).
- High-priority types only (06 §2.2); all events still increment the badge.
- Dedup window 30 s per
eventType+entityId.
4. Navigation from events
- Envelope carries only
{eventType, occurredAt, payload}(ws-bridge.service.ts:17-21); navigation targets are derived fromeventTypevia a static route map (notification.created→ notification detail, etc.)(proposed). - If target entity is gone (REST 404), snackbar "No longer available"; never a dead screen.
5. Ordering & dedup semantics
- In-connection order is guaranteed by socket.io; cross-reconnect order is not — after reconnect, reconcile once per visible live screen (06 §3.1).
- Dedup key:
eventType + entityId(payload). Correlation ID exists on the domain event (events/domain-event.interface.ts:6) but is not forwarded by the bridge — until it is, entityId is the best key (see 12 gap). - Server event rate: bridge forwards every domain event for the tenant
(
ws-bridge.service.ts:16-22) — clients must filter client-side today (08 §5).
6. Offline / reconnect interactions
- On
offline: pause live mutations; keep data; show banner. - On
connected(reconnect): re-subscribeextra rooms (ws.gateway.ts:63-68— rooms die with the socket), then one refetch per visible live screen. - No replay of missed events — accept eventual consistency (fire-and-forget bridge,
ws-bridge.service.ts:16-22).
7. Keyboard / adaptive interactions
- Banner "Retry" is focusable and Enter-activatable; status dot is a button (focusable)
opening the status sheet
(proposed). - Debug view: filter field keyboard enter applies filter; Escape clears.
- Desktop hover on status dot shows tooltip; mobile long-press opens sheet (05 §4).
8. Analytics events (proposed)
app.ws.connect, app.ws.disconnect, app.ws.reconnect{attempt}, app.ws.offline{ms},
app.ws.auth_error, app.ws.event_received{eventType} (sampled ≤ 1%), app.ws.toast_tap,
app.ws.status_open, admin.ws.{open,pause,filter}.
Logging rule: never log payload contents or tokens; eventType + occurredAt + sizes only (06 §6, 07 §6).