wt 100005379b
Test, build and publish / All tests and Linux binary (push) Failing after 26s
Test, build and publish / Container smoke test and Gitea publish (push) Skipped
MAM archive storage fault must not drop live message delivery
Monal-iOS reconnect-looped with connection-closed reason=
protocol-or-transport-error on every message. The cause was a damaged
MAM archive redo baseline ('archive redo baseline changed in place'): the
native archive at data/<host>/archive/<user>.list no longer matched the
anchor recorded in its .rredo journal, so every archive_for_user() call
returned Err and the '?' propagated up through authenticated_transport,
turning a storage fault into a dropped session.

Delivery is an attribute of MAM, not a prerequisite. Make archival
best-effort at the three inbound/outbound message sites (sender,
recipient, incoming federation): on storage failure the original stanza
is still routed, both sessions stay alive, and a sanitized
'mam-archive-skipped' log is emitted instead of a connection-closed.

Offline storage-checkpoint now repairs the damaged journal: prepare_rewrite
detects an untrusted baseline (changed in place, shorter, missing, or
journal overflows bound), treats the durably synced native as authoritative
and retires the untrusted journal, so MAM history reads and future appends
work again after handoff. Live appends remain fail-closed (the journal is
preserved, never silently dropped).

Tests: redo_rewrite_tests::runtime_append_fails_closed... and
offline_checkpoint_retires_untrusted_redo_baseline; new network regression
mam_broken_baseline_network.py proves message delivery and both sessions
survive a broken baseline and that storage-checkpoint restores MAM reads.
2026-10-21 18:52:53 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 17:41:56 +07:00
2026-10-20 15:59:55 +07:00
2026-10-20 15:59:55 +07:00

Rust XMPP 0.8.3

Сервер на Rust, разрабатываемый для замены Prosody 13.0 nightly 100, cafd74b9c5ea с предоставленными модулями. Читает существующий Lua-конфиг, а также JSON, YAML/YML и TOML. Использует внутреннее файловое хранилище Prosody: конвертация аккаунтов и истории для проверенных сценариев не нужна. Nginx не требуется: HTTPS, WebSocket, BOSH и загрузка файлов обслуживаются самим сервером; coturn остаётся отдельным сервисом.

Это работающая экспериментальная реализация, полная взаимозаменяемость ещё не достигнута. Уже реализованы вход, сообщения, контакты, MAM, MUC, PEP/pubsub, закладки, offline, carbons, SM, push, TLS-федерация и HTTP. Точные ограничения перечислены в docs/COMPATIBILITY.md, проверки — в docs/VALIDATION.md.

Нестандартные HTTP-пути и TLS reverse proxy: docs/HTTP-PROXY.md. Пример для слияния с действующим конфигом: examples/reverse-proxy.fragment.yaml.

MUC и восстановление после сбоя, включая SM resume: docs/MUC-RECOVERY.md. Изменения 0.8.0: CHANGELOG-0.8.0.md.

Встроенный http_altconnect: docs/HTTP-ALTCONNECT.md.

Сборка и изолированный запуск

Нужны Rust 1.99.1 (rustup установит версию из rust-toolchain.toml), C-компилятор и make. Для тестовых сертификатов и сетевых проверок нужны OpenSSL CLI, Bash и Python 3; HTTP-тест дополнительно использует Python websockets. Системные CA-сертификаты нужны для проверки удалённых серверов федерации. Cargo.lock фиксирует зависимости; первая сборка требует их загрузки.

cd rust-xmpp
cargo build --release --locked
bash scripts/make-demo.sh
./target/release/rust-xmpp serve demo/config.toml --experimental

Demo слушает только 127.0.0.1:55222 и создаёт отдельное хранилище demo/data. Аккаунты: alice@localhost / alice-test-only и bob@localhost / bob-test-only. Для ручного клиента используйте STARTTLS и доверьте сгенерированному demo/cert.pem. make-demo.sh не перезаписывает существующий demo. Сертификаты и аккаунты в исходный архив не включены.

Существующий конфиг без редактирования

./target/release/rust-xmpp check-config /etc/prosody/prosody.cfg.lua
./target/release/rust-xmpp serve /etc/prosody/prosody.cfg.lua --experimental

check-config проверяет разбор и базовые типы; ограничения runtime проверяются при serve. Существующий Lua-файл читается непосредственно, преобразовывать его в другой формат не требуется. Процессу нужны права на сертификат, ключ, каталог данных и Unix admin socket. Используйте тот же UID/GID, что и Prosody, чтобы сохранять доступ при возврате к нему.

Первую проверку выполняйте на копии данных с отдельными портами: сервер пишет аккаунты, историю, комнаты и другие данные в обычном режиме. Одновременно запускать Rust и Prosody с одним каталогом данных нельзя. Между экземплярами Rust действует блокировка inode каталога данных, в том числе при разных портах и путях-синонимах. Prosody в этой блокировке не участвует. Команда create-user также отказывается писать в каталог работающего Rust-сервера; для изменения аккаунтов во время работы используйте admin shell. Для переключения остановите один процесс и запустите другой. Резервная копия нужна для проверки отката до переключения рабочего сервера; тестирование формата не доказывает совместимость всех ваших записей.

Ваш Docker Compose

Распакуйте каталог rust-xmpp рядом с исходным docker-compose.yml. Дополнительный файл заменяет образ только сервиса prosody. Порты, тома, healthcheck prosodyctl check и сервис coturn наследуются из исходного файла.

docker compose -f docker-compose.yml -f rust-xmpp/compose.override.yml config
docker compose -f docker-compose.yml -f rust-xmpp/compose.override.yml up -d --build prosody

Эта команда запускает сервер на томах из исходного Compose; применяйте её после проверки на копии. Исходные docker-compose.yml и prosody.cfg.lua редактировать не требуется. Образ содержит CA-сертификаты и команду prosodyctl, совместимую с указанным healthcheck. Это проверка ответа работающего процесса через admin socket, а не полный аналог диагностики prosodyctl check.

Entrypoint определяет UID/GID владельца /var/lib/prosody и запускает процесс с этими правами, не меняя рекурсивно владельцев существующих файлов. Если каталог принадлежит root, а файлы внутри другому UID, задайте XMPP_UID и XMPP_GID в окружении контейнера через дополнительный Compose-файл. При другом пути данных задайте также XMPP_DATA_DIR. Выбранный пользователь должен читать TLS-ключ и писать данные. Docker-образ в среде разработки не собирался: здесь нет Docker; состав образа и override подготовлены, но запуск на целевом Docker ещё предстоит проверить.

Форматы конфигурации

Все форматы используют одну структуру: global и hosts; у хоста есть options и, для компонента, component. Надёжнее получить её из Lua:

./target/release/rust-xmpp convert /etc/prosody/prosody.cfg.lua json config.json
./target/release/rust-xmpp convert /etc/prosody/prosody.cfg.lua yaml config.yml
./target/release/rust-xmpp convert /etc/prosody/prosody.cfg.lua toml config.toml
./target/release/rust-xmpp check-config config.yml

Конвертер сохраняет области настроек и Include, не меняет исходный файл, не перезаписывает существующий выходной и создаёт его с правами 0600. Выходной файл содержит секреты конфигурации. Lua выполняется в ограниченной VM без системных библиотек; произвольные Lua-плагины не исполняются. Поддержка Lua в проекте также нужна для точного чтения файлов данных Prosody.

Команды и проверки

Полный локальный прогон: bash scripts/verify-local.sh. XMPP_LOAD_CHECK=1 добавляет нагрузочный сценарий; настройки native Prosody для дополнительных проверок описаны в scripts/prosody_compat/README.md.

cargo test --locked
cargo clippy --locked --all-targets -- -D warnings
cargo build --release --locked
python3 scripts/smoke.py                    # после make-demo.sh
python3 scripts/integration_xmpp.py
python3 tests/sasl_network.py --spawn --hash sha1
python3 tests/sasl_network.py --spawn --hash sha256
python3 tests/sasl2_bind.py target/release/rust-xmpp
python3 scripts/integration_http.py         # требует websockets
python3 scripts/load_smoke.py --clients 500 --accounts 100 --rounds 10 --message-rounds 10 --archive

Все сетевые тесты создают отдельные тестовые данные; кроме smoke с портом 55222, выбирают свободные loopback-порты. Оригинальная Prosody отдельно проверяет формат данных и пароли: инструкции в scripts/prosody_compat/README.md.

./target/release/rust-xmpp create-user CONFIG USER --password-stdin
./target/release/rust-xmpp check [CONFIG]
./target/release/rust-xmpp shell CONFIG 'server:status()'

Пароль create-user принимает через stdin; существующий аккаунт не заменяет. Admin shell реализует ограниченный набор команд управления сервером и аккаунтами. Произвольный Lua-код и горячая перезагрузка модулей не поддержаны.

Дополнительный SASL2 Bind2

Модуль sasl2_bind2 (alias bind2) включает привязку ресурса внутри SASL2, inline SM/CSI/Carbons и MAM metadata. Добавьте его в modules_enabled вместе с sasl2 только если эта функция нужна. Исходный конфиг по-прежнему работает без включения нового модуля. Ресурс генерируется случайно; прежние соединения того же аккаунта с тем же валидным UUIDv4 user-agent завершаются после успешного входа. Inline возобновление SM через SASL2 поддерживается, в том числе после перезапуска при наличии действующей сохранённой SM-сессии.

PEP, push и pre-authenticated roster

В 0.5.0 исправлены ответы disco для bare JID аккаунта. При включённых pep и cloud_notify (они уже есть в предоставленном конфиге) изменение конфига не требуется. После обновления переподключите аккаунт в клиенте, чтобы повторить service discovery. Push требует также настройки клиентского push-сервиса; реальный APNs/FCM шлюз здесь не имитируется.

При включённом roster клиент может обнаружить и вызвать контактную ad-hoc команду urn:xmpp:invite#invite на серверном JID. Она возвращает xmpp:…?roster;preauth=… и срок действия. Регистрацию аккаунта такое приглашение не разрешает. XEP-0379 presence tokens сохраняются даже для неизвестных серверу приглашений, созданных самим клиентом.

Переподключение в 0.6.0

Повторная привязка одного ресурса по умолчанию заменяет старое соединение, как в Prosody. conflict_resolve поддерживает kick_old, kick_new, increment и random. Если явно задан kick_new, занятый ресурс по-прежнему получит protocol conflict — это выбранная политика.

SM восстанавливается при гонке со старым TCP и внутри SASL2. Исправлено освобождение ресурсов при BOSH/WebSocket close. Подробности: CHANGELOG-0.6.0.md.

Android SASL в 0.6.1

Добавлен tls-server-end-point для TLS1.2/1.3 и исправлена SSDP-проверка соединений WebSocket без channel binding. Причина воспроизводимого not-authorized в Conversations, область тестирования и ограничения описаны в CHANGELOG-0.6.1.md и docs/ANDROID-SASL.md.

Логирование в 0.7.0

Добавлены журнал TLS/SASL/bind/SM с единым connection ID, точные причины отказов, файлы/console, JSON/plain и SIGHUP rotation reopen. Для диагностики Conversations/monocles используйте docs/LOGGING.md.

Исправления 0.7.5

Cached SASL2 Bind2/SM requests допускают legacy fallback, XEP-0258/0077 объявляются для Gajim; policy/classifications схема может использоваться как каталог labels. Дубликаты одинаковых log destinations устранены. Подробности — CHANGELOG-0.7.5.md.

HTTP Upload в 0.7.9

Несколько upload components с разными HTTP hosts или mounts и S3-compatible gateway с multipart streaming описаны в docs/HTTP-UPLOAD.md. Добавлены offline миграция с SHA-256/resume, точечная очистка multipart и карантин неопределённого completion. Реальные 10 GiB через MinIO проверены с описанной адаптацией тестовой среды. Изменения и границы подтверждения — CHANGELOG-0.7.9.md.

MUC и SM после сбоя в 0.8.0

MUC фиксирует конфигурацию, роли, членство и ограниченную историю без MAM до публикации соответствующего ответа. Последний сохранённый журнал позволяет восстановить persistent и временные комнаты после аварийной остановки. Heartbeat обновляет живое состояние; срок уже ожидающего восстановления не продлевается повторным запуском. muc_recovery_grace_period задаётся в секундах: по умолчанию 300, пределы 1..604800.

Действующие приватные SM-записи восстанавливают логические сессии и MUC до открытия listeners, поэтому offline-доставка может попасть в сохранённую очередь. XEP-0198 resume через legacy SASL или SASL2 требует нового TLS/SASL-транспорта и токена того же владельца; TCP/TLS-сокеты не сохраняются. Без действующей SM-записи MUC ожидает новую аутентификацию точного полного JID и available presence либо обычный явный MUC-вход.

Native-файлы экспортируются для Prosody; источником согласованного crash recovery Rust служит собственный журнал. Перед откатом ознакомьтесь с порядком переключения. Произвольные community Lua-модули не выполняются; неизвестные явно включённые MUC-модули отклоняются при запуске. Результаты проверки — в docs/VALIDATION-0.8.0.md.

GitHub Actions и Gitea Registry

Полные тесты, Linux binary artifact и Docker push после проверок: настройка workflow. Registry и credentials задаются через GitHub Actions variables/secrets.

Задержка сообщений в0.8.1

Устранены полный проход по MUC-архиву на каждом сообщении, повторные записи неизменённых native-файлов и no-op CSI checkpoints. Проверенный сценарий с100000 MAM-записей: median MUC delivery2.5с→4.7мс на loopback. Причины, измерения и границы.

Личные сообщения в0.8.2

Push routing больше не блокирует отправителя/SM ACK; CSI defaults немедленно передают bodyless OMEMO и receipts. Bind2/MAM metadata не сканируют всю историю. Причины, тесты и конфигурация.

Durable IO личных сообщений в0.8.3

Сокращены последовательные sync MAM/SM через checksummed redo journals, добавлены замеры этапов медленной обработки и crash/replay проверки. Перед передачей файлов Prosody/откатом выполните offline storage-checkpoint. Durability, команда handoff и диагностика.

S
Description
No description provided
Readme MIT
2.6 MiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 77.9%
Python 20.5%
Lua 1.1%
Shell 0.4%