Skip to content

refactor(matrix): migrate from matrix-nio to mautrix-python - #27095

Closed
Master-Rensei wants to merge 9 commits into
NousResearch:mainfrom
Master-Rensei:feat/mautrix-migration
Closed

refactor(matrix): migrate from matrix-nio to mautrix-python#27095
Master-Rensei wants to merge 9 commits into
NousResearch:mainfrom
Master-Rensei:feat/mautrix-migration

Conversation

@Master-Rensei

Copy link
Copy Markdown

Summary

Replaces matrix-nio with mautrix-python as the Matrix SDK dependency, fixing Nix flake build failures caused by matrix-nio's transitive dep atomicwrites (sdist-only, archived, missing build-system metadata).

This reopens closed PR #7488 (by @alt-glitch, closed without merge) with 9 additional fix commits addressing code review findings from the original submission.

What's new since PR #7488 was closed

9 commits by @alt-glitch addressing review feedback:

  1. E2EE crypto store persistence — pickle/store to disk with HMAC-SHA256 signing to prevent tampering
  2. Simplified adapter — deduplicated 40+ lines of mention/thread/DM gating via _resolve_message_context(); consolidated imports; cached env var parsing
  3. Session leak fix — close aiohttp sessions on E2EE dep and setup failure paths
  4. Bot-to-bot loop prevention — ignore m.notice messages (conventional bot response msgtype)
  5. Thread tracking cleanup — removed redundant _track_thread() calls; added sender-self and startup-grace filters to encrypted handler
  6. HMAC-signed pickle store — prevent arbitrary code execution from tampered crypto store files

All original adapter features preserved: E2EE, reactions, threading, mention gating, text batching, media caching, MSC3245 voice messages.

Test plan

  • 157 unit tests passing (pytest tests/gateway/test_matrix*.py tests/test_project_metadata.py)
  • nix flake check passes clean
  • uv lock --check validates lockfile consistency
  • Manual smoke test on a real Matrix homeserver

matrix-nio pulls in peewee -> atomicwrites (sdist-only, archived,
missing build-system metadata) which breaks nix flake builds.
mautrix-python publishes wheels, has a leaner dep tree, and its
[encryption] extra uses the same python-olm without the problematic
transitive chain.
Translate all nio SDK calls to mautrix equivalents while preserving the
adapter structure, business logic, and all features (E2EE, reactions,
threading, mention gating, text batching, media caching, voice MSC3245).

Key changes:
- nio.AsyncClient -> mautrix.client.Client + HTTPAPI + MemoryStateStore
- Manual E2EE key management -> OlmMachine with auto key lifecycle
- isinstance(resp, nio.XxxResponse) -> mautrix returns values directly
- add_event_callback per type -> single ROOM_MESSAGE handler with
  msgtype dispatch
- Room state (member_count, display_name) via async state store lookups
- Upload/download return ContentURI/bytes directly (no wrapper objects)
Rewrite mock infrastructure across three test files:
- test_matrix.py: replace fake nio module with fake mautrix module tree,
  update all client method mocks to new API names and return types
- test_matrix_voice.py: update event construction, download/upload mocks,
  handler invocation (single event arg, no room object)
- test_matrix_mention.py: update mock module, event construction, DM
  detection via _dm_rooms cache instead of room.member_count

157 tests passing.
Address two bugs found by code review:

1. MemoryCryptoStore loses all E2EE keys on restart — now pickle the
   store to disk on disconnect and restore on connect, preserving
   Megolm sessions across restarts.

2. Encrypted events buffered for retry were silently dropped after
   decryption because _on_encrypted_event registered the event ID
   in the dedup set, then _on_room_message rejected it as a
   duplicate. Now clear the dedup entry before routing decrypted
   events.
- Extract _resolve_message_context() to deduplicate ~40 lines of
  mention/thread/DM gating logic between text and media handlers
- Move mautrix.types imports to module level (16 scattered local
  imports consolidated)
- Parse mention/thread env vars once in __init__ instead of per-message
- Cache _is_bot_mentioned() result instead of calling 3x per event
- Consolidate send_emote/send_notice into shared _send_simple_message()
- Use _is_dm_room() in get_chat_info() instead of inline duplication
- Add _CRYPTO_PICKLE_PATH constant (was duplicated in 2 locations)
- Fix fragile event_ts extraction (double getattr, None safety)
- Clean up leaked aiohttp session on auth failure paths
- Remove redundant trailing _track_thread() calls
…kle store

- Add api.session.close() on E2EE dep check and E2EE setup failure
  paths (two missing cleanup points from the mautrix migration)
- Replace raw pickle.load/dump with HMAC-SHA256 signed payloads to
  prevent arbitrary code execution from a tampered store file
The old nio code only handled RoomMessageText (m.text). The mautrix
rewrite dispatched both m.text and m.notice, which would cause infinite
loops between bots since m.notice is the conventional msgtype for bot
responses in the Matrix ecosystem.
… to encrypted handler

- Remove trailing _track_thread() in _resolve_message_context (already
  called in the DM-mention-thread and auto-thread branches)
- Add sender == self check and startup grace period filter to
  _on_encrypted_event so own messages and old initial-sync events
  don't waste buffer space
@Master-Rensei
Master-Rensei requested a review from a team May 16, 2026 19:33
@cardtest15-coder

This comment was marked as spam.

@alt-glitch alt-glitch added type/refactor Code restructuring, no behavior change P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/matrix Matrix adapter (E2EE) area/nix Nix flake, NixOS module, container packaging labels May 16, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #7518 (already merged). This PR reopens a previously closed fork branch, but the feature (matrix mautrix migration) was already landed via a salvage PR.

@Master-Rensei Master-Rensei closed this by deleting the head repository May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/nix Nix flake, NixOS module, container packaging comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/matrix Matrix adapter (E2EE) type/refactor Code restructuring, no behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants