SHA256
Документировать новый DM-протокол и формат (в коде пока не реализовано)
This commit is contained in:
@@ -56,9 +56,12 @@
|
||||
- Перед каждым `AddBlock` обязательно проверять/актуализировать текущее состояние вершины блокчейна (`last global number/hash`) и использовать его при формировании блока.
|
||||
|
||||
## Документация личных сообщений (DM)
|
||||
- Актуальная документация по логике личных сообщений находится в `Dev_Docs/Personal_Messages/README.md`.
|
||||
- При любом изменении кода, связанного с личными сообщениями (формат подписанного DM-блока, типы DM-сообщений, правила доставки/ACK/read-receipt, роутинг по сессиям, UI-логика чатов), обязательно обновлять `Dev_Docs/Personal_Messages/README.md`.
|
||||
- Логика личных сообщений в коде должна всегда соответствовать `Dev_Docs/Personal_Messages/README.md`.
|
||||
- Актуальная документация по логике личных сообщений находится в `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`.
|
||||
- Точный байтовый формат DM находится в `Dev_Docs/Personal_Messages/Формат_DM_v1.md`.
|
||||
- При любом изменении кода, связанного с личными сообщениями (формат подписанного DM-блока, типы DM-сообщений, правила доставки/ACK/read-receipt, роутинг по сессиям, UI-логика чатов), обязательно обновлять оба документа:
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`
|
||||
- `Dev_Docs/Personal_Messages/Формат_DM_v1.md`
|
||||
- Логика личных сообщений в коде должна всегда соответствовать этим документам.
|
||||
- Документ по личным сообщениям обязан поддерживаться в актуальном состоянии.
|
||||
|
||||
## Документация API сервера
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
Подробная логика DM и бинарного формата:
|
||||
|
||||
- `Dev_Docs/Personal_Messages/README.md`
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`
|
||||
- `Dev_Docs/Personal_Messages/Формат_DM_v1.md`
|
||||
|
||||
## 1. `UpsertPushToken`
|
||||
|
||||
|
||||
@@ -159,7 +159,8 @@ Self-message - это сообщение пользователя самому
|
||||
## Связанные документы
|
||||
|
||||
- `Dev_Docs/Keys/DERIVATION.md` - **источник истины по конкретной деривации** секрета и ключей (формулы Argon2id, `base64|suffix→SHA-256→Ed25519`, суффиксы `root.key`/`bch.key`/`client.key`/`homeserver.key:<имя>`, Solana-ключ, ссылки на код).
|
||||
- `Dev_Docs/Personal_Messages/README.md` - текущая документация личных сообщений.
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md` - текущая логическая документация личных сообщений.
|
||||
- `Dev_Docs/Personal_Messages/Формат_DM_v1.md` - точный байтовый формат личных сообщений.
|
||||
- `Dev_Docs/Blockchain/README.md` - точка входа по форматам SHiNE-блокчейна.
|
||||
- `Dev_Docs/Solana_Architecture/README.md` - архитектура Solana-программ, PDA-счетов, DAO и движения средств.
|
||||
- `Dev_Docs/Инициализация_Solana_регистрации/README.md` - деплой и первичная инициализация Solana-регистрации.
|
||||
|
||||
@@ -0,0 +1,526 @@
|
||||
# Личные сообщения (DM) — спецификация v1
|
||||
|
||||
## Статус документа
|
||||
|
||||
Этот файл — актуальная логическая спецификация DM-протокола SHiNE следующего этапа.
|
||||
|
||||
Важно:
|
||||
|
||||
- это целевая спецификация;
|
||||
- в текущем коде она ещё реализована не полностью;
|
||||
- при реализации код должен приводиться именно к этой спецификации, а не наоборот.
|
||||
|
||||
Документ фиксирует:
|
||||
|
||||
- модель DM и смысл типов сообщений;
|
||||
- правила редактирования, перешифровки и удаления;
|
||||
- роли существующих API-методов;
|
||||
- правила межсерверной маршрутизации через `access_servers`;
|
||||
- общее поведение сервера и БД.
|
||||
|
||||
Точный байтовый формат контейнера вынесен отдельно:
|
||||
|
||||
- `Dev_Docs/Personal_Messages/Формат_DM_v1.md`
|
||||
|
||||
Устаревшая предыдущая версия сохранена отдельно:
|
||||
|
||||
- `Dev_Docs/Personal_Messages/Спецификация_DM_v0.5_устаревшая.md`
|
||||
|
||||
## 1. Основная модель
|
||||
|
||||
Личное сообщение в SHiNE хранится как две логические копии одного сообщения:
|
||||
|
||||
- `type=1` — входящее сообщение для получателя;
|
||||
- `type=2` — исходящая копия сообщения для отправителя.
|
||||
|
||||
Обе копии имеют общий логический идентификатор:
|
||||
|
||||
- `baseKey = fromLogin|toLogin|timeMs|nonce`
|
||||
|
||||
Идентификатор конкретной копии:
|
||||
|
||||
- `messageKey = baseKey|messageType`
|
||||
|
||||
Поля `timeMs` и `nonce` не меняются никогда.
|
||||
|
||||
`nonce` обязателен, потому что одного `timeMs` недостаточно для гарантированной уникальности.
|
||||
|
||||
## 2. Ключи и шифрование
|
||||
|
||||
### 2.1. Общий принцип
|
||||
|
||||
У пользователя в PDA публикуется один публичный `clientKey` в формате `Ed25519`.
|
||||
|
||||
Из того же ключевого материала стандартным способом выводится ключ `X25519` для E2EE-шифрования DM.
|
||||
|
||||
Отдельный публичный `dmEncKey` в текущей архитектуре не хранится.
|
||||
|
||||
Подробности стандартного преобразования:
|
||||
|
||||
- `Dev_Docs/Протоколы/Преобразование_ED25519_в_X25519.md`
|
||||
|
||||
### 2.2. Правило шифрования копий
|
||||
|
||||
- `type=1` шифруется на ключ получателя;
|
||||
- `type=2` шифруется на ключ отправителя.
|
||||
|
||||
Следствия:
|
||||
|
||||
- входящую копию может прочитать только получатель;
|
||||
- исходящую копию может прочитать только отправитель;
|
||||
- сервер не должен расшифровывать DM;
|
||||
- ciphertext у `type=1` и `type=2` обычно разный и не обязан совпадать побайтно.
|
||||
|
||||
## 3. Типы сообщений
|
||||
|
||||
В версии v1 используются следующие `messageType`:
|
||||
|
||||
- `1` — входящее сообщение;
|
||||
- `2` — исходящая копия сообщения;
|
||||
- `3` — входящее подтверждение прочтения;
|
||||
- `4` — исходящая копия подтверждения прочтения;
|
||||
- `5` — сообщение удалено отправителем;
|
||||
- `6` — сообщение удалено получателем;
|
||||
- `7` — переписка удалена отправителем;
|
||||
- `8` — переписка удалена получателем.
|
||||
|
||||
Типы `1/2` — это обычные контентные DM, в том числе их последующие ревизии.
|
||||
|
||||
Типы `3/4` — служебные подтверждения прочтения.
|
||||
|
||||
Типы `5/6/7/8` — служебные события удаления без зашифрованного тела.
|
||||
|
||||
## 4. Базовые операции
|
||||
|
||||
### 4.1. Создание нового сообщения
|
||||
|
||||
Новое сообщение отправляется парой блоков через:
|
||||
|
||||
- `SendMessagePair`
|
||||
- `ReceiveOutcomingMessage` как алиас
|
||||
|
||||
Пару создаёт автор сообщения.
|
||||
|
||||
Пара содержит:
|
||||
|
||||
- одну входящую копию `type=1`;
|
||||
- одну исходящую копию `type=2`;
|
||||
- одинаковые `fromLogin`, `toLogin`, `timeMs`, `nonce`;
|
||||
- одинаковый логический plaintext;
|
||||
- разные ciphertext для разных владельцев копий.
|
||||
|
||||
### 4.2. Редактирование сообщения
|
||||
|
||||
Редактирование общего текста делает автор сообщения.
|
||||
|
||||
При редактировании:
|
||||
|
||||
- `baseKey` остаётся тем же;
|
||||
- `messageType` остаётся тем же;
|
||||
- `revisionTimeMs` увеличивается;
|
||||
- автор заново шифрует обе копии и снова отправляет пару через `SendMessagePair`.
|
||||
|
||||
Если `revisionTimeMs = 0`, это исходная версия.
|
||||
|
||||
Если `revisionTimeMs > 0`, это новая ревизия сообщения.
|
||||
|
||||
### 4.3. Перешифровка
|
||||
|
||||
Перешифровка нужна для будущего сценария полной или частичной перепаковки истории сообщений при сохранении тех же логических идентификаторов сообщений.
|
||||
|
||||
При перешифровке:
|
||||
|
||||
- `baseKey` остаётся прежним;
|
||||
- `messageKey` остаётся прежним;
|
||||
- plaintext может остаться тем же;
|
||||
- ciphertext меняется;
|
||||
- `reencryptedAtMs` получает ненулевое значение;
|
||||
- `revisionTimeMs` увеличивается.
|
||||
|
||||
Если сообщение уже удалено одним из типов `5/6`, его перешифровывать больше нельзя.
|
||||
|
||||
Если переписка уже удалена типом `7/8`, более старые сообщения этой пары тоже перешифровывать нельзя.
|
||||
|
||||
### 4.4. Приём входящей копии
|
||||
|
||||
Для server-to-server доставки одной входящей копии используется:
|
||||
|
||||
- `ReceiveIncomingMessage`
|
||||
|
||||
Этот метод должен принимать:
|
||||
|
||||
- новые входящие сообщения;
|
||||
- входящие обновления/редактирования;
|
||||
- входящие служебные события удаления;
|
||||
- будущие входящие перешифрованные копии.
|
||||
|
||||
## 5. Удаление одного сообщения
|
||||
|
||||
### 5.1. Общая логика
|
||||
|
||||
Удаление одного сообщения в v1 всегда глобальное у обеих сторон.
|
||||
|
||||
Локального удаления только у себя в этой версии протокола не вводится.
|
||||
|
||||
### 5.2. Типы удаления
|
||||
|
||||
- `type=5` — сообщение удалено отправителем;
|
||||
- `type=6` — сообщение удалено получателем.
|
||||
|
||||
Удаляющее сообщение:
|
||||
|
||||
- не содержит зашифрованного тела;
|
||||
- хранится в БД как tombstone;
|
||||
- терминально закрывает это сообщение;
|
||||
- не даёт больше принять никакую более позднюю содержательную версию этого же `messageKey`.
|
||||
|
||||
### 5.3. Метод удаления
|
||||
|
||||
Для удаления одного сообщения нужен отдельный метод, условно:
|
||||
|
||||
- `DeleteMessage`
|
||||
|
||||
Если сервер впервые получает валидное удаляющее сообщение:
|
||||
|
||||
- сохраняет tombstone в БД;
|
||||
- удаляет или замещает прежнюю версию сообщения tombstone-записью;
|
||||
- распространяет это же удаление на серверы доступа обеих сторон;
|
||||
- не принимает в будущем попытки "оживить" это сообщение.
|
||||
|
||||
## 6. Удаление всей переписки
|
||||
|
||||
### 6.1. Отдельное служебное сообщение
|
||||
|
||||
Удаление всей переписки между двумя пользователями — это отдельное служебное сообщение без ciphertext.
|
||||
|
||||
Типы:
|
||||
|
||||
- `type=7` — переписка удалена отправителем;
|
||||
- `type=8` — переписка удалена получателем.
|
||||
|
||||
### 6.2. Граница удаления
|
||||
|
||||
Границей удаления считается:
|
||||
|
||||
- `timeMs` самого служебного сообщения удаления переписки
|
||||
|
||||
Отдельное `deleteBeforeTimeMs` в этой версии не вводится.
|
||||
|
||||
### 6.3. Правило применения
|
||||
|
||||
Если сервер получает такое сообщение впервые:
|
||||
|
||||
- сохраняет его в БД как tombstone переписки;
|
||||
- удаляет из БД все сообщения этой пары пользователей с `timeMs` меньше времени служебного сообщения;
|
||||
- больше не принимает новые или повторно доставленные сообщения с `timeMs` раньше этой границы;
|
||||
- распространяет это же сообщение удаления переписки на серверы доступа обеих сторон.
|
||||
|
||||
### 6.4. Поведение при позднем старом сообщении
|
||||
|
||||
Если после удаления переписки приходит старое сообщение, у которого:
|
||||
|
||||
- `timeMs < deleteConversationMessage.timeMs`
|
||||
|
||||
то сервер:
|
||||
|
||||
- не принимает это сообщение;
|
||||
- в ответ возвращает то же сообщение удаления переписки;
|
||||
- ожидает, что вторая сторона обработает его как обычное уже известное удаление переписки.
|
||||
|
||||
### 6.5. Будущие новые сообщения
|
||||
|
||||
После удаления всей переписки новые сообщения между этими же пользователями разрешены, если:
|
||||
|
||||
- их `timeMs` больше времени служебного сообщения удаления переписки.
|
||||
|
||||
## 7. Серверы и маршрутизация
|
||||
|
||||
### 7.1. `access_servers`
|
||||
|
||||
Для обычного пользователя список серверов доставки и доступа задаётся через:
|
||||
|
||||
- `access_servers`
|
||||
|
||||
Это:
|
||||
|
||||
- сервера доступа пользователя;
|
||||
- сервера relay;
|
||||
- сервера, через которые пользователь получает личные сообщения и другие пользовательские операции.
|
||||
|
||||
### 7.2. `sync_servers`
|
||||
|
||||
`sync_servers` относятся не к обычной пользовательской маршрутизации DM, а к server-to-server партнёрству серверного узла.
|
||||
|
||||
Они используются для:
|
||||
|
||||
- синхронизации серверных данных;
|
||||
- синхронизации пользовательских блокчейнов SHiNE;
|
||||
- общей межсерверной координации.
|
||||
|
||||
`sync_servers` не являются списком пользовательских серверов доставки DM.
|
||||
|
||||
### 7.3. Несколько серверов у отправителя и получателя
|
||||
|
||||
Протокол должен поддерживать ситуацию, когда:
|
||||
|
||||
- у отправителя несколько `access_servers`;
|
||||
- у получателя несколько `access_servers`;
|
||||
- часть серверов у сторон совпадает;
|
||||
- часть серверов уникальна.
|
||||
|
||||
Из этого следуют требования:
|
||||
|
||||
- все DM-операции должны быть идемпотентны;
|
||||
- повторное получение уже известного события не должно ломать состояние;
|
||||
- дубль tombstone должен быть безопасен;
|
||||
- сервер не должен "оживлять" более старую версию сообщения после уже принятого tombstone.
|
||||
|
||||
## 8. Методы и их роли
|
||||
|
||||
### 8.1. Существующие методы, которые сохраняются
|
||||
|
||||
- `SendMessagePair`
|
||||
- `ReceiveOutcomingMessage`
|
||||
- `ReceiveIncomingMessage`
|
||||
|
||||
Их роли в v1:
|
||||
|
||||
- `SendMessagePair` — новая пара сообщений и редактирование старой пары автором;
|
||||
- `ReceiveIncomingMessage` — приём одной входящей копии, входящих редактирований и служебных DM-событий;
|
||||
- `ReceiveOutcomingMessage` — алиас `SendMessagePair`.
|
||||
|
||||
### 8.2. Новые методы, которые нужны
|
||||
|
||||
Нужны как минимум отдельные операции:
|
||||
|
||||
- `DeleteMessage`
|
||||
- `DeleteConversation`
|
||||
|
||||
Названия могут быть другими, но логически это две разные операции:
|
||||
|
||||
- удалить одно сообщение у обеих сторон;
|
||||
- удалить всю переписку до заданной временной границы.
|
||||
|
||||
## 9. Правила валидации и применения
|
||||
|
||||
### 9.1. Общее правило по ревизиям
|
||||
|
||||
Для одного и того же `messageKey` сервер сравнивает только:
|
||||
|
||||
- уже сохранённый `revisionTimeMs`;
|
||||
- `revisionTimeMs` входящего сообщения.
|
||||
|
||||
Правило:
|
||||
|
||||
- если новый `revisionTimeMs` больше сохранённого, сообщение применяется;
|
||||
- если новый `revisionTimeMs` равен сохранённому, сообщение не применяется;
|
||||
- если новый `revisionTimeMs` меньше сохранённого, сообщение не применяется.
|
||||
|
||||
Содержимое `body` при этом сравнении не участвует.
|
||||
|
||||
То есть если `revisionTimeMs` совпадает, сервер считает, что такая ревизия у него уже есть.
|
||||
|
||||
### 9.2. Повторный tombstone
|
||||
|
||||
Повторный tombstone означает ситуацию, когда сервер повторно получает то же самое событие удаления:
|
||||
|
||||
- того же сообщения;
|
||||
- или той же переписки.
|
||||
|
||||
Это может произойти из-за:
|
||||
|
||||
- повторной межсерверной доставки;
|
||||
- нескольких `access_servers`;
|
||||
- сетевых retry;
|
||||
- дублирующей пересылки с разных маршрутов.
|
||||
|
||||
Правило:
|
||||
|
||||
- повторный tombstone должен быть полностью безопасен;
|
||||
- если соответствующее удаление уже сохранено, сервер ничего не меняет и просто игнорирует повтор.
|
||||
|
||||
### 9.3. Сообщения старше границы удалённой переписки
|
||||
|
||||
Если для пары пользователей уже есть сохранённая граница удаления переписки, и приходит:
|
||||
|
||||
- обычное сообщение;
|
||||
- удаление одного сообщения;
|
||||
- повторное удаление переписки;
|
||||
- любое другое DM-событие;
|
||||
|
||||
у которого `timeMs` меньше этой границы, сервер:
|
||||
|
||||
- ничего не меняет в БД;
|
||||
- не восстанавливает старую историю;
|
||||
- не применяет это событие повторно.
|
||||
|
||||
Такие сообщения считаются частью уже удалённой истории.
|
||||
|
||||
### 9.4. Приоритет удаления переписки
|
||||
|
||||
Если сначала пришло удаление переписки, а потом удаление одного старого сообщения из этой переписки, сервер должен:
|
||||
|
||||
- проигнорировать это удаление одного сообщения;
|
||||
- не создавать новых изменений поверх уже удалённой истории.
|
||||
|
||||
То же правило действует и для обычных сообщений, и для редактирований старых сообщений.
|
||||
|
||||
## 10. JSON API v1
|
||||
|
||||
### 10.1. `SendMessagePair`
|
||||
|
||||
Назначение:
|
||||
|
||||
- клиент отправляет новый DM;
|
||||
- клиент отправляет редактирование старого DM;
|
||||
- клиент отправляет парную новую ревизию типов `1/2`.
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "SendMessagePair",
|
||||
"requestId": "req-123",
|
||||
"payload": {
|
||||
"incomingBlobB64": "...",
|
||||
"outgoingBlobB64": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Правила:
|
||||
|
||||
- клиенту достаточно отправить пару на один любой доступный сервер;
|
||||
- сервер после принятия сам отвечает за дальнейшую межсерверную доставку.
|
||||
|
||||
### 10.2. `ReceiveIncomingMessage`
|
||||
|
||||
Назначение:
|
||||
|
||||
- приём одной входящей копии по схеме server-to-server;
|
||||
- приём входящего редактирования;
|
||||
- приём служебного входящего события удаления;
|
||||
- приём входящего read-receipt.
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "ReceiveIncomingMessage",
|
||||
"requestId": "req-456",
|
||||
"payload": {
|
||||
"incomingBlobB64": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10.3. `DeleteMessage`
|
||||
|
||||
Назначение:
|
||||
|
||||
- удалить одно сообщение у обеих сторон.
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "DeleteMessage",
|
||||
"requestId": "req-789",
|
||||
"payload": {
|
||||
"blobB64": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ожидается контейнер типа:
|
||||
|
||||
- `5`, если удаление инициировал отправитель;
|
||||
- `6`, если удаление инициировал получатель.
|
||||
|
||||
### 10.4. `DeleteConversation`
|
||||
|
||||
Назначение:
|
||||
|
||||
- удалить всю переписку до времени самого служебного сообщения.
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "DeleteConversation",
|
||||
"requestId": "req-790",
|
||||
"payload": {
|
||||
"blobB64": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ожидается контейнер типа:
|
||||
|
||||
- `7`, если удаление инициировал отправитель;
|
||||
- `8`, если удаление инициировал получатель.
|
||||
|
||||
## 11. Межсерверная доставка
|
||||
|
||||
### 11.1. Клиентская сторона
|
||||
|
||||
Клиенту достаточно отправить сообщение на:
|
||||
|
||||
- любой один доступный сервер.
|
||||
|
||||
### 11.2. Серверная сторона
|
||||
|
||||
После принятия валидного события сервер должен отправлять его:
|
||||
|
||||
- на все серверы из `access_servers` отправителя;
|
||||
- на все серверы из `access_servers` получателя.
|
||||
|
||||
Если часть серверов совпадает, это допустимо.
|
||||
|
||||
Идемпотентность обязательна.
|
||||
|
||||
### 11.3. Ошибки доставки
|
||||
|
||||
Если часть серверов временно недоступна:
|
||||
|
||||
- это не должно отменять локальное принятие уже валидного сообщения;
|
||||
- повторная доставка может делаться отдельным retry-механизмом;
|
||||
- повторное получение того же события должно быть безопасным.
|
||||
|
||||
## 12. Хранение в БД
|
||||
|
||||
Основная таблица остаётся:
|
||||
|
||||
- `signed_messages_v2`
|
||||
|
||||
В ней должны сохраняться:
|
||||
|
||||
- обычные контентные DM;
|
||||
- tombstone одного сообщения;
|
||||
- tombstone удаления переписки.
|
||||
|
||||
Сообщение об удалении одного сообщения хранится в БД и не удаляется физически, чтобы:
|
||||
|
||||
- защищать от повторного приёма старых версий;
|
||||
- не терять факт удаления;
|
||||
- корректно синхронизировать событие между серверами.
|
||||
|
||||
Сообщение об удалении переписки тоже хранится в БД, а старые сообщения до его времени из БД удаляются.
|
||||
|
||||
## 13. Что обязательно должно измениться в коде относительно v0.5
|
||||
|
||||
- сервер не должен требовать одинаковый `encryptedBody` у `type=1` и `type=2`;
|
||||
- сервер не должен трактовать `encryptedBody` как обычный UTF-8 текст;
|
||||
- DM должны реально шифроваться end-to-end;
|
||||
- удаление одного сообщения должно стать терминальным tombstone;
|
||||
- удаление всей переписки должно стать отдельным служебным событием;
|
||||
- межсерверная маршрутизация DM должна идти через `access_servers`;
|
||||
- логика должна быть безопасна для нескольких серверов у каждой стороны.
|
||||
|
||||
## 14. Что в v1 пока не входит
|
||||
|
||||
- вложения в DM;
|
||||
- хранение отдельного `keyId` шифрования в DM;
|
||||
- ротация `clientKey`;
|
||||
- финальная конкретная UI-реализация массовой перешифровки;
|
||||
- физическая полная реализация DM federation в текущем коде.
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
# Личные сообщения (DM)
|
||||
# Личные сообщения (DM) — v0.5 устаревшая спецификация
|
||||
|
||||
## Статус документа
|
||||
|
||||
Этот документ устарел и сохранён только как историческое описание ранее реализованной схемы DM.
|
||||
|
||||
Aктуальная целевая спецификация:
|
||||
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`
|
||||
|
||||
Что в этом документе считать устаревшим:
|
||||
|
||||
- трактовку `encryptedBody` как фактически одинакового содержимого пары;
|
||||
- отсутствие нормального E2EE-шифрования DM;
|
||||
- старую модель удаления через пустую ревизию без терминального tombstone;
|
||||
- старую трактовку обновления только как общей пары без отдельной будущей модели перешифровки;
|
||||
- все упоминания legacy-формата read-receipt как части целевой архитектуры следующего этапа.
|
||||
|
||||
## Текущее состояние
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
# Формат DM v1
|
||||
|
||||
## Статус документа
|
||||
|
||||
Этот файл фиксирует байтовый формат DM-контейнеров SHiNE v1.
|
||||
|
||||
Важно:
|
||||
|
||||
- это целевой формат следующего этапа;
|
||||
- в текущем коде он ещё реализован не полностью;
|
||||
- особенно это касается перехода всех типов `1..8` на единый контейнер `SHiNE_DM`.
|
||||
|
||||
Логика протокола, API и поведение сервера описаны отдельно:
|
||||
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`
|
||||
|
||||
## 1. Общие правила
|
||||
|
||||
- Числа кодируются в `big-endian`.
|
||||
- `toLogin` и `fromLogin` — ASCII строки длиной `1..60`.
|
||||
- Подпись — `Ed25519`, 64 байта.
|
||||
- `nonce` — `u32`.
|
||||
- `messageType` — `u8`.
|
||||
- `timeMs`, `revisionTimeMs`, `reencryptedAtMs` — `u64`.
|
||||
|
||||
## 2. Типы сообщений
|
||||
|
||||
- `1` — входящее сообщение
|
||||
- `2` — исходящая копия сообщения
|
||||
- `3` — входящее подтверждение прочтения
|
||||
- `4` — исходящая копия подтверждения прочтения
|
||||
- `5` — сообщение удалено отправителем
|
||||
- `6` — сообщение удалено получателем
|
||||
- `7` — переписка удалена отправителем
|
||||
- `8` — переписка удалена получателем
|
||||
|
||||
## 3. Контейнер `SHiNE_DM`
|
||||
|
||||
```text
|
||||
SHiNE_DM
|
||||
- prefix = "SHiNE_DM"
|
||||
- formatVersionMajor: u8
|
||||
- formatVersionMinor: u8
|
||||
- toLoginLen: u8
|
||||
- toLogin
|
||||
- fromLoginLen: u8
|
||||
- fromLogin
|
||||
- timeMs: u64
|
||||
- nonce: u32
|
||||
- messageType: u8
|
||||
- revisionTimeMs: u64
|
||||
- reencryptedAtMs: u64
|
||||
- bodyLen: u32
|
||||
- body
|
||||
- signature: [64]
|
||||
```
|
||||
|
||||
## 4. Смысл полей `SHiNE_DM`
|
||||
|
||||
### `timeMs`
|
||||
|
||||
Это время исходного создания сообщения.
|
||||
|
||||
Для типов `7/8` это время самого служебного сообщения удаления переписки и одновременно граница, раньше которой сообщения этой пары считаются недействительными.
|
||||
|
||||
### `nonce`
|
||||
|
||||
Дополнительное поле уникальности сообщения.
|
||||
|
||||
Используется вместе с `timeMs` для построения стабильного логического ID.
|
||||
|
||||
### `messageType`
|
||||
|
||||
Определяет смысл контейнера:
|
||||
|
||||
- обычное сообщение;
|
||||
- исходящая копия;
|
||||
- read-receipt;
|
||||
- удаление одного сообщения;
|
||||
- удаление всей переписки.
|
||||
|
||||
### `revisionTimeMs`
|
||||
|
||||
- `0` для исходной версии сообщения;
|
||||
- ненулевое значение для новой ревизии сообщения;
|
||||
- при редактировании или удалении должно быть больше предыдущего значения для этого же `messageKey`.
|
||||
|
||||
То есть это `0` или время, когда сообщение было отредактировано либо удалено.
|
||||
|
||||
### `reencryptedAtMs`
|
||||
|
||||
- `0`, если перешифровки не было;
|
||||
- ненулевое значение, если копия сообщения была перешифрована.
|
||||
|
||||
Для типов `5/6/7/8` должно быть `0`.
|
||||
|
||||
### `bodyLen`
|
||||
|
||||
- `> 0` для типов `1/2/3/4`;
|
||||
- `0` для типов `5/6/7/8`;
|
||||
- для всех типов используется один и тот же контейнер `SHiNE_DM`.
|
||||
|
||||
## 5. Поле `body` для типов `1/2`
|
||||
|
||||
Для обычного контентного DM поле `body` содержит не голый ciphertext, а контейнер шифрования:
|
||||
|
||||
```text
|
||||
EncryptedBody_v1_0
|
||||
- cryptoMethod: u8
|
||||
- cryptoVersion: u8
|
||||
- ephemeralPubKeyLen: u8
|
||||
- ephemeralPubKey: bytes[ephemeralPubKeyLen]
|
||||
- ivLen: u8
|
||||
- iv: bytes[ivLen]
|
||||
- cipherTextLen: u32
|
||||
- cipherText: bytes[cipherTextLen]
|
||||
```
|
||||
|
||||
### Смысл полей `EncryptedBody_v1_0`
|
||||
|
||||
#### `cryptoMethod`
|
||||
|
||||
Идентификатор метода шифрования.
|
||||
|
||||
В версии v1 резервируется:
|
||||
|
||||
- `1` — `X25519 + HKDF-SHA256 + AES-256-GCM`
|
||||
|
||||
#### `cryptoVersion`
|
||||
|
||||
Версия конкретного метода шифрования.
|
||||
|
||||
Для текущей версии:
|
||||
|
||||
- `0`
|
||||
|
||||
#### `ephemeralPubKey`
|
||||
|
||||
Публичный ephemeral `X25519` ключ отправителя конкретной ревизии.
|
||||
|
||||
Практически ожидается длина:
|
||||
|
||||
- `32`
|
||||
|
||||
#### `iv`
|
||||
|
||||
Nonce/IV для `AES-GCM`.
|
||||
|
||||
Практически ожидается длина:
|
||||
|
||||
- `12`
|
||||
|
||||
#### `cipherText`
|
||||
|
||||
Зашифрованное содержимое сообщения.
|
||||
|
||||
Сервер не должен трактовать это поле как UTF-8 текст и не должен пытаться расшифровывать его в обычной DM-логике.
|
||||
|
||||
## 6. Поле `body` для типов `3/4`
|
||||
|
||||
Для read-receipt типов `3/4` поле `body` содержит открытый контейнер ссылки на исходное сообщение:
|
||||
|
||||
```text
|
||||
ReadReceiptBody_v1_0
|
||||
- refToLoginLen: u8
|
||||
- refToLogin
|
||||
- refFromLoginLen: u8
|
||||
- refFromLogin
|
||||
- refTimeMs: u64
|
||||
- refNonce: u32
|
||||
```
|
||||
|
||||
Смысл:
|
||||
|
||||
- `refToLogin`
|
||||
- `refFromLogin`
|
||||
- `refTimeMs`
|
||||
- `refNonce`
|
||||
|
||||
однозначно указывают на логическое сообщение по его `baseKey`.
|
||||
|
||||
Отдельный `refType` в v1 не нужен, потому что подтверждение прочтения относится к самому логическому сообщению, а не к выбору между копиями `type=1` и `type=2`.
|
||||
## 7. Контент типов `1/2`
|
||||
|
||||
Для типов `1/2`:
|
||||
|
||||
- `bodyLen > 0`
|
||||
- `body` обязан быть контейнером `EncryptedBody_v1_0`
|
||||
- ciphertext у `type=1` и `type=2` может быть разным
|
||||
|
||||
### Новое сообщение
|
||||
|
||||
- `revisionTimeMs = 0`
|
||||
- `reencryptedAtMs = 0`
|
||||
|
||||
### Редактирование
|
||||
|
||||
- `revisionTimeMs > 0`
|
||||
- `reencryptedAtMs = 0` или больше нуля, если одновременно произошла перешифровка
|
||||
|
||||
### Перешифровка
|
||||
|
||||
- `revisionTimeMs > 0`
|
||||
- `reencryptedAtMs > 0`
|
||||
|
||||
## 8. Контент типов `3/4`
|
||||
|
||||
Типы:
|
||||
|
||||
- `3` — входящее подтверждение прочтения
|
||||
- `4` — исходящая копия подтверждения прочтения
|
||||
|
||||
Правила:
|
||||
|
||||
- `bodyLen > 0`
|
||||
- `body` обязан быть контейнером `ReadReceiptBody_v1_0`
|
||||
- `revisionTimeMs = 0`
|
||||
- `reencryptedAtMs = 0`
|
||||
|
||||
Тип `3` и тип `4` по стилю полностью подчиняются общему контейнеру `SHiNE_DM`:
|
||||
|
||||
- тот же `prefix = "SHiNE_DM"`
|
||||
- те же `formatVersionMajor = 1`
|
||||
- те же `formatVersionMinor = 0`
|
||||
|
||||
Различается только `messageType` и формат `body`.
|
||||
|
||||
## 9. Контент типов `5/6`
|
||||
|
||||
Типы:
|
||||
|
||||
- `5` — сообщение удалено отправителем
|
||||
- `6` — сообщение удалено получателем
|
||||
|
||||
Правила:
|
||||
|
||||
- `bodyLen = 0`
|
||||
- `body` отсутствует
|
||||
- `revisionTimeMs > 0`
|
||||
- `reencryptedAtMs = 0`
|
||||
|
||||
Это terminal tombstone конкретного сообщения.
|
||||
|
||||
После принятия такого контейнера содержательная версия этого же `messageKey` больше не должна приниматься.
|
||||
|
||||
## 10. Контент типов `7/8`
|
||||
|
||||
Типы:
|
||||
|
||||
- `7` — переписка удалена отправителем
|
||||
- `8` — переписка удалена получателем
|
||||
|
||||
Правила:
|
||||
|
||||
- `bodyLen = 0`
|
||||
- `body` отсутствует
|
||||
- `revisionTimeMs = 0`
|
||||
- `reencryptedAtMs = 0`
|
||||
|
||||
Здесь роль границы удаления играет:
|
||||
|
||||
- `timeMs` самого контейнера
|
||||
|
||||
После принятия такого контейнера:
|
||||
|
||||
- более старые сообщения этой пары должны быть удалены;
|
||||
- более старые новые поступления этой пары не должны приниматься.
|
||||
|
||||
## 11. Подпись
|
||||
|
||||
Поле `signature` всегда подписывает весь контейнер от `prefix` до конца `body` включительно.
|
||||
|
||||
Правило подписи по `messageType`:
|
||||
|
||||
- `1`, `2`, `5`, `7` подписывает отправитель сообщения;
|
||||
- `6`, `8` подписывает получатель сообщения.
|
||||
|
||||
## 12. Какие поля должны совпадать у пары `1/2`
|
||||
|
||||
При обычной парной отправке через `SendMessagePair` у двух копий должны совпадать:
|
||||
|
||||
- `fromLogin`
|
||||
- `toLogin`
|
||||
- `timeMs`
|
||||
- `nonce`
|
||||
- `revisionTimeMs`
|
||||
|
||||
Дополнительно:
|
||||
|
||||
- логический plaintext должен быть одинаковым;
|
||||
- ciphertext может различаться;
|
||||
- `reencryptedAtMs` при одной парной ревизии тоже должен совпадать.
|
||||
|
||||
## 13. Примечание о текущем коде
|
||||
|
||||
В текущем коде типы `3/4` пока ещё реализованы старым контейнером `SHiNE_dm2`.
|
||||
|
||||
Для версии протокола v1 целевой формат фиксируется уже как единый `SHiNE_DM` для всех типов `1..8`.
|
||||
@@ -1,73 +0,0 @@
|
||||
# Черновик будущих вложений в DM
|
||||
|
||||
## Важно
|
||||
|
||||
Этот документ описывает только ранний черновик идеи.
|
||||
|
||||
Сейчас в проекте **нет** поддержки вложений в личных сообщениях:
|
||||
|
||||
- в реализованном формате `SHiNE_DM` поле `attachmentsCount` пока всегда должно быть `0`;
|
||||
- UI не показывает кнопку прикрепления файлов;
|
||||
- сервер не принимает upload файлов для DM;
|
||||
- сервер не раздаёт специальные DM-файлы по отдельным endpoints;
|
||||
- сервер не хранит отдельные файловые связи для личных сообщений.
|
||||
|
||||
Этот документ нужен только для того, чтобы рядом с актуальной документацией было явно видно:
|
||||
|
||||
- какие идеи обсуждались;
|
||||
- что это **не реализовано**;
|
||||
- что формат, хранение и способ загрузки потом могут сильно измениться.
|
||||
|
||||
## Что обсуждалось
|
||||
|
||||
Рассматривался такой общий подход:
|
||||
|
||||
- у контентного DM есть внешний список вложений;
|
||||
- во внешнем формате лежат только технические данные;
|
||||
- человекочитаемые данные о файле живут внутри зашифрованного тела сообщения;
|
||||
- один и тот же blob-файл теоретически мог бы переиспользоваться в нескольких сообщениях.
|
||||
|
||||
Черновой вариант внешнего списка:
|
||||
|
||||
- `attachmentsCount`
|
||||
- далее для каждого вложения:
|
||||
- `encFileHashSHA256` (`32 bytes`)
|
||||
- `encFileSize` (`u64`)
|
||||
|
||||
Черновой вариант внутреннего маркера в тексте:
|
||||
|
||||
```text
|
||||
<<file:file-format(1.0):type|fileName|origSize|origHashB64u|encHashB64u|encSize|keyB64u|nonceB64u>>
|
||||
```
|
||||
|
||||
Где обсуждались поля:
|
||||
|
||||
- `type`
|
||||
- `fileName`
|
||||
- `origSize`
|
||||
- `origHashB64u`
|
||||
- `encHashB64u`
|
||||
- `encSize`
|
||||
- `keyB64u`
|
||||
- `nonceB64u`
|
||||
|
||||
## Что может измениться
|
||||
|
||||
В будущем могут измениться любые части идеи:
|
||||
|
||||
- сам бинарный формат;
|
||||
- способ привязки файлов к сообщению;
|
||||
- момент загрузки файла относительно отправки сообщения;
|
||||
- серверное хранение blob-файлов;
|
||||
- права доступа к скачиванию;
|
||||
- способ рендера вложения в UI.
|
||||
|
||||
Именно поэтому этот файл не надо воспринимать как актуальную спецификацию.
|
||||
|
||||
## Источник истины на сейчас
|
||||
|
||||
Актуальное состояние личных сообщений описано только в:
|
||||
|
||||
- `Dev_Docs/Personal_Messages/README.md`
|
||||
|
||||
Если между этим черновиком и основным README есть расхождение, верным считается `README.md`.
|
||||
@@ -273,7 +273,7 @@ ServerProfileBlock
|
||||
- `address_format_version` — версия формата адреса, сейчас `0`;
|
||||
- `sync_servers_count` максимум `32`;
|
||||
- `server_address` - строковый адрес сервера в соответствии с `address_format_type`;
|
||||
- `sync_servers` - логины SHiNE-пользователей, зарегистрированных как серверы, с которыми этот сервер синхронизирует блокчейн и личные сообщения. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы.
|
||||
- `sync_servers` - логины SHiNE-пользователей, зарегистрированных как серверы, с которыми этот сервер синхронизирует серверные данные и пользовательские блокчейны SHiNE. Это server-to-server список партнёров самого серверного узла, а не список серверов доставки личных сообщений для обычного пользователя. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы.
|
||||
|
||||
## 13. AccessServersBlock
|
||||
|
||||
@@ -291,7 +291,7 @@ AccessServersBlock
|
||||
|
||||
- блок может отсутствовать, если серверы доступа не заданы;
|
||||
- список может обновляться при изменении маршрутизации пользователя;
|
||||
- `access_servers` - логины пользователей системы, используемых как серверы доступа/relay. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы;
|
||||
- `access_servers` - логины пользователей системы, используемых как серверы доступа/relay для конкретного пользователя. Через этот список клиентская и серверная логика SHiNE может маршрутизировать доставку личных сообщений, доступ к сессиям и другие пользовательские операции. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы;
|
||||
- точная семантика выбора сервера доступа определяется клиентской/серверной логикой SHiNE.
|
||||
|
||||
## 14. SessionsBlock
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
# Преобразование Ed25519 в X25519
|
||||
|
||||
## Назначение
|
||||
|
||||
Этот документ фиксирует единое правило проекта SHiNE:
|
||||
|
||||
- публичная идентичность пользователя задаётся одним `clientKey` в формате `Ed25519`;
|
||||
- подпись пользовательских сообщений и команд выполняется ключом `Ed25519`;
|
||||
- шифрование личных сообщений использует ключ `X25519`, получаемый детерминированно из того же ключевого материала;
|
||||
- для преобразования используется только стандартное преобразование `Ed25519 <-> X25519`;
|
||||
- самодельные формулы, альтернативные хэши и нестандартные схемы преобразования в проекте не допускаются.
|
||||
|
||||
Цель документа: исключить путаницу между ключом подписи и ключом шифрования и зафиксировать один общий способ преобразования для клиента, сервера и будущих реализаций.
|
||||
|
||||
## Краткое правило
|
||||
|
||||
Если у пользователя есть:
|
||||
|
||||
- приватный ключ `Ed25519 private`;
|
||||
- публичный ключ `Ed25519 public` (`clientKey`);
|
||||
|
||||
то для шифрования личных сообщений из них получаются:
|
||||
|
||||
- `X25519 private` для расшифровки своих копий;
|
||||
- `X25519 public` для шифрования сообщений на этого пользователя.
|
||||
|
||||
При этом:
|
||||
|
||||
- в профиле пользователя по-прежнему публикуется только `clientKey`;
|
||||
- отдельный публичный `dmEncKey` не требуется;
|
||||
- владелец устройства локально может использовать один и тот же исходный секрет и для подписи, и для вывода ключа шифрования.
|
||||
|
||||
## Что считается стандартным преобразованием
|
||||
|
||||
Под "стандартным преобразованием" в проекте понимается совместимое с общепринятой практикой libsodium/NaCl преобразование:
|
||||
|
||||
- из `Ed25519 private` получается `X25519 private` через стандартную процедуру на основе SHA-512 и clamping;
|
||||
- из `Ed25519 public` получается `X25519 public` через стандартное преобразование точки Edwards в точку Montgomery.
|
||||
|
||||
Иными словами:
|
||||
|
||||
- приватный ключ шифрования должен получаться из приватного ключа подписи стандартным способом;
|
||||
- публичный ключ шифрования должен получаться из публичного `clientKey` стандартным способом;
|
||||
- обе стороны должны получать одинаковый `X25519 public` по одному и тому же `clientKey`.
|
||||
|
||||
## Преобразование приватного ключа
|
||||
|
||||
Исходные данные:
|
||||
|
||||
- `Ed25519 private` в SHiNE рассматривается как 32-байтный seed приватного ключа.
|
||||
|
||||
Стандартная процедура:
|
||||
|
||||
1. Вычислить `SHA-512(seed32)`.
|
||||
2. Взять первые 32 байта результата.
|
||||
3. Применить стандартный clamping для `X25519 private`.
|
||||
4. Полученный результат использовать как `X25519 private`.
|
||||
|
||||
Замечания:
|
||||
|
||||
- нельзя использовать для `X25519 private` просто исходный 32-байтный `Ed25519 seed` без преобразования;
|
||||
- нельзя заменять `SHA-512` на `SHA-256`, `HMAC`, `HKDF` или произвольную пользовательскую формулу;
|
||||
- clamping обязателен.
|
||||
|
||||
## Преобразование публичного ключа
|
||||
|
||||
Исходные данные:
|
||||
|
||||
- `clientKey` пользователя в формате `Ed25519 public` (32 байта).
|
||||
|
||||
Стандартная процедура:
|
||||
|
||||
1. Декодировать публичную точку Edwards из `Ed25519 public`.
|
||||
2. Выполнить стандартное преобразование Edwards -> Montgomery.
|
||||
3. Полученное значение использовать как `X25519 public`.
|
||||
|
||||
На уровне математики используется стандартное отображение:
|
||||
|
||||
- `u = (1 + y) / (1 - y)`
|
||||
|
||||
где `y` берётся из публичной точки Ed25519, а результат `u` кодируется как публичный ключ `X25519`.
|
||||
|
||||
Замечания:
|
||||
|
||||
- нельзя получать `X25519 public` простым хэшированием `clientKey`;
|
||||
- нельзя получать `X25519 public` "через приватный ключ на сервере";
|
||||
- любой клиент должен уметь вывести `X25519 public` другого пользователя, имея только его `clientKey`.
|
||||
|
||||
## Что хранится в проекте
|
||||
|
||||
На текущем архитектурном уровне:
|
||||
|
||||
- в публичном профиле пользователя хранится только `clientKey` (`Ed25519 public`);
|
||||
- приватная часть `clientKey` хранится только у владельца устройства;
|
||||
- `X25519 private` и `X25519 public` считаются производными величинами и могут вычисляться по мере необходимости;
|
||||
- отдельный `keyId` для DM пока не вводится.
|
||||
|
||||
Это означает:
|
||||
|
||||
- если в будущем пользователь сменит `clientKey`, старые DM должны будут быть перешифрованы;
|
||||
- массовая перешифровка истории рассматривается как отдельная функция более позднего этапа;
|
||||
- текущая архитектура должна оставлять возможность такой перешифровки, но не обязана реализовывать её прямо сейчас.
|
||||
|
||||
## Как это применяется в DM
|
||||
|
||||
Для личных сообщений SHiNE:
|
||||
|
||||
- входящая копия сообщения шифруется на `X25519 public`, полученный из `clientKey` получателя;
|
||||
- исходящая копия сообщения шифруется на `X25519 public`, полученный из `clientKey` отправителя;
|
||||
- расшифровать входящую копию может только владелец приватного ключа получателя;
|
||||
- расшифровать исходящую копию может только владелец приватного ключа отправителя.
|
||||
|
||||
Следствия:
|
||||
|
||||
- `encryptedBody` у входящей и исходящей копии одного логического сообщения обычно разный;
|
||||
- сервер не должен требовать побайтного совпадения ciphertext у пары;
|
||||
- сервер не должен уметь расшифровывать содержимое DM;
|
||||
- подпись и шифрование используют один корневой секрет пользователя, но разные стандартно выведенные представления ключа.
|
||||
|
||||
## Ограничения и компромиссы
|
||||
|
||||
Эта архитектура осознанно имеет следующие свойства:
|
||||
|
||||
- компрометация приватного `clientKey` одновременно даёт злоумышленнику возможность и подписывать от имени пользователя, и расшифровывать его личные сообщения;
|
||||
- отдельное разделение ключа подписи и ключа шифрования пока не используется;
|
||||
- простота пользовательской модели и минимизация числа публичных ключей считаются в проекте более важными, чем разделение этих ролей на текущем этапе.
|
||||
|
||||
Если позже проекту понадобится более строгая модель безопасности, допускается переход на отдельный публичный ключ шифрования, но только как отдельная версия протокола.
|
||||
|
||||
## Что запрещено
|
||||
|
||||
В проекте запрещено:
|
||||
|
||||
- придумывать собственное "детерминированное преобразование" `Ed25519 -> X25519`;
|
||||
- хэшировать `clientKey` произвольным образом и считать результат `X25519 public`;
|
||||
- использовать `Ed25519 public` напрямую как ключ ECDH;
|
||||
- использовать сырой `Ed25519 seed` как `X25519 private` без стандартной процедуры;
|
||||
- смешивать разные способы преобразования в разных клиентах.
|
||||
|
||||
## Требование к реализациям
|
||||
|
||||
Любая реализация SHiNE, которая:
|
||||
|
||||
- подписывает DM;
|
||||
- шифрует DM;
|
||||
- расшифровывает DM;
|
||||
- проверяет совместимость личных сообщений между устройствами;
|
||||
|
||||
обязана использовать именно этот подход.
|
||||
|
||||
Если библиотека уже предоставляет готовые совместимые функции преобразования `Ed25519 -> X25519`, нужно использовать их вместо самодельной реализации.
|
||||
@@ -36,6 +36,6 @@
|
||||
## Какие документы потом обновить
|
||||
|
||||
- `Dev_Docs/Blockchain/sync-between-servers.md`;
|
||||
- `Dev_Docs/Personal_Messages/README.md`;
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`;
|
||||
- `Dev_Docs/Personal_Messages/Формат_DM_v1.md`;
|
||||
- `Dev_Docs/API/`.
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
|
||||
- `Dev_Docs/Blockchain/README.md` и связанные файлы, если изменятся типы служебных сообщений или форматы блокчейн-команд.
|
||||
- `Dev_Docs/API/` если изменится публичный серверный API или появятся новые операции.
|
||||
- `Dev_Docs/Personal_Messages/README.md` если часть маршрутизации или подтверждений будет встроена в существующую логику доставки/сессий.
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md` если часть маршрутизации или подтверждений будет встроена в существующую логику доставки/сессий.
|
||||
- Документацию по homeserver/ESP32, если появится пользовательская или сервисная файловая логика на устройстве.
|
||||
|
||||
## С какого места продолжать позже
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
## Документы, которые нужно обновить при возврате
|
||||
|
||||
- `Dev_Docs/Keys/README.md`
|
||||
- `Dev_Docs/Personal_Messages/README.md`
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`
|
||||
- `Dev_Docs/API/`
|
||||
- `Dev_Docs/Blockchain/`, если появятся новые блоки или команды для файлов.
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
- `Dev_Docs/Solana_Architecture/README.md`
|
||||
- `Dev_Docs/Инициализация_Solana_регистрации/README.md`
|
||||
- `Dev_Docs/Keys/README.md`
|
||||
- `Dev_Docs/Personal_Messages/README.md`, если изменится адресация DM по типам сессий
|
||||
- `Dev_Docs/Personal_Messages/Протокол_DM_v1.md`, если изменится адресация DM по типам сессий
|
||||
- `Dev_Docs/API/`, если появятся новые серверные операции или изменятся ответы
|
||||
|
||||
## Что пока не делать
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
client.version=1.2.296
|
||||
server.version=1.2.276
|
||||
client.version=1.2.297
|
||||
server.version=1.2.277
|
||||
|
||||
@@ -273,7 +273,7 @@ ServerProfileBlock
|
||||
- `address_format_version` — версия формата адреса, сейчас `0`;
|
||||
- `sync_servers_count` максимум `32`;
|
||||
- `server_address` - строковый адрес сервера в соответствии с `address_format_type`;
|
||||
- `sync_servers` - логины SHiNE-пользователей, зарегистрированных как серверы, с которыми этот сервер синхронизирует блокчейн и личные сообщения. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы.
|
||||
- `sync_servers` - логины SHiNE-пользователей, зарегистрированных как серверы, с которыми этот сервер синхронизирует серверные данные и пользовательские блокчейны SHiNE. Это server-to-server список партнёров самого серверного узла, а не список серверов доставки личных сообщений для обычного пользователя. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы.
|
||||
|
||||
## 13. AccessServersBlock
|
||||
|
||||
@@ -291,7 +291,7 @@ AccessServersBlock
|
||||
|
||||
- блок может отсутствовать, если серверы доступа не заданы;
|
||||
- список может обновляться при изменении маршрутизации пользователя;
|
||||
- `access_servers` - логины пользователей системы, используемых как серверы доступа/relay. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы;
|
||||
- `access_servers` - логины пользователей системы, используемых как серверы доступа/relay для конкретного пользователя. Через этот список клиентская и серверная логика SHiNE может маршрутизировать доставку личных сообщений, доступ к сессиям и другие пользовательские операции. Solana-программа не обязана проверять, что эти логины действительно зарегистрированы как серверы;
|
||||
- точная семантика выбора сервера доступа определяется клиентской/серверной логикой SHiNE.
|
||||
|
||||
## 14. SessionsBlock
|
||||
|
||||
Reference in New Issue
Block a user