../constitution/founding-constitution.md
⚠️ Reconstructed from the material we have, not recovered. Tags: [derived] is supported by evidence in the repository · [inferred] is deduced · [proposed] is a gap I filled.
Context
A console showing live queue depth, a member portal updating a balance, an operator watching an import — all need server-to-client push. The options are managed (Pusher, Ably, Supabase Realtime) or self-hosted WebSockets, which means owning connection state, scaling and reconnection. [inferred]Decision
Pusher Channels, with tokens signed by our API. [derived] A client never authenticates directly against Pusher. It asks our API for a signed token scoped to the channels it may hear, which keeps channel authorization inside our permission model rather than in a second one. [inferred] Realtime is a consumer of the outbox (ADR-004), not a parallel publish path. [derived] Anything delivered in realtime already happened and is already recorded.Consequences
- No connection state, no scaling of long-lived sockets, no reconnection logic.
- Channel authorization uses our permissions, so there is one authorization model.
− A vendor in the hot path of a user-visible experience, and a per-connection cost.
− Realtime is behind
RealtimePort(ADR-003), so replacing Pusher is an adapter — which is exactly why the port exists. [inferred]