Skip to content

feat(realtime)!: add semantic event stream - #2257

Open
hmans wants to merge 4 commits into
mainfrom
hmans/review-realtime-api-ux
Open

feat(realtime)!: add semantic event stream#2257
hmans wants to merge 4 commits into
mainfrom
hmans/review-realtime-api-ux

Conversation

@hmans

@hmans hmans commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Why

The protocol-2 realtime channel exposes frontend projection mutations as its public API. Bots and integrations need authorized Chatto activity—messages, edits, reactions, membership changes, calls, and similar events—without learning the bundled frontend's cache model. The bundled frontend must still bootstrap from one ordered stream instead of making many resource requests.

What changed

  • Replace realtime protocol 2 with protocol 3 and one bot-shaped semantic event vocabulary used by bots, alternate clients, and the bundled frontend.
  • Add explicit SNAPSHOT and LIVE_ONLY initial-state choices. Report SNAPSHOT, LIVE_ONLY, or RESUME as the selected recovery mode.
  • Put durable cursors and common metadata outside the event oneof, so clients can skip additive event variants and still advance safely.
  • Keep the frontend as a projection consumer through authorized state items, retained-room timeline hydration, and semantic reducers for messages, reactions, pins, notifications, calls, users, and room state.
  • Resume recent gaps with bounded direct JetStream point reads. The server creates no per-WebSocket or per-catch-up NATS consumer.
  • Bind opaque cursors to the viewer and stream incarnation, expire them after 24 hours, and bound replay to 10,000 EVT sequences, 2,000 delivered events, admission limits, and a 30-second deadline.
  • Apply current authorization, membership, deletion, and erasure state to live delivery, resume, snapshots, and hydration.
  • Add protocol-focused E2E coverage for snapshot hydration, unretained semantic events, edit/reaction resume, mentions, and direct-message notifications. Fix the room-hydration member-state gap and a device-timezone E2E race found during the full suite.
  • Record the design and invariants in ADR-087 and FDR-045, and update the glossary, architecture inventory, release notes, generated API reference, and integration guides.

Compatibility and rollout

Classification: breaking public realtime API change.

  • Older clients against newer servers fail the realtime handshake because the server accepts only protocol 3.
  • Newer clients against older servers fail the handshake because protocol 2 does not accept protocol 3.
  • Deploy the server and bundled frontend together. External integrators must regenerate protobuf clients, send protocol version 3, choose an initial-state mode, and consume semantic events and state items.
  • This break is accepted for the 0.5 alpha. It removes frontend cache operations and capability matrices from the public contract. Persisted chatto.core protobufs are unchanged.
  • The cursor contains no public NATS or JetStream coordinates. Current authorization prevents replay from restoring revoked or erased data.
  • Catch-up limits and existing realtime metrics bound operational cost. Long-offline reliable automation remains a separate future webhook or paged-activity contract.

Test plan

  • mise codegen-proto — passed; generated Go, TypeScript, and API-reference output reproduces cleanly.
  • mise lint — passed, including Go vet, TypeScript, ESLint, Svelte diagnostics, actionlint, shellcheck, production frontend build, bundle limits, and CSP checks.
  • mise test-cli — passed, including the complete realtime HTTP-server package and the durable-bio replay regression.
  • mise test-frontend — passed: 1,362 server tests, 2,001 client tests, 231 Storybook tests, and 5 performance tests.
  • Docs website production build — passed.
  • Realtime protobuf E2E file — passed 9/9 repeatedly.
  • Hydration-affected E2E subset — passed 14/14 after the member-state fix.
  • Full E2E run — 679 passed and one device-timezone race failed; the test was fixed and then passed 3/3 in isolation. The final full-suite rerun remains for CI.
  • Chrome DevTools verification — signed in through the real development stack, hydrated #general, posted a message, reloaded, and confirmed the snapshot restored the message and room membership.
  • mise license-check and git diff --check — passed.

@hmans hmans added the api-breaking-change Intentional pre-1.0 public API breaking change label Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-breaking-change Intentional pre-1.0 public API breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant