| .. | ||
| README.md | ||
| TODO_доработка_персональных_сообщений_для_агентов.md | ||
| Черновик_будущих_DM_вложений.md | ||
Личные сообщения (DM)
Текущее состояние
Сейчас в проекте реализованы:
- новый формат контентных личных сообщений
SHiNE_DM; - ревизии сообщений через
revisionTimeMs; - редактирование сообщения через повторную отправку той же логической пары;
- удаление сообщения через пустую ревизию;
upsertпоследней версии сообщения на сервере.
Сейчас в проекте не реализованы:
- вложения в DM;
- upload/download файлов для DM;
- UI-кнопка прикрепления файла;
- серверное хранение файловых связей для DM.
Черновик будущих вложений вынесен отдельно:
Dev_Docs/Personal_Messages/Черновик_будущих_DM_вложений.md
Общая схема
Личное сообщение по-прежнему отправляется парой signed-блоков:
type=1— входящий блок для получателя;type=2— исходящая копия для отправителя.
Read-receipt пока остаются в legacy-формате:
type=3— входящее подтверждение прочтения;type=4— исходящая копия подтверждения.
Ключи сообщения:
baseKey = fromLogin|toLogin|timeMs|noncemessageKey = baseKey|messageType
Логический идентификатор письма задаётся парой:
timeMsnonce
Эти поля не меняются при редактировании или удалении. Меняется только:
revisionTimeMs- содержимое
encryptedBody
Сервер хранит только последнюю версию записи для каждого messageKey.
Формат контентного DM: SHiNE_DM
Префикс бинарного блока:
SHiNE_DM
Поля идут в big-endian порядке:
formatVersionMajor(u8) =1formatVersionMinor(u8) =0toLoginLen(u8) +toLogin(ASCII,1..60)fromLoginLen(u8) +fromLogin(ASCII,1..60)timeMs(u64)nonce(u32)messageType(u16) — только1или2revisionTimeMs(u64)attachmentsCount(u8)encryptedBodyLen(u32)encryptedBody(bytes)signature(64 bytes, Ed25519)
Ограничения
attachmentsCountсейчас всегда должен быть0encryptedBodyLenсейчас ограничен сервером до16384байтrevisionTimeMsне может быть отрицательным
Если приходит attachmentsCount != 0, сервер отклоняет такой DM как:
ATTACHMENTS_DISABLED
Legacy read-receipt: SHiNE_dm2
Подтверждения прочтения type=3/4 пока используют старый контейнер SHiNE_dm2:
toLoginLen(u8) +toLoginfromLoginLen(u8) +fromLogintimeMs(u64)nonce(u32)messageType(u16) —3или4payloadLen(u16)payloadBytessignature
Редактирование
Редактирование делается новой отправкой той же логической пары сообщения:
timeMsиnonceостаются теми же;messageTypeостаётся1/2;revisionTimeMsстановится больше;encryptedBodyсодержит новую версию текста.
Если на сервер приходит более старая ревизия, она игнорируется.
Если приходит та же ревизия и тот же бинарный блок, сервер тоже её не применяет повторно.
Удаление
Удаление личного сообщения делается как новая ревизия того же сообщения:
timeMsиnonceостаются прежними;revisionTimeMsувеличивается;attachmentsCount = 0;encryptedBodyLen = 0;encryptedBodyпустой.
В UI такое сообщение не показывается.
На сервере это не отдельный тип сообщения, а просто последняя пустая ревизия того же messageKey.
Поведение сервера
Для контентных DM сервер:
- принимает пару signed-блоков
type=1/2; - валидирует формат, подпись и совпадение ключевых полей пары;
- проверяет, что для обеих сторон пары совпадают:
fromLogintoLogintimeMsnoncerevisionTimeMsencryptedBody
- делает
upsertпоследней версии вsigned_messages_v2; - сбрасывает pending-доставку по сессиям для новой ревизии;
- рассылает актуальную версию адресатам через
SignedMessageArrived.
История старых ревизий сейчас не хранится отдельно: в таблице остаётся только последняя версия по каждому messageKey.
Хранение в БД
Основная таблица:
signed_messages_v2
Для контентных DM в ней используются:
message_keybase_keytarget_loginfrom_loginto_logintime_msnoncemessage_typerevision_time_msraw_blockcreated_at_ms
Отдельных таблиц файлов для DM сейчас нет.
События и доставка
Запрос на отправку по WebSocket остаётся прежним:
SendMessagePairReceiveOutcomingMessageкак алиас
Клиент отправляет:
incomingBlobB64outgoingBlobB64
Событие в активные сессии:
SignedMessageArrived
Если пришла новая ревизия того же сообщения, messageKey остаётся прежним, а внутри blobB64 будет более новый revisionTimeMs.
Подтверждение доставки в сессию:
AckSessionDelivery
Правила UI
UI сейчас работает так:
- показывает только текст
encryptedBody; - умеет обновлять уже существующее сообщение по тому же
messageKey; - не показывает удалённые сообщения;
- позволяет владельцу сообщения вызвать меню
Скопировать как текст / Прочесть / Изменить / Удалить; - при редактировании показывает над полем ввода полоску
Редактируем сообщение: ...с кнопкой отмены; - после редактирования показывает под временем отдельную строку
изменено: <дата время>; - не показывает и не принимает вложения.
Что обязательно помнить
- вложения в DM сейчас отключены на уровне протокола и UI;
- любые старые описания
/f/...,/uploadи файловых таблиц для DM больше не актуальны; - если позже вложения вернутся, их формат и серверная логика могут быть другими.