Realtime is opt-in per topic through the remotely supplied feature flags. Each enabled topic seeds client state from one REST request, applies ordered realtime events through useRealtimeResource, and keeps an explicit refresh action where the UI exposes one. REST is the bounded fallback when the transport is unavailable; there are no interval polls in the data hooks.
| Path | Current state | Disposition |
|---|---|---|
useOracleStatus interval/backoff/manual refresh |
The hook was empty on the upstream baseline; no data interval or polling backoff existed. The landing page's one-second interval only updates the “seconds ago” label. | Keep manual refresh; use realtime topic oracle.status with one REST seed/fallback. Retain the display clock because it does not fetch data. |
useRecentClaims polling constants/controls |
The hook was empty; no polling constants existed. | Use claims.recent, one REST seed/fallback, and the landing payouts refresh action. |
useClaims holder polling |
The hook was empty; no polling constants existed. | Use claims.holder.<address> when its kill switch is enabled, one REST seed/fallback, and an explicit dashboard refresh. |
useNotifications interval/backoff/manual refresh |
No notification-specific polling existed; it derives from shared hooks. | Keep derived notifications and inherit each source's freshness policy. |
Shared interval/backoff helpers in src/lib/ |
No data polling helper was present. WebSocket reconnect backoff remains transport recovery, not data polling. | Keep reconnect backoff; do not hand it to adaptive polling. |
/ seconds-ago clock |
A one-second UI timer updates elapsed-time text only. | Keep; it does not request data or write cache state. |
Topic flags default off and act as kill switches. The retirement is staged: no legacy poll was deleted because none existed in the upstream baseline. For each topic, keep the flag off until production has met the team's agreed observation window; then enable the topic, observe fallback/error rates, and remove any subsequently introduced legacy interval only after the window. The observation-window duration is an operational decision and should be recorded with the rollout.
The transport accepts an optional numeric sequence and numeric or ISO timestamp on each envelope. Higher sequence wins when both updates carry one; otherwise a strictly newer timestamp wins when both carry one. Equal or missing ordering keys favor the already-applied realtime update. REST responses started before a realtime event are aborted and also rejected by a generation guard if cancellation races completion. Comparable newer REST snapshots may advance state during a degraded connection. Cancellation is an optimization; the freshness checks remain authoritative.
Realtime diagnostics pass through src/lib/realtime/redact.ts. Sensitive keys (auth tokens, wallet/address/holder identifiers, signatures, session credentials) are redacted recursively, arrays and objects are bounded, error messages are omitted, and unknown strings are truncated. Verbose message summaries are off in production and can be temporarily enabled in a development tab with sessionStorage.setItem("refract:realtime-debug", "1"); the switch expires when the tab's session ends. Only topic-safe summaries, byte counts, and error names are logged.