# ESP Pairing и режимы подключения Этот документ фиксирует текущие и новые режимы входа/подключения в SHiNE без клиентской UI-реализации. Он нужен как отдельная точка входа по сценариям подключения, чтобы не смешивать обычную авторизацию и серверный pairing через доверенное уже авторизованное устройство пользователя. ## 1. Текущие режимы ### 1. Создание новой сессии через `deviceKey` Поток: `AuthChallenge -> CreateAuthSession` Смысл: - новое устройство уже владеет приватным `deviceKey`; - сервер проверяет подпись `deviceKey`; - создаётся обычная активная сессия пользователя; - этот поток остаётся без изменений. ### 2. Повторный вход в существующую сессию через `sessionKey` Поток: `SessionChallenge -> SessionLogin` Смысл: - устройство уже владеет приватным `sessionKey`; - сервер проверяет подпись `sessionKey`; - соединение снова входит в существующую сессию; - этот поток тоже остаётся без изменений. ## 2. Новый режим: добавление сессии через доверенное устройство пользователя Новый поток не заменяет обычный логин, а живёт рядом с ним. Цель: - новое устройство знает `login`, а `pairing password` используется только если он включён на доверённом устройстве; - сервер использует пароль только как фильтр от мусора; - реальное доверие даёт любая уже онлайн доверенная сессия пользователя; - сервер не выдаёт приватные ключи сам от себя. Поток версии `v1`: 1. Любая доверенная сессия пользователя создаёт на сервере pairing-настройку: `UpsertEspPairingSettings` 2. Новое устройство создаёт pending-заявку: `StartEspPairing` 3. Онлайн доверенная сессия видит список активных заявок: `ListEspPairingRequests` 4. Доверенная сессия либо подтверждает заявку: `ApproveEspPairing` 5. Либо отклоняет: `RejectEspPairing` 6. Новое устройство читает результат: `GetEspPairingStatus` ## 3. Что именно делает сервер - хранит включённость pairing и optional opaque `passwordHash`; - хранит pairing-заявки всех статусов, но в список активных для доверённого устройства отдаёт только pending `created`; - рассчитывает короткий код `shortCode` из `7` цифр; - рассчитывает длинный `fingerprintB58` из `SHA-256` заявки; - уведомляет онлайн доверенные сессии событием `IncomingEspPairingRequest`, если такие сессии подключены; - хранит переданный `encryptedPayload` как непрозрачную строку и не анализирует его содержимое. ## 4. Чего сервер в этой версии не делает - не передаёт приватный `deviceKey`; - не расшифровывает `encryptedPayload`; - не проверяет криптографию содержимого payload; - не делает клиентский UI; - не навязывает конкретную схему `Ed25519 -> X25519` в коде сервера. Это намеренно: серверная версия `v1` подготавливает безопасный каркас маршрутизации и состояния, а настоящая E2E-логика упаковки ключей будет жить на клиентах и ESP-устройствах. ## 5. Роли и ограничения - любая уже авторизованная доверенная сессия пользователя может вызывать: - `UpsertEspPairingSettings` - `ListEspPairingRequests` - `ApproveEspPairing` - `RejectEspPairing` - новое устройство может вызвать `StartEspPairing` и `GetEspPairingStatus` без уже существующей авторизованной сессии; - `payloadType` поддерживается в вариантах: - `1` — минимальный пакет - `2` — расширенный пакет - `3` — полный пакет Сервер не интерпретирует эти три типа глубже, а только фиксирует их в состоянии заявки. ## 6. Статусы pairing-заявки - `created` — заявка создана и ждёт решения доверенной сессии; - `approved` — доверенная сессия подтвердила и приложила `encryptedPayload`; - `rejected` — доверенная сессия отклонила заявку; - `expired` — TTL заявки истёк до подтверждения. ## 7. Практический смысл Эта схема даёт нужное разделение доверия: - пароль на сервере, если он включён, только отсеивает лишних; - онлайн доверенная сессия решает, добавлять ли новую сессию; - сервер остаётся маршрутизатором и хранилищем состояния, а не владельцем секретов.