Обновить UI чата и закрыть проверенные DM задачи

This commit is contained in:
AidarKC
2026-07-10 12:26:36 +04:00
parent 0fb1147eb7
commit 5a5e9c01ce
9 changed files with 320 additions and 57 deletions
@@ -1,23 +0,0 @@
# DM v1: E2EE, tombstone и fan-out
- краткое описание фичи:
Новый протокол личных сообщений `SHiNE_DM` v1: реальные зашифрованные тела `X25519 + HKDF-SHA256 + AES-256-GCM`, read-receipt в том же контейнере, удаление одного сообщения, удаление истории переписки и межсерверная доставка по `access_servers`.
- что именно проверять:
1. Отправка нового DM между двумя пользователями и чтение текста на стороне получателя.
2. Отправка/чтение своей исходящей копии у отправителя.
3. Редактирование сообщения с тем же `baseKey` и ростом `revisionTimeMs`.
4. Подтверждение прочтения `type=3/4`.
5. Удаление исходящего сообщения отправителем (`type=5`) и удаление входящего сообщения получателем (`type=6`).
6. Удаление истории переписки (`type=7/8`) и игнорирование более старых сообщений после tombstone.
7. Сценарий с несколькими `access_servers`, включая случай общего сервера у обеих сторон.
8. Первый DM пользователю, которого ещё нет в локальной `solana_users`, с lazy-import из Solana PDA.
9. Две версии одного сообщения с одинаковым `revisionTimeMs`, но разным `reencryptedAtMs`: должна победить версия с большим `reencryptedAtMs`.
10. После уже известного `DeleteConversation` отправка старого сообщения с другого сервера должна приводить к повторной рассылке tombstone удаления переписки.
11. Попытка вызвать legacy `SendDirectMessage` должна не работать, а новый UI должен использовать только `SendMessagePair`.
- ожидаемый результат:
Сообщения шифруются и расшифровываются только на клиенте, сервер не показывает plaintext из ciphertext, lazy-import из PDA позволяет отправить первый DM без ручного прогрева БД, версия с большим `reencryptedAtMs` корректно замещает старую при равном `revisionTimeMs`, старые ревизии не оживают после tombstone, общие серверы не получают лишних дублей пары, а удаление и read-receipt корректно доходят обеим сторонам.
- статус:
pending
@@ -1,16 +0,0 @@
Lf dc` hfm# TURN: только один живой узел для звонков
- краткое описание:
- в серверном конфиге оставлен только один TURN-узел `185.229.109.118:3478` для ICE-конфига звонков;
- мёртвый узел `93.170.12.154:3478` убран из локальной конфигурации и test-деплоя `t2`.
- что проверять:
- открыть два клиента на `t2.shineup.me`;
- начать аудиозвонок между ними;
- убедиться, что `GetCallIceConfig` отдаёт только TURN `185.229.109.118`;
- убедиться, что звонок выходит из стадии `connecting` и появляется `call_connected` либо как минимум `relay`-кандидаты в клиентской диагностике.
- ожидаемый результат:
- клиентам больше не предлагается `93.170.12.154`;
- звонок проходит стабильнее, чем до изменения;
- в серверных логах нет новых `incoming_failed/outgoing_failed` только из-за нерабочего TURN.
- статус:
- pending
@@ -446,6 +446,11 @@ Request:
- `5`, если удаление инициировал отправитель;
- `6`, если удаление инициировал получатель.
UI-следствие для клиента:
- пользователь может удалить как своё исходящее сообщение, так и входящее;
- для удаления входящего UI должен отправлять вариант, где удаление инициировал получатель (`type=6`).
### 10.4. `DeleteConversation`
Назначение:
@@ -469,6 +474,13 @@ Request:
- `7`, если удаление инициировал отправитель;
- `8`, если удаление инициировал получатель.
UI-следствие для клиента:
- действие `Очистить историю` должно отправлять служебное сообщение удаления переписки;
- для обычной клиентской кнопки очистки истории допускается вариант удаления, инициированный текущим получателем (`type=8`);
- после применения такого сообщения UI может оставлять в чате видимую служебную точку отсечения истории;
- отдельное UI-действие `Удалить чат` может дополнительно спросить, нужно ли вместе с удалением контакта также отправить `DeleteConversation`.
## 11. Межсерверная доставка
### 11.1. Клиентская сторона
@@ -296,6 +296,12 @@ ReadReceiptBody_v1_0
- `1`, `2`, `5`, `7` подписывает отправитель сообщения;
- `6`, `8` подписывает получатель сообщения.
Практическое UI-следствие:
- клиентский UI может инициировать удаление входящего сообщения через `type=6`;
- клиентский UI может инициировать очистку истории переписки через `type=8`;
- сами контейнеры и байтовый формат при этом не отличаются от уже описанных типов `5/6/7/8`.
## 12. Какие поля должны совпадать у пары `1/2`
При обычной парной отправке через `SendMessagePair` у двух копий должны совпадать: