Этап 3: TOFU и комнаты — ключ комнаты, атомарный rekey, участники
Сервер: комнаты, состав и завёрнутые ключи; смена состава и rekey одним атомарным запросом с проверкой keys[].to против итогового состава; обрезка до двух последних ключей; передача владения по joined_at; события room каждому со своим ключом и room_left удалённым; членство и keyId в проверках сообщения; миграция 002. Клиент: TOFU на всех путях, по которым публичный ключ доходит до клиента; предупреждение о смене ключа с блокировкой отправки и повторной расшифровкой сохранённого raw; заворачивание и разворачивание ключей комнаты, включая себе — тем же кодом, без ветвления; расшифровка любым известным keyId; экраны участников, создание комнаты, карточка контакта с двумя отпечатками. ADR-037: roomId генерирует клиент. crypto.md вплетает roomId в заворачивание, а оно происходит до запроса — создатель обязан привязать ключ к идентификатору, которого по прежнему протоколу ещё не существовало. ADR-039: завёрнутый ключ принимается только от участника. Иначе сервер подставляет ключ, завёрнутый посторонним аккаунтом, TOFU молчит — ник незнакомый, первый ключ запоминается молча, — и комната уезжает на ключ сервера. Одно подменённое поле в ответе, без сговора и подмены кода. ADR-041: долг по rekey — состояние комнаты, а не свойство события. Владелец, офлайн в момент выхода участника, не узнавал о долге никогда, и комната навсегда оставалась на ключе, который вышедший знает. ADR-038, 040, 042, 043, 044: тексты экранов комнат, снятие pending при возврате прежнего ключа, порядок ключей, форма раньше прав, экран покинутой комнаты. Приёмка на боевом: комната на троих, добавленный четвёртый читает только новое, вышедший после rekey новых не получает и писать не может, keys_mismatch, key_exists, not_owner, owner, room_conflict, чужой X-Device. Подмена public_key в базе даёт у собеседника предупреждение и блокирует отправку — проверено в Chrome. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DbCjVfTFq4ZFG8juD45YJ
This commit is contained in:
+10
-4
@@ -256,13 +256,19 @@ func (s *server) deleteMe(w http.ResponseWriter, r *http.Request) {
|
||||
if !s.confirm(w, in.AuthKey, u) {
|
||||
return
|
||||
}
|
||||
// Устройства, сессии, контакты, членство и очереди уносит каскад.
|
||||
// Комнаты, где пользователь владелец, требуют передачи владения
|
||||
// (ADR-018) — это этап 3, до появления комнат случай не наступает.
|
||||
if err := s.st.DeleteUser(r.Context(), u.Nick); err != nil {
|
||||
// Устройства, сессии, контакты, членство, ключи комнат и очереди уносит
|
||||
// каскад; комнаты, где пользователь владелец, меняют владельца или
|
||||
// удаляются пустыми (ADR-018) — всё в одной транзакции хранилища.
|
||||
changes, err := s.st.DeleteUser(r.Context(), u.Nick)
|
||||
if err != nil {
|
||||
s.internal(w, r, err)
|
||||
return
|
||||
}
|
||||
// Удаление аккаунта — выход из всех его комнат: оставшимся уходит room
|
||||
// с needsRekey, каждому со своим ключом (ADR-041).
|
||||
for _, change := range changes {
|
||||
s.sendRoom(r, change, "")
|
||||
}
|
||||
auth.ClearCookie(w)
|
||||
noContent(w)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user