fix(sync): resolve $ME and $LAZY state keys in sliding sync required_state #1690

Closed
Reaster wants to merge 2 commits from Reaster/continuwuity:Sync--$ME-and-$LAZY into main
First-time contributor

Summary

collect_required_state in src/api/client/sync/v5.rs currently only
expands the * wildcard when building a sliding sync response. The
$ME and $LAZY sentinel values defined by MSC3575 are passed
through as literal state keys, so the subsequent room_state_get
lookups always miss.

This breaks clients built on the Matrix Rust SDK (most notably
Element X iOS / Android), which rely on $ME to fetch the current
user's push rules during sync. When the lookup fails the client falls
back to silent notifications.

Closes #1661. Related: #1533, #1424,
element-hq/element-x-ios#5132.

Changes

  • collect_required_state now also takes sender_user and the
    room's timeline_pdus.
  • $ME → replaced by sender_user.as_str() before the state lookup.
  • $LAZY (only meaningful for m.room.member) → expanded to the
    member events of every user that sent a timeline event plus the
    target of every m.room.member event in the timeline, matching the
    behaviour of Synapse and Tuwunel.
  • The literal "$LAZY" key is no longer looked up directly; it would
    always return Err.
  • A small fetched set de-duplicates events so an explicit member
    key combined with $LAZY, or with an earlier * expansion, does
    not push the same event twice.
  • $LAZY is skipped when m.room.member has already been wildcard-
    expanded in the same request.

The control flow was reshaped from if / else if to a match on the
state key for readability, but the * branch and the default branch
behave exactly as before.

Non-goals

  • The lazy_members: true boolean from the RoomSubscription schema
    is still not implemented. Only the $LAZY sentinel in
    required_state is handled here. Left for a follow-up.

Testing

  • Local build via docker compose build conduwuit against the
    bundled Dockerfile.
  • Manually verified with Element X iOS that push rules are now
    delivered on initial sync and that notifications produce sound /
    vibration again.
  • Existing sliding sync flows (wildcard expansion, explicit state
    keys) are unchanged — covered by the existing Complement suite.

Reference

The resolution logic mirrors Tuwunel's
src/api/client/sync/v5/rooms.rs (lines ~150-260),
adapted to continuwuity's non-stream loop style.

Changelog entry — add file changelog.d/<PR_NUMBER>.bugfix (replace number after MR created):

Resolve $ME and $LAZY sentinels in sliding sync required_state, fixing push-rule loading for Element X and other Matrix Rust SDK
clients.

## Summary `collect_required_state` in `src/api/client/sync/v5.rs` currently only expands the `*` wildcard when building a sliding sync response. The `$ME` and `$LAZY` sentinel values defined by [MSC3575] are passed through as literal state keys, so the subsequent `room_state_get` lookups always miss. This breaks clients built on the Matrix Rust SDK (most notably Element X iOS / Android), which rely on `$ME` to fetch the current user's push rules during sync. When the lookup fails the client falls back to silent notifications. Closes #1661. Related: #1533, #1424, element-hq/element-x-ios#5132. ## Changes - `collect_required_state` now also takes `sender_user` and the room's `timeline_pdus`. - `$ME` → replaced by `sender_user.as_str()` before the state lookup. - `$LAZY` (only meaningful for `m.room.member`) → expanded to the member events of every user that sent a timeline event plus the target of every `m.room.member` event in the timeline, matching the behaviour of Synapse and Tuwunel. - The literal `"$LAZY"` key is no longer looked up directly; it would always return `Err`. - A small `fetched` set de-duplicates events so an explicit member key combined with `$LAZY`, or with an earlier `*` expansion, does not push the same event twice. - `$LAZY` is skipped when `m.room.member` has already been wildcard- expanded in the same request. The control flow was reshaped from `if / else if` to a `match` on the state key for readability, but the `*` branch and the default branch behave exactly as before. ## Non-goals - The `lazy_members: true` boolean from the `RoomSubscription` schema is still not implemented. Only the `$LAZY` sentinel in `required_state` is handled here. Left for a follow-up. ## Testing - Local build via `docker compose build conduwuit` against the bundled Dockerfile. - Manually verified with Element X iOS that push rules are now delivered on initial sync and that notifications produce sound / vibration again. - Existing sliding sync flows (wildcard expansion, explicit state keys) are unchanged — covered by the existing Complement suite. ## Reference The resolution logic mirrors Tuwunel's [`src/api/client/sync/v5/rooms.rs`][tuwunel] (lines ~150-260), adapted to continuwuity's non-stream loop style. [MSC3575]: https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3575-sync.md [tuwunel]: https://github.com/matrix-construct/tuwunel/blob/main/src/api/client/sync/v5/rooms.rs Changelog entry — add file changelog.d/<PR_NUMBER>.bugfix (replace number after MR created): Resolve `$ME` and `$LAZY` sentinels in sliding sync `required_state`, fixing push-rule loading for Element X and other Matrix Rust SDK clients.
Reaster force-pushed Sync--$ME-and-$LAZY from a0e4efe1d1
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 30s
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
to 5b6d65b87c
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 8s
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m49s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 7m0s
2026-04-21 09:57:48 +00:00
Compare
Reaster force-pushed Sync--$ME-and-$LAZY from 5b6d65b87c
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 8s
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m49s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 7m0s
to bf82c07a44
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 32s
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
2026-04-27 13:41:15 +00:00
Compare
Reaster force-pushed Sync--$ME-and-$LAZY from bf82c07a44
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 32s
Documentation / Build and Deploy Documentation (pull_request) Has been cancelled
Checks / Prek / Pre-commit & Formatting (pull_request) Has been cancelled
Checks / Prek / Check changed files (pull_request) Has been cancelled
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
to 490ac05dfe
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 14s
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 2m13s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 8m10s
2026-05-03 15:09:49 +00:00
Compare
Member

RE #1661, I don't think this is wanted, as its not in current SSS spec, and therefore not a Continuwuity issue. Feel free to leave a comment if I am incorrect, just cleaning stuff up.

RE #1661, I don't think this is wanted, as its not in current SSS spec, and therefore not a Continuwuity issue. Feel free to leave a comment if I am incorrect, just cleaning stuff up.
Henry-Hiles closed this pull request 2026-05-10 01:36:59 +00:00
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 14s
Required
Details
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Check changed files (pull_request) Successful in 6s
Required
Details
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 2m13s
Required
Details
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 8m10s
Required
Details

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
continuwuation/continuwuity!1690
No description provided.