Files
rust-xmpp/docs/MUC-RECOVERY.md
T
wt 7f60661eef - MUC сохраняет согласованный журнал конфигурации, affiliations, nick,
ролей,
  членства и ограниченной истории без MAM. Изменение фиксируется до
  публикации
  ответа; при ошибке записи состояние комнаты откатывается.
- Crash recovery использует последнее сохранённое поколение после
  SIGKILL,
  включая временные комнаты. Heartbeat обновляет живое членство;
  ожидающие записи сохраняют исходный deadline через повторные
  перезапуски.
  `muc_recovery_grace_period`: по умолчанию 300 секунд, пределы
  1..604800.
- Подтверждённые выходы, смена nick, ролей и политик комнаты не
  заменяются
  старой записью восстановления. Native config/state остаются экспортом
  для
  Prosody; согласованное восстановление Rust использует собственный
  sidecar.
- Исправлены MUC probe, неизвестные типы presence, вход без MUC `<x/>`,
  ошибки
  доставки и статус 333. Обычные presence extensions сохраняются в живом
  обмене; поддельная MUC identity фильтруется. `subject` вместе с `body`
  либо
  `thread` не изменяет тему комнаты.
- Подключены `muc_max_rooms`, `restrict_room_creation`, политики
  регистрации
  и зарегистрированного nick, `muc_tombstone_expiry`; добавлены
  встроенные
  административные ad-hoc команды уничтожения комнат и изменения
  affiliation.
- Hub сохраняет resumable XEP-0198 сессии, счётчики и очередь. Resume
  после
  перезапуска доступен на новом TLS/SASL-транспорте через legacy SASL и
  SASL2.
  Действующие приватные SM-записи восстанавливают логические сессии и
  MUC
  до открытия listeners: offline-доставка попадает в очередь,
  синтетический
  join и история повторно не отправляются. SM resume не требует
  дополнительной
  available presence; без SM восстановление MUC требует новой
  аутентификации
  точного полного JID и available presence либо явного MUC-входа.
  Входящий handled-счётчик обновляется после обработки. Сокеты TCP/TLS
  не сохраняются; неопределённая сетевая отправка допускает повторную
  доставку.
- Известные встроенные MUC-возможности Prosody отображаются на
  Rust-реализацию.
  Произвольные Lua/community-модули не исполняются; неизвестные явно
  включённые
  MUC-модули отклоняются при запуске. Общие и host `modules_disabled`
  учитываются
  для vCard и occupant-id.

Порядок восстановления, ограничения хранения и отката на Prosody:
[docs/MUC-RECOVERY.md](docs/MUC-RECOVERY.md).

Проверка: 293 Rust tests, Clippy/fmt/release, полный сетевой прогон, 500
TLS
MUC+SM ресурсов с SIGKILL/resume и native reference — успешно.
Подробности: [docs/VALIDATION-0.8.0.md](docs/VALIDATION-0.8.0.md).
2026-10-20 17:34:43 +07:00

13 KiB
Raw Blame History

MUC: протокол и восстановление 0.8.0

Реализация сопоставлена с предоставленной Prosody cafd74b9c5ea, прежде всего plugins/muc и mod_muc_mam.lua. Известные встроенные возможности перенесены в Rust; произвольный Lua-код и community-модули Prosody не исполняются. Неизвестный явно включённый MUC-модуль отклоняется при запуске, а не молча игнорируется. Список modules_disabled применяется с учётом общих и host-настроек, в том числе для muc_vcard и muc_occupant_id.

Что сохраняется

MUC теперь записывает единый журнал компонента rust_muc_checkpoint: конфигурацию комнат, affiliations, текущие nick и роли участников, безопасные поля presence и ограниченную историю обсуждения. Это относится к persistent и временным комнатам и работает без MAM. Журнал содержит согласованное поколение состояния; запись через временный файл, синхронизацию и rename предшествует возврату результата операции и публикации соответствующих MUC-ответов. При ошибке сохранения изменение состояния комнаты откатывается в памяти.

Сохранение выполняется при изменениях членства, конфигурации, affiliations, ролей и истории, а также при штатной остановке. Поэтому восстановление больше не зависит только от SIGTERM: после SIGKILL используется последнее успешно зафиксированное поколение. Heartbeat обновляет отметки живых участников даже в тихой комнате. Неудачный heartbeat фиксируется в журнале сервера; состояние, которое не удалось сохранить, нельзя считать защищённым от следующего сбоя.

Обычная история без MAM сохраняет порядок, время сообщений и ограничения maxstanzas, maxchars, seconds, since; subject хранится отдельно в конфигурации комнаты. MAM остаётся самостоятельным архивом и не превращается в часть одной транзакции со всеми внешними эффектами. Presence-события MAM и groupchat-запросы остаются раздельными.

Возвращение участников

Без сохранённой SM-сессии после запуска членство становится ожидающей записью, а не активным адресатом маршрутизации. Автоматический MUC-вход возможен после новой аутентификации, bind того же полного JID и общей available presence. Bare JID или чужой resource не заменяют эту проверку. Обычный явный вход с MUC <x/> тоже доступен; актуальные ограничения комнаты проверяются повторно.

Срок ожидания задаёт muc_recovery_grace_period в секундах: по умолчанию 300, диапазон 1..604800 (значения ограничиваются этими пределами). Живое членство получает свежую отметку при фиксации и heartbeat. Уже ожидающая запись имеет фиксированный срок: запросы, неудачные попытки и повторные перезапуски его не продлевают. Неактивированные временные комнаты удаляются после истечения срока.

Смена пароля, affiliations или иной конфигурации отменяет старые ожидающие разрешения. Подтверждённые изменения роли, явный выход и удаление комнаты попадают в журнал до ответа, поэтому следующая авария не должна возвращать предыдущую роль или прежний nick. Успешное восстановление создаёт текущее членство: при следующей аварии восстанавливается его последняя сохранённая версия, а не навсегда погашенная старая запись.

В checkpoint presence входят только show, status, priority. MUC-пароли и произвольные расширения presence туда не копируются. При живом обмене обычные caps, avatar и idle сохраняются; присланные клиентом MUC identity, occupant-id и hats фильтруются. Пароль комнаты остаётся в её конфигурации.

Если имеется действующая приватная SM-запись Rust, логическая сессия продолжает членство без транспорта. При запуске повторно проверяются наличие и состояние аккаунта и текущие ограничения комнаты. Маршрутизация восстанавливается до приёма клиентов: сообщения для ещё не подключившегося участника попадают в его сохранённую SM-очередь. Синтетические join presence и история повторно не отправляются. Доставка по сети требует новой TLS/SASL-аутентификации и корректного SM-токена того же владельца; native MUC-файлы сами по себе этого не разрешают.

Native-файлы и переход между серверами

Native config, persistent index и state/<roomnode>.dat читаются и экспортируются для совместимости с Prosody. При работе Rust источником согласованного восстановления служит его журнал, а native-файлы являются экспортом после commit. Устаревший экспорт после сбоя не должен возвращать предыдущее членство. Native state без подтверждающих Rust-метаданных сам по себе не разрешает автоматический вход.

Редактирование native-конфигурации администратором обнаруживается по отпечатку: старые разрешения восстановления и история, привязанная к прежней политике, отбрасываются; удаление ранее экспортированной конфигурации отменяет её восстановление. Это не универсальное слияние параллельных записей двух серверов.

Для отката на Prosody остановите Rust и сохраните резервную копию всего data_path. Prosody использует native-экспорт и не читает Rust-журнал. Перед возвратом с Prosody на Rust согласуйте данные и устраните устаревший rust_muc_checkpoint в остановленном экземпляре: иначе неизменившиеся native файлы могут быть приняты за экспорт предыдущего поколения Rust. Удаление журнала означает отказ от его crash recovery, включая историю временных комнат. Не запускайте оба сервера с общей записываемой директорией.

Поддерживаемые политики

  • Доступны hats из affiliation data, язык комнаты, роли presence broadcast, политики PM и модераторских PM, формы конфигурации и offline affiliation presence.
  • muc_vcard и muc_occupant_id управляют соответствующими возможностями. MAM учитывает muc_log_all_rooms, muc_log_presences, muc_log_include_total.
  • restrict_room_creation: false разрешает создание по умолчанию, true ограничивает его настроенными администраторами, "local" — локальными зарегистрированными пользователями и администраторами. muc_max_rooms ограничивает число комнат; существующее членство не требует повторного разрешения на создание.
  • Регистрация учитывает allow_unaffiliated_register, enforce_registered_nickname, muc_registration_include_form. Срок tombstone задаёт muc_tombstone_expiry (по умолчанию 31 день).
  • Администраторам компонента доступны ad-hoc команды http://prosody.im/protocol/muc#destroy и http://prosody.im/protocol/muc#set-affiliation. Полномочия проверяются на каждом шаге; изменения проходят обычный механизм фиксации MUC.

Presence probe не создаёт участника и возвращает сведения только допущенному участнику. Новый вход без MUC <x/> отклоняется; неизвестные типы presence не превращаются во вход. Presence errors исключают соответствующую сессию; message errors делают это для native-набора ошибок доставки. Последняя сессия получает статус 333; остальные ошибки приватного сообщения могут быть переданы адресату. Сообщение с subject и body либо thread остаётся обычным сообщением и не меняет тему комнаты.

Границы и проверка

Старые TCP/TLS-сокеты после остановки процесса не существуют. Восстановление членства MUC и XEP-0198 resume — отдельные механизмы. В 0.8.0 Hub сохраняет resumable SM-сессии, счётчики и очередь неподтверждённых stanza. Resume проходит на новом защищённом аутентифицированном транспорте, включая legacy SASL и SASL2; успешный SM resume восстанавливает MUC без дополнительной available presence. Входящая stanza учитывается в handled-счётчике после обработки. Heartbeat и штатная остановка сохраняют снимок; offline deadline не продлевается простыми проверками или повторными запусками.

SM-снимок приватный: предел 256 MiB суммарно, 8 MiB и 4096 stanza на сессию. Он не является native-форматом Prosody. Нельзя обещать сохранение сокета или ровно одну доставку при неопределённом результате сетевой отправки.

Буфер истории ограничен max_history_messages (по умолчанию 100, предел 4096), состояние комнаты — 4096 ресурсами. Большие необязательные поля presence исключаются из checkpoint; отдельные сообщения истории больше 16 KiB не восстанавливаются. Общий checkpoint компонента ограничен 16 MiB: превышение лимита приводит к ошибке записи, а не к успешному подтверждению несохранённого изменения. Долговечность предполагает исправный диск и файловую систему, соблюдающую синхронизацию записи.

Команды и результаты проверки версии 0.8.0 публикуются в VALIDATION-0.8.0.md. Полный прогон завершён успешно. Общие границы совместимости: COMPATIBILITY.md.