# Логика установки звонка через сервер (актуальная) ## 1) Ключевые API - `CallInviteBroadcast` — широковещательный старт входящего звонка (`type=100`) по пользователю. - `CallSignalToSession` — точечный сигнал в конкретную сессию (`RINGING/ACCEPT/DECLINE/TIMEOUT/HANGUP/OFFER/ANSWER/ICE`). ## 2) Базовый поток звонка 1. Инициатор отправляет `CallInviteBroadcast(toLogin, callId, type=100)`. 2. Сервер отправляет онлайн-сессиям callee событие `IncomingCallInvite` по WS. 3. Офлайн-сессиям callee сервер отправляет WebPush `incoming_call` (с TTL). 4. Любая сессия callee, получив invite, может отправить `RINGING`. 5. Инициатор после первого `RINGING` показывает «Вызываем…». 6. При `ACCEPT` выбирается одна целевая сессия, остальные получают `HANGUP/stop_call` и закрывают экран входящего. 7. Далее только выбранная пара сессий обменивается `OFFER/ANSWER/ICE`. ## 3) WebPush по звонкам ### `incoming_call` - Используется как fallback для офлайн-сессий. - Поля: `kind`, `callId`, `fromLogin`, `fromSessionId`, `toLogin`, `sentAtMs`, `expiresAtMs`. - TTL сейчас: **10 секунд**. - Если push пришёл после `expiresAtMs`, уведомление не показывается. ### `stop_call` - Отправляется при завершении/отмене/принятии на другом устройстве. - Поля: `kind`, `callId`, `reason`, `fromLogin`, `fromSessionId`, `toLogin`, `sentAtMs`. - Service Worker закрывает уведомление по `tag=callId`. ## 4) Кнопки в push-уведомлении - Для `incoming_call` есть actions: - `accept` — «Ответить» - `decline` — «Сбросить» - По нажатию action: - Service Worker шлёт событие в открытые вкладки, - и открывает/фокусит UI с параметрами действия. - UI пытается выполнить действие сразу (принять/отклонить), если сессия уже авторизована. ## 5) Важные ограничения - Источник истины по звонку — серверный сигналинг (WS + серверные сигналы), push только вспомогательный канал. - Push может прийти с задержкой и не по порядку, поэтому клиент фильтрует устаревшие события (`expiresAtMs` + `callId` + `stop_call`). - Полноценный «автоответ в фоне без открытия UI» в web/PWA не гарантируется платформой. ## 6) Ограничение текущей архитектуры - Сейчас звонки надёжно работают в рамках одного сигнального контура (когда обе стороны подключены к совместимому серверу/кластеру). - Межсерверный сценарий «A и B на полностью разных серверах» пока не завершён и вынесен в TODO.