Реализовать SHiNE_DM v1 с E2EE и tombstone

This commit is contained in:
AidarKC
2026-07-07 18:07:10 +04:00
parent 9c588bd9b5
commit 1b7a2a8f7c
33 changed files with 1636 additions and 445 deletions
+2
View File
@@ -61,6 +61,8 @@
| `SendMessagePair` | `12_Direct_Messages_Push_Calls_API.md` | отправка пары входящий/исходящий DM |
| `ReceiveOutcomingMessage` | `12_Direct_Messages_Push_Calls_API.md` | алиас `SendMessagePair` |
| `ReceiveIncomingMessage` | `12_Direct_Messages_Push_Calls_API.md` | прием входящего DM-блока |
| `DeleteMessage` | `12_Direct_Messages_Push_Calls_API.md` | tombstone одного личного сообщения у обеих сторон |
| `DeleteConversation` | `12_Direct_Messages_Push_Calls_API.md` | tombstone удаления истории переписки |
| `AckSessionDelivery` | `12_Direct_Messages_Push_Calls_API.md` | подтверждение доставки в сессию |
| `CallInviteBroadcast` | `12_Direct_Messages_Push_Calls_API.md` | broadcast приглашения к звонку |
| `CallSignalToSession` | `12_Direct_Messages_Push_Calls_API.md` | сигнал звонка в конкретную сессию |
@@ -73,7 +73,7 @@
- `incomingBlobB64` — блок `type=1` или `type=3`
- `outgoingBlobB64` — блок `type=2` или `type=4`
Для контентных сообщений `type=1/2` внутри base64 лежит бинарный формат `SHiNE_DM`.
Все типы в этой паре используют бинарный формат `SHiNE_DM`.
### Запрос
@@ -110,8 +110,7 @@
- `400 / BAD_FIELDS` — пустой `incomingBlobB64` или `outgoingBlobB64`
- `400 / BAD_BLOCK_FORMAT` — base64 или бинарный контейнер повреждён
- `400 / BAD_CONTENT_FORMAT` — для контентного сообщения пришёл не `SHiNE_DM`
- `400 / ATTACHMENTS_DISABLED` — в `SHiNE_DM` пришёл `attachmentsCount != 0`
- `400 / BAD_CRYPTO_METHOD` — неподдерживаемый метод шифрования контейнера `EncryptedBody_v1_0`
- `404 / USER_NOT_FOUND` — один из логинов не найден
- `460 / BAD_SIGNATURE` — подпись блока не прошла проверку
@@ -123,6 +122,11 @@
Используется там, где нужно принять только incoming-вариант сообщения.
Принимаемые типы:
- `type=1` — входящая копия сообщения
- `type=3` — входящий read-receipt
### Запрос
```json
@@ -135,7 +139,39 @@
}
```
## 5. `AckSessionDelivery`
## 5. `DeleteMessage`
Принимает один signed DM-блок `type=5` или `type=6`.
### Запрос
```json
{
"op": "DeleteMessage",
"requestId": "dm-del-001",
"payload": {
"blobB64": "BASE64_DELETE_BLOCK"
}
}
```
## 6. `DeleteConversation`
Принимает один signed DM-блок `type=7` или `type=8`.
### Запрос
```json
{
"op": "DeleteConversation",
"requestId": "dm-del-all-001",
"payload": {
"blobB64": "BASE64_DELETE_CONVERSATION_BLOCK"
}
}
```
## 7. `AckSessionDelivery`
Требует авторизации. Подтверждает доставку в текущую сессию.
@@ -151,7 +187,7 @@
}
```
## 6. Событие `SignedMessageArrived`
## 8. Событие `SignedMessageArrived`
Сервер присылает его по WebSocket в активные сессии адресата.
@@ -174,18 +210,19 @@
Если это новая ревизия того же письма, `messageKey` остаётся тем же, а `revisionTimeMs` меняется внутри бинарного блока.
## 7. `CallInviteBroadcast`
Для типов `5/6/7/8` событие тоже приходит в таком же конверте, но логика применения определяется `messageType` и бинарным `blobB64`.
## 9. `CallInviteBroadcast`
Требует авторизации. Шлёт приглашение к звонку в активные сессии `toLogin`.
## 8. `CallSignalToSession`
## 10. `CallSignalToSession`
Требует авторизации. Шлёт сигнал звонка в конкретную сессию.
## 9. Замечания
## 11. Замечания
- read-receipt `type=3/4` пока остаются в legacy-формате `SHiNE_dm2`
- контентные DM `type=1/2` используют `SHiNE_DM`
- сервер хранит только последнюю версию контентного сообщения по `messageKey`
- удаление сообщения реализуется новой ревизией с пустым телом и `attachmentsCount = 0`
- все DM-типы `1..8` используют `SHiNE_DM`
- сервер не расшифровывает DM и не использует ciphertext как preview текста
- сервер хранит последнюю применённую ревизию контентного сообщения и отдельные tombstone-события удаления
- HTTP endpoints для DM-файлов сейчас отсутствуют