Commit Graph
4194 Commits
Author SHA1 Message Date
Jason LittleandPaul Chobert 7530874a12 Raise default room version to "12" (#20130)
Requires
* #19768 
* #19782 
* https://github.com/matrix-org/complement/pull/915

To meet the requirements for bumping Synapse to support [Matrix spec to
1.16](https://github.com/element-hq/synapse/issues/19414) the default
room version should be incremented to "12".

Other than the two separate Synapse PRs above(which are included here
but marked as "[diverted]" and should be removed prior to review) there
is only [one other real
change](https://github.com/element-hq/synapse/commit/c005e96c665b5a098a9b95d10f33faf224564be9)
to the code base itself to fix a `KeyError` during logging for a `/sync`
test against unknown room versions. Everything else should be on the
unit tests themselves.

Standard unit test running applies, should be nothing special to test
this outright.
`poetry run trial -jN tests` and similar for Postgresql.

Probably ok to review commit-by-commit

I took the liberty of writing a [room creating
helper](https://github.com/element-hq/synapse/commit/5ba81ad5d4a0a6787b7626bdb3293f633ea4097a)
for the two test series that try and test the sharding of the
`event_persister` workers. I'm not certain it stands up to scrutiny, but
at least does not do any funny mocking when producing room v12
appropriate room IDs.

I also took the liberty of writing an [assertion
helper](https://github.com/element-hq/synapse/pull/20130/commits/e408cef241d1b9c6a88f069eb5832de053790f9b)
for comparing lists of dicts for a select subset of keys/values. This is
used to compare stripped state selections while waiting on
https://github.com/element-hq/synapse/pull/19723 to be completed.

### 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: Paul Chobert <paul@chobert.fr>
2026-09-17 18:32:51 +00:00
Paul Chobert d553b05e45 Return allowed_room_ids in the client /hierarchy response (#20154)
Part of #18731 (Support Matrix 1.15).

Since Matrix 1.15, the
[spec](https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv1roomsroomidhierarchy)
defines `allowed_room_ids` on the room summaries returned by `GET
/_matrix/client/v1/rooms/{roomId}/hierarchy`, so that clients can tell
whether a restricted room can be joined or only knocked at:

> **`allowed_room_ids`** — `[Room ID]` — If the room is a [restricted
room](https://spec.matrix.org/v1.19/client-server-api/#restricted-rooms),
these are the room IDs which are specified by the join rules. Empty or
omitted otherwise. Added in `v1.15`
>
> — [Matrix
Spec](https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv1roomsroomidhierarchy)

Synapse currently strips the field from the client `/hierarchy` response
before returning it — a guard added in matrix-org/synapse#12175 (2022),
correct at the time, when the spec defined the field for federation only
and it was leaking into client responses. The other two surfaces that
define the field (`/room_summary` and the federation `/hierarchy`)
already return it.

This PR removes the strip in `_RoomEntry.as_json` (and the now-unused
`for_client` parameter), so client hierarchy entries include
`allowed_room_ids` for restricted rooms, both local and received over
federation. The first commit adds the failing test coverage, the second
removes the strip.


---

### 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))
2026-09-17 10:16:25 +00:00
Paul Chobert 84ac9ffe37 Drop federation device list updates from non-compliant user IDs (#20115)
This partially fixes the bug
https://github.com/element-hq/synapse/issues/20116

Device list update EDUs from non-compliant (grandfathered historical)
user IDs are currently accepted over federation, stored, and surfaced to
clients in `/sync`'s `device_lists.changed` array.

> 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.
>
> -- [Matrix
spec](https://spec.matrix.org/v1.14/appendices/#historical-user-ids),
clarified in Matrix v1.14 by
[matrix-spec#1506](https://github.com/matrix-org/matrix-spec/issues/1506)


### Problem Example

A remote server sends an `m.device_list_update` EDU for
`@héllo:remote.example` (non-ASCII localpart, outside the compliant
U+0021–U+007E range). Synapse:
- accepts and processes the update (resyncing the user's device list if
needed)
- stores it in the remote device list cache
- forwards `@héllo:remote.example` to local clients via
`device_lists.changed` in `/sync` (**the leak** — a non-compliant user
ID referenced outside event context)

---

### 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))
2026-09-16 11:08:36 +02:00
Paul Chobert 8c11b13f63 Fix state events missing from MSC4222 state_after when the since token falls inside a persist batch (#20171)
This PR fixes the issue described as comment here:
https://github.com/element-hq/synapse/issues/18793#issuecomment-3502202379

In Element Call, this shows up as ghost participants: someone who left
the call keeps being displayed until a later state change refreshes the
room.

The bug is not specific to Element Call: any state event can be
affected, RTC membership just changes often enough to make it visible.

## What happens

Alice has a client syncing against a homeserver where events are
persisted by one worker (the event persister) and `/sync` is served by
another (the sync worker). Her client is parked in a long-poll: `GET
/sync?since=s99&timeout=30000`.

Bob joins a call at the same moment Carol sends a message. Carol's
message reaches the persister first; Bob's `m.call.member` arrives while
that write is still in flight, so the per-room persist queue groups them
into one transaction:

```
events (each gets its own stream ordering):
    stream_ordering 100:  m.room.message   Carol
    stream_ordering 101:  m.call.member    Bob        (state)

current_state_delta_stream (how state_after finds state changes):
    stream_id 100 ────►  (m.call.member, @bob) -> $bob_join_call
          ▲
          └─ stamped with the batch MINIMUM (100), not the event's own 101
              (see `_update_current_state_txn`)
```

The transaction commits: both events and the delta row are now in the
database, atomically.

The persister then announces the new events over replication, one RDATA
token per stream ordering — rows are only merged into one token when
they share a position, and 100 and 101 don't. So the sync worker's
events-stream position steps 99 → 100 → 101, and on reaching 100 it
pokes the notifier.

Alice's long-poll wakes at exactly that moment. Her response is built at
the worker's *current* position — `end = 100` — with RDATA 101 still in
the queue:

```
Sync A  (since=99, end=100):
  timeline:     events   99 < ordering ≤ 100  →  [Carol's message]
  state_after:  deltas   99 < stream_id ≤ 100 →  [$bob_join_call]  ← delivered EARLY
  next_batch:   s100                                               ← mid-batch token
```

No race on the client's side is needed: the server *hands out* the
mid-batch token as `next_batch`. Alice's client re-polls with it, as
every sync client does. The worker has meanwhile processed RDATA 101:

```
Sync B  (since=100, end=101):
  timeline:     events   100 < ordering ≤ 101  →  [Bob's m.call.member @101]  ✓
  state_after:  deltas   100 < stream_id ≤ 101 →  []     row is stamped 100   ✗
```

A state event in the timeline with an empty `state_after`. An MSC4222
client trusts `state_after` over timeline state events, so Alice's copy
of Bob's call membership never updates from this response.

On a single process this cannot happen: the batch's stream IDs are
released as a whole, so the position visible to `/sync` jumps 99 → 101
and `s100` is never handed out. Only a process that learns its position
from replication — any sync worker — ticks through the middle of a
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))
2026-09-16 11:07:25 +02:00
Devon HudsonandClaude Sonnet 5 f7c16d0148 Support configuring a username for Redis connections (#20187)
Adds a `redis.username` config option.

Details:
A `username` without a `password` (or `password_path`) is refused at
startup. Redis has no wire form for a username without a password, and
txredisapi only sends `AUTH` when a password is set, so the username
would otherwise be silently ignored. An explicitly empty password is
accepted, since that is how a `nopass` ACL user is configured.

This relies on txredisapi 1.4.12, the first release to accept a
`username` kwarg. That upstream support was contributed by @karolyi
specifically to unblock this.

Fixes #19238.


### 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: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 17:16:47 +00:00
Olivier 'reivilibre cd2c84b5a5 Stop treating unset display names and avatar URLs as profile fields with a null value. (#20145)
Instead, treat them as absent fields as they feel like they should be.

The database implementation detail that these fields have a dedicated
column with `NULL`
when unset is kept to the storage layer.

The goal here is to reduce the amount of special casing needed for these
two original profile fields and treat them a little bit more like
regular profile fields.

Follows: #20003

Follows: #20147 (needed as a bugfix to continue sending them down
oldschool sync when they get deleted. Without #20147, this PR would
break that — which matches how custom profile fields were broken too.)

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-09-15 15:49:51 +01:00
Skye ElliotandAndrew Morgan 8c8138d572 Reject OTK uploads if clients exceed 500 server-side keys (#20162)
Co-authored-by: Andrew Morgan <andrew@amorgan.xyz>
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
2026-09-14 15:05:23 +00:00
Olivier 'reivilibre 6825c98eb2 Add support for un-soft-failing MSC4354 Sticky Events when room state changes, making federation support more reliable. (#20204)
Part of: MSC4354

Experimental feature tracking issue:
https://github.com/element-hq/synapse/issues/19409

Related Complement tests currently in
https://github.com/matrix-org/complement/pull/806/files#diff-6c9d6d169485d0848c6b20dd9b43f6fe669a8a710e42f953d08fa25a99cc8f4cR509

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-09-14 11:41:21 +01:00
Paul Chobert 3f17bd706a Return 200 {} again for an unset displayname/avatar_url (#20200)
Part of: #19414

When
[MSC4133](https://github.com/matrix-org/matrix-spec-proposals/pull/4133)
(custom profile fields) was implemented, the returned value for an unset
display name changed from `200 {}` to `200 { displayname: null }`. This
happened first on the unstable `uk.tcpip.msc4133` path in #17488
(1.123.0), then on the stable path when #18635 (1.135.0) unified the
`displayname`, `avatar_url` and custom field servlets. Neither PR
discussed the change in review, so it looks like an unintended side
effect of the refactor rather than a deliberate decision.

The v1.16 spec mandated to change from returning `200 {}` to `404` but
change was not identified as breaking and was eventually not implemented
in other clients and server. This PR has a sister MSC that proposes to
return to the pre-1.16 error codes:
[MSC4537](https://github.com/matrix-org/matrix-spec-proposals/pull/4537).

Before:

```
GET /_matrix/client/v3/profile/@alice:test/displayname
  200 {"displayname": null}
```

After:

```
GET /_matrix/client/v3/profile/@alice:test/displayname
  200 {}
```

### 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))
2026-09-11 15:54:31 +00:00
Kegan DougalandEric Eastwood 54c0a78f76 MSC4242: State DAGs (serving) (#20133)
Adds the serving functions needed for MSC4242: State DAGs. This PR adds
MSC4242 support to /make_join, /send_join and /get_missing_events, as
well as calculates the destinations for /send events correctly using
`prev_state_events`.

Built on top of https://github.com/element-hq/synapse/pull/19718 for the
storage functions it makes.

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/matrix-org/matrix-spec-proposals/pull/4242)
([storage](https://github.com/element-hq/synapse/pull/19718),
[fedclient](https://github.com/element-hq/synapse/pull/20127), serving
(this PR), inbound-joins, inbound-pulls).

Whilst this is mostly a port of the code in #19425 there are a few
changes:
- `/get_missing_events` accepts message events when walking the state
DAG, in which case it resolves the first hop to be that event's
`prev_state_events`. The original PR made the client `/event` the
message event and then set `latest=[prev_state_events]` on its own. This
is not very efficient (extra round trip to fetch the event) and there's
no reason why the server can't do the message->prev_state_events lookup,
so we do so. This matches the MSC examples.
- We cap the amount of events fetched via `/get_missing_events`. The MSC
allows it, so it's a good safety check.
- We sort the returned state DAG in `/send_join` by depth then event ID
so it's "mostly" sorted. This is more a formality than anything else,
the MSC does not mandate this, but it makes `/send_join` responses
deterministic.
- `notify_on_event_delivered_over_federation` is a new thing since
#19425, so we include state DAG events in it like we do with
state/auth_chain.

This PR does remove the forced `m.federate: false` setting for MSC4242
rooms, so it makes it possible for federated MSC4242 rooms to be made.
This is mostly so we can test via the endpoints. Given you must opt-in
to MSC4242 via the experimental features config option, it seems
reasonable to loosen this setting. The forced no-federation flag existed
prior to review saying that the MSC4242 room version could itself be
gated behind an experimental feature.

Reviewable commit-by-commit.

### 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 <erice@element.io>
2026-09-11 11:44:40 +01:00
Olivier 'reivilibre 3a2fa70157 Improve the rendering of the set inequality errors produced by assertEqual in the tests. (#20193)
This also changes the rendering of our custom helper `assertIncludes`.

Spawns from
https://github.com/element-hq/synapse/pull/20019#discussion_r3676539092

This PR hijacks `assertEqual` in order to substitute in our own error
rendering logic for set inequality.
(The motivation to do this is that we should just render sets in our
preferred style by default, without having to think about
`assertIncludes` with the `exact` flag or risk forgetting it.)

The error rendering for `assertIncludes` is adapted to make it reusable
in our `assertEqual` and to make it clearer _to me_ (I found it a bit
jarring that `+` was used more like a tick, when in other test
frameworks
I expect to see that as a diff marker).
I have tried to make it as clear as I could without being cryptic.

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-09-09 14:04:35 +01:00
Johannes Marbach f8f7738f5d Add experimental support for sending federation requests from app services as per MSC4512 (#19977)
This implements the outgoing part of
[MSC4512](https://github.com/matrix-org/matrix-spec-proposals/pull/4512)
and is another stopgap towards
https://github.com/element-hq/voip-internal/issues/641.

This adds the ability for proxying app services
(https://github.com/element-hq/synapse/pull/19972) to trigger federation
requests under their own proxy prefix.

This depends on https://github.com/element-hq/synapse/pull/19972 and
cannot make progress before it lands.
2026-09-08 13:29:03 +01:00
Paul ChobertandQuentin Gliech e35c8f0eff Fix client_secret param validator (#20104)
The validation of `client_secret` params accepts invalid values: any
value that includes a char in `[0-9a-zA-Z.=_-]` is accepted, for example
`"café"` is accepted.

Instead synapse should only accept if all chars are within
`[0-9a-zA-Z.=_-]`, not just one.

This is the current validator:

```python
ClientSecretStr = Annotated[
    str,
    StringConstraints(
        pattern="[0-9a-zA-Z.=_-]",
        min_length=1,
        max_length=255,
        strict=True,
    ),
]
```

Unfortunately, Pydantic only defines the `pattern` argument as:

> ### pattern
> A regex pattern that the string must match.

Which is extremely imprecise.

Here is a little script to verify the behavior:

```python
from typing import Annotated
from pydantic import BaseModel, StringConstraints, ValidationError


def check(pattern: str) -> None:
    ClientSecretStr = Annotated[
        str,
        StringConstraints(pattern=pattern, min_length=1, max_length=255, strict=True),
    ]

    class Body(BaseModel):
        client_secret: ClientSecretStr

    try:
        Body.model_validate({"client_secret": "café"})
        print(f"pattern = {pattern!r}: 'café' ACCEPTED  <-- should have been rejected")
    except ValidationError:
        print(f"pattern = {pattern!r}: 'café' rejected")


check("[0-9a-zA-Z.=_-]")  # before the fix (unanchored)
check("^[0-9a-zA-Z.=_-]+$")  # after the fix
```

which would output


```
pattern = '[0-9a-zA-Z.=_-]': 'café' ACCEPTED  <-- should have been rejected
pattern = '^[0-9a-zA-Z.=_-]+$': 'café' rejected
```

## History

This is a regression of a previously reported and fixed bug:

- matrix-org/synapse#6766 (2020) reported that Synapse did not enforce
the spec's `client_secret` regex at all — with real-world fallout:
FluffyChat had started sending secrets containing `:` because nothing
rejected them. Fixed by introducing `assert_valid_client_secret`
(matrix-org/synapse#6767).
- matrix-org/synapse#13188 (Synapse 1.66.0) ported the account endpoints
to Pydantic and transcribed the regex without anchors/quantifier;
Pydantic v1's `re.match` semantics meant only the *first* character was
validated.
- #19071 (Synapse 1.142.0) migrated to Pydantic v2, whose *search*
semantics weakened it further to "any one character anywhere".


---

### 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: Quentin Gliech <quenting@element.io>
2026-09-07 10:35:33 +02:00
Paul Chobert 470b941895 Fix private read receipts of other users being leaked to application services (#20114)
Application services that opt in to receiving ephemeral events
(`receive_ephemeral: true` in the
[registration](https://spec.matrix.org/v1.19/application-service-api/#registration),
added in Matrix v1.13 from
[MSC2409](https://github.com/matrix-org/matrix-spec-proposals/pull/2409))
are sent the private read receipts (`m.read.private`) of **every** user
in the rooms they are interested in — not just their own users.

The [Application Service
API](https://spec.matrix.org/v1.19/application-service-api/#pushing-ephemeral-data)
is explicit about this (*Pushing ephemeral data*, `m.receipt`):

> Private read receipts MUST only be sent for users matching one of the
application service's namespaces. Normal read receipts and threaded read
receipts are always sent.

This matches the [Client-Server
API](https://spec.matrix.org/v1.19/client-server-api/#private-read-receipts):
"Servers MUST NOT send the `m.read.private` receipt to any other user
than the one which originally sent it."

The restriction to namespaced users is safe because the appservice could
learn those receipts anyway by syncing as the user. For everyone else,
`m.read.private` exists precisely so that nobody — including bridges and
bots in the room — can observe it.

For example, take an appservice registered with:

```yaml
namespaces:
  users:
    - regex: "@_bridge_.*:example\\.org"
      exclusive: true
```

When `@alice:example.org` (a regular user, not one of the appservice's)
and `@_bridge_bob:example.org` (a namespaced user) each send read
receipts in a bridged room, the appservice receives:

```json
{
    "type": "m.receipt",
    "room_id": "!room:example.org",
    "content": {
        "$event": {
            "m.read": { "@alice:example.org": { "ts": 1436451550453 } },
            "m.read.private": {
                "@_bridge_bob:example.org": { "ts": 1436451550453 },
                "@alice:example.org": { "ts": 1436451550453 }
            }
        }
    }
}
```

- `m.read` from `@alice` — correct, public read receipts are always
sent.
- `m.read.private` from `@_bridge_bob` — correct, the user is within the
appservice's namespaces.
- `m.read.private` from `@alice` — **the leak**: their private read
receipt must not be sent to the appservice.

## History

- matrix-org/synapse#8437 (Oct 2020, Synapse 1.22.0) implemented MSC2409
ephemeral event delivery to appservices. No leak at that point: private
read receipts did not exist yet.
- matrix-org/synapse#10413 (Jul 2021, Synapse 1.40.0) added the initial,
experimental-flag-gated implementation of MSC2285 ("hidden" read
receipts) and filtered them out of the `/sync` path
(`filter_out_hidden`) — but not out of the appservice path in the same
file. This is where the leak originates, for servers with
`msc2285_enabled`.
- matrix-org/synapse#12168 (May 2022, Synapse 1.59.0) reworked this into
the `m.read.private` receipt type and `filter_out_private_receipts`; the
appservice path was again left unfiltered.
- matrix-org/synapse#13273 (Aug 2022, Synapse 1.65.0) moved to the
stable `m.read.private` identifier; the appservice path has leaked it
ever since.

---

### 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))
2026-09-07 10:35:03 +02:00
Paul Chobert bd21823818 Fix 500 error when setting a custom profile field for a user with no profile row (#20172)
Follow-up to #20149, which fixed the 500 when *getting* a profile field
for a user with no `profiles` row. The same crash was still reachable
when *setting* one via `PUT /_matrix/client/v3/profile/{userId}/{field}`
(as server admin). This PR splits that case in two:

* **The user exists but has no `profiles` row** (e.g. profile erased
upon deactivation):
* Before: `500 M_UNKNOWN` (`TypeError: cannot unpack non-sequence
NoneType` in the profile size check).
  * After: `200`, the profile row is recreated with the field set.
* **The user does not exist at all**:
  * Before: `500 M_UNKNOWN` (same crash).
* After: `404 M_NOT_FOUND`, without conjuring up an orphan profile row.

Fixing the crash also surfaced a latent SQLite-only bug where a field
set on a freshly created profile row was stored under the wrong key,
making it 404 on `GET` right after a successful `PUT`.



### 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))
2026-09-07 10:34:30 +02:00
Jason Little a0b5a45c91 fix MSC3912-relation-based-redaction for room versions > 10 (#19782) 2026-09-04 08:35:28 +00:00
Kegan Dougal 0088e43da7 MSC4242: State DAGs (fed client) (#20127)
Split out from https://github.com/element-hq/synapse/pull/19425

- Add federation support for MSC4242 fields in `/send_join` and
`/get_missing_events`
- Move the gate preventing joining MSC4242 rooms higher in the call
stack


Part of a series of 5x PRs to land the federation part of MSC4242
(storage, fedclient, serving, inbound-joins, inbound-pulls).


### 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))
2026-09-04 08:08:38 +00:00
Paul Chobert 207f6560ce Stabilize the M_APPSERVICE_LOGIN_UNSUPPORTED error code (#20180)
Part of: https://github.com/element-hq/synapse/issues/19415

Return `M_APPSERVICE_LOGIN_UNSUPPORTED` error code instead of the
unstable `IO.ELEMENT.MSC4190.M_APPSERVICE_LOGIN_UNSUPPORTED` identifier.

> Servers MUST still allow application services to use the `/register`
endpoint with a login type of `m.login.application_service` even if they
don't support the Legacy Authentication API. In that case application
services MUST set the `"inhibit_login": true` parameter as they cannot
use it to log in as users. If the `inhibit_login` parameter is not set
to `true`, the server MUST return a 400 HTTP status code with an
`M_APPSERVICE_LOGIN_UNSUPPORTED` error code.
>
> [...]
>
> Application services MUST NOT use the `/login` endpoint if the server
doesn't support the Legacy authentication API. If `/login` is called
with the `m.login.application_service` login type the server MUST return
a 400 HTTP status code with an `M_APPSERVICE_LOGIN_UNSUPPORTED` error
code.
>
> — [Matrix v1.19, Application Service
API](https://spec.matrix.org/v1.19/application-service-api/#registration)

Synapse returns the correct 400 on both endpoints, but with the unstable
identifier.

Before:

```
POST /_matrix/client/v3/login    {"type": "m.login.application_service", ...}  # appservice with MSC4190 device management
POST /_matrix/client/v3/register {"type": "m.login.application_service", ...}  # without "inhibit_login": true
  400 {"errcode": "IO.ELEMENT.MSC4190.M_APPSERVICE_LOGIN_UNSUPPORTED"}
```

After:

```
POST /_matrix/client/v3/login    {"type": "m.login.application_service", ...}  # appservice with MSC4190 device management
POST /_matrix/client/v3/register {"type": "m.login.application_service", ...}  # without "inhibit_login": true
  400 {"errcode": "M_APPSERVICE_LOGIN_UNSUPPORTED"}
```

A Sister PR exists in MAS:
https://github.com/element-hq/matrix-authentication-service/pull/5961 ;
when delegation is enabled, `/login` reaches MAS instead of Synapse, and
MAS currently answers `m.login.application_service` with `M_UNKNOWN`.
2026-09-03 15:07:51 +01:00
Paul Chobert 366a020f79 Fix MSC4178 error codes on /account/3pid/{email,msisdn}/requestToken (#20101)
Part of https://github.com/element-hq/synapse/issues/18118

## What the spec says

Since Matrix v1.13 (introduced by
[MSC4178](https://github.com/matrix-org/matrix-spec-proposals/pull/4178)),
the `400` response of [`POST
/_matrix/client/v3/account/3pid/email/requestToken`](https://spec.matrix.org/v1.19/client-server-api/#post_matrixclientv3account3pidemailrequesttoken)
lists, among the "Error codes that can be returned":

> - `M_THREEPID_MEDIUM_NOT_SUPPORTED`: The homeserver does not support
adding email addresses.
> - `M_INVALID_PARAM`: The email address given was not valid.

and [`POST
/_matrix/client/v3/account/3pid/msisdn/requestToken`](https://spec.matrix.org/v1.19/client-server-api/#post_matrixclientv3account3pidmsisdnrequesttoken)
likewise:

> - `M_THREEPID_MEDIUM_NOT_SUPPORTED`: The homeserver does not support
adding phone numbers.
> - `M_INVALID_PARAM`: The phone number given was not valid.

## What was missing

Synapse implemented the headline case (unsupported medium), but around
it:

- A malformed email address or country code was reported with the
generic `M_BAD_JSON` instead of `M_INVALID_PARAM`. The email validator
deliberately kept `M_BAD_JSON` "to ensure backward compatibility of HTTP
error codes" (matrix-org/synapse#13687, 2022) — that predates Matrix
v1.13, which now lists `M_INVALID_PARAM` for this case.
- On the msisdn variant, the unsupported-medium check ran after the
denied/in-use checks, so a request wrong in two ways reported the other
fault; the email variant checks it first.

## What this PR changes

- Malformed email addresses and country codes on
`/account/3pid/{email,msisdn}/requestToken` are reported with
`M_INVALID_PARAM`. Both flow through the existing errcode translation as
`value_error`: the email validator raises a plain `ValueError`, and the
country-code constraint (`ISO3166_1_Alpha_2`) declares its own error via
pydantic-core's `custom_error_schema`.
- On the msisdn variant the unsupported-medium check now runs before the
denied/in-use checks, as on the email variant.
- The country-code type is renamed from `ISO3116_1_Alpha_2` to
`ISO3166_1_Alpha_2` (typo in the standard's number).

[`/account/password/email/requestToken`](https://spec.matrix.org/v1.19/client-server-api/#post_matrixclientv3accountpasswordemailrequesttoken)
(not covered by the v1.13 change) shares the email request body model,
so a malformed email there is now also reported with `M_INVALID_PARAM`
instead of `M_BAD_JSON`. Its `400` response is described as "the request
was invalid" and only names `M_SERVER_NOT_TRUSTED` explicitly ("can be
returned if…") rather than restricting the server to a fixed list, and
`M_INVALID_PARAM` is the spec's generic code for "A parameter that was
specified has the wrong value" ([other error
codes](https://spec.matrix.org/v1.19/client-server-api/#other-error-codes)).
2026-09-03 12:05:08 +01:00
Paul Chobert 1727ceee7b Ratelimit the room reporting endpoint (MSC4151) (#20036)
Apply the `rc_reports` rate limit to the room reporting endpoint, [`POST
/_matrix/client/v3/rooms/{roomId}/report`](https://spec.matrix.org/v1.19/client-server-api/#post_matrixclientv3roomsroomidreport)
(added in Matrix v1.13).

The spec marks this endpoint as **Rate-limited: Yes** (clients must
expect a `429 M_LIMIT_EXCEEDED`), and homeservers [SHOULD implement rate
limiting](https://spec.matrix.org/v1.19/client-server-api/#rate-limiting)
in general, but Synapse currently applies no limit here. The sibling
user reporting endpoint already uses `rc_reports`, so this reuses the
same limit instead of introducing a new config option.

Changes:

- Move the room report logic from `ReportRoomRestServlet` into a new
`ReportsHandler.report_room`, mirroring the existing `report_user`. The
rate limit is checked before the room existence lookup, so it bounds the
DB work a caller can trigger and cannot be used to tell existing rooms
from non-existing ones.
- The servlet keeps the existing behaviour of returning `200` regardless
of room existence when `msc4277_enabled` is set (the spec allows this
since v1.18).
- Add a regression test covering the `429` response and the per-user
rate limit override.
2026-09-03 12:01:21 +01:00
Paul Chobert d4de2ae1c5 Fix state_after for left rooms including post-leave lazy-loaded memberships (#20169)
## The bug

With the experimental
[MSC4222](https://github.com/matrix-org/matrix-spec-proposals/pull/4222)
implementation enabled (`use_state_after`) and lazy-loading of room
members, an incremental `/sync` could disclose state from **after** the
user's leave in a left room's `state_after`.

1. Alice syncs with `lazy_load_members: true` and
`use_state_after=true`.
2. Bob sends a message in a room they share.
3. Alice leaves the room.
4. Bob updates his per-room displayname
5. Alice does an incremental sync covering steps 2–3. Alice's
`state_after` contains Bob's post-leave membership event from step 4

Alice should not see the new per-room display name of Bob.


## The fix

Copy what has been done for `_compute_state_delta_for_full_sync`: pass
`joined` down and, for rooms the user is no longer joined to, fetch the
memberships as of `end_token` via state groups (`get_state_ids_at`)
instead of current state.
2026-09-03 11:58:56 +01:00
guillermo 8f27ac006f Add unit tests for parse_stripped_state_event (#20136)
This PR adds a suite of tests for Synapse state events. It covers key
scenarios around creation, updates and state consistency to prevent
regressions in event processing and serialization.
The primary goal is to increase test coverage.
2026-09-02 16:49:44 +01:00
dea059a94d Restrict message events from being redacted by local users if past allowed period. (#20138)
Closes: #20065 

---------

Co-authored-by: defaultdino <adve@adisve.net>
Co-authored-by: Olivier 'reivilibre <oliverw@element.io>
2026-09-02 16:36:35 +01:00
FrenchGithubUser c40ab6e3b9 Fix sending duplicate m.room.encryption events on room creation (#20106)
On room creation when the client already supplies one in the initial
state and `encryption_enabled_by_default_for_room_type` is enabled.
2026-09-02 15:52:41 +01:00
Paul Chobert f94abb6924 Return 403 instead of 400 when profile changes are disabled (#20173)
With `enable_set_displayname: false` (or `enable_set_avatar_url:
false`), refusing a profile change returned the right errcode with the
wrong status:

```
PUT /_matrix/client/v3/profile/@alice:example.com/displayname   (displayname already set)
→ 400 {"errcode": "M_FORBIDDEN", "error": "Changing display name is disabled on this server"}

DELETE /_matrix/client/v3/profile/@alice:example.com/displayname
→ 400 {"errcode": "M_FORBIDDEN", "error": "Changing display name is disabled on this server"}
```

With this fix:

```
PUT /_matrix/client/v3/profile/@alice:example.com/displayname   (displayname already set)
→ 403 {"errcode": "M_FORBIDDEN", "error": "Changing display name is disabled on this server"}

DELETE /_matrix/client/v3/profile/@alice:example.com/displayname
→ 403 {"errcode": "M_FORBIDDEN", "error": "Changing display name is disabled on this server"}
```

The spec defines the [403 response of `PUT
/_matrix/client/v3/profile/{userId}/{keyName}`](https://spec.matrix.org/v1.19/client-server-api/#put_matrixclientv3profileuseridkeyname)
as "The server is unwilling to perform the operation, either due to
insufficient permissions or **because profile modifications are
disabled**", while 400 is reserved for malformed input (`M_BAD_JSON`,
`M_MISSING_PARAM`, …).

Clients seem to rely on `errcode` field more than the HTTP Status Code,
that change seems safe.
2026-09-02 14:29:08 +01:00
Paul Chobert b6798a1353 Fix event_search background reindex skipping m.room.topic events (#20119)
Room topics are dropped from the search index whenever the
`event_search` background reindex runs (e.g. after a search index
rebuild, or when the background update is re-run on an upgraded
homeserver), making topics unsearchable even though the live write path
indexes them correctly.

The cause is a trailing comma in `_background_reindex_search`, which
turns the topic `value` into a 1-tuple instead of a string:


https://github.com/element-hq/synapse/blob/14c96c0f5444cbe28b6ac0361cf94216b8d352db/synapse/storage/databases/main/search.py#L211-L213

The downstream `if not isinstance(value, str): continue` guard then
silently skips *every* `m.room.topic` event, so no topic ever reaches
`event_search` during a reindex.

The regression was introduced in #18195, which added rich-text topic
support (MSC3765) to the reindex path.

### Problem Example

1. A room has topic "project roadmap".
2. An admin rebuilds the search index (or the `event_search` background
update re-runs).
3. `m.room.message` and `m.room.name` events are reindexed fine, but
every `m.room.topic` event is skipped.
4. Searching for "project roadmap" with key `content.topic` returns 0
results — the topic is permanently unsearchable until the event is sent
again.

---

### 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))
2026-09-02 14:27:38 +01:00
Kegan DougalandEric Eastwood 54bfa1a01b MSC4242: State DAGs (storage) (#19718)
Split out from https://github.com/element-hq/synapse/pull/19425

Add storage functions needed for federation support for MSC4242:
- `get_missing_events_state_dag`: will be used to satisfy
`/get_missing_events` requests.
 - `get_state_dag`: will be used to satisfy `/send_join` requests.


Part of a series of 5x PRs to land the federation part of MSC4242
(storage, fedclient, serving, inbound-joins, inbound-pulls).


### 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>
2026-09-02 09:12:49 +01:00
Andrew Morgan 652558495f Remove unstable /auth_issuer endpoint (#20163) 2026-09-01 16:45:39 +00:00
Hubert ChathiandAndrew Morgan 89363f45d2 Relax validation of signature upload for master keys, and allow updates (#19915)
Co-authored-by: Andrew Morgan <andrew@amorgan.xyz>
2026-09-01 09:13:56 +00:00
Eric Eastwood fc1e1213e3 Merge branch 'release-v1.160' into develop 2026-08-31 18:59:58 -05:00
Soyoung Kim 30355721f6 Fix public_chat preset and deepmerge when it is needed (#20050) 2026-08-28 21:34:27 +00:00
Andrew Ferrazzutti a92a21600c MSC4140: update error for exceeding delay maximum (#20156)
Use the HTTP code & errcode specified in the latest revision of the MSC

(The changes were added by
https://github.com/matrix-org/matrix-spec-proposals/pull/4140/changes/0c7193aaa07c9a2634dccd7cf3bd83e2733a806e)
2026-08-28 08:53:30 -04:00
Johannes Marbach 57d6da409c Add experimental support for letting application services proxy namespaces in the C-S and S-S API as per MSC4512 (#19972)
This implements the proxying part of
[MSC4512](https://github.com/matrix-org/matrix-spec-proposals/pull/4512)
and is a stopgap towards
https://github.com/element-hq/voip-internal/issues/641. It introduces a
new configuration property `io.element.msc4512.proxy` that allows
application services to claim namespaces in the C-S and S-S API. For
requests underneath a claimed namespace, Synapse first authorizes the
request and then reverse-proxies it to the application services. For
now, the only allowed namespace that can be claimed is
`unstable/io.element.msc4195/rtc/livekit`.

This pull request can be reviewed by commits.

### 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))

---------

Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2026-08-28 13:45:54 +01:00
Andrew FerrazzuttiandOlivier 'reivilibre' c3bec60936 MSC4140: support getting a single delayed event (#19926)
See
https://github.com/matrix-org/matrix-spec-proposals/blob/toger5/expiring-events-keep-alive/proposals/4140-delayed-events-futures.md#getting-a-single-delayed-event

Co-authored-by: Olivier 'reivilibre' <olivier@librepush.net>
2026-08-28 02:05:59 -04:00
Andrew Ferrazzutti 305faa2ab5 MSC3866: Apply missed filter on /users response (#20152)
For the Admin API /users endpoint, the response is meant to exclude the
approval flag when MSC3866 is enabled, but the filter that applies the
exclusion never actually got used. Fix things so that it does.
2026-08-27 16:53:03 +01:00
83193b378d Fix retrying failed event persistence (#20148)
If we failed to persist an event and then retried, this would fail due
to a conflict error trying to reinsert the state groups that we are
persisting.

This blocks all new events being persisted in the room until the
instance is restarted (which clears entries from the table matching the
instance name). This is because we always mark the [latest persisted
state group in the room as being
persisted](https://github.com/element-hq/synapse/blob/781d08df263e640d85ca5c8b5ff514433e019c6f/synapse/storage/databases/state/deletion.py#L242-L243).

Also add an `inserted_ts` field which we use to detect stale entries,
e.g. from instances that have been taken offline permanently. These
aren't a problem beyond blocking deletion of the associated state groups

Introduced in https://github.com/element-hq/synapse/pull/18107

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
2026-08-27 15:57:00 +01:00
Johannes MarbachandAndrew Morgan c246d81dec Add support for specifying the SFU WebSocket URL together with configured LiveKit transports (#20146)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2026-08-27 11:21:47 +00:00
Jason Robinson 4245bdc6f0 Fix sending down removed custom profile fields in legacy sync (#20147)
When a client (correctly) calls the `DELETE` endpoint to remove a custom
profile field (like Element X does with `m.status`), we incorrectly
don't include it in the sync response in legacy sync. This was due to
the fact that we cleaned up the sent fields down to what fields the
profile currently has.

Always ensure any fields in `ProfileUpdateAction.UPDATE` are sent down,
as `null` values for profile fields which have been deleted.

Fixes an issue where clearing a user status from Element X does not
reflect in the user status being cleared on Element Web.

Note, target is the v1.160.0 release branch due to customer commitments,
and this fixes web and mobile clients not working together correctly.

### 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
* [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))
2026-08-27 06:29:50 +00:00
Olivier 'reivilibre 781d08df26 Fix the /profile endpoint giving 500 when the profile does not exist at all. (#20149)
Drive-by fix for a problem noticed when doing some other work.

This only triggers for 'custom'/generic fields, not the built-in
`displayname` and `avatar_url`.

Not seeing an open issue for it.

Return a 404, not 500, when looking up a profile field on a missing
profile

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
2026-08-26 14:27:28 +01:00
Jason Robinson d59856b9a7 Fix sync stream not being woken up when a user updates a profile field without belonging to any rooms (#20135)
Fix sync stream not being woken up when a user updates a profile field
without belonging to any rooms.

Fixes https://github.com/element-hq/synapse/issues/20110
2026-08-25 17:14:17 +01:00
4bb07152c8 Support for profile updates over Sliding Sync (MSC4262) (#20003)
This PR implements support for profile updates over Sliding Sync:
https://github.com/matrix-org/matrix-spec-proposals/pull/4262. This pr
may be easier to review as a whole than commit by commit.

This builds on the legacy sync profile updates feature
https://github.com/element-hq/synapse/pull/19556, specifically the
profile updates stream it added.

Submitting for early review to get consensus on implementation. There
are some things we would like to add still, from spec, mainly:

* > Homeservers should only consider a profile field update "accepted"
by a client
> once the client returns with a new /sync request with the next /sync
token,
> NOT just after sending down the profile update. The client may never
receive
> response due to network conditions, or a bug in the client
implementation.
* > When a room enters this subset in this connection for the first
time, all requested
> fields from profiles of users in that room MAY be sent down. This
gives the client
> a base set of information for which future field updates can be
applied on top of.
> The homeserver MAY omit some fields and profiles if it believes that
the client has
> already received them, likewise repeat profiles MAY be sent down based
on homeserver
  > implementation.
* > Finally, if the list of fields expands to cover a new field ID,
those fields should
> be sent down for all users that are within the current room subset.
Future incremental
  > updates will then include changes to this field.
* Additionally, we would need to implement a lazy loading cache similar
to the legacy sync. (not part of MSC as such)

Depending on review these could either be added to this pr, or to keep
this pr from not growing too much, be added in a follow-up pr, as they
are more enhancement to this base sliding sync profile updates
functionality than a part of the core functionality.

### 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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Olivier 'reivilibre' <olivier@librepush.net>
Co-authored-by: Olivier 'reivilibre <oliverw@element.io>
2026-08-25 14:37:03 +00:00
catfromplan9 3db77e80a5 Fix WebP thumbnails losing their transparency (#20094)
Signed-off-by: cat <cat@plan9.rocks>
2026-08-24 12:02:44 +00:00
Johannes Marbach d0b105757e Add experimental support for MSC4502: Targeted and unrestricted room member queries (#19974)
This is another stopgap towards
https://github.com/element-hq/voip-internal/issues/641 and adds
experimental support for
[MSC4502](https://github.com/matrix-org/matrix-spec-proposals/pull/4502).

This adds a new endpoint `/rooms/{roomId}/is_joined` to query if a user
or server is joined to a room known to the homeserver. Access to the
endpoint is guarded behind a new OAuth scope that can be assigned when
registering application services.

Tracking issue: https://github.com/element-hq/synapse/issues/20118

---------

Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2026-08-20 15:27:11 +01:00
FrenchGithubUser c0357de4ed fix: presence stream stalling intermittently (#20090)
This is a fix for presence updates silently stalling when a `/sync`
request is cancelled mid-write, causing a stream ID to be leaked into
`_unfinished_ids` and permanently pinning the persisted stream position.

Fixes https://github.com/element-hq/synapse/issues/19800

### 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))
2026-08-13 15:30:51 +00:00
Erik JohnstonandClaude Fable 5 0c6714d0d2 Allow specifying multiple action_name and status params in the scheduled tasks admin API (#20067)
We have an internal usage of `/scheduled_tasks` that would like to fetch
multiple actions at once (janitor).

We also make it so that invalid `status` values now return a 400 rather
than a 500.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-13 14:02:07 +01:00
catfromplan9 0b086d1531 Fix thumbnailing MPO images (#20025)
Signed-off-by: cat <cat@plan9.rocks>
2026-08-11 13:52:49 +00:00
Eric Eastwood 93f4ea43c7 Fix tests that use homeserver_to_use=GenericWorkerServer not being able to be run standalone (#20017)
*Spawning from
https://github.com/element-hq/synapse/pull/19057#discussion_r2427537811,*

Fix tests that use `homeserver_to_use=GenericWorkerServer` not being
able to be run standalone

Fix https://github.com/element-hq/synapse/issues/15671 (previously
https://github.com/matrix-org/synapse/issues/15671)

Before this change:

```shell
$ poetry run trial tests.storage.test_rollback_worker.WorkerSchemaTests.test_rolling_back
tests.storage.test_rollback_worker
  WorkerSchemaTests
    test_rolling_back ...                                               [ERROR]

===============================================================================
[ERROR]
Traceback (most recent call last):
  File "synapse/tests/unittest.py", line 129, in new
    return code(orig, *args, **kwargs)
  File "synapse/tests/unittest.py", line 223, in setUp
    return orig()
  File "synapse/tests/unittest.py", line 398, in setUp
    self.hs = self.make_homeserver(self.reactor, self.clock)
  File "synapse/tests/storage/test_rollback_worker.py", line 54, in make_homeserver
    hs = self.setup_test_homeserver(homeserver_to_use=GenericWorkerServer)
  File "synapse/tests/unittest.py", line 669, in setup_test_homeserver
    hs = setup_test_homeserver(
  File "synapse/tests/server.py", line 1260, in setup_test_homeserver
    prepare_database(
  File "synapse/synapse/storage/prepare_database.py", line 167, in prepare_database
    raise UpgradeDatabaseException(EMPTY_DATABASE_ON_WORKER_ERROR)
synapse.storage.prepare_database.UpgradeDatabaseException: Uninitialised database: run the main synapse process to prepare the database schema before starting worker processes.

tests.storage.test_rollback_worker.WorkerSchemaTests.test_rolling_back
-------------------------------------------------------------------------------
Ran 1 tests in 0.034s

FAILED (errors=1)
```


### What was the problem before?

[`PREPPED_SQLITE_DB_CONN`](https://github.com/element-hq/synapse/blob/1a1af7b622f219ba0f2501709298caa230ad3912/tests/server.py#L1247-L1262)
is a process global and shared between all tests. Whichever test first
calls `setup_test_homeserver(...)` builds the template database for the
whole trial run.

`prepare_database(...)` has a built-in check to refuse upgrading the
database ["to avoid multiple workers doing it at
once."](https://github.com/element-hq/synapse/blob/1a1af7b622f219ba0f2501709298caa230ad3912/synapse/storage/prepare_database.py#L164-L167)
and throw `UpgradeDatabaseException`.

This means that if we happen to first run a test that uses a worker
(`homeserver_to_use=GenericWorkerServer`), `prepare_database(...)` will
just throw its `UpgradeDatabaseException`. And since
`PREPPED_SQLITE_DB_CONN` is assigned before `prepare_database(...)`, it
will never try to prepare again and the rest of the tests will fail.
2026-08-10 16:34:56 -05:00
Erik JohnstonandClaude Fable 5 62a4bc4620 Fix quarantined_media stream not being replicated (#20085)
The registration of `QuarantinedMediaStream` in
`ReplicationCommandHandler._streams_to_replicate` was missed when the
stream was added, so an instance configured as the
quarantined_media_changes stream writer never sent RDATA/POSITION for it
unless it was the main process.

Also add the stream to the `instance_map` config validation.

Stream was introduced in
https://github.com/element-hq/synapse/pull/19558

Fixes https://github.com/element-hq/synapse/issues/20080

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 15:47:01 +01:00
c5f02a9313 Introduce support for MSC4429: Profile Updates for Legacy Sync (#19556)
Implements support for [MSC4429: Profile Updates for Legacy
Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4429).

Paired with https://github.com/matrix-org/complement/pull/849 and
https://github.com/matrix-org/sytest/tree/anoa/msc4429

Tracking issue for removing unstable identifiers in Synapse:
https://github.com/element-hq/synapse/issues/19891
Further improvements tracked in:
https://github.com/element-hq/synapse/issues/19981

---------

Co-authored-by: Half-Shot <will@half-shot.uk>
Co-authored-by: Jason Robinson <jasonr@element.io>
Co-authored-by: Olivier 'reivilibre' <oliverw@element.io>
2026-08-06 15:35:07 +01:00
Jason Little 415a869f1f fix RemoteJoinHelper to handle v12 rooms (#20021)
While preparing for the default room version change to "12", the new
tests for
[FederationJoinUpgradedRoomTestCase](https://github.com/element-hq/synapse/blob/36664cac4fdec38993c68078cd9a82452b56dca7/tests/federation/test_federation_join_upgraded_room.py#L44)
were unable to handle creation events inside of the manufactured
`auth_events` sections. All of these tests fail.

Related to https://github.com/element-hq/synapse/pull/20015 as another
recent fix to `RemoteJoinHelper`


### Testing strategy

To test, I recommend changing the `DEFAULT_ROOM_VERSION` in [the
`server.py` config
file](https://github.com/element-hq/synapse/blob/36664cac4fdec38993c68078cd9a82452b56dca7/synapse/config/server.py#L179)
to `"12"`, then running `poetry run trial
tests.federation.test_federation_join_upgraded_room.FederationJoinUpgradedRoomTestCase`
for these selective tests. Alternatively, creating the
`default_config()` for the `TestCase` in question to set the default
room version, but that is more work.
2026-08-03 13:47:26 -05:00