ролей, членства и ограниченной истории без 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).
143 lines
13 KiB
Markdown
143 lines
13 KiB
Markdown
# 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](VALIDATION-0.8.0.md). Полный прогон завершён успешно. Общие границы совместимости:
|
||
[COMPATIBILITY.md](COMPATIBILITY.md).
|