Two weeks of WebRTC plumbing are live. From the conversation header you can now tap the phone or camera icon and start a call to any other Tacitus user — same in the iOS app, same in the web client.
How the media flows
WebRTC negotiates a direct UDP path between the two browsers (or one browser and one iPhone). If NAT traversal fails we fall back to our Coturn relay, but the relay still only ever sees DTLS-SRTP encrypted frames — the media key exchange happens between the peers. Our server never sees your audio or video.
Signalling
The offer/answer/ICE exchange goes over the same
/ws/signaling WebSocket that the chat uses, as a set
of typed envelopes: call_invite,
call_ringing, call_offer,
call_answer, call_ice,
call_end. A Redis pub/sub bus fans the envelopes
across web replicas so two users on different backend servers can
still reach each other.
iOS
The iOS app is a full CallKit citizen. Incoming calls ring the lock screen, answer from the lock screen, the call lives in Recents like a phone call. The entitlement for unrestricted VoIP push is still pending with Apple; until it clears, the app has to be in foreground (or recently backgrounded) to ring — once the entitlement lands, calls will wake the device via PushKit.