MSC4370: Federation endpoint for retrieving current extremities#4370
MSC4370: Federation endpoint for retrieving current extremities#4370
Conversation
There was a problem hiding this comment.
Implementation requirements:
- Server (calling)
- Server (serving)
There was a problem hiding this comment.
I'd recommend waiting to implement this MSC until it has a reasonably healthy amount of review given the security considerations.
There was a problem hiding this comment.
This MSC has not had the healthy amount of review recommended, but I've started an implementation anyway: element-hq/synapse#19314
I intend to keep that PR in a draft state until MSC review can happen, disqualifying it as an implementation for now.
There was a problem hiding this comment.
There's been some review on this, so the implementation was put forward for review and has now landed. Next steps are to get it implemented in another server, probably policyserv.
This comment was marked as duplicate.
This comment was marked as duplicate.
| this may mean requesting state at each event and merging the results for a good enough representation | ||
| of current state - specific handling is left as an implementation detail. | ||
|
|
||
| ## Potential issues |
There was a problem hiding this comment.
This doesn't seem to consider v1 or v2 rooms, which have
prev_eventslaid out differently.
(please use threads to ensure comments are visible and can be replied to)
There was a problem hiding this comment.
in all honesty, I'm not concerned about v1 or v2 rooms at this point in our history. If a server really wants to support those room versions, it can call this endpoint then the GET /event/:eventId endpoint to get the hash, then wedge that tuple into whatever it needs to.
| @@ -0,0 +1,141 @@ | |||
| # MSC4370: Federation endpoint for retrieving current extremities | |||
There was a problem hiding this comment.
Overall, I approve of this MSC. We need something like this in order to ensure eventual delivery in Matrix. MSC4242 actually talks about this:
In current Matrix, eventual delivery of events is only ensured under the assumption that any server continuously sends new events. The additional assumption is needed because homeservers do not eagerly share known forward extremities with each other: it relies on servers sending events. As such, you can have two servers who disagree on the current state because one server is aware of events that affect the current state and the other is not. This is less of a problem than the soft-failure case because it will correct itself when an event is sent, but the system requires some external input to provide eventual delivery, in order to eventually converge. This will be addressed in a future MSC.
Having an endpoint which is compatible with those aims as well as policy server's aims would be helpful.
That being said.. what exactly does the policy server do with the information it gets from this new endpoint? The proposal as written is unclear:
so it may then retrieve the current state for the room
that server can request (and cache) current state whenever it feels it needs to rather than waiting for a remote server to become active.
There is no such endpoint to do this today. The closest is GET /_matrix/federation/v1/state/{roomId} but this only accepts a single event ID. It is not secure to just pick a random prev event and use that state, nor is it secure to just merge individual states together without doing state resolution.
There was a problem hiding this comment.
In policyserv, there's a concept of "trusted" servers that it's willing to learn state from. Currently, that state learning happens when policyserv receives an event from one of those trusted servers. It uses that event's ID to make a /state request if it hasn't updated its room state in a while. This can cause its state information to be old if the trusted server doesn't send an event for a while, which isn't great.
The hope is to keep that same "call /state with an event ID" logic, but using the trusted server's extremities. If there's multiple extremities, the policy server can send an event, wait a bit, then learn state off its own event ID. This does mean that a server becomes trusted to not only supply resolved state, but also trusted to be moderately up to date on the room to provide recent extremities.
This isn't perfectly secure because yes, the state can and does change depending on how you look at the DAG, but /state is supposed to do that state resolution to some degree, and the policy server in this case isn't actually that concerned with it being a perfect representation of state anyway. If it gets "wrong" state, it will mean the cache of some state events is a little broken for a bit. In policyserv, that might mean not recognizing a recently-promoted admin as an admin or missing a policy rule from a moderation bot - both of these are easily correctable the next time the cron job runs.
Aside from that, the policy server can also use the extremities from a (trusted) server to send its own redactions and other events without having to bear the burden of the DAG itself.
| ``` | ||
| Content-Type: application/json | ||
| { | ||
| "prev_events": ["$event1", "$event2"] |
There was a problem hiding this comment.
Must this contain ALL prev_events, even if there are thousands of them? Millions? There is unfortunately no limit to how many forward extremities you can have.
There was a problem hiding this comment.
it should be "whatever you'd need to send an event", which I think is limited in some way. Will clarify in the MSC if it's not already there.
| } | ||
| ``` | ||
|
|
||
| The response is contained in an object for future expansion. `prev_events` is required, and MUST have |
There was a problem hiding this comment.
(Minor: Is prev_events a good name for this, or is it a Synapsism? They aren't really 'previous' to anything yet. I'm not fussy though.)
There was a problem hiding this comment.
The theory is someone could just copy the object on top of an event template, though that's not exactly a thing we need to support.
MSC (recommended reading): matrix-org/matrix-spec-proposals#4370 ### 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: turt2live <1190097+turt2live@users.noreply.github.com> Co-authored-by: Olivier 'reivilibre' <oliverw@element.io>
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [element-hq/synapse](https://github.com/element-hq/synapse) | minor | `v1.149.1` → `v1.150.0` | --- ### Release Notes <details> <summary>element-hq/synapse (element-hq/synapse)</summary> ### [`v1.150.0`](https://github.com/element-hq/synapse/releases/tag/v1.150.0) [Compare Source](element-hq/synapse@v1.149.1...v1.150.0) ### Synapse 1.150.0 (2026-03-24) No significant changes since 1.150.0rc1. ### Synapse 1.150.0rc1 (2026-03-17) #### Features - Add experimental support for the [MSC4370](matrix-org/matrix-spec-proposals#4370) Federation API `GET /extremities` endpoint. ([#​19314](element-hq/synapse#19314)) - [MSC4140: Cancellable delayed events](matrix-org/matrix-spec-proposals#4140): When persisting a delayed event to the timeline, include its `delay_id` in the event's `unsigned` section in `/sync` responses to the event sender. ([#​19479](element-hq/synapse#19479)) - Expose [MSC4354 Sticky Events](matrix-org/matrix-spec-proposals#4354) over the legacy (v3) /sync API. ([#​19487](element-hq/synapse#19487)) - When Matrix Authentication Service (MAS) integration is enabled, allow MAS to set the user locked status in Synapse. ([#​19554](element-hq/synapse#19554)) #### Bugfixes - Fix `Build and push complement image` CI job pointing to non-existent image. ([#​19523](element-hq/synapse#19523)) - Fix a bug introduced in v1.26.0 that caused deactivated, erased users to not be removed from the user directory. ([#​19542](element-hq/synapse#19542)) #### Improved Documentation - In the Admin API documentation, always express path parameters as `/<param>` instead of as `/$param`. ([#​19307](element-hq/synapse#19307)) - Update docs to clarify `outbound_federation_restricted_to` can also be used with the [Secure Border Gateway (SBG)](https://element.io/en/server-suite/secure-border-gateways). ([#​19517](element-hq/synapse#19517)) - Unify Complement developer docs. ([#​19518](element-hq/synapse#19518)) #### Internal Changes - Put membership updates in a background resumable task when changing the avatar or the display name. ([#​19311](element-hq/synapse#19311)) - Add in-repo Complement test to sanity check Synapse version matches git checkout (testing what we think we are). ([#​19476](element-hq/synapse#19476)) - Migrate `dev` dependencies to [PEP 735](https://peps.python.org/pep-0735/) dependency groups. ([#​19490](element-hq/synapse#19490)) - Remove the optional `systemd-python` dependency and the `systemd` extra on the `synapse` package. ([#​19491](element-hq/synapse#19491)) - Avoid re-computing the event ID when cloning events. ([#​19527](element-hq/synapse#19527)) - Allow caching of the `/versions` and `/auth_metadata` public endpoints. ([#​19530](element-hq/synapse#19530)) - Add a few labels to the number groupings in the `Processed request` logs. ([#​19548](element-hq/synapse#19548)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My44NC4yIiwidXBkYXRlZEluVmVyIjoiNDMuODQuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=--> Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/5040 Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net> Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Rendered
Disclosure: I am Director of Standards Development at The Matrix.org Foundation C.I.C., Matrix Spec Core Team (SCT) member, employed by Element, and operate the t2bot.io service. This proposal is written and published as a Trust & Safety team member allocated in full to the Foundation.