SHA256
Довести DM v1 до соответствия коду и документации
This commit is contained in:
@@ -15,3 +15,4 @@
|
||||
|
||||
- код DM и оба документа `Протокол_DM_v1.md` + `Формат_DM_v1.md` всегда должны обновляться синхронно;
|
||||
- если меняется поведение DM в коде, в том же наборе изменений обновляется и эта документация.
|
||||
- локальная таблица пользователей для DM считается кэшем, а источником истины остаётся Solana PDA; если серверная логика DM меняет правила lazy-import пользователей из PDA, это тоже обязательно фиксируется в документации.
|
||||
|
||||
@@ -71,6 +71,19 @@
|
||||
- сервер не должен расшифровывать DM;
|
||||
- ciphertext у `type=1` и `type=2` обычно разный и не обязан совпадать побайтно.
|
||||
|
||||
### 2.3. Источник истины по пользователю
|
||||
|
||||
Для DM-проверки сервер использует:
|
||||
|
||||
- локальную `solana_users` как кэш;
|
||||
- Solana PDA как источник истины по `clientKey` и `access_servers`.
|
||||
|
||||
Если нужного пользователя нет локально, сервер обязан попытаться lazy-import из Solana PDA:
|
||||
|
||||
- в `GetUser`;
|
||||
- при серверной верификации DM-подписи;
|
||||
- перед межсерверной маршрутизацией через `access_servers`.
|
||||
|
||||
## 3. Типы сообщений
|
||||
|
||||
В версии v1 используются следующие `messageType`:
|
||||
@@ -135,7 +148,8 @@
|
||||
- plaintext может остаться тем же;
|
||||
- ciphertext меняется;
|
||||
- `reencryptedAtMs` получает ненулевое значение;
|
||||
- `revisionTimeMs` увеличивается.
|
||||
- `revisionTimeMs` может остаться прежним, в том числе нулевым, если менялось только шифрование без редактирования текста;
|
||||
- сервер при выборе актуальной версии обязан учитывать обе метки времени.
|
||||
|
||||
Если сообщение уже удалено одним из типов `5/6`, его перешифровывать больше нельзя.
|
||||
|
||||
@@ -223,7 +237,7 @@
|
||||
то сервер:
|
||||
|
||||
- не принимает это сообщение;
|
||||
- в ответ возвращает то же сообщение удаления переписки;
|
||||
- распространяет уже известный tombstone удаления переписки на серверы доступа обеих сторон;
|
||||
- ожидает, что вторая сторона обработает его как обычное уже известное удаление переписки.
|
||||
|
||||
### 6.5. Будущие новые сообщения
|
||||
@@ -281,6 +295,8 @@
|
||||
- `SendMessagePair`
|
||||
- `ReceiveOutcomingMessage`
|
||||
- `ReceiveIncomingMessage`
|
||||
- `DeleteMessage`
|
||||
- `DeleteConversation`
|
||||
|
||||
Их роли в v1:
|
||||
|
||||
@@ -290,34 +306,27 @@
|
||||
|
||||
### 8.2. Новые методы, которые нужны
|
||||
|
||||
Нужны как минимум отдельные операции:
|
||||
|
||||
- `DeleteMessage`
|
||||
- `DeleteConversation`
|
||||
|
||||
Названия могут быть другими, но логически это две разные операции:
|
||||
|
||||
- удалить одно сообщение у обеих сторон;
|
||||
- удалить всю переписку до заданной временной границы.
|
||||
Отдельный legacy-метод `SendDirectMessage` в DM v1 не используется и должен оставаться отключённым, чтобы не было параллельного старого стека доставки.
|
||||
|
||||
## 9. Правила валидации и применения
|
||||
|
||||
### 9.1. Общее правило по ревизиям
|
||||
|
||||
Для одного и того же `messageKey` сервер сравнивает только:
|
||||
Для одного и того же контентного сообщения сервер сравнивает пару:
|
||||
|
||||
- уже сохранённый `revisionTimeMs`;
|
||||
- `revisionTimeMs` входящего сообщения.
|
||||
- `revisionTimeMs`;
|
||||
- `reencryptedAtMs`.
|
||||
|
||||
Правило:
|
||||
|
||||
- если новый `revisionTimeMs` больше сохранённого, сообщение применяется;
|
||||
- если новый `revisionTimeMs` равен сохранённому, сообщение не применяется;
|
||||
- если новый `revisionTimeMs` меньше сохранённого, сообщение не применяется.
|
||||
- если `revisionTimeMs` равен, но новый `reencryptedAtMs` больше сохранённого, сообщение применяется;
|
||||
- если обе величины равны, сообщение не применяется;
|
||||
- если новая пара (`revisionTimeMs`, `reencryptedAtMs`) меньше или равна сохранённой, сообщение не применяется.
|
||||
|
||||
Содержимое `body` при этом сравнении не участвует.
|
||||
|
||||
То есть если `revisionTimeMs` совпадает, сервер считает, что такая ревизия у него уже есть.
|
||||
То есть если сервер уже видел ту же пару (`revisionTimeMs`, `reencryptedAtMs`), он считает, что такая версия у него уже есть.
|
||||
|
||||
### 9.2. Повторный tombstone
|
||||
|
||||
@@ -353,6 +362,8 @@
|
||||
- не восстанавливает старую историю;
|
||||
- не применяет это событие повторно.
|
||||
|
||||
Если это старое контентное сообщение или входящая копия, сервер дополнительно перерассылает уже известный tombstone удаления переписки на `access_servers` обеих сторон, чтобы отстающие серверы сами подчистили историю.
|
||||
|
||||
Такие сообщения считаются частью уже удалённой истории.
|
||||
|
||||
### 9.4. Приоритет удаления переписки
|
||||
@@ -475,6 +486,8 @@ Request:
|
||||
|
||||
Если часть серверов совпадает, это допустимо.
|
||||
|
||||
Если один и тот же сервер присутствует у обеих сторон, он не должен слать сообщение сам себе повторно, но обязан локально сохранить событие и доставить его в нужные пользовательские сессии.
|
||||
|
||||
Идемпотентность обязательна.
|
||||
|
||||
### 11.3. Ошибки доставки
|
||||
@@ -513,6 +526,9 @@ Request:
|
||||
- удаление одного сообщения должно стать терминальным tombstone;
|
||||
- удаление всей переписки должно стать отдельным служебным событием;
|
||||
- межсерверная маршрутизация DM должна идти через `access_servers`;
|
||||
- сервер должен добирать отсутствующих пользователей из Solana PDA до проверки подписи DM;
|
||||
- при выборе актуальной версии должен учитываться `reencryptedAtMs`, если `revisionTimeMs` совпадает;
|
||||
- legacy `SendDirectMessage` должен быть отключён;
|
||||
- логика должна быть безопасна для нескольких серверов у каждой стороны.
|
||||
|
||||
## 14. Что в v1 пока не входит
|
||||
|
||||
@@ -81,11 +81,12 @@ SHiNE_DM
|
||||
|
||||
### `revisionTimeMs`
|
||||
|
||||
- `0` для исходной версии сообщения;
|
||||
- ненулевое значение для новой ревизии сообщения;
|
||||
- при редактировании или удалении должно быть больше предыдущего значения для этого же `messageKey`.
|
||||
- `0` для исходной версии контентного сообщения;
|
||||
- ненулевое значение для новой текстовой ревизии сообщения;
|
||||
- для типов `5/6` это время tombstone удаления одного сообщения;
|
||||
- для типов `7/8` всегда `0`.
|
||||
|
||||
То есть это `0` или время, когда сообщение было отредактировано либо удалено.
|
||||
То есть `revisionTimeMs` отвечает именно за изменение смыслового содержимого сообщения, а не за сам факт перешифровки.
|
||||
|
||||
### `reencryptedAtMs`
|
||||
|
||||
@@ -94,6 +95,13 @@ SHiNE_DM
|
||||
|
||||
Для типов `5/6/7/8` должно быть `0`.
|
||||
|
||||
`reencryptedAtMs` не требует, чтобы `revisionTimeMs` был ненулевым. Допустим сценарий:
|
||||
|
||||
- `revisionTimeMs = 0`
|
||||
- `reencryptedAtMs > 0`
|
||||
|
||||
если исходное сообщение не редактировалось, но было перешифровано позже.
|
||||
|
||||
### `bodyLen`
|
||||
|
||||
- `> 0` для типов `1/2/3/4`;
|
||||
@@ -213,7 +221,7 @@ ReadReceiptBody_v1_0
|
||||
|
||||
### Перешифровка
|
||||
|
||||
- `revisionTimeMs > 0`
|
||||
- `revisionTimeMs = 0` или `> 0`
|
||||
- `reencryptedAtMs > 0`
|
||||
|
||||
## 8. Контент типов `3/4`
|
||||
|
||||
Reference in New Issue
Block a user