# chat-service Подсистема 2 платформы (RPC-чат, друзья, presence, телеметрия виджетов). Сейчас реализован только **GUI presence**; чат и друзья позже (WebSocket). Сервис без БД: состояние в памяти, живёт секунды. ## GUI presence (идея из evo `GuiPresence`, наш вариант) Зачем: LoVisual-игроки видят друг у друга над рукой мини-копию открытого меню клиента (какая категория, куда наведён курсор, поиск), и знают, кто вообще пользуется LoVisual (значок у ника). Без видео и без чужих данных: только положение курсора и флаги. ### Протокол `POST /presence/gui` (через gateway, нужен device-токен `lvd_...`, gateway кладёт `x-lovisual-account-id`): ```json { "server": "play.example.com", "mc": "", "gui": "|null", "want": ["", "..."], "publish": true } ``` Ответ: `{ "players": [ { "mc": "", "gui": "|null", "age": 120 } ] }`, `age` в мс с последнего обновления. - Один запрос и публикует состояние вызывающего, и возвращает состояние тех, кого он видит (`want`, не больше 40). - `publish = false` (по умолчанию true): только чтение, вызывающий сам не появляется у других. - `gui = null` значит «меню закрыто, но LoVisual запущен» (значок у ника). Запись живёт 6 с без обновления. - Игроки разных серверов не видят друг друга (ключ `server`, нормализуется в нижний регистр, ≤64 символов). - Частота клиента: раз в ~350 мс при открытом меню (пачка до 8 сэмплов курсора по 100 мс), раз в 2 с при закрытом. Лимит на gateway: 6 запросов в секунду на аккаунт. ### Формат `gui` (36 байт максимум, base64 ≤48 символов; сервис его не разбирает, только проверяет алфавит и длину) | байт | значение | |---|---| | 0 | версия = 1 | | 1 | биты 0-3 категория (0..15), бит 4 открыта страница настроек, бит 5 поиск, бит 7 меню закрыто | | 2 | индекс модуля под курсором в списке категории (255 = нет) | | 3 | число сэмплов n (0..8) | | 4+4i | сэмпл: x (0..255 по ширине меню), y (0..255 по высоте), бит 0 = зажата ЛКМ, прокрутка списка (0..255) | ### Безопасность - Идентичность только из заголовка gateway; прямой доступ закрыт общим секретом (как у остальных сервисов). - Привязка `mc uuid` к аккаунту: чужой аккаунт не может публиковать за занятый uuid (409), привязка снимается через 10 мин простоя; аккаунт владеет одним uuid, смена альта освобождает прежний. Это защита от подделки, не доказательство владения аккаунтом Minecraft: серверной верификации uuid нет. - Размер тела ≤8 КБ, payload только `[A-Za-z0-9+/=]`, `want` ≤40. ### Структура `src/presence/{payload.rs (валидация), store.rs (состояние + TTL + привязка), handlers.rs (sync)}`; тесты: модульные в `store.rs`, `payload.rs`, интеграционные `tests/presence.rs`. Порт `CHAT_PORT` (8083), `INTERNAL_KEY` общий. В gateway маршрут `/presence/*`. ### Не сделано Просмотр видео (`.watch` у evo), чат и друзья (WebSocket), метрики, горизонтальное масштабирование (состояние в памяти одного процесса).