# Выдать браузеру поток его сессии и восстанавливаемый результат

> Исторический snapshot. После разделения chat/voice адреса и deployment ownership изменились: чат — https://chat-agent.gis-master.ru/, file UI/diagnostics — https://voice.gis-master.ru/. Текущая поставка: [DEPLOYMENT](</experiments/voice-ai/archive/w/DOCS/DEPLOYMENT.md>). Старые адреса и service owners ниже описывают дату исследования, а не инструкции для текущего runtime.

Статус: предложение, не реализовано. Инвазивность: **Средняя → высокая**. Основа: `webrtc-komaroff@772de4a`, 16.09.2026.

Сейчас браузер напрямую подключается к NATS WebSocket и подписывается на `nats.events.user123`. HTTP-команда возвращает данные ответа, но показ текста и команд карты опирается на отдельные события. Без согласованного snapshot/cursor reconnect может пропустить результат, а клиентский subject сам по себе не обеспечивает разграничение пользователей.

![Сессия как граница клиентского потока](</experiments/voice-ai/archive/w/DOCS/architecture-2026-09-16/diagrams/p06-events.svg>)

Предлагаемый event gateway проверяет пользователя, открывает только принадлежащую ему сессию и возвращает поток с event_id. Внутренний NATS остаётся транспортом между сервисами.

## Предлагаемая правка

Сначала формализовать identity: как ingress identity превращается в user_id, кто проверяет право на session_id и кто разрешает edit. Добавить эти проверки в HTTP и subscriptions. Фильтр в браузере не заменяет server-side authorization.

Затем выбрать один client delivery contract. Для однонаправленных UI events подойдёт SSE; WebSocket нужен, если действительно требуется двусторонний протокол. Сохранить HTTP для отправки turn. В ответе вернуть стабильный turn_id/status; stream отдаёт события и terminal result. Reconnect начинает с cursor, а слишком старый cursor приводит к snapshot.

Можно сохранить прямой browser NATS, если выданы краткоживущие credentials и subject permissions на конкретного пользователя/сессию. Это меньшая миграция, но модель cursor/replay и обработка пропусков всё равно нужны. Выбор SSE — не универсальное требование.

## Измеряемая приёмка

Исходная точка — один зафиксированный event subject в frontend. Цель: **0 событий чужой сессии** в browser fixtures и негативных authorization-тестах. После принудительного reconnect каждый committed terminal event либо воспроизводится, либо представлен в snapshot, без двойного добавления сообщения.

Считать число активных subscriptions на браузер, event bytes/turn, p95 delivery lag, gap rate и duplicate UI actions. Проверить 2 пользователя × 2 сессии, смену сессии, revoke, reconnect в момент ответа и истечение retention. Retention выбрать явно; бессрочный event log не нужен по умолчанию.

## Риски

Появится gateway и ещё один сетевой переход. Изменятся auth и reconnect semantics. При больших потоках gateway нужно масштабировать отдельно, а replay читать из общей event store. Не проксировать через него каждый PCM frame, если задача — только доставка UI results.

Включать новый клиентский канал по сессиям. Во время перехода один UI использует один источник событий, иначе сам dual delivery создаст дубли. Возможность вернуться к старому каналу сохраняется до удаления его backend.

## Основания

[frontend config](</experiments/voice-ai/archive/w/src_front/src/config/appConfig.ts>), [HTTP CommandHandler](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/src_front/src/core/commandHandler.ts>), [NATS event handlers](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/src_front/src/assistant/assistantApp.ts>), [UiEventPublisher](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/blob/772de4a714ae6c5abea91946e85a1953ee919ec3/src_agent/ui_events.py>). [Core NATS delivery](<https://docs.nats.io/learn/core-nats/>) подтверждает отсутствие хранения offline-сообщений; [NATS authorization](<https://docs.nats.io/running-a-nats-service/configuration/securing_nats/authorization>) описывает subject permissions. Фактические broker ACL текущего production в этом аудите не проверялись.

[Все предложения](</experiments/voice-ai/archive/w/DOCS/architecture-2026-09-16/improvements/README.md>) · [Фактическая архитектура](</experiments/voice-ai/archive/w/DOCS/architecture-2026-09-16/README.md>)
