Путь сообщения: от шифрования до истории

У сообщения нет единственного момента «отправлено».

В ZionVox я разделяю локальную операцию, криптографический пакет, серверную запись, realtime-событие, доставку и прочтение. Между этапами может исчезнуть маршрут, хотя Core продолжает работать.

Начнём с приватного E2EE-сценария. Клиент сначала загружает существующее состояние Double Ratchet. Если оно подходит, X3DH заново не запускается. При отсутствии состояния получает и проверяет prekey bundle, затем инициализирует сессию. Retry доставки — не причина заново устанавливать криптографическую сессию.

В конверте ciphertext и iv отделены от protocolMetadata. clientMessageId обозначает логическую отправку; tempId связывает локальную исходящую запись с ответом. Повтор должен перевозить подготовленный пакет, а не незаметно создавать новое сообщение.

На сервере createOrMergeSenderChatMessage ищет запись в контексте chatId, senderId и clientMessageId. Если ciphertext и iv совпали, возвращает существующее сообщение и объединяет допустимые метаданные. Если нет — CLIENT_MESSAGE_ID_CONFLICT. Иначе повтор мог бы стать скрытым редактированием.

Важная оговорка: find-then-create сам по себе не доказывает атомарную защиту от двух конкурентных вставок. Для строгой гарантии нужен отдельно подтверждённый механизм хранения. Я не называю последовательную проверку универсальным exactly-once.

У REST и Socket.IO общий контракт new_message. Это помогает не терять метаданные при смене пути доставки. При этом создание серверной записи, deliveredAt и readAt — разные факты: ACK отправителю не доказывает прочтение адресатом.

После возвращения основного маршрута история проходит merge. Серверная запись и mesh placeholder могут представлять одну отправку. Старый пакет не должен побеждать только потому, что пришёл последним; удаление и свежесть правок требуют отдельных правил.

И ещё одна граница: восстановить ciphertext из истории не значит восстановить утраченный ratchet state.

Что взять себе: сохранять идентичность retry, явно обрабатывать конфликт, проверять конкурентную идемпотентность и согласовать realtime с историей.

В полной статье — поля, псевдокод и последовательность переходов. Я проектирую такие протоколы и для клиентских продуктов.

https://arhellist.ru/blog/put-soobscheniya-ot-shifrovaniya-do-istorii/

Путь сообщения: от шифрования до истории | Сетка — социальная сеть от hh.ru