Commit Graph
4288 Commits
Author SHA1 Message Date
Paul Chobert a513adc191 Test private read receipts of non-members in announcement rooms 2026-10-28 18:09:29 +01:00
Paul Chobert aa7ddf8994 Keep read receipts in announcement rooms private to their sender 2026-10-28 18:09:29 +01:00
Paul Chobert c8b2706de2 Test that a non-member's read receipt is not sent to other users 2026-10-28 18:09:29 +01:00
Paul Chobert 5cb675a5c7 Test that a non-member's read receipt reaches their other devices 2026-10-28 17:17:23 +01:00
Paul Chobert ff17c60028 Test that a non-member can send a read receipt in an announcement room 2026-10-28 16:58:14 +01:00
Paul Chobert 638f4ea516 Remove the sliding sync revoked invite test for server announcements
Users are never invited to announcement rooms.
2026-10-28 16:01:30 +01:00
Paul Chobert 4220f9137c Check the server announcement device list test against a regular room
The test only checked that a non-member does not get the announcer's
device change, so it would also pass if the change produced no device
list update at all. A user sharing a regular room with the announcer now
gets that same change in the same test.
2026-10-28 16:01:30 +01:00
Paul Chobert 0567ffba94 Remove the sliding sync unread count test for server announcements
Sliding sync always sends 0 for the notification and highlight counts of every room, so the test could not fail.
2026-10-28 16:01:30 +01:00
Paul Chobert 3294f0e2aa Send server announcement rooms with what they missed while left out
A sender removed before anything was announced gets the synthetic join,
then the room is left out of their lists until the first announcement.
It was dropped from the rooms checked for updates outside the lists, so
the connection kept it as sent up to its last token: when the
announcement listed it again, only that announcement went down and any
change made in between, such as a new room name, was lost.

The rooms left out are now kept among the rooms checked for updates,
without being listed. A change while they are left out marks them as
only partly sent, and they come back with everything since. This reuses
the existing tracking of rooms outside the list ranges, instead of
resending the room from scratch when it is listed again, which would
need its own bookkeeping.
2026-10-28 16:01:30 +01:00
Paul Chobert 2a9475f48c Stop treating a ban like a kick for server announcements in sliding sync
Nobody is banned from an announcement room in practice: senders are
removed from the config, which kicks them. Only a leave now gives way to
the synthetic join again.
2026-10-28 16:01:29 +01:00
Paul Chobert 9530a96772 List server announcement rooms in sliding sync as legacy sync does
An announcement room the user is not a member of is now listed when it
holds an announcement, or when the user left, was kicked or was banned
within the request's window, and otherwise left out. A user removed
before anything was announced no longer gets the room on a new
connection, and a user leaving on their own before any announcement gets
the synthetic join in the same response instead of their leave.

The room is then never sent with the user's real leave, so resending it
from scratch afterwards is no longer needed.
2026-10-28 16:01:29 +01:00
Paul Chobert 51e50b7d0c Treat a ban like a kick for server announcements in sliding sync
A user banned from an announcement room kept their real ban, so they
stopped getting announcements. As in legacy sync, a ban now gives way to
the synthetic join like a kick does, and is left out of `required_state`
and the timeline.
2026-10-28 16:01:29 +01:00
Paul Chobert cae4f60ada Test a member leaving before any server announcement in sliding sync 2026-10-28 16:01:29 +01:00
Paul Chobert 857850bedc Switch removed members to the synthetic join before any announcement
A member removed from the configured senders before anything was
announced got their kick, and the room only came back as joined with the
first announcement. Their room now gets the synthetic join straight away,
at the position of the kick until there is an announcement.

Only kicks count: both paths always keep them in the user's memberships,
while the new tables leave out the user's own past leaves.

Also test that a removed member added back gets their real join and the
power levels that let them post again.
2026-10-28 16:01:29 +01:00
Paul Chobert 169640a46b Switch leaving members straight to the synthetic join in sliding sync
A member who left or was removed from an announcement room first got
their leave, then the synthetic join on the next sync. They now get the
synthetic join instead of their leave in the same sync, as in legacy
sync, once the room has had an announcement. Before that, the leave
still goes down and the room is sent again from scratch later.
2026-10-28 16:01:29 +01:00
Paul Chobert c4130fe15b Test that leaving members get server announcements on the next sliding sync 2026-10-28 16:01:28 +01:00
Paul Chobert bb05d6579a Leave the user's own membership out of server announcement timelines
A timeline reaching back to the user's leave or kick ended with that
membership after the synthetic join in `required_state`, so clients saw
the user as having left. The user's own membership events are now dropped
from the timeline of a server announcement room, as they already are from
its `required_state`.
2026-10-28 16:01:28 +01:00
Paul Chobert a4ef9b36c0 Resend server announcement rooms from scratch after the user leaves
A user who left or was kicked while their connection was open never got
the synthetic join afterwards, since only state changes were sent. When a
response sends the user's new leave in an announcement room, the room is
now recorded as never sent, so its next delivery holds the full
`required_state` with the synthetic join.
2026-10-28 16:01:28 +01:00
Paul Chobert b5fd5083c1 Deliver server announcements to removed members in sliding sync
A user removed from the configured senders is kicked, and both paths
kept the kick as their membership, so they never got the synthetic join.
Only a leave that isn't newly left now gives way to the synthetic join.

On an existing connection, the synthetic join is still not sent after
the kick, as `test_removed_member_existing_connection` shows.
2026-10-28 16:01:28 +01:00
Paul Chobert c9a8974d3d Merge remote-tracking branch 'upstream/barodeur/srv-announcements-sync-legacy' into barodeur/srv-announcements-sync-sliding 2026-10-28 11:12:25 +01:00
Paul Chobert 9e9d613663 Deliver announcement rooms for any new event after their first announcement 2026-10-28 10:42:19 +01:00
Paul Chobert ed314d8022 Test device lists and state_after for announcement rooms 2026-10-28 10:42:19 +01:00
Paul Chobert da93cff424 Deliver announcement rooms whose last announcement is out of the timeline 2026-10-28 10:42:18 +01:00
Paul Chobert 29eb4b5f44 Deliver announcement rooms in the sync that carries the user's leave 2026-10-28 10:42:18 +01:00
Paul Chobert 0b6a20fa1e Deliver announcements to members removed while offline on incremental sync 2026-10-28 10:42:17 +01:00
Paul Chobert f1d933c0e5 Deliver announcements to removed members on initial sync 2026-10-27 17:25:04 +01:00
Paul Chobert 14a30ca064 Strip the user's real membership from announcement room timelines 2026-10-27 17:20:41 +01:00
Paul Chobert 0358d215c1 Test that sliding sync sends no unread counts or device list changes from server announcement rooms 2026-10-27 16:52:33 +01:00
Paul Chobert 86794866dc Deliver server announcements to self-left members in sliding sync fallback
The fallback path kept the self-leave in the membership map, so the
announcement room was skipped and then filtered out of the lists. Only
memberships the lists keep now prevent the synthetic join.

Also test that the room stays in the list, is ordered like the user's
other rooms, and can be subscribed to directly.
2026-10-27 16:52:33 +01:00
Paul Chobert ed34029626 Deliver server announcements to non-members in sliding sync 2026-10-27 16:52:33 +01:00
Paul Chobert ddf8b70388 Test server announcement delivery in legacy sync 2026-10-27 13:57:20 +01:00
Eric Eastwood 4cece59c30 Drop support for Python 3.10 (#20359)
Fix https://github.com/element-hq/synapse/issues/20041

Keywords:

 - `3.10`
 - `py310`
 - `cp310`
2026-10-26 16:26:19 -05:00
Andrew MorganandPaul Chobert b27615282d [Server Announcements] [Create/Configure Rooms] Configure announcement rooms and reconcile them on startup (#20372)
Co-authored-by: Paul Chobert <paul@chobert.fr>
2026-10-26 17:20:04 +00:00
Johannes MarbachandOlivier 'reivilibre 0d28e93a7a Move the sticky events sliding sync extension to the global pos and MSC4508 scoping (#20363)
This includes the following:
    
- Implements ['Implicit Forward
Pagination'](https://github.com/matrix-org/matrix-spec/issues/2378).
Remove the extension's `since` and `next_batch` fields. The position is
now tracked via the global `pos`, with per-room connection state
recording how far each room has been sent so that `limit` paginates
without holding `pos` back and lost responses are re-delivered.
- Discussed in
https://github.com/matrix-org/matrix-spec-proposals/pull/4480#discussion_r4165887827
- Honour the `lists` and `rooms` fields.
- Send all unexpired sticky events when a room enters scope for the
first time or is newly joined, and catch up on events sent while a room
was out of scope when it re-enters.
- Enabling the extension partway through a connection returns all
unexpired sticky events for in-scope rooms, and re-enabling it after
disabling it returns the unexpired sticky events sent in the meantime.

I tried to split this up into standalone commits though the bulk of the
change is in the third commit.

---------

Co-authored-by: Olivier 'reivilibre <git.oo@emunest.net>
2026-10-26 14:02:22 +00:00
Hugh Nimmo-Smith d99e5fe783 Implement transaction IDs for MSC4388 and other updates (sign-in with QR code) (#19906) 2026-10-26 11:56:06 +00:00
7d44c81d5c Fix new state saved with the last local user's leave missing from state_after (#20314)
> [!NOTE]
> This PR will be rebased on `develop` once
https://github.com/element-hq/synapse/pull/20081 is merged

This PR is a follow up to
https://github.com/element-hq/synapse/pull/20081 and is based on its
code.
The scope of that original PR is limited to recovering the leave event
missing from `state_after`.

I noticed that state events from the leave event batch would only be
recovered if they were previously defined.

That made me add a pre-condition to the test: the topic had to be set
first.


https://github.com/element-hq/synapse/blob/bccf1679aed0a5d86de87165c548f8c459758055/tests/handlers/test_sync.py#L1096-L1099

This PR attempts to recover new state events that only appeared first in
the leave batch.

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [x] Pull request is based on the develop branch
* [x] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
The entry should:
- Be a short description of your change which makes sense to users.
"Fixed a bug that prevented receiving messages from other servers."
instead of "Moved X method from `EventStore` to `EventWorkerStore`.".
  - Use markdown where necessary, mostly for `code blocks`.
  - End with either a period (.) or an exclamation mark (!).
  - Start with a capital letter.
- Feel free to credit yourself, by adding a sentence "Contributed by
@github_username." or "Contributed by [Your Name]." to the end of the
entry.
* [x] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))

---------

Co-authored-by: Fefaine <fefaine@gmail.com>
Co-authored-by: Quentin Gliech <quenting@element.io>
Co-authored-by: Eric Eastwood <madlittlemods@gmail.com>
Co-authored-by: Eric Eastwood <erice@element.io>
2026-10-19 09:25:23 +00:00
Paul Chobert 26a92c7111 MSC4140: Reject scheduling a delayed event that the sender could not send at that time (#20266)
## What the MSC says

From MSC4140's [Auth rule
evaluation](https://github.com/matrix-org/matrix-spec-proposals/blob/b7cb09664fed684388ba656459d08cfaf786c1d1/proposals/4140-delayed-events-futures.md#auth-rule-evaluation):

> The server SHOULD also check the event could be sent when it is
scheduled and reject the request if not. In particular, servers SHOULD
check the sender is in the room (or otherwise authorized to send the
event) to avoid storing events for rooms the user is not in.

## This PR

- Checks the event against the room's auth rules as if it were sent now,
and returns the same 403 `M_FORBIDDEN` that `/send` and `/state` would.
- Changes to the sender's own membership are exempt: a join or knock can
be sent from outside the room, which is how this PR reads the MSC's "or
otherwise authorized". They are checked by the auth rules when they are
sent.

Here are a few examples:

| Delayed event | Before | After |
| ----------------------------------------------------------------- |
--------------------------------------- |
---------------------------------------- |
| `m.room.message` from outside the room | 200 `delay_id`, fails at send
time | 403 `M_FORBIDDEN` |
| Kick of another member from outside the room | 200 `delay_id`, fails
at send time | 403 `M_FORBIDDEN` |
| `m.room.name` from a member whose power level is too low | 200
`delay_id`, fails at send time | 403 `M_FORBIDDEN` |
| **Exception**: join of a public room from outside it | 200 `delay_id`,
joins at send time | unchanged |
| Join from outside the room, then a message due after it | both
accepted, message sent once joined | join accepted, message 403
`M_FORBIDDEN` |
2026-10-16 14:38:12 +01:00
Olivier 'reivilibre 4785f06e0e In legacy sync, lazy-load the memberships of the senders of MSC4354 Sticky Events. (#20362)
Part of: MSC4354 (Sticky Events, Experimental Feature tracking issue
#19409)

When a user is the sender of a sticky event that comes down sync, that
user is now in scope for having their lazy-loaded membership sent down
in sync.

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-10-15 20:26:51 +01:00
Andrew Morgan 98735bc6db Remove remaining references to lxml python dependency, which is no longer required (#20356) 2026-10-15 12:54:54 +00:00
542554c093 MSC4242: State DAGs (inbound joins) (#20194)
Process inbound requests to join a state DAG room.

Split out from https://github.com/element-hq/synapse/pull/19425

Part of a series of 5x PRs to land the federation part of MSC4242
(https://github.com/element-hq/synapse/pull/19718,
https://github.com/element-hq/synapse/pull/20127,
https://github.com/element-hq/synapse/pull/20133, inbound-joins (this
PR), inbound-pulls).

Has some Complement tests:
```
PASS TestMSC4242JoinLeaveRejoinPublicRoom 9.19s
PASS TestMSC4242JoinPublicRoomWithRejectedStateDAGEvents 0.88s
```

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [x] Pull request is based on the develop branch
* [x] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
The entry should:
- Be a short description of your change which makes sense to users.
"Fixed a bug that prevented receiving messages from other servers."
instead of "Moved X method from `EventStore` to `EventWorkerStore`.".
  - Use markdown where necessary, mostly for `code blocks`.
  - End with either a period (.) or an exclamation mark (!).
  - Start with a capital letter.
- Feel free to credit yourself, by adding a sentence "Contributed by
@github_username." or "Contributed by [Your Name]." to the end of the
entry.
* [x] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))

---------

Co-authored-by: Eric Eastwood <madlittlemods@gmail.com>
Co-authored-by: Eric Eastwood <erice@element.io>
2026-10-15 13:17:08 +01:00
Olivier 'reivilibre b9b74e8892 Catch up historical MSC4354 Sticky Events to remote homeservers that are newly joining the room. (#20337)
Part of: MSC4354 (Experimental Feature tracking issue #19409)

Follows: #20165 (Sticky Event federation backlog + catch-up
transactions)


The MSC says that we need to tell a newly-joining server about all of
our sticky events (yes, even the ones before the server joined the
room).
This PR introduces the mechanism, building on the 'Sticky Event backlog'
mechanism introduced in #20165, to make that happen.

Most of the logic is taken from the original Sticky Events PR #18968,
but the Sticky Event backlog system did not exist back then.
(The benefit of having the persistent Sticky Event backlog is that we
don't need to rely on the federation senders not crashing to make sure
we get around to sending the Sticky Events out.)

- Add NEW_SERVER_JOINED replication command. (This is a cross-worker
'wake-up call' to check for a sticky event backlog)
We send it when persisting a state change that causes a new server to be
in the room.
We handle it by waking up federation senders for the destination,
including checking the sticky event backlog tables.

- When a server newly joins a room, we insert a sticky event backlog row
for that server, if there are any Sticky Events needing to be sent.

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-10-15 09:53:02 +01:00
Olivier 'reivilibreandAndrew Morgan 1423a29f93 Reject null profile field values (following an optional clause in the specification), in order to avoid clients accidentally harming interoperability. (#20153)
Depends on: https://github.com/matrix-org/complement/pull/914

`displayname` and `avatar_url` already did not permit nulls, seemingly
from #8223.

The specification at v1.15 does not permit `null` for those fields
either, so this seems consistent with historical specification.

This only changes behaviour for 'custom' fields.

---------

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
2026-10-15 09:52:28 +01:00
Olivier 'reivilibre e86eb378af Require a strictly positive stickiness duration for MSC4354 Sticky Events. (#20350)
Part of: MSC4354 (Sticky Events, Experimental Feature tracking issue
#19409)

Since a zero value would be meaningless, don't accept it.

Spawns from
https://github.com/matrix-org/matrix-spec-proposals/pull/4354#discussion_r4211703962

- MSC4354 Sticky Events: only strictly positive durations are valid

  MSC clarified in

https://github.com/matrix-org/matrix-spec-proposals/commit/2d1c3d646aae3738680f8a9a0ccb38b2d941a45f
  to require strict positivity!

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-10-15 09:51:56 +01:00
Olivier 'reivilibre 64689d45f4 Fix Sliding Sync considering a displayname/avatar change to mean the room was newly-joined (#20339)
Follows: #18375

This bugfix is a prerequisite for MSC4354 (Sticky Events, Experimental
Feature tracking issue #19409) changes.

- Add a failing test for join->join being newly_joined

- Fix the join->join transition being treated as a new join

  (when prev_events didn't coincidentally mask the problem)

  Rationale:

  `event_edges` / `prev_events` does NOT link a membership event
  to its previous state.
  (It could even be someone else's membership!)
In most real-world cases, this would generate a `prev_membership` of
NULL
  for every normal membership change.

  It appears as though the author intended some kind of 'previous state'
  relationship, but if you fix the first branch of the `UNION` query
  to use `current_state_delta_stream` for this (which is the source of
  state transitions), then it looks very redundant with the second
  branch.

It looks like the real reason we want to use the snapshots table is for
  out-of-band memberships (outlier memberships).
  So we continue using that for those, but ONLY for those.

  The `SUSPICIOUS` if block is removed because it appears to have been
papering over this issue by deduplicating the spurious `NULL` ->
non-null transitions,
but when you remove those duplicates at the source, it causes more
trouble
  because it doesn't know that what it's 'deduplicating' is actually the
  same membership transition.
This means if you join, then out-of-band leave (e.g. last member on the
server
to leave), that room would appear in `newly_joined` on a new initial
sync.
  (Tests did in fact catch this, too.)

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-10-15 09:48:51 +01:00
Paul Chobert d773067277 MSC4140: authenticate the delayed event management endpoints and allow guests (#20257) 2026-10-13 16:24:30 +00:00
Paul Chobert 766f057305 Stop forwarding non compliant user ids (#20338)
Closes #20116

> [!NOTE]
> This PR Follows #20115 which already implemented this for
`m.device_list_update`

> User IDs with localparts containing characters outside the range
U+0021 to U+007E, or with
> an empty localpart, are considered non-compliant. For current room
versions, servers must
> still accept events using such user IDs over federation; however they
SHOULD NOT forward
> such user IDs to clients when referenced outside the context of an
event. For example,
> device list updates from non-compliant user IDs would be dropped by
the receiving server.
>
> — [Spec
1.19](https://spec.matrix.org/v1.19/appendices/#historical-user-ids)

This PR prevents from forwarding non compliant user ids for the
following events:

- `m.signing_key_update` 8c3c35e95d
- `m.presence` 26a8dfe862
- `m.typing` 1110cf2d73
- `m.receipt` 9e2da8b0a6
- `m.direct_to_device` 9541232a30
2026-10-13 11:10:48 +01:00
Richard van der Hoff 52f053abef Remove support for unstable MSC2965 (#20143)
These things are not needed now that MSC2965 has stabilised. In any
case, they
should never have been exposed without a config flag in the first place.
2026-10-12 16:43:38 +00:00
Will Hunt c52121d4b4 Add m.preview_url capability (Stabilise MSC4452) (#20298)
For https://github.com/element-hq/synapse/issues/19719

MSC4452 is now merged, so the stable capability can be made visible.
I've kept in the unstable flag in order to transition away at a later
date.

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [ ] Pull request is based on the develop branch
* [ ] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
The entry should:
- Be a short description of your change which makes sense to users.
"Fixed a bug that prevented receiving messages from other servers."
instead of "Moved X method from `EventStore` to `EventWorkerStore`.".
  - Use markdown where necessary, mostly for `code blocks`.
  - End with either a period (.) or an exclamation mark (!).
  - Start with a capital letter.
- Feel free to credit yourself, by adding a sentence "Contributed by
@github_username." or "Contributed by [Your Name]." to the end of the
entry.
* [ ] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))
2026-10-12 14:40:44 +01:00
Will Hunt 91020a9518 Short-circuit push rule evaluation when only one user is in a room (#20315)
This speeds up the /createRoom calls a tiny bit by not checking the
senders push rules.

This helps speed up a lot of test runs in Element Web which 
runs a lot of tests in one-person rooms (and creates a heck of a lot of rooms)
2026-10-12 11:56:27 +01:00
40acb97022 MSC4140: drop delayed state interference (#19495)
No longer cancel a user's delayed state events by a more recent state
event sent from a different user. This behaviour has been delegated to
an "alternative" in the delayed event MSC for some time now, and is not
known to be used by any module other than experimental iterations of
MatrixRTC.

See also: https://github.com/matrix-org/complement/pull/845

Opens: https://github.com/element-hq/synapse/issues/20311

---------

Co-authored-by: Olivier 'reivilibre' <olivier@librepush.net>
Co-authored-by: Paul Chobert <paul@chobert.fr>
2026-10-12 10:33:13 +01:00