# 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 `` тоже доступен; актуальные ограничения комнаты проверяются повторно. Срок ожидания задаёт `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/.dat` читаются и экспортируются для совместимости с Prosody. При работе Rust источником согласованного восстановления служит его журнал, а native-файлы являются экспортом после commit. Устаревший экспорт после сбоя не должен возвращать предыдущее членство. Native state без подтверждающих Rust-метаданных сам по себе не разрешает автоматический вход. Редактирование native-конфигурации администратором обнаруживается по отпечатку: старые разрешения восстановления и история, привязанная к прежней политике, отбрасываются; удаление ранее экспортированной конфигурации отменяет её восстановление. Это не универсальное слияние параллельных записей двух серверов. Для отката на Prosody остановите Rust и сохраните резервную копию всего `data_path`. Начиная с0.8.3 перед сменой writer выполните новым binary `rust-xmpp storage-checkpoint CONFIG`: он фиксирует MAM redo и SM JSON exports. Это не перенос Rust SM-сессий в Prosody и не универсальная конверсия MUC journal. Подробности — [DURABLE-MESSAGE-IO.md](DURABLE-MESSAGE-IO.md). 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 `` отклоняется; неизвестные типы 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](VALIDATION-0.8.0.md). Полный прогон завершён успешно. Общие границы совместимости: [COMPATIBILITY.md](COMPATIBILITY.md).