Добавить ESP pairing через доверенные сессии

This commit is contained in:
AidarKC
2026-06-14 18:21:23 +04:00
parent 5d13112b00
commit 3e04727022
36 changed files with 2500 additions and 6 deletions
@@ -0,0 +1,106 @@
# 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 и opaque `passwordHash`;
- хранит pending/approved/rejected pairing-заявки;
- рассчитывает короткий код `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. Практический смысл
Эта схема даёт нужное разделение доверия:
- пароль на сервере только отсеивает лишних;
- онлайн доверенная сессия решает, добавлять ли новую сессию;
- сервер остаётся маршрутизатором и хранилищем состояния, а не владельцем секретов.