From 3ec3737a4731162b52c24487f898ce70fedae049 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 21 Feb 2023 17:59:15 +0000 Subject: [PATCH 1/4] Change the server aggregation for edits --- .../client_server/newsfragments/1440.feature | 1 + .../modules/event_replacements.md | 52 ++++++++++++------- 2 files changed, 33 insertions(+), 20 deletions(-) create mode 100644 changelogs/client_server/newsfragments/1440.feature diff --git a/changelogs/client_server/newsfragments/1440.feature b/changelogs/client_server/newsfragments/1440.feature new file mode 100644 index 000000000..366158214 --- /dev/null +++ b/changelogs/client_server/newsfragments/1440.feature @@ -0,0 +1 @@ +Changes to the server-side aggregation of `m.replace` (edit) events, per [MSC3925](https://github.com/matrix-org/matrix-spec-proposals/pull/3925). diff --git a/content/client-server-api/modules/event_replacements.md b/content/client-server-api/modules/event_replacements.md index a4257fc3a..f3f728d3c 100644 --- a/content/client-server-api/modules/event_replacements.md +++ b/content/client-server-api/modules/event_replacements.md @@ -133,13 +133,6 @@ being overwritten entirely by `m.new_content`, with the exception of `m.relates_ which is left *unchanged*. Any `m.relates_to` property within `m.new_content` is ignored. -{{% boxes/note %}} -Note that server implementations must not *actually* overwrite -the original event's `content`: instead the server presents it as being overwritten -when it is served over the client-server API. See [Server-side replacement of content](#server-side-replacement-of-content) -below. -{{% /boxes/note %}} - For example, given a pair of events: ```json @@ -199,10 +192,11 @@ Note that there can be multiple events with an `m.replace` relationship to a given event (for example, if an event is edited multiple times). These should be [aggregated](#aggregations) by the homeserver. -The aggregation format of `m.replace` relationships gives the `event_id`, -`origin_server_ts`, and `sender` of the **most recent** replacement event. The -most recent event is determined by comparing `origin_server_ts`; if two or more -replacement events have identical `origin_server_ts`, the event with the +The aggregation format of `m.replace` relationships gives the **most recent** +replacement event, formatted as normal for the client-server API (see [Room Event Format](#room-event-format)). + +The most recent event is determined by comparing `origin_server_ts`; if two or +more replacement events have identical `origin_server_ts`, the event with the lexicographically largest `event_id` is treated as more recent. This aggregation is bundled under the `unsigned` property as `m.relations` for any @@ -211,16 +205,35 @@ event that is the target of an `m.replace` relationship. For example: ```json { "event_id": "$original_event_id", - // irrelevant fields not shown + "type": "m.room.message", + "content": { + "body": "I really like cake", + "msgtype": "m.text", + "formatted_body": "I really like cake" + }, "unsigned": { "m.relations": { "m.replace": { "event_id": "$latest_edit_event_id", "origin_server_ts": 1649772304313, "sender": "@editing_user:localhost" + "type": "m.room.message", + "content": { + "body": "* I really like *chocolate* cake", + "msgtype": "m.text", + "m.new_content": { + "body": "I really like *chocolate* cake", + "msgtype": "m.text" + }, + "m.relates_to": { + "rel_type": "m.replace", + "event_id": "$original_event_id" + } + } } } } + // irrelevant fields not shown } ``` @@ -231,15 +244,14 @@ subsequent replacements are themselves redacted). Note that this behaviour is specific to the `m.replace` relationship. See also [redactions of edited events](#redactions-of-edited-events) below. -##### Server-side replacement of content - -Whenever an `m.replace` is to be bundled with an event as above, the server -should also modify the content of the original event according to the -`m.new_content` of the most recent replacement event (determined as above). +{{< changed-in v="1.7" >}} In previous versions of the specification, only the +`event_id`, `origin_server_ts`, and `sender` of the replacement event were included +in the aggregation. v1.7 extends the aggregation to the full event. -An exception applies to [`GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}`](#get_matrixclientv3roomsroomideventeventid), -which should return the unmodified event (though the relationship should still -be bundled, as described above). +{{< changed-in v="1.7" >}} In previous versions of the specification, servers +were expected to replace the content of the original event with that of the +replacement event. However that behaviour made reliable client-side +implementation difficult, and servers should no longer make this replacement. #### Client behaviour From 97b7544f2c212ef19323c1f835607e3b57331593 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 28 Feb 2023 14:19:51 +0000 Subject: [PATCH 2/4] Address review comments --- .../client_server/newsfragments/1440.feature | 2 +- .../modules/event_replacements.md | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/changelogs/client_server/newsfragments/1440.feature b/changelogs/client_server/newsfragments/1440.feature index 366158214..119ab2d6d 100644 --- a/changelogs/client_server/newsfragments/1440.feature +++ b/changelogs/client_server/newsfragments/1440.feature @@ -1 +1 @@ -Changes to the server-side aggregation of `m.replace` (edit) events, per [MSC3925](https://github.com/matrix-org/matrix-spec-proposals/pull/3925). +Changes to the server-side aggregation of `m.replace` (edit) events, as per [MSC3925](https://github.com/matrix-org/matrix-spec-proposals/pull/3925). diff --git a/content/client-server-api/modules/event_replacements.md b/content/client-server-api/modules/event_replacements.md index f3f728d3c..b15f93faf 100644 --- a/content/client-server-api/modules/event_replacements.md +++ b/content/client-server-api/modules/event_replacements.md @@ -188,12 +188,14 @@ replacement event. ##### Server-side aggregation of `m.replace` relationships +{{< changed-in v="1.7" >}} + Note that there can be multiple events with an `m.replace` relationship to a given event (for example, if an event is edited multiple times). These should be [aggregated](#aggregations) by the homeserver. The aggregation format of `m.replace` relationships gives the **most recent** -replacement event, formatted as normal for the client-server API (see [Room Event Format](#room-event-format)). +replacement event, formatted as normal (see [Room Event Format](#room-event-format)). The most recent event is determined by comparing `origin_server_ts`; if two or more replacement events have identical `origin_server_ts`, the event with the @@ -237,21 +239,23 @@ event that is the target of an `m.replace` relationship. For example: } ``` -If the original event is -[redacted](#redactions), any +If the original event is [redacted](#redactions), any `m.replace` relationship should **not** be bundled with it (whether or not any subsequent replacements are themselves redacted). Note that this behaviour is specific to the `m.replace` relationship. See also [redactions of edited events](#redactions-of-edited-events) below. -{{< changed-in v="1.7" >}} In previous versions of the specification, only the -`event_id`, `origin_server_ts`, and `sender` of the replacement event were included -in the aggregation. v1.7 extends the aggregation to the full event. - -{{< changed-in v="1.7" >}} In previous versions of the specification, servers -were expected to replace the content of the original event with that of the -replacement event. However that behaviour made reliable client-side -implementation difficult, and servers should no longer make this replacement. +**Note:** the `content` of the original event is left intact. In particular servers +should **not** replace the content with that of the replacement event. + +{{ boxes/rationale }} +In previous versions of the specification, servers were expected to replace the +content of an edited event whenever it was served to clients (with the +exception of the +[`GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}`](#get_matrixclientv3roomsroomideventeventid) +endpoint). However, that behaviour made reliable client-side implementation +difficult, and servers should no longer make this replacement. +{{ /boxes/rationale }} #### Client behaviour From 05d1779d1fa6e9e56bc32c20e6ca20aeb9dee762 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 28 Feb 2023 14:24:30 +0000 Subject: [PATCH 3/4] Clients cannot ignore edits --- .../modules/event_replacements.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/content/client-server-api/modules/event_replacements.md b/content/client-server-api/modules/event_replacements.md index b15f93faf..c9cfb5a2e 100644 --- a/content/client-server-api/modules/event_replacements.md +++ b/content/client-server-api/modules/event_replacements.md @@ -259,17 +259,9 @@ difficult, and servers should no longer make this replacement. #### Client behaviour -Clients can often ignore `m.replace` events, because any events returned -by the server to the client will be updated by the server to account for -subsequent edits. - -However, clients should apply the replacement themselves when the server is -unable to do so. This happens in the following situations: - - * The client has already received and stored the original event before the - message edit event arrives. - - * The original event (and hence its replacement) are encrypted. +Since the server will not replace the content of any edited events, clients +should take note of any replacement events they receive, and apply the +replacement whenever possible and appropriate. Client authors are reminded to take note of the requirements for [Validity of replacement events](#validity-of-replacement-events), and to ignore any From f6063f939170068ec21f639250e56bb643817800 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 28 Feb 2023 14:41:18 +0000 Subject: [PATCH 4/4] more review tweaks --- content/client-server-api/modules/event_replacements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/client-server-api/modules/event_replacements.md b/content/client-server-api/modules/event_replacements.md index c9cfb5a2e..a50ba830e 100644 --- a/content/client-server-api/modules/event_replacements.md +++ b/content/client-server-api/modules/event_replacements.md @@ -195,7 +195,7 @@ given event (for example, if an event is edited multiple times). These should be [aggregated](#aggregations) by the homeserver. The aggregation format of `m.replace` relationships gives the **most recent** -replacement event, formatted as normal (see [Room Event Format](#room-event-format)). +replacement event, formatted [as normal](#room-event-format). The most recent event is determined by comparing `origin_server_ts`; if two or more replacement events have identical `origin_server_ts`, the event with the