# Реверс-инжиниринг аналогов и технологический разбор для AGIL Calls

> Документ команды AGIL Calls. Цель — понять, что в существующих WebRTC-решениях стоит
> копировать по механике, что переиспользовать по коду/лицензии, а что писать самим.
> Все данные о репозиториях и версиях сняты **13.11.2026** через GitHub REST API,
> npm registry и официальную документацию. Ссылки на источники — в конце каждого раздела
> и в общем списке (раздел 10).
>
> Пометка **«не подтверждено»** означает: факт не удалось проверить первоисточником,
> его нельзя использовать в маркетинге или юридических документах без отдельной проверки.
>
> ⚠️ Юридические формулировки в документе — инженерная оценка рисков, **не юридическая
> консультация**. Перед выпуском проприетарного продукта лицензионную модель должен
> подтвердить юрист.

---

## Оглавление

1. [Методика и границы разбора](#1-методика-и-границы-разбора)
2. [Jitsi Meet](#2-jitsi-meet-open-source-apache-20)
3. [LiveKit](#3-livekit-open-source-apache-20)
4. [Медиа-серверы второго эшелона: Janus, mediasoup, Pion, ion-sfu, Galene, SRS](#4-медиа-серверы-второго-эшелона-janus-mediasoup-pion-ion-sfu-galene-srs)
5. [Яндекс Телемост](#5-яндекс-телемост-закрытый-продукт)
6. [Коммерческие embedded SDK](#6-коммерческие-embedded-sdk)
7. [Технологии для фич AGIL Calls](#7-технологии-для-фич-agil-calls)
8. [MCP: протокол и проектирование сервера для нейросетей](#8-mcp-model-context-protocol)
9. [Итоговая матрица «берём / делаем / покупаем»](#9-итоговая-матрица-берём--делаем--покупаем)
10. [Безопасность и комплаенс у конкурентов](#10-безопасность-и-комплаенс-у-конкурентов)
11. [Детекция AI-медиа и deepfake](#11-детекция-ai-медиа-и-deepfake)
12. [AI-ассистенты встреч и транскрипты](#12-ai-ассистенты-встреч-и-транскрипты)
13. [Файлы, запись, STT и демонстрация экрана](#13-файлы-запись-stt-и-демонстрация-экрана)
14. [Панели разработчика и админки конкурентов](#14-панели-разработчика-и-админки-конкурентов)
15. [Источники](#15-источники)

---

## 1. Методика и границы разбора

Что делали:

| Шаг | Действие | Инструмент |
|-----|----------|-----------|
| 1 | Сбор метаданных репозиториев: лицензия, язык, звёзды, объём, дата последнего коммита | GitHub REST API (`/repos`, `/languages`) |
| 2 | Чтение официальной архитектурной документации (handbook, docs.*) | `web_fetch` |
| 3 | Сверка публичных API-контрактов (IFrame API, JWT-гранты, REST, web components) | docs + примеры кода |
| 4 | Проверка версий пакетов, которые реально придётся ставить | npm registry `latest` |
| 5 | Проверка состояния браузерных API (Baseline, caniuse) | web-features explorer, MDN |
| 6 | Классификация лицензий по риску для проприетарного SaaS | анализ текста лицензий |

Что **не** делали и почему:

- не декомпилировали и не дизассемблировали проприетарные клиенты (Телемост, Zoom, Daily) —
  это прямо запрещено пользовательскими соглашениями и создаёт юридический риск;
- не разворачивали полный кластер Jitsi/LiveKit с нагрузочным тестом — это отдельная задача
  (см. `docs/estimate.md`, блок B/C), в рамках реверса достаточно документации и API;
- не бенчмаркали SFU вживую — сравнение по архитектуре и заявленным возможностям,
  реальные цифры появятся только на своём стенде.

Базовая линия для сравнения — **AGIL Calls MVP**: браузер, mesh 2–8 участников, свой API,
темы (light/dark + кастомный бренд), чат при плохой связи, блюр/замена фона, MCP-сервер,
визуальный редактор панели. Всё, что не нужно для MVP, помечено как «потом».

---

## 2. Jitsi Meet (open source, Apache-2.0)

### 2.1 Что это и из чего состоит

Jitsi — не один продукт, а набор сервисов. Это одновременно главный плюс (полнота)
и главный минус (сложность эксплуатации) для тех, кто хочет «просто встроить звонок».

| Компонент | Репозиторий | Роль | Стек | Лицензия |
|-----------|-------------|------|------|----------|
| Jitsi Meet (meet-web) | `jitsi/jitsi-meet` | Веб/мобильный клиент, React + React Native | TypeScript, SCSS, Java/ObjC/Swift (обёртки) | Apache-2.0 |
| Jitsi Videobridge (JVB) | `jitsi/jitsi-videobridge` | SFU: маршрутизация RTP между участниками | Kotlin (+Java) | Apache-2.0 |
| Jicofo | `jitsi/jicofo` | Focus: управление конференциями, балансировка между JVB | Kotlin | Apache-2.0 |
| Prosody | `prosody/prosody` + плагины Jitsi | XMPP-сервер сигналинга | Lua | MIT (сам Prosody) |
| lib-jitsi-meet | `jitsi/lib-jitsi-meet` | Низкоуровневая JS-библиотека для своего UI | TypeScript | Apache-2.0 |
| Jigasi | `jitsi/jigasi` | SIP-шлюз (телефонные участники) | Java | Apache-2.0 |
| Jibri | `jitsi/jibri` | Запись/трансляция через headless Chrome + ffmpeg | Java/Kotlin | Apache-2.0 |

Источник состава: [Architecture — Jitsi Handbook](https://jitsi.github.io/handbook/docs/architecture/).

Масштаб кодовой базы (GitHub API, 13.11.2026):

| Метрика | `jitsi-meet` | `jitsi-videobridge` |
|---------|--------------|---------------------|
| Звёзды / форки | 30 228 / 8 125 | 3 109 / 1 038 |
| Основной язык | TypeScript | Kotlin |
| Объём репозитория (KB, git) | 391 543 (~382 MB с историей) | 234 647 (~229 MB) |
| Разбивка Linguist, байты | TS 8 067 961; Lua 1 296 334; JS 1 243 615; Java 239 810; Objective-C 145 981; SCSS 102 536; HTML 47 781; Swift 37 279; Shell 31 598 | Kotlin 4 147 341; Java 653 347; Perl 20 254; Shell 9 794; Python 7 802 |
| Последний push | 13.11.2026 | 12.11.2026 |

Вывод по размеру: **клиент Jitsi — это ~8 МБ TypeScript-исходников**, и в них входят
все фичи сразу (конференция, чат, запись, виртуальный фон, breakout rooms, реакции,
переводы на десятки языков). Для AGIL Calls это означает: форк Jitsi = унаследованный
техдолг и месяцы на изучение, а не «быстрый старт».

### 2.2 Как устроен SFU и сигналинг

Схема потока (упрощённо):

```
Браузер A ──XMPP/WebSocket──> Prosody <──> Jicofo ──Colibri/WebSocket──> JVB
     │                                                                    │
     └────────── WebRTC (DTLS-SRTP, ICE, simulcast) ─────────────────────┘
                                  ▲
Браузер B ────────────────────────┘
```

| Слой | Механика | Что важно для нас |
|------|----------|-------------------|
| Сигналинг | XMPP: клиент подключается к Prosody (BOSH/WebSocket), входит в MUC-комнату `room@conference.domain`, обменивается Jingle-описаниями | Зрелый, но тяжёлый протокол: чтобы что-то менять, нужен опыт в XMPP/Lua |
| Управление медиа | Colibri (Jitsi-расширение XMPP): Jicofo даёт JVB команды «создай канал, привяжи участника, отдай SDP» | Идея «отдельный control plane, отдельный media plane» — правильная, её стоит повторить |
| Медиа | JVB терминирует ICE/DTLS, пересылает RTP, умеет simulcast, SVC (VP9), last-N, bandwidth allocation | Именно эти алгоритмы (last-N, layer selection) — самая ценная часть Jitsi |
| Дата-каналы | SCTP поверх Colibri WebSocket + WebRTC data channels (чат, передача файлов, реакции) | Чат Jitsi идёт по data channel и XMPP — не только по медиапути |
| Авторизация | JWT проверяется Prosody-плагином: shared secret (HMAC) или public key с `kid` → keyserver | Готовая модель «токен = грант на комнату» |
| Запись | Jibri поднимает виртуальный дисплей + Chrome + ffmpeg: дорого по CPU, ~1 инстанс на запись | Для AGIL: вынести в egress-сервис (см. LiveKit), не тащить Jibri |

Ключевая архитектурная идея Jitsi, которую стоит скопировать: **сигналинг не равен медиа**.
Клиент получает от control plane (Jicofo) только «кто в комнате и какие каналы открыть»,
а вся тяжёлая работа — в отдельном пуле JVB, который масштабируется горизонтально и
не хранит состояние конференции.

### 2.3 Embedding: IFrame API и lib-jitsi-meet

Jitsi даёт два уровня встраивания:

| Уровень | Что получаешь | Когда брать |
|---------|---------------|-------------|
| `external_api.js` + `JitsiMeetExternalAPI` | Готовый UI Jitsi в iframe, управление через `executeCommand`, события через `addListener` | Быстро, но дизайн почти не кастомизируется |
| `lib-jitsi-meet` | Своя вёрстка, своя логика, готовый media/signaling-слой | Полный контроль, но нужно самим собрать весь UX |

Публичный контракт IFrame API (по [официальной документации](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe/)):

```js
const api = new JitsiMeetExternalAPI('meet.example.com', {
  roomName: 'agil-demo',
  parentNode: document.querySelector('#meet'),
  width: 640, height: 480,
  jwt: '<token>',
  userInfo: { displayName: 'Анна', email: 'a@example.com' },
  configOverwrite: { startWithAudioMuted: true },
  interfaceConfigOverwrite: { TILE_VIEW_MAX_COLUMNS: 2 },
  devices: { videoInput: 'cam-label' },
  lang: 'ru'
});
api.executeCommand('toggleAudio');
api.addListener('participantJoined', (p) => {});
```

Наблюдения по контракту (важно для нашего дизайна API):

1. **Конструктор вместо create/join** — iframe сам подключается к комнате. Для AGIL
   лучше разделить: `new AgilCall(config)` → `call.join(token)`.
2. **Два объекта конфигурации** (`configOverwrite` и `interfaceConfigOverwrite`) — наследие
   старого `interface_config.js`; в AGIL это один типизированный `TenantConfig`
   (см. `packages/protocol/src/config.ts`), иначе получаем два источника правды.
3. **Команды — строки** (`'toggleAudio'`, `'muteEveryone'`, `'pinParticipant'`) — без типов
   и без валидации. В AGIL команды должны быть типизированным union + zod-валидация
   по ту же сторону, где живёт `tenantConfigSchema`.
4. **События — единственный канал наружу** (participantJoined/Left, videoConferenceJoined,
   chatUpdated и т.п.). Это правильная модель: наружу отдаём события, внутрь — команды.
5. **JWT передаётся в iframe как есть**, проверка — на сервере сигналинга. Для AGIL то же,
   но с ограничением TTL и явными `role`/`roomId`/`tenantId` в claims.

Что мы **не** копируем: postMessage-протокол Jitsi как формат. У него нет версии,
нет схемы, нет гарантий обратной совместимости. Наш iframe-мост должен иметь
`{ v: 1, type, payload, id }` и версионироваться.

Как устроена авторизация токенами:

- JWT подписывается HMAC (shared secret) **или** приватным ключом; Prosody проверяет
  подпись и знает `application ID`;
- при публичном ключе Prosody ходит по URL за PEM по `kid`; поддержка JWKS
  (`/.well-known/jwks.json`) — [открытый feature request #15526](https://github.com/jitsi/jitsi-meet/issues/15526),
  то есть «как в OIDC» из коробки не работает;
- документация JWT-плагина: [jitsi/lib-jitsi-meet doc/tokens.md](https://github.com/jitsi/lib-jitsi-meet/blob/master/doc/tokens.md).

Для AGIL: HS256 на первом этапе (как уже сделано в `packages/protocol/src/token.ts`),
RS256/JWKS — когда появится мультитенантность и внешние IdP.

### 2.4 Кастомизация темы

| Возможность | Как реализовано | Ограничение |
|-------------|-----------------|-------------|
| Логотип, название, ссылки | Динамический брендинг + конфиг деплоя | Требует отдельного бренд-конфига на инстанс |
| Цвета | SCSS-переменные + `interfaceConfigOverwrite` | Переопределение на уровне сборки/шаблона, не «на лету» для тенанта |
| Скрытие кнопок | `interfaceConfigOverwrite`, `configOverwrite` | Только «скрыть», не «переставить» |
| Светлая/тёмная тема | Поддерживается | Кастомная палитра под бренд клиента — через SCSS-сборку |
| JaaS-брендинг | Коммерческий слой 8x8 | Привязывает к вендору |

Вывод: **темизация Jitsi — это темизация сборки, а не рантайма**. Для SaaS с
«клиент за 5 минут настраивает свой вид» такой подход не подходит. AGIL должен
строиться на CSS-переменных, вычисляемых из `TenantConfig` (у нас уже есть
`toCssVars()`/`applyBrandColor()`/`auditTheme()` в `packages/protocol/src/theme.ts`,
пресеты `light/dark/corporate/night/minimal`), и на проверке контраста
(WCAG) при сохранении темы.

### 2.5 Сильные и слабые места Jitsi

| Сильные | Слабые |
|---------|--------|
| Чистая Apache-2.0 на всех ключевых компонентах — можно форкать и закрывать | 4+ сервиса в эксплуатации: Prosody, Jicofo, JVB, nginx, плюс Jibri/Jigasi |
| Проверен на масштабе (meet.jit.si), есть torture-тесты | XMPP/Lua — редкая экспертиза, мало кто в команде это знает |
| Богатый набор фич: E2EE, SIP, запись, breakout, реакции, виртуальный фон | UI монолитен, кастомизация под бренд = сборка SCSS/патчи |
| Готовый IFrame API и React SDK | Тяжёлый клиент, много legacy-кода (JS/TS/Lua/Java вместе) |
| Низкая задержка аудио (Opus + собственный аудио-микшер/Red) | Запись через Jibri экономически невыгодна на потоке |
| E2EE на Insertable Streams: JVB видит только шифротекст | E2EE зависит от поддержки Insertable Streams в браузере; Safari — проблемная зона |

Про E2EE Jitsi: реализация описана в документации класса `E2EEcontext` в
[lib-jitsi-meet API docs](https://jitsi.github.io/lib-jitsi-meet/classes/JitsiConference._internal_.E2EEcontext.html) —
используются WebRTC Insertable Streams, ключ выводится из общего пароля, SFU не может
читать медиа. Ограничение по браузерам подтверждается сообществом («не все браузеры
поддерживают Insertable Streams»), официальной матрицы совместимости в handbook
найти не удалось — **не подтверждено** для конкретных версий Safari.

### 2.6 Что берём из Jitsi

| Идея/компонент | Решение |
|----------------|---------|
| Разделение control plane / media plane | Берём как архитектурный принцип |
| JWT-грант на комнату с ролью | Берём (уже реализовано в `token.ts`) |
| Событийная модель наружу + команды внутрь | Берём, но с версионированным протоколом |
| Last-N / выбор слоёв simulcast | Повторяем концептуально при переходе на SFU |
| Код Jitsi | **Не форкаем** для MVP: цена входа в 8 МБ TS + Kotlin JVB не окупается |
| Jibri | Не берём: вместо него egress-сервис |

---

## 3. LiveKit (open source, Apache-2.0)

### 3.1 Что это

LiveKit — «end-to-end realtime stack»: SFU на Go + серверные API + SDK на десяток
платформ + агентский фреймворк для AI. В отличие от Jitsi, у него **нет обязательного
набора из четырёх сервисов**: один бинарник, конфиг YAML/env, опционально Redis
для мультиузлового режима.

| Параметр | Значение |
|----------|----------|
| Лицензия | Apache-2.0 ([GitHub API](https://api.github.com/repos/livekit/livekit)) |
| Язык | Go |
| Звёзды / форки | 22 185 / 2 563 |
| Объём репозитория | 17 169 KB (~17 MB) |
| Последний push | 13.11.2026 |
| Клиентские SDK | JS/TS, React, React Native, Python, Go, Rust, Swift, Kotlin, Flutter, Unity, Node, Ruby, PHP (по [docs.livekit.io](https://docs.livekit.io/home/)) |
| Доп. сервисы | `livekit-egress` (запись/стриминг), `livekit-ingress` (RTMP/WHIP/SRT), `livekit-cli`, `livekit-agents` |

Показательно сравнение объёмов: **LiveKit-сервер ~17 MB репозитория против ~229 MB у JVB**
и ~382 MB у клиента Jitsi. Это не «лучше/хуже», это разная степень «всё в одном»:
LiveKit сознательно вынес UI и продуктовые фичи в SDK/приложения.

### 3.2 Модель данных и токены

```
Room ── Participant ── TrackPublication ── Track
```

| Сущность | Смысл | Аналог в AGIL |
|----------|-------|---------------|
| Room | Комната/встреча, живёт на конкретном узле | `RoomInfo` (`id`, `tenantId`, `locked`) |
| Participant | Участник с identity (без PII!), name, metadata, permissions | `Participant` (`id`, `name`, `role`, `state`) |
| Track | Аудио/видео/дата-трек, publish/subscribe | Медиа-треки mesh-соединений (пока) |
| TrackPublication | Декларация публикации (muted, simulcast, codec) | Состояние `mic/cam/screen` |

Токены: JWT, подписанный API secret, содержит grants
([Access tokens & grants](https://docs.livekit.io/home/server/generating-tokens/)):

- `room`, `roomJoin`, `roomAdmin`, `roomCreate`, `roomList`
- `canPublish`, `canSubscribe`, `canPublishData`
- `hidden`, `recorder`
- время жизни, refresh и revocation; предупреждение вендора — **не класть PII
  в identity/room name**, потому что они попадают в логи и трассы.

Это ровно тот же принцип, что у нас: `sub/name/role/tenantId/roomId/iat/exp`
в `TokenClaims`, HS256, TTL по умолчанию 1 час. Практический вывод: наш формат
почти совместим по смыслу, и при миграции на LiveKit-медиаплейн маппинг claims
будет однострочным.

### 3.3 Egress / Ingress

| Сервис | Что делает | Зачем AGIL |
|--------|-----------|-----------|
| Egress | Запись и стриминг: RoomComposite, Web, Participant, TrackComposite, Track; выход в MP4/HLS/RTMP/S3 | Запись встреч, трансляции, экспорт в хранилище |
| Ingress | Ввод: RTMP, WHIP, SRT, URL | Подключение внешних камер/стримов, «вход» из OBS |
| SIP server | Телефонные участники | Потом (аналог Jigasi) |

Источники: [Egress overview](https://docs.livekit.io/home/egress/overview/),
[Ingress overview](https://docs.livekit.io/home/ingress/overview/).

Для AGIL это готовый ответ на вопрос «как делать запись без Jibri»: egress — отдельный
сервис, который подключается к комнате как участник и рендерит композицию. Это
масштабируется горизонтально и не требует headless-браузера на каждый звонок
(хотя web-egress его использует внутри — важно для оценки стоимости).

### 3.4 Embedding-подход

LiveKit **не даёт «однострочный iframe» уровня Jitsi/Daily**. Модель встраивания:

| Уровень | Пакет | Что даёт |
|---------|-------|----------|
| Компоненты React | `@livekit/components-react` (npm 2.9.25) | Готовые `LiveKitRoom`, `VideoConference`, `ParticipantTile`, `Chat`, `ControlBar` |
| Низкоуровневый клиент | `livekit-client` (npm 2.24.0) | Room/participant/track API, события, data channels |
| Свой UI | — | Собираешь всё сам поверх `livekit-client` |

Следствие: чтобы сделать AGIL-widget на LiveKit, наш SDK всё равно остаётся нужен —
он инкапсулирует «комната + тема + брендинг + MCP». LiveKit даёт медиаплейн и клиент,
но не продуктовый контракт. Это подтверждает нашу стратегию: **свой тонкий слой
поверх чужого SFU**.

### 3.5 AI-экосистема и MCP

`livekit-agents` (Python) — 15 211 звёзд, активная разработка (push 13.11.2026),
имеет **first-class поддержку MCP**: агент подключает MCP-серверы как источники
инструментов, с фильтрацией и трансформацией результатов
([docs: MCP](https://docs.livekit.io/agents/logic/tools/mcp.md)).

Что это значит для AGIL:

1. Ниша «MCP для видеоплатформы» уже частично занята — но занята **со стороны агента
   внутри звонка** (AI-участник), а не со стороны **администрирования платформы**.
   Наш MCP-сервер настраивает комнату/темы/панель — это другая плоскость, конкуренции нет.
2. Формат инструментов у LiveKit-агентов — стандартный MCP, поэтому наш сервер
   можно будет подключить и к их агентам как источник room-контекста
   (например, `agil://rooms/{id}/state`).
3. Версии протокола быстро меняются (см. раздел 8) — встраивать MCP-логику
   нужно через адаптер, а не в ядро.

### 3.6 Лицензия и что переиспользовать

Apache-2.0 — самая удобная для продукта: можно использовать, модифицировать,
распространять, в том числе в закрытом SaaS, с сохранением NOTICE и патентным грантом.

| Что | Переиспользуем | Как |
|-----|----------------|-----|
| `livekit-server` (SFU) | Да | Ставим как отдельный сервис, не линкуемся в код |
| `livekit-egress` / `livekit-ingress` | Да | Отдельные поды, включаем по тарифу |
| `livekit-client` (JS) | Да | Внутри нашего widget/SDK, как зависимость |
| `@livekit/components-react` | Опционально | Для быстрого админского «превью», не для брендируемого UI |
| Код сервера как библиотека | Нет | Не форкаем: обновления вендора важнее локальных патчей |
| Брендинг/название | Нет | Apache-2.0 не даёт прав на товарные знаки |

Риск: LiveKit Cloud vs self-host. Для on-prem/152-ФЗ нужен self-host, а это значит
мы сами отвечаем за Redis, TURN, обновления и мультирегион — эти часы есть в оценке.

---

## 4. Медиа-серверы второго эшелона

### 4.1 Сводная таблица

Данные GitHub API на 13.11.2026:

| Проект | Лицензия | Язык | Звёзды | Объём (KB) | Последний push | Роль |
|--------|----------|------|--------|-----------|----------------|------|
| Janus Gateway (`meetecho/janus-gateway`) | **GPL-3.0** | C | 9 204 | 46 977 | 10.11.2026 | Плагинный WebRTC-шлюз: VideoRoom (SFU), Streaming, SIP, Record&Play |
| mediasoup (`versatica/mediasoup`) | **ISC** | C++ | 7 417 | 177 042 | 12.11.2026 | SFU-библиотека: worker'ы на C++, control — Node.js |
| mediasoup-client | ISC | TypeScript | 672 | 5 258 | 12.11.2026 | Клиентская часть (npm 3.26.0) |
| Pion (`pion/webrtc`) | **MIT** | Go | 16 895 | 7 447 | 12.11.2026 | Полный WebRTC-стек на Go (не SFU, а конструктор) |
| ion-sfu (`ionorg/ion-sfu`) | MIT | Go | 1 106 | 4 804 | **21.07.2023** | SFU на Pion; фактически заброшен |
| Galene (`jech/galene`) | MIT | Go | 1 431 | 3 998 | 09.11.2026 | Лёгкий SFU + встроенный веб-клиент, академический проект |
| SRS (`ossrs/srs`) | MIT | C++ | 29 440 | — | 31.10.2026 | Стриминговый сервер с WebRTC/WHIP; про broadcast, не про встречи |
| «sfu (MIT)» из брифа | — | — | — | — | — | Обобщённое имя для мелких MIT-SFU; конкретный пакет не идентифицирован — **не подтверждено** |

### 4.2 Юридический риск лицензий (важно для проприетарного продукта)

| Лицензия | Можно ли использовать в закрытом SaaS | Риск | Комментарий |
|----------|--------------------------------------|------|-------------|
| MIT / ISC / BSD | Да | Низкий | Сохранить копирайт-нотис; патентной защиты нет |
| Apache-2.0 | Да | Низкий | + патентный грант, + требование NOTICE при распространении |
| GPL-2.0 | Спорно | Высокий | «Производное произведение» при линковке/модификации → раскрытие исходников |
| GPL-3.0 (Janus) | Спорно | **Высокий** | Нет linking exception; агрессивная трактовка производности; для SaaS-раздачи бинарника риск ещё выше |
| AGPL-3.0 | Практически нет | **Критический** | Сетевое использование = распространение; для SaaS не берём |

Практическая позиция для AGIL:

1. **Janus (GPL-3.0) не включаем.** Аргумент «он отдельным процессом, общаемся по сети»
   в GPL-сообществе не общепризнан, а судебной практики в РФ по этому вопросу нет —
   **не подтверждено**, значит риск не просчитан. Если очень нужен Janus-плагин
   (например, SIP), выносим в отдельный контейнер, отдаём юристу на review
   и держим как «необязательную интеграцию, поставляемую заказчику отдельно».
2. **mediasoup (ISC) — безопасно**, но это библиотека: сигналинг, комнаты, авторизацию,
   реконнект, запись и мультирегион пишем сами. Это ~+800–1200 ч к оценке.
3. **Pion (MIT) — безопасно** и полезно как «кирпичи» (ICE, DTLS, SRTP) для собственных
   сервисов; LiveKit уже построен на нём, так что для нашей архитектуры это транзитивная
   зависимость.
4. **ion-sfu — не берём**: нет коммитов с июля 2023. Для production это стоп-фактор
   (нет security-фиксов в WebRTC-стеке).
5. **Galene — интересен как референс** минималистичного SFU (один Go-бинарник + клиент),
   но не как основа: маленькое сообщество, академическая модель развития.
6. **SRS — не для встреч**: это broadcast-сервер (RTMP/HLS/WHIP), у него нет
   комнатной семантики и управления подписками.

### 4.3 Сравнение по «стоимости владения»

| Критерий | Janus | mediasoup | LiveKit | Jitsi | Pion (с нуля) |
|----------|-------|-----------|---------|-------|----------------|
| Лицензия для closed-source | GPL-3.0 ⚠️ | ISC ✅ | Apache-2.0 ✅ | Apache-2.0 ✅ | MIT ✅ |
| Готовый сигналинг | Нет | Нет | **Да** | Да (XMPP) | Нет |
| Готовый клиент | Нет | mediasoup-client | **SDK на 10+ платформ** | lib-jitsi-meet/iframe | Нет |
| Запись/стриминг | Плагин | Нет | **Egress** | Jibri (тяжело) | Нет |
| Мультирегион | Вручную | Вручную | Redis + комнаты на узлах | Jicofo + JVB pool | Нет |
| Порог входа в код | C + plugin API | C++/Node | Go, читаемый | TS+Kotlin+Lua | Go, читаемый |
| Кому подходит | Легаси/SIP | Своя платформа | Продукт | Готовый продукт | Исследования/ниши |

Вывод раздела: для AGIL реалистичны три пути — **LiveKit как медиаплейн** (рекомендуемый),
**mediasoup** (если нужен полный контроль и есть ресурс на свой сигналинг),
**Jitsi-форк** (если нужен готовый продукт «как есть», но не кастомизация).
Расчёт сроков по каждому — в `docs/estimate.md`, раздел C.

---

## 5. Яндекс Телемост (закрытый продукт)

### 5.1 Что можно утверждать по фактам

Телемост — проприетарный сервис Яндекса. Исходников нет, клиент минифицирован,
лицензия закрытая. При этом **важное уточнение: серверный API у Телемоста есть** —
это REST API для организаций на Яндекс 360, он позволяет создавать встречи,
управлять ими и трансляциями, работать с перепиской
([О сервисе — API Яндекс Телемоста](https://www.yandex.com/dev/telemost/doc/ru/)).

| Наблюдаемый факт | Подтверждение |
|------------------|---------------|
| REST API для создания/управления встречами | `POST` создания конференции возвращает `id`, `join_url`, `access_level` (`PUBLIC`/`ORGANIZATION`/`UNKNOWN`), `waiting_room_level`, `live_stream`, `cohosts`, `is_auto_cloud_recording_enabled`, `is_auto_summarization_enabled` — [документация создания видеовстречи](https://www.yandex.ru/dev/telemost/doc/ru/conferences/conference-create) |
| API ограничено бизнес-аккаунтами Яндекс 360 на домене организации | «Работа с API Телемоста доступна только для пользователей Яндекс 360 для бизнеса с аккаунтами на домене организации» — [там же](https://www.yandex.com/dev/telemost/doc/ru/) |
| Встраиваемого iframe/JS-виджета (как у Jitsi/Daily) в публичной документации нет | Найден только `join_url` и нативные приложения; публичного embed-SDK не обнаружено — **не подтверждено** как «не существует», но публично не документировано |
| Роли: организатор, соорганизаторы; комната ожидания; отключение камер/микрофонов/записи | [Manage a call — Yandex Support](https://yandex.com/support/yandex-360/customers/telemost/desktop/en/call/administration) |
| Запись: на компьютер (Яндекс Браузер/Chrome) или облачная, авто-запись и авто-суммаризация через API | [Запись звонка](https://www.yandex.ru/support/yandex-360/business/telemost/desktop/ru/call/record), API-поля `is_auto_cloud_recording_enabled`, `is_auto_summarization_enabled` |
| Поддержка трансляций (live stream) и переписки через API | [О сервисе](https://www.yandex.com/dev/telemost/doc/ru/) |

### 5.2 Что можно предполагать по поведению (и чего нельзя утверждать)

| Гипотеза | Статус | Пояснение |
|----------|--------|-----------|
| Транспорт — WebRTC в браузере | Высокая уверенность | Без установки плагинов, работает в Chrome/Safari/Firefox и в нативных приложениях |
| Для 1:1 возможен P2P, для групп — SFU | **Не подтверждено** | Требует инспекции ICE-кандидатов и SDP; без этого утверждать нельзя |
| Количество участников ограничено тарифом | Подтверждено косвенно | «Разные лимиты участников на разных тарифах» — [обзор](https://trueconf.ru/blog/reviews/obzor-yandex-telemost); точные цифры меняются, **не подтверждено** |
| Кодеки: VP8/VP9/H.264 + Opus | **Не подтверждено** | Стандартный набор для WebRTC, но конкретика Телемоста не документирована |
| Шумоподавление и блюр фона | Подтверждено как фича продукта | Реализация (MediaPipe/собственная) неизвестна |

Как легально проверять гипотезы: только black-box — DevTools, WebRTC-internals
(`chrome://webrtc-internals`), анализ SDP своего же соединения. Это анализ
**своего** трафика, а не декомпиляция чужого кода, и он допустим.

### 5.3 Что из UX/механик Телемоста стоит повторить

| Механика | Почему хорошо | Как делаем в AGIL |
|----------|---------------|-------------------|
| Вход по ссылке без установки и без регистрации | Минимальный порог входа — главный драйвер роста | Гостевая ссылка + JWT-грант `role: guest` |
| Экран проверки камеры/микрофона до входа | Снижает «чёрные квадраты» в первые 30 секунд | Preview-экран, `joinWithoutPreview: false` в конфиге |
| Комната ожидания (waiting room) | Защита от случайных гостей | `security.waitingRoom` уже есть в схеме конфига |
| Соорганизаторы | Делегирование модерации без передачи «владельца» | Роли `host` / `moderator` / `guest` |
| Явные индикаторы «микрофон выключен организатором» | Убирает непонимание, почему не слышно | Системные сообщения в чат + состояние в `ParticipantState` |
| Авто-запись и авто-суммаризация на уровне API | B2B-фича, за которую платят | Egress + поле в тарифе, потом транскрипция |
| Светлая/тёмная тема, крупные кнопки, минимум настроек | Массовый пользователь не любит конфигураторы | Пресеты темы + «простой» режим редактора |
| Трансляция (live stream) как отдельный сценарий | Вебинары без WebRTC-нагрузки на зрителей | HLS/RTMP через egress-сервис |

Чего **не** делаем: не копируем визуальный дизайн, иконки, тексты, анимации.
Это объекты авторского права и товарные знаки; «похожесть до смешения» — отдельный
риск. Референс допустим на уровне паттернов взаимодействия, не пикселей.

### 5.4 Почему код нельзя реверсить

| Основание | Что означает на практике |
|-----------|--------------------------|
| Закрытая лицензия / пользовательское соглашение | Запрет декомпиляции, обхода защиты, извлечения кода; нарушение = расторжение договора + убытки |
| Авторское право (ГК РФ, ст. 1259, 1260, 1280) | Программа — объект авторского права; ст. 1280 разрешает декомпиляцию **только** для достижения совместимости с собственной программой, и запрещает использовать результат для создания аналогичной программы |
| Обход технических средств защиты (ст. 1299 ГК РФ) | Минификация/обфускация — не «защита» в смысле ст. 1299, но обход иных ТСЗ и извлечение кода — риск |
| Уголовная ответственность (ст. 146 УК РФ) | Незаконное использование объектов авторского права в крупном размере |
| Товарные знаки | Использование «Телемост»/логотипов в своём продукте — отдельное нарушение |
| Зарубежная аналогия (DMCA §1201) | Обход защиты и извлечение кода — самостоятельное нарушение, даже без распространения |

Правильная модель — **clean room**: одна группа описывает наблюдаемое поведение
и требования (этот документ), другая реализует по описанию, не видя чужого кода.
Именно так и построена работа команды AGIL Calls.

---

## 6. Коммерческие embedded SDK

### 6.1 Сравнение публичных API

| Вендор | Модель встраивания | Серверный API | Авторизация | Темизация | События |
|--------|--------------------|---------------|-------------|-----------|---------|
| **Daily** | iframe `daily.co/<room>` + `daily-js` (call object) | REST: domains, rooms, meeting tokens | meeting token (JWT) + API key | Цветовые темы Prebuilt, кастомный UI через call object | `daily-js` events (`participant-joined`, `track-started` и т.д.) |
| **Twilio Video** | JS/iOS/Android SDK, без iframe | Rooms API, Access Tokens (JWT), Data Track | Access Token (JWT, grants) | Нет готового UI — рисуете сами | `Room`/`Participant`/`Track` events |
| **Zoom Meeting SDK for Web** | WebAssembly-модуль: Client View (полный экран) или Component View (части страницы), можно в iframe | Meeting API отдельно; SDK key/secret + JWT-подпись | SDK JWT (signature) | Ограниченная (своя тема Zoom) | `onMeetingStatus`, participant events |
| **100ms** | Prebuilt (`HMSPrebuilt`, web component `<hms-prebuilt room-code="...">`), RoomKit; кастомный UI через SDK | Room codes, auth tokens, roles/templates | Room code **или** auth token | Брендинг Prebuilt + темы | HMS SDK listeners |
| **Whereby Embedded** | Web component `<whereby-embed>` + prebuilt UI; Browser SDK / Core SDK | REST `/meetings` (обязательный `endDate`), host/viewer room URL | API key + room URL/JWT | Брендинг, логотип, цвета, элементы | Webhooks + SDK events |

Уточнения по фактам:

- **Daily**: Prebuilt — «полнофункциональный виджет, встраиваемый парой строк»; кастомизация —
  через `daily-js` call object; есть HIPAA add-on, темы оформления, локализация
  ([Daily Prebuilt](https://docs.daily.co/guides/products/prebuilt), [REST API](https://docs.daily.co/reference/rest-api)).
- **Twilio**: в марте 2024 объявили EOL Programmable Video на 5 декабря 2026, затем
  **отменили** это решение — Video остаётся отдельным продуктом
  ([справка Twilio](https://help.twilio.com/articles/20950630029595), [changelog](https://www.twilio.com/en-us/changelog)).
  Вывод: вендорская стратегия у Twilio нестабильна, как основа платформы — риск.
- **Zoom**: Meeting SDK — WebAssembly, два режима (Client View / Component View),
  поддерживает iframe и WebView; политика запрещает ботов/AI-нотекеров, для realtime-медиа
  предлагается RTMS ([Meeting SDK for Web](https://developers.zoom.us/docs/meeting-sdk/web/)).
  Это важный сигнал: платформы начали лицензионно ограничивать AI-сценарии.
- **100ms**: Room Code = короткий код, кодирующий Room ID + Role; для кастомного UI
  нужен `getAuthTokenByRoomCode` ([Room Code Authentication](https://github.com/100mslive/100ms-docs/blob/main/docs/prebuilt/v2/prebuilt/room-codes/room-code-auth.mdx)).
- **Whereby**: `POST /meetings` с обязательным `endDate`, можно запросить `hostRoomUrl`/`viewerRoomUrl`;
  комнаты удаляются не мгновенно после `endDate` ([REST API](https://docs.whereby.com/),
  [Initial setup](https://docs.whereby.com/getting-started/overview-of-whereby-embedded/initial-setup)).
- **Яндекс Телемост** — см. раздел 5: REST API есть, embed-SDK нет.

### 6.2 Минимальный API-контракт, который стоит реализовать

Из пяти вендоров выкристаллизовывается общий минимум. Он же — целевой контракт AGIL Calls.

| Группа | Метод/элемент | Семантика | Статус в AGIL |
|--------|---------------|-----------|---------------|
| Сервер | `POST /v1/rooms` | Создать комнату; возвращает `room`, `joinUrl`, `embedUrl`, `token` | Реализуется (`packages/server`) |
| Сервер | `POST /v1/tokens` | Выдать JWT-грант: `tenantId`, `roomId`, `participant.name/role`, `ttlSec` | Реализовано (`signToken`) |
| Сервер | `GET /v1/rooms/:roomId` | Комната + участники | Реализуется |
| Сервер | `DELETE /v1/rooms/:roomId` | Закрыть комнату | Реализуется |
| Сервер | `GET /v1/rooms/:roomId/messages` | История чата (для fallback-режима) | Реализуется |
| Сервер | `GET/PUT/PATCH /v1/tenants/:tenantId/config` | Чтение и обновление `TenantConfig` (`etag` для конкурентности) | Схема готова |
| Сервер | `GET /v1/ice` | ICE-серверы (STUN/TURN) | Реализуется |
| Сервер | `GET /v1/health` | Здоровье сервиса | Реализуется |
| Клиент | `new AgilCall({ container, token, config? })` → `join()` / `leave()` | Жизненный цикл звонка | В работе |
| Клиент | `call.on('*', cb)` / `call.off()` | События: peer-joined/left, chat, state, quality | Протокол описан (`signaling.ts`) |
| Клиент | `call.execute({ type: 'toggleAudio' \| ... })` | Типизированные команды | Типизируется через zod |
| iframe | `postMessage({ v, id, type, payload })` | Мост с версионированием | Требует реализации (`packages/widget`) |
| iframe | `agil:ready`, `agil:event`, `agil:command`, `agil:error` | Набор типов сообщений | Требует реализации |
| Тема | `data-agil-theme` + CSS-переменные | Рантайм-темизация без пересборки | Реализовано (`toCssVars`) |
| Пресеты | `themePresets` в `@agil/protocol` | `light/dark/corporate/night/minimal`, отдаются вместе с конфигом (отдельного HTTP-эндпоинта нет) | Готово |
| MCP | `tools/list`, `tools/call`, 13 инструментов `agil_*` | Настройка платформы нейросетью | Реализуется (`packages/mcp`) |

Отличия от вендоров, которые мы сознательно делаем:

1. **Версионирование моста и протокола.** У Jitsi postMessage-протокол описан как набор
   команд/событий, но не как версионированный контракт; у Daily и Zoom мост закрытый.
   У нас `{ v: 1 }` + zod-валидация и явная политика обратной совместимости.
2. **Тема как данные, а не как сборка.** Jitsi умеет «динамический брендинг» (логотип,
   ограниченный набор цветов на инстанс), Daily — темы Prebuilt, Zoom — почти ничего.
   Полноценной палитры, вычисляемой из бренд-цвета клиента в рантайме, нет ни у кого —
   это наше конкурентное преимущество (`themeFromBrandColor`, `auditTheme`).
3. **MCP как first-class.** Ни у одного из пяти вендоров нет MCP-сервера для
   администрирования платформы (у LiveKit — только MCP для агентов внутри звонка).
4. **Чат, независимый от медиа.** У вендоров чат обычно поверх data channel; при деградации
   сети он умирает вместе с медиа. У нас чат идёт по signaling-WebSocket
   (`chatOverSignaling`), а data channel — опциональное ускорение.

---

## 7. Технологии для фич AGIL Calls

### 7.1 Видеокодеки

| Кодек | Лицензия/роялти | Сильные стороны | Слабые | Роль в AGIL |
|-------|------------------|-----------------|--------|-------------|
| **VP8** | Royalty-free (Google) | Универсальная поддержка, обязательный «baseline» для WebRTC, только simulcast | Хуже качество/битрейт, нет SVC | Fallback-кодек |
| **VP9** | Royalty-free | SVC (пространственно-временные слои), хорошее качество на низком битрейте | Тяжелее энкод, не везде аппаратно | Основной для 1:1 и «экономного» режима |
| **AV1** | Royalty-free (AOMedia) | Лучший битрейт/качество, SVC | Тяжёлый энкод на слабых устройствах, поддержка в WebRTC фрагментарна | Включаем при `hardware`/`isSupported`, иначе не предлагаем |
| **H.264 (CBP)** | MPEG-LA pool, **роялти** | Аппаратное кодирование/декодирование, лучшая совместимость с Safari/iOS | Лицензионные отчисления, хуже при низком битрейте | Обязателен для Safari/iOS-совместимости |

Практика: для WebRTC H.264 Constrained Baseline Profile — обязательный к реализации
кодек для совместимости (RFC 7742), но для проприетарного продукта это ещё и
потенциальные роялти MPEG-LA — **уточнять у юриста**, «не подтверждено» для конкретных
условий поставки.

Simulcast vs SVC (важное различие для SFU):

| | Simulcast | SVC |
|---|-----------|-----|
| Как работает | Несколько независимых потоков (SSRC) разного разрешения | Один битстрим со слоями; верхний слой зависит от нижнего |
| Плюсы | Работает с VP8/H.264, простой выбор слоя | Экономия битрейта, плавная адаптация |
| Минусы | Дублирование энкод-ресурсов | Только VP9/AV1; зависимость слоёв усложняет потери |
| Кто умеет | Все браузеры | Chrome/Chromium в первую очередь |

Источник по различиям и ограничениям VP8 (только simulcast, без spatial SVC):
[W3C public-webrtc обсуждение webrtc-svc](https://lists.w3.org/Archives/Public/public-webrtc-logs/2022Jan/0073.html).

Insertable Streams / Encoded Transform (E2EE и сквозная обработка кадров):

- Jitsi делает E2EE именно на Insertable Streams
  ([E2EEcontext docs](https://jitsi.github.io/lib-jitsi-meet/classes/JitsiConference._internal_.E2EEcontext.html));
  шифрование в кадре — SFU видит только шифротекст;
- API переезжает в стандарт **WebRTC Encoded Transform** (Working Draft W3C, апрель 2026),
  `createEncodedStreams()` считается устаревшим путём;
  Chromium впереди, Safari отстаёт — по данным отраслевого обзора
  ([callsphere, 2026](https://callsphere.ai/blog/vw3e-webrtc-encoded-transform-api-status-2026));
- практическое следствие: E2EE в AGIL — фича «для поддерживаемых браузеров»,
  с явным предупреждением в UI и деградацией до «шифрование на транспорте (DTLS-SRTP)».

### 7.2 Низкая задержка: ручки, которые реально работают

| Ручка | Что делает | Статус/поддержка |
|-------|-----------|------------------|
| `jitterBufferTarget` | Целевая задержка джиттер-буфера в мс (не «hint», а цель) | Baseline 2026, «newly available»; Chromium 113+, Firefox 124+ — [MDN](https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpReceiver/jitterBufferTarget) |
| `playoutDelayHint` | Подсказка браузеру по задержке воспроизведения | Нестандартизовано, Chromium; на Firefox может игнорироваться — **не подтверждено** для всех версий |
| `degradationPreference` | `maintain-framerate` / `maintain-resolution` / `balanced` — что терять первым при нехватке полосы | Стандартная ручка sender'а |
| `contentHint` | `detail` / `motion` / `text` — подсказка энкодеру | Стандарт; влияет на битрейт/качество |
| `ptime` | Длительность пакета Opus (10/20/60 мс) | Влияет на задержку vs overhead; 20 мс — компромисс |
| ICE/TURN | Relay при симметричном NAT; TCP/TLS-443 как последний шанс | Обязательно, иначе часть корпоративных сетей не подключится |
| Congestion control | GCC/transport-cc, pacer | Управляется браузером, но требует корректного SFU |

Практический вывод для MVP (mesh): задержку задаёт в основном сеть и jitter-буфер;
`jitterBufferTarget = 0–200 мс` для интерактивных сценариев, `200–500 мс` — для
плохих каналов; для аудио жертвуем битрейтом, но не задержкой.

### 7.3 WebTransport / QUIC

- API работает по HTTP/3, статус **Newly Available с 24.03.2026**: Firefox 114+,
  Safari 26.4+, Chromium — [web-features explorer](https://web-platform-dx.github.io/web-features-explorer/features/webtransport/),
  [caniuse](https://caniuse.com/mdn-api_webtransport_createunidirectionalstream).
- Для медиа WebTransport сам по себе не нужен: медиа в браузере всё равно идёт через
  WebRTC (congestion control, jitter buffer, echo cancellation — всё в стеке).
- Где он реально полезен AGIL: **резервный транспорт для чата/сигналинга** при
  плохом WebSocket, передача файлов, синхронизация состояния редактора панели.
- Вывод: держим как «фаза 2», не блокирует MVP. Слишком свежий (Safari 26.4) —
  нельзя делать единственным путём.

### 7.4 Блюр и замена фона

| Подход | Пакет/технология | Плюсы | Минусы |
|--------|------------------|-------|--------|
| MediaPipe Tasks Vision: `ImageSegmenter` / selfie segmenter | `@mediapipe/tasks-vision` **1.2.3** | Быстро, GPU/CPU delegate, активно поддерживается Google | Нужна загрузка WASM+модели (~несколько МБ), инициализация 200–500 мс |
| MediaPipe Selfie Segmentation (legacy) | `@mediapipe/selfie_segmentation` 0.1.1675465747 | Простой API | Legacy-пакет, версия «заморожена» с 2023 |
| TensorFlow.js BodyPix | `@tensorflow/body-pix` | Гибкая сегментация тела | Тяжелее, медленнее, проект фактически не развивается |
| WebGL-шейдеры + собственная маска | raw WebGL | Полный контроль над краями/цветокоррекцией | Всё пишем сами |
| WebGPU | нативная API | Максимальная скорость | Поддержка не везде (Safari появилась позже) — **не подтверждено** для всех целевых версий |
| CSS `backdrop-filter: blur()` | CSS | Дешево | **Не влияет на исходящий видеопоток** — только локальный вид; получатель видит фон как есть |

Рабочий пайплайн AGIL:

```
getUserMedia → <video> → (rAF/VideoFrame) → сегментация → композит в canvas/WebGL
            → canvas.captureStream(30) → MediaStreamTrack → replaceTrack() в sender
```

Ключевые ограничения, которые нужно заложить в UI:

1. **Бюджет 33 мс/кадр**: сегментация + композит должны укладываться в кадр 30 fps,
   иначе включается троттлинг (проверять `requestVideoFrameCallback`).
2. **Safari/iOS**: `canvas.captureStream` и производительность WASM ограничены;
   нужен graceful fallback («блюр недоступен — выключить»), а не «белый экран».
3. **Тёплый старт**: модель грузим лениво при первом включении фичи, а не при join.
4. **Приватность**: кадры не покидают устройство — это маркетинговое преимущество,
   его надо явно писать в UI («обработка на устройстве»).

### 7.5 Чат и fallback при плохой связи

| Механизм | Когда хорош | Ограничения |
|----------|-------------|-------------|
| WebRTC data channel (reliable/ordered) | Низкая задержка при живом медиа | Умирает вместе с медиа; при ICC-проблемах дублируется/теряется |
| WebRTC data channel (unordered, `maxRetransmits`) | Реакции, курсоры | Не для сообщений чата |
| Signaling WebSocket | Основной путь для чата в AGIL | Нужен reconnect/backoff, heartbeat |
| HTTP + long-poll / SSE | Последний fallback, когда WS блокируется прокси | Задержка, нагрузка на сервер |
| CDN/edge long-poll + очередь | Совсем плохая сеть, «чат-first» режим | Дороже, сложнее |
| Локальный outbox (IndexedDB) | Гарантия «сообщение не потерялось» при обрыве | Нужны idempotency-ключи и порядок |

Реализованная в AGIL модель (см. `packages/protocol/src/signaling.ts`): чат идёт по тому же
WebSocket, что и сигналинг, с полем `chatOverSignaling: true`; data channel может
дублировать доставку для скорости, но **не заменяет** её. При деградации качества
(тиры `good/fair/poor/critical/offline` из `quality.ts`) стратегия переключается на
`reduce-video` → `audio-only` → `chat-first`.

### 7.6 Шумоподавление

| Вариант | Лицензия | Качество | Стоимость/риск |
|---------|----------|----------|----------------|
| Нативное `noiseSuppression: true` в getUserMedia | — (браузер) | Базовое, зависит от ОС | Бесплатно, но «режет» голос на некоторых микрофонах |
| **RNNoise** (Xiph) | **BSD-3-Clause** | Хорошее для стационарного шума | Нужен AudioWorklet + WASM; сборки: `@jitsi/rnnoise-wasm`, `@shiguredo/rnnoise-wasm` |
| SpeexDSP | BSD-3 | Среднее | Дополнительная зависимость |
| **Krisp** | Коммерческая | Лучшее на рынке | Лицензия + стоимость на пользователя, SDK/облако |

Для AGIL: MVP — нативный `noiseSuppression` + пресеты (`off/low/medium/high` в конфиге аудио),
фаза 2 — RNNoise через AudioWorklet (BSD-3 позволяет проприетарное использование),
Krisp — только если появится B2B-требование и бюджет.

---

## 8. MCP (Model Context Protocol)

### 8.1 Актуальная спецификация

| Параметр | Значение на 13.11.2026 |
|----------|------------------------|
| Текущая ревизия | **2026-07-28** ([modelcontextprotocol.io/specification/latest](https://modelcontextprotocol.io/specification/latest)) |
| Предыдущие ревизии | 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05 |
| Кодирование | JSON-RPC 2.0, UTF-8 |
| Роли | Hosts (LLM-приложение), Clients (коннектор), Servers (поставщик возможностей) |
| Серверные примитивы | `tools`, `resources`, `prompts` (+ discovery) |
| Транспорты | **stdio** (newline-delimited поверх stdin/stdout) и **Streamable HTTP** (POST на один endpoint, ответ — JSON или request-scoped SSE); допускаются кастомные транспорты |
| TypeScript SDK | `@modelcontextprotocol/sdk` **1.32.2** (npm, MIT), репозиторий `modelcontextprotocol/typescript-sdk` — 13 757 звёзд |

Ключевые изменения ревизии 2026-07-28, которые влияют на дизайн нашего сервера
(по [changelog](https://modelcontextprotocol.io/specification/2026-07-28/changelog)):

1. **Протокол стал stateless**: handshake `initialize` / `notifications/initialized` удалён;
   версия протокола и capabilities клиента передаются в `_meta` каждого запроса
   (`io.modelcontextprotocol/protocolVersion`, `.../clientCapabilities`),
   несовпадение версии → `UnsupportedProtocolVersionError`.
2. **`server/discover`** — обязательный RPC: сервер объявляет поддерживаемые версии,
   capabilities и идентичность. Клиент может вызвать его до всего остального.
3. **`subscriptions/listen`** заменил HTTP GET-эндпоинт и `resources/subscribe/unsubscribe`:
   один долгоживущий поток для серверных нотификаций с подпиской на типы.
4. **Удалены** `ping`, `logging/setLevel`, `notifications/roots/list_changed`;
   уровень логов задаётся в `_meta` запроса.
5. **Multi Round-Trip Requests (MRTR)**: вместо серверных запросов к клиенту
   (`roots/list`, `sampling/createMessage`, `elicitation/create`) сервер возвращает
   `InputRequiredResult` (`resultType: "input_required"`), клиент повторяет запрос
   с `inputResponses`.
6. **`resultType` стал обязательным** в результатах: `"complete"` / `"input_required"`.
7. **Tasks вынесены в расширение** `io.modelcontextprotocol/tasks` (поллинг `tasks/get`,
   `tasks/update`), из ядра убраны.

Практический вывод: **экосистема MCP быстро ломает совместимость**. Наш сервер должен:
- реализовывать `server/discover` и корректно отвечать на неизвестную версию;
- держать слой адаптеров «наша доменная модель ↔ MCP-схемы», чтобы пережить смену ревизии;
- не строить на MCP критичный путь (создание комнаты не должно зависеть от MCP —
  только настройка/автоматизация).

### 8.2 Как спроектировать MCP-сервер для AGIL Calls

Принцип: **MCP — это админ-плоскость, а не медиа-плоскость**. Нейросеть настраивает
внешний вид и поведение платформы, но не участвует в передаче медиа.

Домены инструментов (tools) — имена зафиксированы в командном контракте
(`docs/contract.md`, §9), здесь — их назначение и риск:

| Tool | Вход | Что делает | Плоскость | Риск |
|------|------|-----------|-----------|------|
| `agil_get_config` | `{ tenantId }` | Прочитать `TenantConfig` | онлайн (HTTP) | Нет |
| `agil_validate_config` | `{ patch }` | Проверить патч по zod-схеме | офлайн | Нет |
| `agil_update_config` | `{ tenantId, patch }` | Частично обновить конфиг | онлайн | Средний |
| `agil_generate_theme` | `{ brandColor, preset? }` | Сгенерировать палитру из бренд-цвета | офлайн | Нет |
| `agil_apply_theme` | `{ tenantId, theme }` | Применить тему | онлайн | Низкий |
| `agil_list_theme_presets` | `{}` | Вернуть 5 пресетов | офлайн | Нет |
| `agil_create_room` | `{ tenantId, name, ttlMin }` | Создать комнату | онлайн | Низкий |
| `agil_create_token` | `{ tenantId, roomId, role, ttlSec }` | Выдать гостевой токен | онлайн | **Высокий** |
| `agil_get_embed_snippet` | `{ roomId, theme? }` | Сгенерировать HTML-вставку | офлайн | Нет |
| `agil_audit_accessibility` | `{ theme }` | Проверить контраст (WCAG) | офлайн | Нет |
| `agil_suggest_lowbandwidth_profile` | `{ constraints }` | Предложить профиль деградации | офлайн | Нет |
| `agil_get_server_health` | `{}` | Здоровье сервера/комнат | онлайн | Нет |
| `agil_get_docs` | `{ topic }` | Вернуть документацию | офлайн | Нет |

Ключевое архитектурное решение: **часть инструментов работает офлайн** (генерация темы,
валидация конфига, аудит контраста, сниппет вставки) — они не требуют доступного сервера.
Это важно и для UX нейросети, и для безопасности: «придумать тему» можно без доступа
к продакшену, а «применить/выдать токен» — только с правами.

Ресурсы (resources):

| URI | Содержимое | Зачем нейросети |
|-----|-----------|------------------|
| `agil://docs/theming` | Документация по темам и токенам | Не выдумывать имена токенов |
| `agil://docs/api` | HTTP/WS-контракт | Генерировать корректные запросы |
| `agil://config/schema` | JSON Schema `TenantConfig` | Валидные патчи без галлюцинаций |

Промпты (prompts):

- `agil-brand-setup` — «вот бренд-цвет и логотип, собери тему и проверь контраст»;
- `agil-embed-install` — «вставь звонок на страницу, сгенерируй iframe/JS-сниппет».

Транспорт и аутентификация:

| Сценарий | Транспорт | Авторизация |
|----------|-----------|-------------|
| Локальный CLI/IDE (Claude Desktop и т.п.) | **stdio** (основной для MVP) | env: `AGIL_SERVER_URL`, `AGIL_API_KEY`, `AGIL_TENANT_ID` |
| Облачный сервис | Streamable HTTP | OAuth 2.1 / Bearer + отдельные scopes |
| Внутренний агент | Streamable HTTP + `subscriptions/listen` | mTLS/service token |

Разделение прав по инструментам (важно сделать явно, а не «всё или ничего»):

| Scope MCP-токена | Разрешённые tools |
|------------------|-------------------|
| `read` | `get_config`, `list_theme_presets`, `get_server_health`, `get_docs` |
| `design` | `read` + `generate_theme`, `validate_config`, `audit_accessibility`, `suggest_lowbandwidth_profile`, `get_embed_snippet` |
| `write` | `design` + `update_config`, `apply_theme`, `create_room` |
| `admin` | `write` + `create_token` (только с подтверждением и аудитом) |


Требования к безопасности (обязательные, иначе MCP станет дырой):

1. **Разделение токенов**: комнатный JWT (участник) и MCP-токен (администратор) — разные
   секреты, разные scopes, разные TTL.
2. **Подтверждение destructive-операций**: через MRTR `input_required` — нейросеть
   просит подтверждение у пользователя, а не делает молча.
3. **Идемпотентность**: `Idempotency-Key` для create/mint, чтобы ретраи не плодили комнаты.
4. **Аудит**: кто (agent id), что, когда, с каким патчем; хранить 90+ дней.
5. **Валидация**: zod-схемы из `@agil/protocol` → JSON Schema в `tools/list`;
   серверная валидация — та же, что у REST (один источник правды).
6. **Rate limit и kill-switch** на уровне MCP-сервера, отдельно от REST.
7. **Никакого доступа к медиа/записям** через MCP на MVP.

Схема инструмента (эскиз, совместимый с SDK 1.32.x):

```ts
server.registerTool('agil_apply_theme', {
  title: 'Apply theme to tenant',
  description: 'Applies a resolved theme to a tenant; validates WCAG contrast first.',
  inputSchema: {
    tenantId: z.string(),
    theme: themeSchema
  }
}, async ({ tenantId, theme }) => {
  const issues = auditTheme(theme);
  if (issues.some((i) => i.severity === 'error')) {
    return { isError: true, content: [{ type: 'text', text: JSON.stringify(issues) }] };
  }
  const saved = await api.applyTheme(tenantId, theme);
  return { content: [{ type: 'text', text: JSON.stringify({ theme: saved, issues }) }] };
});
```

Почему такой дизайн правильный: инструменты **не дублируют REST**, а вызывают тот же
сервисный слой; схема описана один раз (zod → JSON Schema); все изменения проверяемы
(`auditTheme`), значит нейросеть не может «сломать» контрастность незаметно;
офлайн-инструменты не требуют сети и потому безопасны для локальных моделей.

---

## 9. Итоговая матрица «берём / делаем / покупаем»

| Решение | Вердикт | Обоснование | Лицензионный риск |
|----------|---------|-------------|-------------------|
| **LiveKit server (SFU)** в production | **Берём** (self-host) | Apache-2.0, Go, один бинарник, egress/ingress, 22k звёзд, активен | Нет (NOTICE сохранить) |
| `livekit-client` JS | **Берём** как зависимость | Зрелый клиент, экономит месяцы на media-слое | Нет |
| `@livekit/components-react` | Опционально | Быстрый внутренний UI, не для брендируемого клиента | Нет |
| **Jitsi Meet** как продукт | **Не берём** | 8 МБ TS + Kotlin/Lua, кастомизация = сборка, тяжёлая эксплуатация | Низкий, но цена входа высокая |
| Код Jitsi (идеи last-N, control/media plane) | **Берём идеи** | Архитектурно правильно, код не нужен | Нет |
| **mediasoup** | Резервный вариант | ISC, отличная производительность, но сигналинг/запись/мультирегион — наши | Нет |
| **Janus** | **Не берём** | GPL-3.0 без linking exception — риск для closed-source | **Высокий** |
| **ion-sfu** | **Не берём** | Нет коммитов с 07.2023 | Нет, но небезопасно |
| **Pion** | Косвенно (через LiveKit) | MIT, отличные «кирпичи» | Нет |
| **Galene** | Референс | MIT, минимализм; маленькое сообщество | Нет |
| **SRS** | Не для встреч | MIT, но broadcast-модель | Нет |
| **MediaPipe tasks-vision** | **Берём** | 1.2.3, Apache-2.0 (Google), быстрый сегментер | Нет |
| **RNNoise** | Берём в фазе 2 | BSD-3, WASM-сборки есть | Нет |
| **Krisp** | Не покупаем (пока) | Лучшее качество, но цена/лицензия на пользователя | Коммерческая |
| **MCP TS SDK** | **Берём** | MIT, 1.32.2, официальный | Нет |
| **Daily / Twilio / Zoom / 100ms / Whereby** | **Не покупаем** | Дорого на масштабе, вендор-лок, нет MCP, нет рантайм-темизации под наш UX; Twilio ещё и менял стратегию (EOL → отмена) | Коммерческие |
| **Свой API + iframe-мост + темы + MCP** | **Делаем сами** | Это и есть продукт; всё остальное — commodity | — |
| **Свой mesh-режим 2–8** | **Делаем сами** | Дёшево, без серверного медиа, хорошо для MVP и on-prem | — |
| **Запись** | Покупаем/берём egress | Свой Jibri-подобный рендер — дорого в разработке и эксплуатации | Нет |
| **TURN** | Берём coturn (BSD) или встроенный TURN LiveKit | Обязателен для корпоративных сетей | Нет |
| **E2EE** | Делаем сами на Encoded Transform/SFrame (фаза 2) | Готовых кроссплатформенных решений нет; Safari отстаёт | Нет (свой код) |
| **AI-провайдер (LLM) для summary/выдержек** | Берём внешний API или self-host LLM | Своя модель не нужна; важна абстракция `aiAgent.mode` (local/external/hybrid) | Зависит от провайдера |
| **STT** | Берём Whisper (self-host) или Deepgram (облако) | Своя STT-модель — не наш продукт; критична резидентность | MIT/коммерческая |
| **Детекция deepfake** | **Не делаем свою модель**: liveness на MediaPipe + интеграция внешних API | Своя модель детекции — годы R&D и adversarial-гонка; риск-скор + человек в контуре | Нет (своя эвристика) |
| **C2PA-провенанс записей** | Делаем сами (дифференциатор) | У конкурентов публично не заявлен; стандарт открытый | Нет |
| **Панель разработчика (dashboard)** | Делаем сами | Это часть продукта: комнаты, конфиг, AI-находки, метрики, ключи | Нет |
| **Файлы** | Делаем сами (HTTP + S3) | Готовые вендорские «файлообменники встреч» не переиспользуемы | Нет |
| **Наблюдаемость** | Prometheus/Grafana (OSS) | Экспорт метрик JVB/LiveKit — стандарт индустрии | Нет |

Одной строкой: **медиаплейн — чужой (LiveKit, Apache-2.0), продуктовый слой —
свой (API, embedding, темы, редактор, чат-фолбэк, MCP), GPL/AGPL не трогаем.**

---

## 10. Безопасность и комплаенс у конкурентов

### 10.1 Доступ: пароли, лобби, waiting room

| Платформа | Механизм | Как работает | Что важно для AGIL |
|-----------|----------|--------------|---------------------|
| **Jitsi Meet** | Лобби (lobby) | Отдельная XMPP-комната ожидания: гость попадает в lobby-MUC, модератор впускает; реализовано Prosody-плагином `mod_muc_lobby_rooms` ([исходник](https://github.com/jitsi/jitsi-meet/blob/master/resources/prosody-plugins/mod_muc_lobby_rooms.lua)) | Лобби — это состояние сигналинга, а не UI. У нас `security.waitingRoom` + роль модератора |
| Jitsi | Пароль комнаты | Пароль в настройках конференции, проверяется на уровне XMPP-комнаты | Пароль храним только как scrypt-хеш (`security.passwordRequired`) |
| Jitsi | JWT / members-only | JWT-грант и/или ограничение «только участники» по XMPP-аффилиации | У нас JWT + `security.requireToken` |
| **Zoom** | Waiting Room | Включён на аккаунте; хост впускает по одному или всех сразу; можно пускать только гостей / только свой домен; экран кастомизируется логотипом и текстом ([90-day security report](https://www.zoom.com/siteassets/wp-content/uploads/2020/06/Ask-Eric-Anything-6-10.pdf)) | Готовый UX-референс для «комнаты ожидания» |
| Zoom | Passcode | Пароль встроен в ссылку (one-click), короткий цифровой — для телефонного дозвона | Аналог нашего пароля + инвайт-ссылки |
| Zoom | Только авторизованные | Водяные знаки и часть политик требуют «Only authenticated users can join» ([документация Zoom](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0068115)) | `security.requireVerifiedIdentity` |
| **Microsoft Teams** | Lobby | Политики meeting policies: кто может обходить лобби (люди из организации, гости, дозвон), отдельно для организатора/участников ([политики встреч](https://learn.microsoft.com/en-us/microsoftteams/meeting-policies-in-teams)) | Раздельные правила «кто обходит лобби» |
| **Google Meet** | Knock (стук) | Неавторизованный гость «стучится», хост впускает; в режиме Client-side Encryption стук отключён ([Meet CSE](https://support.google.com/meet/answer/11605714)) | Лобби + запрет «стука» в защищённом режиме |
| **Яндекс Телемост** | Комната ожидания | `waiting_room_level`: `PUBLIC` (лобби выключено) / `ORGANIZATION` (внешние ждут) ([API](https://www.yandex.ru/dev/telemost/doc/ru/conferences/conference-create)) | Та же модель «уровень доступа на уровне комнаты» |

Вывод: у всех — одна и та же тройка «пароль → лобби → роль». Разница только в том,
на каком слое это реализовано (XMPP-комната, политика аккаунта, поле API).
AGIL уже покрывает это `security.passwordRequired` / `security.waitingRoom` /
`security.moderatorJoinFirst` / `security.lockRoom`, но нужен UX-экран модератора
«впустить/отклонить» и журнал решений.

### 10.2 End-to-end encryption: у кого есть и что ломается

| Платформа | Что шифруется | Требования | Что **отключается** при E2EE |
|-----------|---------------|------------|------------------------------|
| **Jitsi Meet** | Медиа в Insertable Streams, ключ из общего пароля; JVB видит шифротекст | Браузер с Insertable Streams; все участники должны знать пароль | Зависит от браузера; часть серверных фич (запись/транскрипция) требует отдельного контура |
| **Zoom** | E2EE-встречи (AES-GCM, ключи у участников) | Все участники — только из Zoom desktop/mobile/Zoom Rooms; хост на free-аккаунте подтверждает телефон ([Zoom KB0075502](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0075502)) | Облачная запись, live-транскрипция, live-стриминг, опросы, Zoom Notes/Whiteboard (по [FAQ университета Дрездена, 2026](https://faq.tickets.tu-dresden.de/otrs/public.pl?Action=PublicFAQPrint;ItemID=390)) |
| **Microsoft Teams** | E2EE встреч и 1:1-звонков | E2EE встреч — **Teams Premium** у организатора; для 1:1 Premium не нужен; включается политикой ([Microsoft Learn](https://learn.microsoft.com/en-us/microsoftteams/teams-end-to-end-encryption)) | Live-субтитры и транскрипция, запись, compliance recording, RTT, перевод/объединение/парковка вызова, добавление участника, приложения (не видят медиа), breakout rooms, Excel/PowerPoint Live, запрос управления контентом, PSTN-дозвон, Copilot во встречах |
| **Google Meet** | Client-side Encryption (CSE): медиа шифруется браузером участника, ключи — у внешнего key service организации | Только Enterprise Plus / Education Standard / Education Plus + внешний IdP/key service ([Meet CSE](https://support.google.com/meet/answer/11605714)) | Abuse reporting, дозвон, add-ons, breakout rooms, субтитры, live-stream, шумодав, опросы, Q&A, реакции, записи, транскрипции, телефонный звук, Gemini-фичи (включая «Take notes for me») |
| **LiveKit** | E2EE через frame cryptor / Insertable Streams ([docs](https://docs.livekit.io/home/client/tracks/encryption/)) | Клиент поддерживает E2EE; SFU остаётся слепым | Запись/транскрипция на сервере требуют отдельного контура или отключения |
| **Яндекс Телемост** | Шифрование транспорта (TLS/SRTP); собственный E2EE публично не документирован — **не подтверждено** | — | — |

Главный вывод: **E2EE — это не галочка, а режим с матрицей отключённых фич.**
Все четыре крупных вендора отключают при E2EE запись, транскрипцию, субтитры, опросы,
иногда breakout rooms и даже части AI-функций. Для AGIL это означает:
1. E2EE — отдельный режим (`security.e2ee`), при включении UI явно показывает,
   что запись/STT/AI-компаньон недоступны;
2. нельзя обещать «E2EE + транскрипт» в одном режиме без клиентского STT;
3. в матрице фич (`docs/features.md`) E2EE и запись помечаются как взаимоисключающие.

### 10.3 Гео-ограничения и регион-локальность

| Аспект | Как у конкурентов | Что делаем мы |
|--------|-------------------|---------------|
| Блок по стране/IP | Zoom/Teams/Meet дают политики доступа на уровне аккаунта и региональных настроек тенанта; точный набор опций зависит от тарифа — **не подтверждено** для всех редакций | `security.geo.allowedCountries/blockedCountries/blockVpn` (ISO-3166 alpha-2) |
| Резидентность медиа | Jitsi self-host = где поставили; LiveKit Cloud — выбор региона; Meet/Teams — регион тенанта | Выбор региона SFU + TURN, чтобы медиа не уходило за периметр |
| Резидентность данных | Записи/транскрипты — в хранилище вендора | S3-совместимое хранилище в РФ (152-ФЗ), отдельный бакет на тенант |
| Ограничение «медиа не покидает регион» | Реализуется только при pinning SFU и TURN в регионе | Отдельный пункт в SLA, проверяется трассировкой ICE |

### 10.4 Аудит, DLP, запись с согласием, водяные знаки

| Механика | У конкурентов | Вывод для AGIL |
|----------|---------------|----------------|
| Аудит действий | Teams — Purview/audit log; Meet — audit log в Admin console; Zoom — audit logs и dashboard | `security.auditLog` обязателен: кто впустил, кто выгнал, кто включил запись, кто менял конфиг; экспорт в SIEM |
| DLP | M365 Purview DLP для чата/файлов Teams; Google Drive DLP; Zoom — через интеграции | На MVP: правила по флагам `aiCompliance.policyRules` (фразы/regex/PII) + DLP-крючок на файлы |
| Согласие на запись | Meet: админ может требовать явное согласие на Record/Transcribe/Take notes; в greenroom показывается политика ([Google](https://support.google.com/meet/answer/14754931)) | `session.recording.consentRequired` + `notifyParticipants` + баннер «запись идёт» |
| Водяные знаки | Zoom: часть e-mail участника накладывается на шаринг и видео в большинстве раскладок; требует «Only authenticated users can join» ([Zoom](https://support.zoom.com/hc/en/article?id=zm_kb&sysparam_article=KB0068115)) | Водяной знак на запись/стрим и (позже) на шаринг; привязка к user id + время |
| Compliance recording | Teams: пользователь под compliance recording **не может** использовать E2EE (Microsoft Learn) | Явно документировать несовместимость compliance-записи и E2EE |
| Индикация записи | Все вендоры показывают уведомление всем участникам | У нас — системное сообщение в чат + иконка + запись в аудит |

### 10.5 C2PA и провенанс контента

- C2PA (Coalition for Content Provenance and Authenticity) — открытый стандарт
  «Content Credentials»: криптографически подписанный манифест с историей
  происхождения медиа ([спецификации C2PA](https://c2pa.org/specifications/specifications/2.2/index.html);
  линейка версий 2.x, в селекторе доступны до 2.5 — точную актуальную версию
  нужно сверить при реализации, **не подтверждено**).
- Практика: платформы уже используют C2PA-метаданные, чтобы автоматически помечать
  AI-контент при загрузке; TikTok делает это по манифесту
  ([IPTC FAQ по C2PA](https://iptc.org/std/guidelines/media-provenance/C2PA-FAQs/IPTC-C2PA-FAQs-v1.0-2027-07-08.pdf)).
- В видеоконференциях C2PA пока не стал стандартом: ни у Jitsi, ни у Zoom/Teams/Meet
  публично не заявлена подпись записей манифестом C2PA (на 11.2026 — **не подтверждено**,
  скорее «нет»). Это реальная ниша для AGIL: подписывать записи и экспортируемые
  транскрипты, показывать «Content Credentials» в плеере.
- Связка с AI: подпись «это запись встречи X, время Y, устройство Z» + хеш файла
  даёт проверяемый провенанс, но **не** доказывает, что собеседник — человек
  (см. раздел 11). Не путать провенанс артефакта и подлинность личности.

---

## 11. Детекция AI-медиа и deepfake

### 11.1 Подходы

| Подход | Суть | Сильные | Слабые |
|--------|------|---------|--------|
| **Liveness challenge** | Случайное задание на входе: повернуть голову, моргнуть, показать жест; проверка через face landmarks (MediaPipe) | Дёшево, работает на клиенте, заметно повышает цену атаки | Раздражает пользователя; продвинутые аватары и «оператор за кадром» обходят |
| **Face landmark / geometry + anti-spoof** | Анализ микродвижений, несоответствий перспективы, границ лица | Офлайн, без утечки кадров | Хрупко к свету/очкам/низкому битрейту; ложные срабатывания |
| **Frame heuristics** | Артефакты синтеза: мерцание, «плывущие» границы, неконсистентный шум/резкость, тайминги кадров | Быстро, можно считать в браузере | Легко ломается компрессией WebRTC и апскейлом |
| **Audio deepfake detection** | Спектральные/фазовые артефакты синтеза речи, проверка дыхания/пауз | Работает на телефонном/аудио-канале | Сильно зависит от кодека и шума; клоны голоса нового поколения всё чище |
| **Внешние API-детекторы** | Отправка кадров/аудио в сервис (Hive, Reality Defender, Sensity, Pindrop) | Лучшее качество, независимая экспертиза | Задержка, стоимость, утечка биометрии за периметр, батч-режим у части вендоров |
| **Провенанс (C2PA/водяные знаки)** | Подпись контента при создании/записи | Юридически проверяемо | Не спасает от «живого» дипфейка в реальном времени |

Обзор вендоров (вторичные источники, требуют пилота): Hive AI — силён в батч-модерации,
«не для live-скрининга звонков»; Pindrop Pulse — детекция синтетической речи в звонках,
«Pulse for Meetings» расширяется на Zoom/Webex/Teams; Reality Defender — мультимодальный
(видео/аудио/изображение), есть бесплатный тир; Sensity — форензика и отчёты
([обзор 2026](https://about.fast.io/resources/best-deepfake-detectors-2026/),
[сравнение 2026](https://guptadeepak.com/tools/top-5-deepfake-detection-tools-2026/)).

### 11.2 Почему браузерная детекция ненадёжна

1. **Компрессия убивает признаки**: WebRTC режет битрейт и высокие частоты — именно то,
   на чём держатся артефакты синтеза.
2. **Нет бюджета CPU/GPU**: кадр и так занят сегментацией фона, блюром и энкодом;
   детекция в реальном времени конкурирует за те же 33 мс.
3. **Adversarial-устойчивость**: детекторы деградируют на новых моделях генерации
   быстрее, чем обновляется эвристика.
4. **Ложные срабатывания**: плохой свет, очки, макияж, низкое качество камеры
   дают те же признаки, что и синтез.
5. **Нет ground truth**: в браузере нет эталонного «оригинала» — только текущий поток.
6. **Точность**: по вторичным обзорам реального времени — 70–88%, постфактум — 80–92%
   ([источник](https://www.eyesift.com/faq/ai-voice-detection-deepfake-audio-2026/));
   для «автоматически выгнать» этого категорически недостаточно.

### 11.3 Юридические ограничения

| Ограничение | Что означает |
|-------------|--------------|
| Биометрия = особая категория ПДн | GDPR ст. 9, 152-ФЗ: обработка биометрии требует отдельного основания и согласия; хранение шаблонов лица — отдельный режим |
| Согласие и прозрачность | Участник должен знать, что его проверяют на «живость»/дипфейк; скрытая детекция — риск |
| Автоматические решения | GDPR ст. 22: нельзя принимать юридически значимые решения только автоматом; «выгнать по скору» — нельзя без человека |
| Локализация | Отправка кадров/аудио за рубеж — нарушение 152-ФЗ; внешний детектор только с локальным контуром или РФ-хостингом |
| Ложные обвинения | Публичное «фейк» без доказательств — репутационный и правовой риск |

### 11.4 Что делаем в AGIL

Схема уже заложена в конфиге — `security.mediaIntegrity`:

| Поле | Поведение |
|------|-----------|
| `livenessChallenge` | Случайный челлендж на входе (поворот/моргание) через MediaPipe; не чаще N раз |
| `frameHeuristics` | Клиентские эвристики (тайминги, резкость, консистентность) → риск-скор, а не вердикт |
| `externalProvider` | URL внешнего детектора (пилот с РФ-хостингом); отправка только по согласию |
| `flagThreshold` | Порог, выше которого участник помечается «подозрительный» |
| `autoMuteOnHighRisk` | Максимум — мьют + уведомление модератора; **никогда** автокик |

Принципы: (1) риск-скор, а не приговор; (2) человек принимает решение; (3) всё
в аудит-лог; (4) честный дисклеймер в UI; (5) в MVP — только liveness + эвристики,
внешние детекторы — roadmap.

---

## 12. AI-ассистенты встреч и транскрипты

### 12.1 Сравнение функций

| Продукт | Что делает | Условия/лицензии | API/интеграции |
|---------|-----------|-------------------|----------------|
| **Zoom AI Companion** (переименовывается в Zoom Workplace AI, ZoomMate — по данным обзора от 31.10.2026) | Summary и next steps, «умные» записи, работа без записи видео, вопросы по встречам | Входит в большинство платных Zoom-планов без доплаты ([Zoom](https://www.zoom.com/en/small-business/ai/)) | Zoom Meeting API, webhooks (`recording.completed`, `meeting.ended`), RTMS для realtime-медиа |
| **Microsoft Teams / Copilot** | Intelligent recap (сводка, задачи, «где это обсуждали»), Copilot в собраниях | Intelligent recap требует Microsoft 365 Copilot (для части сценариев); для событий доступен только организаторам/соорганизаторам/докладчикам ([Microsoft Learn](https://learn.microsoft.com/en-us/microsoftteams/intelligent-recap-calls-meetings)); Copilot недоступен в E2EE-встречах | Microsoft Graph: onlineMeetings, transcripts, recordings, callRecords |
| **Google Meet / Gemini** | «Take notes for me»: заметки-документ в Drive, прикрепляется к событию Calendar и рассылается; один язык за встречу; требует подходящей редакции Workspace ([Google](https://support.google.com/meet/answer/14754931)) | Business Standard/Plus, Enterprise Standard/Plus; в CSE-режиме недоступно | Google Meet API: spaces, conferenceRecords, transcripts, recordings, participants |
| **Otter.ai** | Live-транскрипт, summary, action items, поиск, шеринг | Freemium, лимиты минут — **не подтверждено** в деталях | Публичный API/webhooks заявлены — **не подтверждено**, проверять перед интеграцией |
| **Fireflies.ai** | Транскрипт, summary, AskFred, AI-приложения, аналитика | Freemium | **Подтверждено**: GraphQL API, Webhooks V2, Realtime API, MCP-server ([docs](https://docs.fireflies.ai/)) |

Что общего у всех: «транскрипт → структурированные артефакты (summary, decisions,
action items, risks) → поиск по ним → экспорт в корпоративные системы». Это ровно
наша модель `meetingNotesSchema` в `packages/protocol/src/compliance.ts`
(summary, excerpts, actionItems, decisions, risks, topics, sentiment, source).

### 12.2 Webhook-обмен «транскрипт → корпоративный AI → выдержки/findings»

```
[AGIL STT] --(сегменты)--> [AI-агент: local | external | hybrid]
      |                              |
      |                              +--> meetingNotes {summary, excerpts, actionItems, decisions, risks}
      |                              +--> complianceFindings {ruleId, severity, excerpt, confidence}
      |                              +--> POST {tenant}/ai-webhook (HMAC-подпись, idempotency-key)
      v
[Хранилище: transcript_segments, notes, findings] --(аудит)--> [Dashboard / MCP / экспорт]
```

Контракт события (упрощённо, согласован со схемами `compliance.ts`):

```json
{
  "v": 1,
  "eventId": "0192fa...",
  "type": "transcript.completed",
  "tenantId": "acme",
  "roomId": "room-42",
  "meeting": { "startedAt": 1763000000, "endedAt": 1763001800, "language": "ru" },
  "segments": [
    { "id": "s1", "participantId": "u7", "participantName": "Анна",
      "text": "предлагаю перенести релиз", "start": 12.4, "end": 15.1,
      "isFinal": true, "lang": "ru", "ts": 1763000012 }
  ],
  "policy": { "rules": [{ "id": "pii", "type": "pii", "severity": "critical" }] }
}
```

Ответ корпоративного AI (валидируется `parseAiAgentResponse`, невалидное отбрасывается):

```json
{
  "requestId": "0192fa...",
  "notes": {
    "summary": "Обсудили перенос релиза на неделю",
    "excerpts": [{ "id": "e1", "kind": "decision", "text": "перенос релиза",
                   "start": 12.4, "end": 15.1 }],
    "actionItems": [{ "id": "a1", "text": "обновить план", "owner": "Анна" }],
    "decisions": ["перенос релиза"], "risks": [], "topics": ["релиз"],
    "source": "hybrid", "segmentsAnalyzed": 128, "createdAt": 1763001900
  },
  "findings": [{ "id": "f1", "ruleId": "pii", "ruleName": "PII в речи",
                 "source": "external", "severity": "warn",
                 "excerpt": "номер карты ...", "confidence": 0.82,
                 "recommendation": "уведомить модератора" }]
}
```

Обязательные требования к интеграции (уже заложены в `aiAgentConfigSchema`):

| Требование | Поле конфига |
|-----------|--------------|
| Выбор режима: локально / внешний провайдер / гибрид | `aiAgent.mode` |
| Что отправляем наружу: транскрипт, чат | `sendTranscripts`, `sendChat` |
| Пакетность и таймауты | `batchSize`, `timeoutMs` |
| Срок хранения артефактов | `retentionMin` |
| Уведомление модераторов о находках | `notifyModerators` |
| Политика и правила комплаенса | `policyText`, `policyRules` |
| Секрет провайдера — только из env | `apiKeyEnv` |

### 12.3 Риски compliance для AI-ассистентов

| Риск | Проявление | Мера |
|------|------------|------|
| Согласие на запись/STT | Участник не знал, что его расшифровывают | Баннер + `consentRequired` + запись в аудит |
| Трансграничная передача | Транскрипт ушёл в зарубежный LLM | `mode=local` или РФ-хостинг; запрет external для тенантов с 152-ФЗ-режимом |
| Галлюцинации | Summary приписал решение, которого не было | Каждая выдержка хранит `start/end` и `participantId` — проверяемо |
| Утечка PII в промпт | Номер карты/паспорт попал в модель | PII-редакция до отправки + правила `pii` |
| Retention | Транскрипты хранятся вечно | `retentionMin`, автоудаление, экспорт по запросу |
| E2EE | Транскрипт невозможен без клиентского STT | В E2EE-режиме AI-функции отключены явно |

---

## 13. Файлы, запись, STT и демонстрация экрана

### 13.1 Передача файлов

| Платформа | Как | Ограничения |
|-----------|-----|-------------|
| Jitsi | Файлы в чате (в части сборок — через data channel/XMPP), без постоянного хранилища | Размер, отсутствие полноценного файлового хранилища |
| Zoom | Файлы в чате встречи; в облаке — в записях | Зависит от тарифа, ограничения по типу/размеру |
| Teams | Файлы уходят в OneDrive/SharePoint, в чат попадает ссылка | Нужна лицензия и настроенный SharePoint |
| Google Meet | Вложения в чате (ограниченно), документы — ссылками на Drive | Нет «файлообменника встречи» как класса |
| Daily | Встроенной передачи файлов нет — делают через свой backend + data | Всё сами |
| LiveKit | Data tracks / data packets + свой backend | Всё сами |
| **AGIL** | `session.fileShare {enabled, storeOnServer, maxFileSizeMb, allowedMimeTypes}` + HTTP upload + S3 | Нужны антивирус, DLP, retention (roadmap v2) |

### 13.2 Запись: client-side vs server-side

| Критерий | MediaRecorder (клиент) | Server egress (LiveKit/Jibri) |
|----------|------------------------|-------------------------------|
| Что пишет | Локальный микс, как его видит клиент | Композицию, заданную шаблоном |
| Качество/стабильность | Зависит от устройства, троттлинг фоновых вкладок | Стабильно, но дороже по CPU/GPU |
| Приватность | Файл остаётся у участника | Файл на сервере/в S3 |
| Согласие | Легко «незаметно» — нужен явный индикатор | Индикатор обязателен всем |
| Масштаб | Бесплатно, но N записей = N клиентов | 1 egress-инстанс на запись (или пул) |
| Форматы | WebM (VP8/VP9+Opus) в Chrome, MP4/H.264 в Safari | MP4/HLS/RTMP через egress |
| E2EE | Возможна (запись на клиенте) | Невозможна без ключей |

Рекомендация AGIL: MVP — client-side MediaRecorder с обязательным индикатором
и согласием (`session.recording.consentRequired/notifyParticipants`), Production —
server egress для облачных записей/стриминга и водяных знаков (см. `docs/estimate.md`).

### 13.3 Speech-to-text: браузер vs сервер

| Вариант | Плюсы | Минусы |
|---------|-------|--------|
| **Web Speech API** (`SpeechRecognition`) | Нулевая инфраструктура, есть в Chrome/Edge | В Firefox нет; уходит в облако браузера; нет диаризации и надёжных таймстемпов; качество на русском нестабильно; в Safari ограничено ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API)) |
| **Whisper** (self-host, faster-whisper, whisper.cpp) | Данные не покидают периметр, хорошее качество, дешево на своём GPU | Нужен GPU, задержка при батче, диаризация отдельно |
| **Deepgram** (streaming) | Низкая задержка, диаризация, пунктуация ([docs](https://developers.deepgram.com/docs/live-streaming-audio)) | Оплата за минуты, данные за рубежом (152-ФЗ) |
| **AssemblyAI / облачные STT** | Быстрый старт, богатые фичи | Те же ограничения по резидентности |
| Гибрид | live-субтитры локально, финальный транскрипт — сервером | Сложнее синхронизировать, зато комплаенс ок |

Для AGIL: `session.transcription.provider = browser | server | off`. MVP —
браузерные субтитры + серверный батч-транскрипт (Whisper-совместимый endpoint),
Production — стриминговый STT с диаризацией и РФ-хостингом.

### 13.4 Демонстрация экрана и аннотации

| Возможность | Реализация | Ограничения |
|-------------|-----------|-------------|
| Шаринг экрана/окна/вкладки | `getDisplayMedia()` | Пользователь выбирает поверхность сам; в iframe нужен `allow` |
| Шаринг региона | `getDisplayMedia` + кроп на canvas | Не во всех браузерах нативно |
| Системный звук | Chrome: tab/system audio; Safari — ограниченно | Не во всех ОС/браузерах |
| Аннотации | Прозрачный canvas поверх видео, синхронизация штрихов через signaling/data channel | Нужны лаг-компенсация и debounce |
| Удалённое управление | Отдельный протокол ввода + согласие | Высокий риск безопасности |
| Whiteboard | Отдельная доска (canvas/WebGL) с историей | Дорого по разработке, не в MVP |

У конкурентов: Zoom/Teams/Meet — аннотации и whiteboard как отдельные фичи;
Jitsi — базовый шаринг и (в части сборок) etherpad; Daily/LiveKit — только
транспорт, аннотации пишутся приложением.

---

## 14. Панели разработчика и админки конкурентов

### 14.1 Что есть у конкурентов

| Продукт | Панель | Экраны/метрики | Чему учиться |
|---------|--------|----------------|--------------|
| **Jitsi** | Встроенной админки нет; JVB/Jicofo отдают метрики (Prometheus), эксплуатация — через Grafana/логи; в JaaS — коммерческая консоль | Конференции, участники, нагрузка JVB, потери пакетов | Метрики важнее «красивой панели»: сначала Prometheus-совместимый экспорт |
| **LiveKit** | LiveKit Cloud — дашборд проекта: комнаты, участники, usage | Rooms, participants, egress jobs, usage | Комнаты + live-участники + биллинг-метрики — минимум |
| **Daily** | Дашборд: домены, комнаты, записи, usage, логи | Domain/room settings, recordings, usage | «Домен → комнаты → запись» как навигация |
| **Twilio** | Console: usage, rooms, insights (QoS), логи | Rooms, participants, quality, billing | QoS-инсайты по комнатам — сильная сторона |
| **Zoom** | Admin console: dashboard (live/report), users, rooms, recording, audit logs, QoS | Live-встречи, качество, записи, аудит | Разделение live/report и экспорт отчётов |
| **Teams** | Teams admin center + Purview | Политики, записи, аудит, DLP | Политики как данные, а не как код |
| **Google Meet** | Workspace Admin console | Настройки Meet, аудит, записи | Единая консоль для всех сервисов |

### 14.2 Что нужно AGIL (экраны и метрики)

| Экран | Содержимое | Приоритет |
|-------|-----------|-----------|
| Auth/ключи | API-ключи тенанта, MCP-токены, scopes, ротация | MVP |
| Комнаты (live) | Активные комнаты, участники, состояние медиа, качество (good/fair/poor), кнопки закрыть/заблокировать | MVP |
| Конфиг тенанта | `TenantConfig` целиком: бренд, тема, фичи, лимиты, fallback, security | MVP |
| Тема/бренд | Пресеты, бренд-цвет → палитра, WCAG-аудит, логотип → переход в редактор | MVP |
| Embed/Integration | Готовый iframe/JS-сниппет, ссылка на комнату, QR | MVP |
| AI и комплаенс | Настройки AI-агента, политики, находки (`complianceFindings`), выдержки, экспорт | MVP+ |
| Записи/файлы | Список записей/файлов, retention, удаление, ссылки | Production |
| Метрики QoS | RTT, loss, jitter, битрейт, доля деградаций, тиры качества | Production |
| Аудит-лог | Кто/что/когда, экспорт в SIEM | Production |
| Usage/биллинг | Минуты, участники, записи, STT-минуты, AI-вызовы | Production |

Минимальный набор метрик, который нужно собирать с первого дня (иначе потом нечем
доказывать качество): `rooms_active`, `participants_active`, `join_failures{reason}`,
`ice_failures`, `quality_tier_share{tier}`, `rtt_ms`, `loss_pct`, `jitter_ms`,
`bitrate_kbps`, `recording_minutes`, `stt_minutes`, `ai_calls`, `mcp_gap_errors`.

---

## 15. Источники

Документация и репозитории:

- Jitsi Handbook — Architecture: https://jitsi.github.io/handbook/docs/architecture/
- Jitsi Handbook — IFrame API: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe/
- Jitsi JWT tokens (lib-jitsi-meet): https://github.com/jitsi/lib-jitsi-meet/blob/master/doc/tokens.md
- Jitsi issue #15526 (JWKS): https://github.com/jitsi/jitsi-meet/issues/15526
- Jitsi E2EEcontext: https://jitsi.github.io/lib-jitsi-meet/classes/JitsiConference._internal_.E2EEcontext.html
- Jitsi API commands/events (DeepWiki): https://deepwiki.com/jitsi/jitsi-meet/8.1-api-commands-and-events
- LiveKit docs: https://docs.livekit.io/home/
- LiveKit access tokens & grants: https://docs.livekit.io/home/server/generating-tokens/
- LiveKit egress: https://docs.livekit.io/home/egress/overview/
- LiveKit ingress: https://docs.livekit.io/home/ingress/overview/
- LiveKit agents + MCP: https://docs.livekit.io/agents/logic/tools/mcp.md
- MCP спецификация (latest, 2026-07-28): https://modelcontextprotocol.io/specification/latest
- MCP changelog 2026-07-28: https://modelcontextprotocol.io/specification/2026-07-28/changelog
- MCP транспорты: https://modelcontextprotocol.io/specification/2026-07-28/basic/transports
- MCP TypeScript SDK (npm): https://www.npmjs.com/package/@modelcontextprotocol/sdk
- API Яндекс Телемоста: https://www.yandex.com/dev/telemost/doc/ru/
- Яндекс Телемост — создание встречи (API): https://www.yandex.ru/dev/telemost/doc/ru/conferences/conference-create
- Яндекс Телемост — управление звонком: https://yandex.com/support/yandex-360/customers/telemost/desktop/en/call/administration
- Яндекс Телемост — запись: https://www.yandex.ru/support/yandex-360/business/telemost/desktop/ru/call/record
- Daily Prebuilt: https://docs.daily.co/guides/products/prebuilt
- Daily REST API: https://docs.daily.co/reference/rest-api
- Twilio Video docs: https://www.twilio.com/docs/video
- Twilio: Video остаётся продуктом (отмена EOL): https://help.twilio.com/articles/20950630029595
- Zoom Meeting SDK for Web: https://developers.zoom.us/docs/meeting-sdk/web/
- 100ms Room Code Authentication: https://github.com/100mslive/100ms-docs/blob/main/docs/prebuilt/v2/prebuilt/room-codes/room-code-auth.mdx
- Whereby Embedded: https://docs.whereby.com/
- JaaS (8x8): https://www.8x8.com/products/apis/video
- MDN `jitterBufferTarget`: https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpReceiver/jitterBufferTarget
- WebTransport (web-features): https://web-platform-dx.github.io/web-features-explorer/features/webtransport/
- caniuse WebTransport: https://caniuse.com/mdn-api_webtransport_createunidirectionalstream
- W3C webrtc-svc: SVC vs simulcast: https://lists.w3.org/Archives/Public/public-webrtc-logs/2022Jan/0073.html
- WebRTC Encoded Transform (обзор 2026): https://callsphere.ai/blog/vw3e-webrtc-encoded-transform-api-status-2026
- RNNoise WASM (Jitsi): https://github.com/jitsi/rnnoise-wasm
- MediaPipe tasks-vision (npm): https://www.npmjs.com/package/@mediapipe/tasks-vision

Метаданные репозиториев (GitHub REST API, 13.11.2026):

- `jitsi/jitsi-meet`, `jitsi/jitsi-videobridge`, `jitsi/jicofo`, `jitsi/lib-jitsi-meet`
- `livekit/livekit`, `livekit/agents`, `livekit/client-sdk-js`
- `meetecho/janus-gateway`, `versatica/mediasoup`, `versatica/mediasoup-client`
- `pion/webrtc`, `ionorg/ion-sfu`, `jech/galene`, `ossrs/srs`
- `modelcontextprotocol/typescript-sdk`

Версии пакетов (npm `latest`, 13.11.2026): `@modelcontextprotocol/sdk` 1.32.2,
`mediasoup-client` 3.26.0, `livekit-client` 2.24.0, `@livekit/components-react` 2.9.25,
`lib-jitsi-meet` 1.0.6, `@mediapipe/tasks-vision` 1.2.3, `webrtc-adapter` 9.0.6.

Безопасность, AI и админки (разделы 10–14):

- Jitsi lobby (Prosody-плагин): https://github.com/jitsi/jitsi-meet/blob/master/resources/prosody-plugins/mod_muc_lobby_rooms.lua
- Zoom E2EE (KB0075502): https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0075502
- Zoom watermark (KB0068115): https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0068115
- Zoom 90-day security report (waiting room/passcode): https://www.zoom.com/siteassets/wp-content/uploads/2020/06/Ask-Eric-Anything-6-10.pdf
- Teams E2EE (встречи и 1:1, список недоступных фич): https://learn.microsoft.com/en-us/microsoftteams/teams-end-to-end-encryption
- Teams meeting policies (лобби): https://learn.microsoft.com/en-us/microsoftteams/meeting-policies-in-teams
- Teams intelligent recap: https://learn.microsoft.com/en-us/microsoftteams/intelligent-recap-calls-meetings
- Google Meet Client-side Encryption: https://support.google.com/meet/answer/11605714
- Google Meet «Take notes for me»: https://support.google.com/meet/answer/14754931
- Zoom AI Companion: https://www.zoom.com/en/small-business/ai/
- LiveKit E2EE: https://docs.livekit.io/home/client/tracks/encryption/
- C2PA спецификации: https://c2pa.org/specifications/specifications/2.2/index.html
- IPTC FAQ по C2PA: https://iptc.org/std/guidelines/media-provenance/C2PA-FAQs/IPTC-C2PA-FAQs-v1.0-2027-07-08.pdf
- Обзор детекторов дипфейков 2026 (вторичный): https://about.fast.io/resources/best-deepfake-detectors-2026/
- Сравнение детекторов 2026 (вторичный): https://guptadeepak.com/tools/top-5-deepfake-detection-tools-2026/
- Точность realtime vs post-hoc (вторичный): https://www.eyesift.com/faq/ai-voice-detection-deepfake-audio-2026/
- Fireflies API/GraphQL/Webhooks/MCP: https://docs.fireflies.ai/
- Deepgram streaming STT: https://developers.deepgram.com/docs/live-streaming-audio
- MDN Web Speech API: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API
- Daily Docs (запись/транскрипция/REST): https://docs.daily.co/
- FAQ университета Дрездена по ограничениям Zoom E2EE (вторичный): https://faq.tickets.tu-dresden.de/otrs/public.pl?Action=PublicFAQPrint;ItemID=390

