Skip to content

Famedly release/v1.162 - #288

Merged
itsoyou merged 44 commits into
masterfrom
famedly-release/v1.162
Oct 2, 2026
Merged

itsoyou merged 44 commits into
masterfrom
famedly-release/v1.162

Conversation

@itsoyou

@itsoyou itsoyou commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Famedly Release v1.162.0_1

Docker image tags available:

  • v1.162.0_1-mod032 <- TIM 1.1
  • v1.162.0_1-mod033 <- TIM Pro(and TIM 1.2)

Famedly additions for v1.162.0_1

  • chore: update CI poetry version to 2.4.1 (Soyoung Kim)

ara4n and others added 30 commits September 8, 2026 23:07
…he CTE (#20182)

This solves the root cause of a user opening the thread panel in Element
Web DoSing synapse with recursive relation requests, starving out
delayed events and causing MatrixRTC calls to drop - see
matrix-org/matrix-js-sdk#5519 for papering over
it clientside.

Fixes element-hq/synapse#18788

Claude rationale:

Postgres cannot estimate the size of a recursive CTE. When it guesses
large
it stops probing events by event_id and instead hashes every event in
the
room, so a single recursive `/relations` request in a busy room takes
seconds
and a Threads-panel fan-out of 30 of them can pin a client-reader's DB
pool
for a minute. Joining events per recursion step keeps the lookups as
index
probes regardless of the estimate.

The recursion also moves from `UNION` to `UNION ALL`. An event carries a
single
`m.relates_to` and is stored as exactly one `event_relations` row
(unique index
on `event_id`), so the relation graph is a tree: every node is reached
along
one path and `UNION` never had duplicates to remove. `UNION ALL` drops
the
sort-and-dedupe pass over the working table on every iteration, which
matters more now that each row also carries the joined events columns. A
cycle from bogus events is still terminated by the depth bound, as
before,
and `UNION` gave no protection there anyway since such rows differ in
depth.

Measured on Postgres 16 against a synthetic corpus modelled on a large
homeserver: 4 rooms x 300k events; one 40-reply thread rooted 280k
events
back in the timeline, with 2 reactions per reply; every 5th event
elsewhere
a reaction, plus 200 popular roots with 2000 reactions each so that the
`relates_to_id statistics` are skewed the way they are in production.
Default
limit (6 rows), warm cache, JIT off:

```
                           before     after
  single request           77 ms      1.4 ms
  20 concurrent requests   1.21 s     0.14 s
```

Before: Hash Join with a Hash over all 300k events of the room (4
batches).
After: Nested Loop with an Index Scan on `events_event_id_key` per row.

(found/solved by fable)

---------

Co-authored-by: Eric Eastwood <erice@element.io>
…tEqual` in the tests. (#20193)

This also changes the rendering of our custom helper `assertIncludes`.

Spawns from
element-hq/synapse#20019 (comment)

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>
Signed-off-by: dependabot[bot] <support@github.com>
Bumps [gitpython](https://github.com/gitpython-developers/GitPython)
from 3.1.58 to 3.1.59.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/gitpython-developers/GitPython/releases">gitpython's
releases</a>.</em></p>
<blockquote>
<h2>3.1.59 - Security</h2>
<h2>What's Changed</h2>
<ul>
<li>prepare changelog for upcoming release by <a
href="https://github.com/Byron"><code>@​Byron</code></a> in <a
href="https://redirect.github.com/gitpython-developers/GitPython/pull/2207">gitpython-developers/GitPython#2207</a></li>
<li>Block file-reading Git options by <a
href="https://github.com/Byron"><code>@​Byron</code></a> in <a
href="https://redirect.github.com/gitpython-developers/GitPython/pull/2208">gitpython-developers/GitPython#2208</a></li>
<li>index: write blobs via git hash-object, not gitdb's odb.store by <a
href="https://github.com/caroescm"><code>@​caroescm</code></a> in <a
href="https://redirect.github.com/gitpython-developers/GitPython/pull/2209">gitpython-developers/GitPython#2209</a></li>
<li>Block separate git directories during clone by <a
href="https://github.com/Byron"><code>@​Byron</code></a> in <a
href="https://redirect.github.com/gitpython-developers/GitPython/pull/2210">gitpython-developers/GitPython#2210</a></li>
<li>fix: harden config parsing boundaries by <a
href="https://github.com/Byron"><code>@​Byron</code></a> in <a
href="https://redirect.github.com/gitpython-developers/GitPython/pull/2211">gitpython-developers/GitPython#2211</a></li>
<li><code>repo.index.add()</code> now respects worktree filters <a
href="https://redirect.github.com/gitpython-developers/GitPython/pull/2209">gitpython-developers/GitPython#2209</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/gitpython-developers/GitPython/compare/3.1.58...3.1.59">https://github.com/gitpython-developers/GitPython/compare/3.1.58...3.1.59</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/66340d77aab9a7468f4aed3681d4ef1e3c0ec931"><code>66340d7</code></a>
prepare changelog prior to release</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/a5e047d0db7047c4249c0de335585470b14d50c4"><code>a5e047d</code></a>
Merge pull request <a
href="https://redirect.github.com/gitpython-developers/GitPython/issues/2211">#2211</a>
from gitpython-developers/config-sanitize-more</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/ef7568e3b317ce617eacda39b8b54dcdff8c3b5c"><code>ef7568e</code></a>
fix: ignore includes in submodule configuration</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/4b4e47fc1224e23b0c8ee7220a7192818f2e4abb"><code>4b4e47f</code></a>
fix: preserve multiline config values when writing</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/b473abb0f7de754392e1ec923f2fe296509013ab"><code>b473abb</code></a>
Merge pull request <a
href="https://redirect.github.com/gitpython-developers/GitPython/issues/2210">#2210</a>
from gitpython-developers/fix-clone-unsafe-option</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/5ff52cccca770fd69c6caf0b8f281d3e45d599be"><code>5ff52cc</code></a>
Merge pull request <a
href="https://redirect.github.com/gitpython-developers/GitPython/issues/2209">#2209</a>
from caroescm/fix-index-add-chmod</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/b68afff45af0f49e79a3e2d2162018986b37ad5d"><code>b68afff</code></a>
Block separate git directories during clone</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/93677a00ab9dcb06cc08595fd1f88a4b4a0fa23b"><code>93677a0</code></a>
fix: <code>index.add()</code> now supports filters (<a
href="https://redirect.github.com/gitpython-developers/GitPython/issues/2021">#2021</a>)</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/9729ed3b948f2bde09f1f188c5311e172212b67e"><code>9729ed3</code></a>
Merge pull request <a
href="https://redirect.github.com/gitpython-developers/GitPython/issues/2208">#2208</a>
from gitpython-developers/security-fixes</li>
<li><a
href="https://github.com/gitpython-developers/GitPython/commit/ce9d8e8d150e06ae2e2cc2efa229071cd3048a93"><code>ce9d8e8</code></a>
prepare next release</li>
<li>Additional commits viewable in <a
href="https://github.com/gitpython-developers/GitPython/compare/3.1.58...3.1.59">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=gitpython&package-manager=pip&previous-version=3.1.58&new-version=3.1.59)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/element-hq/synapse/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
### Pull Request Checklist

Replacement for element-hq/synapse#19752 as that
has bit-rotted with element-hq/synapse#19895
being merged.

`/_synapse/mas` is mounted on a worker on matrix.org and can be seen to
be workerisable via
*
https://github.com/element-hq/synapse/blob/v1.160.0/synapse/app/generic_worker.py#L202
*
https://github.com/element-hq/synapse/blob/v1.160.0/synapse/rest/synapse/client/__init__.py#L71
*
https://github.com/element-hq/synapse/blob/v1.160.0/synapse/rest/synapse/mas/__init__.py#L46-L71

<!-- 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))
…le (#20210)

### Pull Request Checklist

Missed off of https://github.com/element-hq/synapse/pull/19926/changes
IMO. My reading of
https://github.com/element-hq/synapse/blob/v1.161.0rc1/synapse/rest/client/delayed_events.py
is that the new endpoint (pattern
`r"/org\.matrix\.msc4140/delayed_events/(?P<delay_id>[^/]+)$"` is
workerisable) given how `register_servlets` flows. However given
`UpdateDelayedEventServlet` covers the same pattern but for `POST`
requests, this should go in the `GET` only part of the documentation.

<!-- 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))
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 element-hq/synapse#19718 for the
storage functions it makes.

Split out from element-hq/synapse#19425

Part of a series of 5x PRs to land the federation part of
[MSC4242](matrix-org/matrix-spec-proposals#4242)
([storage](element-hq/synapse#19718),
[fedclient](element-hq/synapse#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>
Fixes: #20167

The `Schema Diff` workflow posts a PR comment showing the effective
schema diff. For PRs from forks, `GITHUB_TOKEN` is downgraded to
read-only, so the comment-posting step was silently failing.

### Changes
- `schema_diff.yml`: only post the comment directly when the PR is from
the same repository. For forked PRs, upload the diff (and PR number) as
a short-lived artifact instead of trying to comment.
- `schema_diff_comment.yml` (new): triggered by `workflow_run` after
`Schema Diff` completes, with `pull-requests: write` permission (granted
because this workflow always runs in the context of the base
repository). It downloads the artifact, if present, and posts the
comment on behalf of the forked PR.

This avoids `pull_request_target`, per the security concerns raised in
the issue (zizmor flags it as dangerous). The new workflow only ever
treats the downloaded artifact as inert comment text -- it is never
executed.

---------

Co-authored-by: Olivier 'reivilibre <oliverw@element.io>
Part of: #19415

TLDR: return the `M_UNKNOWN_DEVICE` error code instead of the unstable
`ORG.MATRIX.MSC4326.M_UNKNOWN_DEVICE` identifier.

> **[Added in `v1.17`]** Application services MAY similarly masquerade
as a specific device ID belonging the user ID through use of the
`device_id` query string parameter on the request. If the given device
ID is not known to belong to the user, the server will return a 400
`M_UNKNOWN_DEVICE` error.
>
> — [Matrix v1.19, Application Service API — Identity
assertion](https://spec.matrix.org/v1.19/application-service-api/#identity-assertion)

Synapse returns the correct 400, but with the unstable identifier.
MSC4326 was stabilized in Matrix 1.17 and its experimental flag was
already removed in #19033; only the error code identifier was left
behind.

Before:

```
GET /_matrix/client/v3/sync?user_id=@alice:test&device_id=NOT_A_REAL_DEVICE_ID  # appservice token
  400 {"errcode": "ORG.MATRIX.MSC4326.M_UNKNOWN_DEVICE"}
```

After:

```
GET /_matrix/client/v3/sync?user_id=@alice:test&device_id=NOT_A_REAL_DEVICE_ID  # appservice token
  400 {"errcode": "M_UNKNOWN_DEVICE"}
```

I verified that no implementation was currently handling the prefixed
error code.
Part of: #19414

When
[MSC4133](matrix-org/matrix-spec-proposals#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](matrix-org/matrix-spec-proposals#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))
… changes, making federation support more reliable. (#20204)

Part of: MSC4354

Experimental feature tracking issue:
element-hq/synapse#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>
…omplement suite fails. (#20161)

Supersedes: element-hq/synapse-private#155

It would be useful to have the in-repo Complement suite give a status,
even when the normal suite fails (e.g. flakes).

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Co-authored-by: Andrew Morgan <andrew@amorgan.xyz>
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
…eparation and completion. (#20166)

A key refactoring for, and split out of,
element-hq/synapse#20165

Would be easier to land first to isolate the diff.

Should be a standalone change with no behavioural change.

Motivation is that #20165 will round-robin between 'main queue'
transactions and 'sticky event' transactions.
To keep the data flow clear, I wanted to insert a typed struct (well,
`attrs` dataclass) as an interface between the 'preparation' of a
transaction and its 'completion'.
Doing this whilst keeping the asynchronous context manager style did not
lead to a readable result in my opinion.
(I would also say the async context manager is a touch 'magic' /
obscures control flow, but I suspect this is largely down to opinion.)

Replace _TransactionQueueManager with prepare/complete transaction
methods

---------

Signed-off-by: Olivier 'reivilibre <oliverw@matrix.org>
…room version "12" creation events (#19768)
…ith 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>
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>
…ulating the room summary (#20205)

Fix #19905

Directly retrieve the `m.room.join_rules` event so the room summary data
is correct and matches `allowed_room_ids`. Otherwise there could be a
mis-match delay or the `join_rule` could be missing altogether.
…token falls inside a persist batch (#20171)

This PR fixes the issue described as comment here:
element-hq/synapse#18793 (comment)

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))
…115)

This partially fixes the bug
element-hq/synapse#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](matrix-org/matrix-spec#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))
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))
… (#20224)

See https://github.com/element-hq/synapse-private/blob/pro/.dockerignore

Spawning from element-hq/synapse-private#169
where because we now have 'Synapse Variants' builds for the Synapse Pro
container images, we can revert our special `docker/` changes back to
match this repo. In this case, the new comments here make some sense so
let's keep it ⏩
### 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))

Replaces #20198 to remove git issues
Requires
* #19768 
* #19782 
* matrix-org/complement#915

To meet the requirements for bumping Synapse to support [Matrix spec to
1.16](element-hq/synapse#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](element-hq/synapse@c005e96)
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](element-hq/synapse@5ba81ad)
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](element-hq/synapse@e408cef)
for comparing lists of dicts for a select subset of keys/values. This is
used to compare stripped state selections while waiting on
element-hq/synapse#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>
barodeur and others added 12 commits September 18, 2026 12:00
This provides configurable (via `rc_profile`) rate limits for profile
endpoints:
- `GET /profile/{username}`
- `GET /profile/{username}/{keyName}` including (`displayname` &
`avatar_url`)

### 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: Erik Johnston <erik@matrix.org>
For state filters that ask for concrete types. This allows us to cache
the common case of asking for a specific type/state key.

I noticed a bunch of queries in the jaeger traces that could be cached.
Ports the logcontext classes to Rust, and gives tokio tasks a captured
logcontext so that work running in (or spawned from) Rust is attributed
to the request that caused it.

1. **Add characterization tests for logcontext error messages and the
filter** — pins the exact `logcontext_error` message shapes, the
abuse-detection code paths and `LoggingContextFilter`'s observable
behaviour, *against the existing Python implementation* (this commit is
green on its own). These are the behavioural contract the port has to
satisfy.
2. **Port `ContextResourceUsage` to a Rust pyclass** — self-contained:
the new `synapse_rust.logcontext` module, the class, its stub and the
re-export.
3. **Move the logcontext storage and `LoggingContext` to Rust** — the
core change; the commit message carries detailed design notes.
Highlights:
- The slot is typed `Option<Py<LoggingContext>>`, with `None`
representing the sentinel. `_Sentinel`/`SENTINEL_CONTEXT` stay pure
Python (unchanged); thin wrappers on
`current_context`/`set_current_context` convert at the boundary, and
pyo3's extraction enforces the type (`TypeError` otherwise).
- The accounting is native: one `getrusage(RUSAGE_THREAD)` read per
switch via libc, inline `stop`/`start` bookkeeping for base
`LoggingContext`s, Python dispatch only for subclasses
(`BackgroundProcessLoggingContext`) so their overrides run. The thread
id comes from `PyThread_get_thread_ident` (the exact
`threading.get_ident()`
     value) without calling into Python.
- The hot paths avoid per-operation allocation: names are `Py<PyString>`
(the per-log-record `str(context)`/`server_name` reads are INCREF-only),
error branches materialise strings only when hit.
4. **Attribute Rust-spawned work to the caller's logcontext** —
`create_deferred` captures the caller's context and scopes it onto the
spawned task via a tokio task-local (`LogContextHandle`);
`current_context()` gives the task-local read precedence, so
`LoggingContextFilter`/`pyo3-log` resolve the right context on worker
threads with no per-record stamping. `run_python_awaitable` restores the
captured context (via a `with_logcontext` helper, the Rust
`PreserveLoggingContext`) around Python called back from Rust, so e.g.
`runInteraction` from the Rust `/versions` handler accounts its DB usage
against the right request. Integration tests exercise both guarantees
through real production code paths.

Follow-up work on top of this (separate PR): porting
`BackgroundProcessLoggingContext` natively and removing further `Py<_>`
indirections. The fact that `BackgroundProcessLoggingContext` is a
subclass is what forces some of the warts in this PR: e.g. having to use
`Py<LoggingContext>` everywhere, etc.

We don't try (yet) to make this pure Rust, instead we see this as simply
maintaining the Python logcontext machinery when crossing, rather than
trying to make a Rust equivalent that can be used by pure Rust
dependencies. We probably do want to do that in future, as well as wire
up e.g. CPU recording on Rust side, but that is unnecessary for now.
This is an attempt to better cache the cases where there are a large
number of extremities to resolve over, which keep slightly changing.
This spawns from seeing issues on matrix.org.

We already have a cache over the exact state groups being resolved.
However, we can do better by caching the inputs into state res (i.e. the
conflicted sets), which are more likely to be constant across repeated
state res in a room. We key this cache based on a sha256 hash, on the
assumption that this will never conflict.

Also includes a commit that removes needless copying of the state.
…meServer` (#20011)

Previously the tokio runtime was stashed in a hidden attribute on the
reactor object, installed lazily by whichever Rust code first needed it,
and started via `callWhenRunning`.

Instead, we create a `RustRuntime` (accessible via
`HomeServer.get_rust_runtime()`) that holds any per-reactor Rust state,
such as the tokio runtime. It is constructed lazily on use. Rust
consumers (`HttpClient`, `VersionsHandler`, the Python DB pool wrapper)
now receive the runtime or reactor handle explicitly, and the
`reactor.run()` / manual-startup workarounds in tests are no longer
needed.

We also add helper wrappers in Rust for `Reactor` and `HomeServer` that
exposes the needed functionality.

The aim is to allow us to have a Rust-side clock (mainly to get the
current time), that respects the unit test per-reactor time management.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: dependabot[bot] <support@github.com>
When a stream advances in the database but stops being replicated to a
process, that process's view of the stream freezes. Requests that wait
for it to catch up to a token issued by another worker then time out and
return empty responses indefinitely (see #20080), and nothing exported
said so.

Report `get_current_token` from every ID generator, on every process.
The value is comparable between processes, so a stream that has stopped
reaching one of them shows up as divergence with no client traffic
needed. It is also the position that `wait_for_stream_token` waits on,
so its divergence is the failure itself rather than a proxy for it.

Being a watermark over gapless runs of persisted IDs, it also catches a
single writer of a sharded stream going quiet, which a maximum across
writers would hide behind the writers still being replicated.
…over federation and always include `m.room.create` event (#19723)

### Background

This PR was originally just trying to remove the flawed [MSC4311](matrix-org/matrix-spec-proposals#4311) partial implementation as client side API's like `/sync` should still use stripped events. But it turns out we were just re-using the client logic for the federation side and things might break if we didn't include the full `m.room.create` event so this PR now introduces MSC4311 support to use full PDU's in the `invite_room_state`/`knock_room_state` in the federation API's.

The flawed implementation was originally introduced in element-hq/synapse@0eb7252 (no PR I assume because part of Hydra security fix) which was part of [Synapse v1.136.0](https://github.com/element-hq/synapse/blob/7530874a1250d6ad975b39582a784c594d29a505/CHANGES.md#synapse-11360-2025-08-12).

Spawning from reviewing element-hq/synapse#19722 and noticing that we have [`TestMSC4311FullCreateEventOnStrippedState`](https://github.com/matrix-org/complement/blob/1e2e12eebc1edb27bbf12108ec849a8254b6ddcd/tests/v12_test.go#L1341-L1376) in Complement which already passes even though that test looks [flawed](matrix-org/complement#791 (comment)):

> I think this test is mixing up what [MSC4311](matrix-org/matrix-spec-proposals#4311) proposes. Perhaps these were changes to the MSC that came after?
> 
> For the client API's like `/sync`, it only proposes that `m.room.create` is a required *stripped* state event.
> 
> For the federation API's, alongside requiring `m.room.create`, it also mandates using the full event PDU format for all events in the `invite_room_state`/`knock_room_state` on `m.room.member` events (in `unsigned`)

### What does this PR do?

 1. Always use stripped state for client API's
    1. Remove flawed [MSC4311](matrix-org/matrix-spec-proposals#4311) partial implementation (as explained above)
    1. Sanitize stripped state when we receive events over federation
 1. Use full PDU's when sending `invite_room_state`/`knock_room_state` over federation
 1. Validate PDU's and warn when receiving `invite_room_state`/`knock_room_state` over federation
     1. In the future, we will strictly validate and reject

Complement tests: matrix-org/complement#796

---

Part of element-hq/synapse#19414
@itsoyou
itsoyou requested a review from a team as a code owner September 30, 2026 11:57

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8e9756a. Configure here.

Comment thread rust/src/logging/context.rs
@codecov

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.30769% with 128 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.07%. Comparing base (9005cfc) to head (8321b71).

Files with missing lines Patch % Lines
synapse/handlers/federation.py 53.67% 55 Missing and 8 partials ⚠️
synapse/storage/databases/main/sticky_events.py 85.36% 6 Missing and 6 partials ⚠️
synapse/federation/federation_client.py 38.88% 10 Missing and 1 partial ⚠️
synapse/federation/federation_server.py 66.66% 6 Missing and 5 partials ⚠️
synapse/federation/sender/per_destination_queue.py 88.05% 5 Missing and 3 partials ⚠️
synapse/storage/databases/main/state.py 83.87% 3 Missing and 2 partials ⚠️
synapse/handlers/message.py 50.00% 3 Missing and 1 partial ⚠️
synapse/replication/tcp/client.py 40.00% 1 Missing and 2 partials ⚠️
synapse/storage/databases/main/events_worker.py 84.21% 2 Missing and 1 partial ⚠️
synapse/handlers/room_summary.py 71.42% 0 Missing and 2 partials ⚠️
... and 5 more
Additional details and impacted files
@@           Coverage Diff            @@
##           master     #288    +/-   ##
========================================
  Coverage   81.07%   81.07%            
========================================
  Files         509      509            
  Lines       73447    73728   +281     
  Branches    11124    11193    +69     
========================================
+ Hits        59546    59775   +229     
- Misses      10588    10631    +43     
- Partials     3313     3322     +9     
Files with missing lines Coverage Δ
synapse/api/auth/__init__.py 100.00% <100.00%> (ø)
synapse/api/auth/mas.py 78.77% <ø> (ø)
synapse/api/constants.py 100.00% <100.00%> (ø)
synapse/api/errors.py 88.37% <100.00%> (ø)
synapse/config/ratelimiting.py 100.00% <100.00%> (ø)
synapse/config/redis.py 93.93% <100.00%> (+0.60%) ⬆️
synapse/config/server.py 69.30% <100.00%> (ø)
synapse/events/utils.py 94.24% <100.00%> (+0.91%) ⬆️
synapse/federation/sender/__init__.py 80.62% <100.00%> (+0.05%) ⬆️
synapse/federation/transport/server/federation.py 75.98% <100.00%> (+0.07%) ⬆️
... and 38 more

... and 3 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9005cfc...8321b71. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jason-famedly jason-famedly left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
🚀

@itsoyou
itsoyou enabled auto-merge October 2, 2026 12:25
@itsoyou
itsoyou added this pull request to the merge queue Oct 2, 2026
Merged via the queue into master with commit 08a8de7 Oct 2, 2026
71 of 75 checks passed
@itsoyou
itsoyou deleted the famedly-release/v1.162 branch October 2, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.