Добавить SendSignal и remote AddBlock через homeserver

This commit is contained in:
AidarKC
2026-06-28 11:20:51 +04:00
parent c397c28acb
commit aa02e92e4d
19 changed files with 1329 additions and 224 deletions
+136 -26
View File
@@ -2,12 +2,13 @@
Этот файл описывает технические WebSocket-запросы, которые нужны для служебной работы клиента с сервером. Часть операций доступна без авторизации, часть требует успешной авторизованной сессии.
Сейчас здесь восемь методов:
Сейчас здесь девять методов:
- `Ping` — keep-alive запрос для поддержания живого WebSocket-соединения;
- `GetServerInfo` — запрос базовой публичной информации о сервере для выбора узла в децентрализованной сети;
- `ListBlockchainHeads` — краткая сводка по всем локальным блокчейнам сервера для межсерверной синхронизации;
- `GetSyncUserProfile` — межсерверный профиль пользователя для создания локальной цепочки без Solana RPC;
- `SendSignal` — общий межсессионный технический сигнал в одну конкретную сессию или сразу во все активные сессии пользователя;
- `GetCallIceConfig` — выдача STUN/TURN конфигурации для звонков;
- `ClientErrorLog` — отправка клиентской ошибки в серверный лог;
- `ClientDebugLog` — отправка клиентского debug-события в серверный буфер;
@@ -19,6 +20,7 @@
- `GetServerInfo` нужен до авторизации и до работы с данными, чтобы клиент понял, что сервер доступен, и показал пользователю краткую карточку этого узла.
- `ListBlockchainHeads` нужен для сервер-сервер сверки: партнёр получает список heads по всем цепочкам, сравнивает его со своим состоянием и затем добирает недостающие блоки по диапазону.
- `GetSyncUserProfile` нужен для server-to-server режима, когда принимающий сервер хочет создать у себя локальные `solana_users + blockchain_state` без прямого обращения в Solana. Это используется как временный обход ограничений внешнего Solana RPC.
- `SendSignal` нужен для доверенных межсессионных команд одного пользователя. Первое практическое применение — `remote AddBlock via homeserver session`, но формат задуман как общий transport на вырост.
Ниже сначала описаны назначение методов, затем точные форматы запросов и ответов.
@@ -282,7 +284,134 @@
---
## 5. `GetCallIceConfig`
## 5. `SendSignal`
Доступно только после успешной авторизации.
### Назначение
Общий межсессионный технический сигнал.
Этот метод нужен для случаев, когда одна активная сессия пользователя должна быстро передать служебную команду другой сессии того же пользователя или сразу всем его активным сессиям.
Первый целевой сценарий:
- `remote AddBlock via homeserver session`
То есть телефон без локального `blockchain.key` может:
- подготовить unsigned preimage блока;
- подписать сам `SendSignal` своим `session key`;
- дополнительно подписать его `client key`, чтобы homeserver/ESP32 точно видел, что запрос пришёл от доверенного клиента этого же логина;
- отправить запрос в выбранную `homeserver`-сессию;
- получить от неё ответ после настоящего `AddBlock`.
### Режимы доставки
- `targetMode = "single_session"` — доставка в одну конкретную `targetSessionId`.
- `targetMode = "all_sessions"` — доставка во все активные сессии указанного логина.
### Важное правило подписи
Сам `SendSignal` не подписывает поле `data` отдельной вложенной подписью. Вместо этого сервер проверяет подписи по общему preimage сигнала, в который входит:
- `fromLogin`
- `fromSessionId`
- `toLogin`
- `targetMode`
- `targetSessionId`
- `signalType`
- `signalRequestId`
- `timeMs`
- `sha256(data)`
Поддерживаются две подписи:
- `sessionSignatureB64` — обязательная подпись текущей авторизованной `session key`;
- `clientSignatureB64` — необязательная подпись `client key`.
Для сценария `remote AddBlock via homeserver` текущая договорённость такая:
- запрос должен идти только своему же логину;
- запрос должен быть подписан и `session key`, и `client key`;
- в будущем для отдельных wallet-сценариев `clientSignatureB64` может быть пустой.
### Запрос в одну сессию
```json
{
"op": "SendSignal",
"requestId": "ws-req-001",
"payload": {
"toLogin": "alice",
"targetMode": "single_session",
"targetSessionId": "sess-hs-001",
"signalType": "remote_addblock_request",
"signalRequestId": "remote-addblock-001",
"data": "{\"operation\":\"remote_addblock_request\",\"login\":\"alice\",\"blockchainName\":\"alice_main\",\"blockNumber\":152,\"prevBlockHash\":\"abc...\",\"blockPreimageB64\":\"...\"}",
"timeMs": 1774700000123,
"sessionSignatureB64": "BASE64_64",
"clientSignatureB64": "BASE64_64"
}
}
```
### Успешный ответ
```json
{
"op": "SendSignal",
"requestId": "ws-req-001",
"status": 200,
"ok": true,
"payload": {
"deliveredCount": 1,
"deliveredSessionIds": ["sess-hs-001"]
}
}
```
### Событие на принимающей стороне
```json
{
"op": "IncomingSignal",
"eventId": "evt-001",
"payload": {
"fromLogin": "alice",
"fromSessionId": "sess-phone-001",
"toLogin": "alice",
"targetMode": "single_session",
"targetSessionId": "sess-hs-001",
"signalType": "remote_addblock_request",
"signalRequestId": "remote-addblock-001",
"data": "{\"operation\":\"remote_addblock_request\",\"login\":\"alice\",\"blockchainName\":\"alice_main\",\"blockNumber\":152,\"prevBlockHash\":\"abc...\",\"blockPreimageB64\":\"...\"}",
"timeMs": 1774700000123,
"sessionSignatureB64": "BASE64_64",
"clientSignatureB64": "BASE64_64",
"dataSha256B64": "BASE64_32"
}
}
```
### Специфические коды ошибок `SendSignal`
- `422 / NOT_AUTHENTICATED` — требуется авторизация.
- `400 / BAD_FIELDS` — не хватает обязательных полей или нарушено правило `single_session/all_sessions`.
- `400 / BAD_TARGET_MODE` — передан неизвестный `targetMode`.
- `400 / TIME_SKEW``timeMs` отличается от серверного более чем на 30 секунд.
- `500 / NO_CLIENT_KEY` — для текущего пользователя не найден `client key`.
- `404 / USER_NOT_FOUND` — логин адресата не найден.
- `400 / BAD_DATA` — сервер не смог обработать `data`.
- `400 / BAD_SESSION_SIGNATURE` — некорректная подпись `session key`.
- `400 / BAD_CLIENT_SIGNATURE` — некорректная подпись `client key`.
- `404 / SESSION_NOT_FOUND` — при `single_session` целевая сессия не найдена или не онлайн.
- `404 / NO_TARGET_SESSIONS` — при `all_sessions` у пользователя сейчас нет активных онлайн-сессий.
- `404 / DELIVERY_FAILED` — сервер не смог отправить событие ни в одну из целевых сессий.
---
## 6. `GetCallIceConfig`
Доступно только после успешной авторизации.
@@ -332,7 +461,7 @@
---
## 6. `ClientErrorLog`
## 7. `ClientErrorLog`
### Запрос
@@ -379,7 +508,7 @@
---
## 7. `ClientDebugLog`
## 8. `ClientDebugLog`
### Запрос
@@ -417,7 +546,7 @@
---
## 8. `CallDeliveryReport`
## 9. `CallDeliveryReport`
### Запрос
@@ -453,29 +582,10 @@
---
## 7. Короткое резюме
## 10. Короткое резюме
- `Ping` нужен для keep-alive и проверки, что WebSocket-соединение живо.
- `GetServerInfo` нужен для выбора сервера в сети и показа публичной информации об узле.
- `SendSignal` нужен для доверенных межсессионных сигналов одного пользователя, включая `remote AddBlock via homeserver session`.
- `GetCallIceConfig` нужен для WebRTC-звонков и требует авторизации.
- `ClientErrorLog`, `ClientDebugLog`, `CallDeliveryReport` используются для диагностики клиента и звонков.
## 8. Прямое техническое сообщение в конкретную сессию
На текущий момент в публичном JSON API этого документа **нет отдельного RPC** для отправки произвольного технического сообщения в конкретную сессию пользователя (по `sessionId`).
Что уже есть в системе:
- сервер хранит `sessionId` активной сессии;
- есть `ListSessions`, чтобы клиент получил список sessionId своего пользователя;
- у сервера есть внутренний реестр активных WS-подключений по `sessionId`.
Чего не хватает для полноценной фичи «direct tech message by sessionId»:
1. отдельная API-операция (например, `SendSessionTechMessage`);
2. правило авторизации (кто имеет право писать в чужую/свою сессию);
3. унифицированный формат payload и события доставки;
4. коды ошибок (`SESSION_OFFLINE`, `SESSION_NOT_FOUND`, `FORBIDDEN` и т.п.).
Итог: как инфраструктурная база это почти готово, но нужен отдельный RPC-слой и политика доступа.
+1
View File
@@ -37,6 +37,7 @@
| `GetServerInfo` | `05_Technical_Requests_API.md` | публичная информация о сервере |
| `ListBlockchainHeads` | `05_Technical_Requests_API.md` | список heads всех локальных блокчейнов |
| `GetSyncUserProfile` | `05_Technical_Requests_API.md` | межсерверный профиль пользователя для синхронизации |
| `SendSignal` | `05_Technical_Requests_API.md` | общий межсессионный технический сигнал в одну или все сессии пользователя |
| `GetCallIceConfig` | `05_Technical_Requests_API.md` | STUN/TURN конфигурация звонков |
| `ClientErrorLog` | `05_Technical_Requests_API.md` | логирование клиентской ошибки |
| `ClientDebugLog` | `05_Technical_Requests_API.md` | клиентский debug-лог |