From c9794d41e440f1d370607e8b6de5507a1ec15481 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 7 Jul 2020 15:33:37 -0400 Subject: [PATCH 001/109] initial version of serverside aggregations proposal --- proposals/xxxx-aggregations-server.md | 339 ++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 proposals/xxxx-aggregations-server.md diff --git a/proposals/xxxx-aggregations-server.md b/proposals/xxxx-aggregations-server.md new file mode 100644 index 00000000000..514c593e3e8 --- /dev/null +++ b/proposals/xxxx-aggregations-server.md @@ -0,0 +1,339 @@ +# MSCxxxx: Serverside aggregations of message relationships + +It's common to want to send events in Matrix which relate to existing events - +for instance, reactions, edits and even replies/threads. + +Clients typically need to track the related events alongside the original +event they relate to, in order to correctly display them. For instance, +reaction events need to be aggregated together by summing and be shown next to +the event they react to; edits need to be aggregated together by replacing the +original event and subsequent edits; replies need to be indented after the +message they respond to, etc. + +It is possible to treat relations as normal events and aggregate them +clientside, but to do so comprehensively could be very resource intensive, as +the client would need to spider all possible events in a room to find +relationships and maintain an correct view. + +Instead, this proposal seeks to solve this problem by defining APIs to let the +server calculate the aggregations on behalf of the client, and so bundle the +related events with the original event where appropriate. + +This proposal is one in a series of proposals that defines a mechanism for +events to relate to each other. Together, these proposals replace +[MSC1849](https://github.com/matrix-org/matrix-doc/pull/1849). + +* [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) defines a + standard shape for indicating events which relate to other events. +* This proposal defines APIs to let the server calculate the aggregations on + behalf of the client, and so bundle the related events with the original + event where appropriate. +* [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) defines how + users can edit messages using this mechanism. +* [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) defines how + users can annotate events, such as reacting to events with emoji, using this + mechanism. + +## Proposal + +### Receiving relations + +#### Unbundled relation events + +Relations are received during non-gappy incremental syncs (that is, syncs +called with a `since` token, and that have `limited: false` in the portion of +response for the given room) as normal discrete Matrix events. These are +called "unbundled relation events". + +#### Bundled relations + +Other than during non-gappy incremental syncs, an aggregate view of relation +events should be bundled into the unsigned data of the event they relate to, +rather than sending un-bundled individual relation events. This is called a +bundled relation (or bundled aggregation), and by sending a summary of the +aggregations, avoids us having to always send lots of individual unbundled +relation events individually to the client. + +Any API which receives events should bundle relations (apart from non-gappy +incremental syncs), for instance: initial sync, gappy incremental sync, +/messages and /context. + +The bundled relations are grouped according to their `rel_type`, and then +paginated within each group using Matrix's defined pagination idiom of `count`, +`limited` and `chunk` fields - respectively giving the total number of +elements in the list, whether that list has been truncated, and an array of +elements in the list. + +The format of the aggregated value in the bundle depends on the relation type. + +`m.reference` list the `event_id` and event `type` of the events which +reference that event. + +The formats for other relation types may be defined in the proposals that +define the relation types. + +For instance, the below example shows an event with five bundled relations: +three thumbsup reaction annotations, one replace, and one reference. + +```json +{ + ..., + "unsigned": { + "m.relations": { + "m.annotation": { + "chunk": [ + { + "type": "m.reaction", + "key": "👍", + "origin_server_ts": 1562763768320, + "count": 3 + } + ], + "limited": false, + "count": 1 + }, + "m.reference": { + "chunk": [ + { + "type": "m.room.message", + "event_id": "$some_event_id" + } + ], + "limited": false, + "count": 1 + }, + "m.replace": { + "event_id": "$original_event_id", + "origin_server_ts": 1562763768320, + "sender": "@bruno1:localhost" + } + } + } +} +``` + +#### Handling limited (gappy) syncs + +For the special case of a gappy incremental sync, many relations (particularly +reactions) may have occurred during the gap. It would be inefficient to send +each one individually to the client, but it would also be inefficient to send +all possible bundled aggregations to the client. + +The simplest thing a client can do is to just throw away its history for a +room on seeing a gappy incremental sync, and then re-paginate the history of +the room using /messages in order to get a consistent view of the relations +which may have changed during the gap. However, this is quite inefficient, +and prohibits the client from persisting multiple sections of timeline for a +given room. + +Alternatively, the server tells the client the event IDs of events which +predate the gap which received relations during the gap. This means that the +client can invalidate its copy of those events (if any) and then requery them +(including their bundled relations) from the server if/when needed. + +The server does this with the new `stale_events` field of each room object +in the sync response. The `stale_events` field lists all the event IDs +prior to the gap which had updated relations during the gap. The event IDs +are grouped by relation type, and limited to N entries for efficiency. N +should be 100. If the number of events with stale relations exceeds N, the +list is marked as `limited` as per the normal Matrix pagination model. We do +not include events referenced by `m.reference` as stale, in favour of more +sophisticated pagination techniques in future. For instance: + +```json +"!roomid:matrix.org": { + "account_data": {}, + "ephemeral": {}, + "state": {}, + "summary": {}, + "timeline": {}, + "unread_notifications": {}, + "stale_events": { + "m.annotations": { + "chunk": [ + "$12345676321:matrix.org", + "$12345321432:matrix.org" + ], + "limited": false + } + } +} +``` + +This shows that in the gappy sync response, a given room has two events prior +to the gap which received new annotations during the gap. Therefore if the +client has cached a local copy of those events, it should invalidate them, and +subsequently refresh them as needed. + +To refresh events, we need an API to load arbitrary events from the room in +bulk, which the CS API doesn't currently provide. We propose extending GET +`{roomId}/event/{eventId}` to accept a list of event IDs on the URL, e.g: + +`POST /_matrix/client/r0/rooms/{roomId}/event` +```json +{ + "event_ids": [ + "$12345676321:matrix.org", + "$12345321432:matrix.org" + ] +} +``` + +...which returns an array of events with the given IDs. + + XXX: Is this implemented in Synapse yet? + +#### Paginating relations and aggregations + +A single event can have lots of associated relations, and we do not want to +overload the client by including them all in a bundle. Instead, we provide two +new APIs in order to paginate over the relations, which behave in a similar +way to `/messages`, except using `next_batch` and `prev_batch` names (in line +with `/sync` API). Clients can start paginating either from the earliest or +latest events using the `dir` param. + +The `/relations` API lets you iterate over all the **unbundled** relations +associated with an event in standard topological order. You can optionally +filter by a given type of relation and event type: + +``` +GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]] +``` + +```json +{ + "chunk": [ + { + "type": "m.reaction", + "sender": "...", + "content": { } + } + ], + "next_batch": "some_token", + "prev_batch": "some_token" +} +``` + +The endpoint does not have any trailing slashes. + + FIXME: we need to spell out that this API should return the original message + when paginating over `m.replace` relations for a given message. Synapse + currently looks to include this as an `original_event` field alongside + `chunk` on all relations, which feels very redundant when we only need it for + edits. Either we specialcase it for edits, or we just have the client go + call /event to grab the contents of the original? + +The `/aggregations` API lets you iterate over **bundled** relations, and within them. + +To iterate over the bundled relations for an event (optionally filtering by +relation type and target event type): + +``` +GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?filter=id] +``` + +```json +{ + "chunk": [ + { + "type": "m.reaction", + "key": "👍", + "origin_server_ts": 1562763768320, + "count": 5, + } + ], + "next_batch": "some_token", + "prev_batch": "some_token" +} +``` + +The endpoint does not have any trailing slashes. + +Trying to iterate over an relation type which does not use an aggregation key +(i.e. `m.replace` and `m.reference`) should fail with 400 and error +M_INVALID_REL_TYPE. + +To iterate over the unbundled relations within a specific bundled relation, you +use the following API form, identifying the bundle based on its `key` +(therefore this only applies to `m.annotation`, as it is the only current +`rel_type` which groups relations via `key`). + +``` +GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}/${relationType}/{eventType}/{key} +``` + +e.g. + +``` +GET /_matrix/client/r0/rooms/!asd:matrix.org/aggregations/$1cd23476/m.annotation/m.reaction/👍 +``` + +```json +{ + "chunk": [ + { + "type": "m.reaction", + "sender": "...", + "content": { } + }, + ], + "next_batch": "some_token", + "prev_batch": "some_token" +} +``` + +### Redactions + +Trying to call `/relations` or `/aggregations` on a redacted message must return +a 404. + +### Local echo + +As clients only receive unbundled events through /sync, they need to locally +aggregate these unbundled events for their parent event, on top of any +server-side aggregation that might have already happened, to get a complete +picture of the aggregated relations for a given parent event, as a client +might not be aware of all relations for an event. Local aggregation should +thus also take the `m.relation` data in the `unsigned` of the parent event +into account if it has been sent already. The aggregation algorithm is the +same as the one described here for the server. + +For the best possible user experience, clients should also include unsent +relations into the local aggregation. When adding a relation to the send +queue, clients should locally aggregate it into the relations of the parent +event, ideally regardless of the parent event having an `event_id` already or +still being pending. If the client gives up on sending the relation for some +reason, the relation should be de-aggregated from the relations of the parent +event. If the client offers the user a possibility of manually retrying to +send the relation, it should be re-aggregated when the user does so. + +De-aggregating a relation refers to rerunning the aggregation for a given +parent event while not considering the de-aggregated event any more. + +Upon receiving the remote echo for any relations, a client is likely to remove +the pending event from the send queue. Here, it should also de-aggregate the +pending event from the parent event's relations, and re-aggregate the received +remote event from `/sync` to make sure the local aggregation happens with the +same event data as on the server. + +When adding a redaction for a relation to the send queue, the relation +referred to should be de-aggregated from the relations of the target of the +relation. Similar to a relation, when the sending of the redaction fails or +is cancelled, the relation should be aggregated again. + +To support creating relations for pending events, clients will need a way for +events to relate to one another before the `event_id` of the parent event is +known. When the parent event receives its remote echo, the target event id +(`m.relates_to`.`event_id`) of any relations in the send queue will need to be +set the newly received `event_id`. + +Particularly, please remember to let users edit unsent messages (as this is a +common case for rapidly fixing a typo in a msg which is still in flight!) + +## Edge cases + +How do you handle ignored users? + * Information about relations sent from ignored users must never be sent to + the client, either in bundled or unbundled form. This is to let you block + someone from harassing you with emoji reactions (or using edits as a + side-channel to harass you). From 03ce398c85d69f0d83725bedb9a439b80e5b1917 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 7 Jul 2020 16:25:19 -0400 Subject: [PATCH 002/109] fix MSC numbers --- ...aggregations-server.md => 2675-aggregations-server.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename proposals/{xxxx-aggregations-server.md => 2675-aggregations-server.md} (98%) diff --git a/proposals/xxxx-aggregations-server.md b/proposals/2675-aggregations-server.md similarity index 98% rename from proposals/xxxx-aggregations-server.md rename to proposals/2675-aggregations-server.md index 514c593e3e8..7dac3ab3c53 100644 --- a/proposals/xxxx-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -1,4 +1,4 @@ -# MSCxxxx: Serverside aggregations of message relationships +# MSC2675: Serverside aggregations of message relationships It's common to want to send events in Matrix which relate to existing events - for instance, reactions, edits and even replies/threads. @@ -23,14 +23,14 @@ This proposal is one in a series of proposals that defines a mechanism for events to relate to each other. Together, these proposals replace [MSC1849](https://github.com/matrix-org/matrix-doc/pull/1849). -* [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) defines a +* [MSC2674](https://github.com/matrix-org/matrix-doc/pull/2674) defines a standard shape for indicating events which relate to other events. * This proposal defines APIs to let the server calculate the aggregations on behalf of the client, and so bundle the related events with the original event where appropriate. -* [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) defines how +* [MSC2676](https://github.com/matrix-org/matrix-doc/pull/2676) defines how users can edit messages using this mechanism. -* [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) defines how +* [MSC2677](https://github.com/matrix-org/matrix-doc/pull/2677) defines how users can annotate events, such as reacting to events with emoji, using this mechanism. From e5d133ba0a1882da3ee829292c4870117f398a1e Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 2 Jun 2021 17:10:58 -0400 Subject: [PATCH 003/109] clarification --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7dac3ab3c53..4bfc25498aa 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -103,7 +103,7 @@ three thumbsup reaction annotations, one replace, and one reference. "count": 1 }, "m.replace": { - "event_id": "$original_event_id", + "event_id": "$edit_event_id", "origin_server_ts": 1562763768320, "sender": "@bruno1:localhost" } From 2d36c36be7eaea86d36361a7650819dd60e190b8 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 1 Jul 2021 13:28:55 +0000 Subject: [PATCH 004/109] add e2ee section from 2674 here, as it is only needed for server-side aggregations --- proposals/2675-aggregations-server.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4bfc25498aa..fc9e8e5559c 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -282,6 +282,16 @@ GET /_matrix/client/r0/rooms/!asd:matrix.org/aggregations/$1cd23476/m.annotation } ``` + +### End to end encryption + +Since the server has to be able to bundle related events, structural +information about relations must be visible to the server, and so the +`m.relates_to` field must be included in the plaintext. + +A future MSC may define a method for encrypting certain parts of the +`m.relates_to` field that may contain sensitive information. + ### Redactions Trying to call `/relations` or `/aggregations` on a redacted message must return From 8eec329d7d5c525386e2c06cbc9a2ba4e99519d3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 5 Jul 2021 14:33:41 +0000 Subject: [PATCH 005/109] move edge case wrt to calling /context on a relation here from 2674 --- proposals/2675-aggregations-server.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index fc9e8e5559c..66ad508bea8 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -347,3 +347,8 @@ How do you handle ignored users? the client, either in bundled or unbundled form. This is to let you block someone from harassing you with emoji reactions (or using edits as a side-channel to harass you). + +What does it mean to call /context on a relation? + * We should probably just return the root event for now, and then refine it in + future for threading? + * XXX: what does synapse do here? From 343afffc69aac3bb0cfe5710656f2eb7019bcebb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 16:18:37 +0100 Subject: [PATCH 006/109] fix typo --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 66ad508bea8..848f5581dbe 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -54,7 +54,7 @@ bundled relation (or bundled aggregation), and by sending a summary of the aggregations, avoids us having to always send lots of individual unbundled relation events individually to the client. -Any API which receives events should bundle relations (apart from non-gappy +Any API which returns events should bundle relations (apart from non-gappy incremental syncs), for instance: initial sync, gappy incremental sync, /messages and /context. From 8e6c0a3b01fe9d2f6770138b38b41fb93438744d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 16:29:26 +0100 Subject: [PATCH 007/109] clarify which APIs should bundle relations --- proposals/2675-aggregations-server.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 848f5581dbe..2e1b3418d04 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -54,9 +54,15 @@ bundled relation (or bundled aggregation), and by sending a summary of the aggregations, avoids us having to always send lots of individual unbundled relation events individually to the client. -Any API which returns events should bundle relations (apart from non-gappy -incremental syncs), for instance: initial sync, gappy incremental sync, -/messages and /context. +The following Client-Server APIs should bundle relations: + + - `/rooms/{roomId}/messages` + - `/rooms/{roomId}/context` + - `/rooms/{roomId}/event/{eventId}` + - `/sync`, only for room sections in the response where `limited` field is `true`; this amounts to all rooms in the response if the `since` request parameter was not passed, also known as an initial sync. + - `/relations`, as proposed in this MSC. + +Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle relations. The bundled relations are grouped according to their `rel_type`, and then paginated within each group using Matrix's defined pagination idiom of `count`, From d5bbc72acc3ab39f5dafadebb1f9e30c3f0a8963 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 16:44:59 +0100 Subject: [PATCH 008/109] move stale_events over to future extensions section --- proposals/2675-aggregations-server.md | 108 +++++++++++++------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 2e1b3418d04..1555ef4b34f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -118,58 +118,7 @@ three thumbsup reaction annotations, one replace, and one reference. } ``` -#### Handling limited (gappy) syncs - -For the special case of a gappy incremental sync, many relations (particularly -reactions) may have occurred during the gap. It would be inefficient to send -each one individually to the client, but it would also be inefficient to send -all possible bundled aggregations to the client. - -The simplest thing a client can do is to just throw away its history for a -room on seeing a gappy incremental sync, and then re-paginate the history of -the room using /messages in order to get a consistent view of the relations -which may have changed during the gap. However, this is quite inefficient, -and prohibits the client from persisting multiple sections of timeline for a -given room. - -Alternatively, the server tells the client the event IDs of events which -predate the gap which received relations during the gap. This means that the -client can invalidate its copy of those events (if any) and then requery them -(including their bundled relations) from the server if/when needed. - -The server does this with the new `stale_events` field of each room object -in the sync response. The `stale_events` field lists all the event IDs -prior to the gap which had updated relations during the gap. The event IDs -are grouped by relation type, and limited to N entries for efficiency. N -should be 100. If the number of events with stale relations exceeds N, the -list is marked as `limited` as per the normal Matrix pagination model. We do -not include events referenced by `m.reference` as stale, in favour of more -sophisticated pagination techniques in future. For instance: - -```json -"!roomid:matrix.org": { - "account_data": {}, - "ephemeral": {}, - "state": {}, - "summary": {}, - "timeline": {}, - "unread_notifications": {}, - "stale_events": { - "m.annotations": { - "chunk": [ - "$12345676321:matrix.org", - "$12345321432:matrix.org" - ], - "limited": false - } - } -} -``` - -This shows that in the gappy sync response, a given room has two events prior -to the gap which received new annotations during the gap. Therefore if the -client has cached a local copy of those events, it should invalidate them, and -subsequently refresh them as needed. +#### Batch API for fetching events with bundled relations To refresh events, we need an API to load arbitrary events from the room in bulk, which the CS API doesn't currently provide. We propose extending GET @@ -358,3 +307,58 @@ What does it mean to call /context on a relation? * We should probably just return the root event for now, and then refine it in future for threading? * XXX: what does synapse do here? + +## Future extensions + +### Handling limited (gappy) syncs + +For the special case of a gappy incremental sync, many relations (particularly +reactions) may have occurred during the gap. It would be inefficient to send +each one individually to the client, but it would also be inefficient to send +all possible bundled aggregations to the client. + +The simplest thing a client can do is to just throw away its history for a +room on seeing a gappy incremental sync, and then re-paginate the history of +the room using /messages in order to get a consistent view of the relations +which may have changed during the gap. However, this is quite inefficient, +and prohibits the client from persisting multiple sections of timeline for a +given room. + +Alternatively, the server tells the client the event IDs of events which +predate the gap which received relations during the gap. This means that the +client can invalidate its copy of those events (if any) and then requery them +(including their bundled relations) from the server if/when needed. + +The server does this with the new `stale_events` field of each room object +in the sync response. The `stale_events` field lists all the event IDs +prior to the gap which had updated relations during the gap. The event IDs +are grouped by relation type, and limited to N entries for efficiency. N +should be 100. If the number of events with stale relations exceeds N, the +list is marked as `limited` as per the normal Matrix pagination model. We do +not include events referenced by `m.reference` as stale, in favour of more +sophisticated pagination techniques in future. For instance: + +```json +"!roomid:matrix.org": { + "account_data": {}, + "ephemeral": {}, + "state": {}, + "summary": {}, + "timeline": {}, + "unread_notifications": {}, + "stale_events": { + "m.annotations": { + "chunk": [ + "$12345676321:matrix.org", + "$12345321432:matrix.org" + ], + "limited": false + } + } +} +``` + +This shows that in the gappy sync response, a given room has two events prior +to the gap which received new annotations during the gap. Therefore if the +client has cached a local copy of those events, it should invalidate them, and +subsequently refresh them as needed. \ No newline at end of file From 2091034a80f02492f8eabd627e6bd6bbef4f97ca Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 16:49:42 +0100 Subject: [PATCH 009/109] summarize stale_events and make tone conditional to mark that is not part of the MSC --- proposals/2675-aggregations-server.md | 54 +++++---------------------- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 1555ef4b34f..7cee5b7a839 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -313,52 +313,18 @@ What does it mean to call /context on a relation? ### Handling limited (gappy) syncs For the special case of a gappy incremental sync, many relations (particularly -reactions) may have occurred during the gap. It would be inefficient to send +reactions) may have occurred during the gap. It would be inefficient to send each one individually to the client, but it would also be inefficient to send all possible bundled aggregations to the client. -The simplest thing a client can do is to just throw away its history for a -room on seeing a gappy incremental sync, and then re-paginate the history of -the room using /messages in order to get a consistent view of the relations -which may have changed during the gap. However, this is quite inefficient, -and prohibits the client from persisting multiple sections of timeline for a -given room. - -Alternatively, the server tells the client the event IDs of events which -predate the gap which received relations during the gap. This means that the -client can invalidate its copy of those events (if any) and then requery them -(including their bundled relations) from the server if/when needed. - -The server does this with the new `stale_events` field of each room object -in the sync response. The `stale_events` field lists all the event IDs -prior to the gap which had updated relations during the gap. The event IDs -are grouped by relation type, and limited to N entries for efficiency. N -should be 100. If the number of events with stale relations exceeds N, the -list is marked as `limited` as per the normal Matrix pagination model. We do -not include events referenced by `m.reference` as stale, in favour of more -sophisticated pagination techniques in future. For instance: +The server could tell the client the event IDs of events which +predate the gap which received relations during the gap. This means that the +client could invalidate its copy of those events (if any) and then requery them +(including their bundled relations) from the server if/when needed using the proposed extension of the `/event` API for batch requests. -```json -"!roomid:matrix.org": { - "account_data": {}, - "ephemeral": {}, - "state": {}, - "summary": {}, - "timeline": {}, - "unread_notifications": {}, - "stale_events": { - "m.annotations": { - "chunk": [ - "$12345676321:matrix.org", - "$12345321432:matrix.org" - ], - "limited": false - } - } -} -``` +The server could do this with a new `stale_events` field of each room object +in the sync response. The `stale_events` field would list all the event IDs +prior to the gap which had updated relations during the gap. The event IDs +would be grouped by relation type, and paginated as per the normal Matrix pagination model. -This shows that in the gappy sync response, a given room has two events prior -to the gap which received new annotations during the gap. Therefore if the -client has cached a local copy of those events, it should invalidate them, and -subsequently refresh them as needed. \ No newline at end of file +This was originally part of this MSC but left out to limit the scope to what is implemented at the time of writing. \ No newline at end of file From 68c95a408e71194a8e2ae08cc05353a6b4a7d11d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 16:53:05 +0100 Subject: [PATCH 010/109] casing and wording --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7cee5b7a839..941e15bc525 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -54,7 +54,7 @@ bundled relation (or bundled aggregation), and by sending a summary of the aggregations, avoids us having to always send lots of individual unbundled relation events individually to the client. -The following Client-Server APIs should bundle relations: +The following client-server APIs should bundle relations in the `unsigned` property of events they return: - `/rooms/{roomId}/messages` - `/rooms/{roomId}/context` From 84a4a75e39c3b2ef2c5c79bca0db90dcd58394ab Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 23 Nov 2021 17:05:51 +0100 Subject: [PATCH 011/109] clarify in summary an API for requesting relations is also proposed --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 941e15bc525..1899cb144b2 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -17,7 +17,7 @@ relationships and maintain an correct view. Instead, this proposal seeks to solve this problem by defining APIs to let the server calculate the aggregations on behalf of the client, and so bundle the -related events with the original event where appropriate. +related events with the original event where appropriate. It also proposes an API to let clients paginate through all relations of an event. This proposal is one in a series of proposals that defines a mechanism for events to relate to each other. Together, these proposals replace From ca4ceff541115a3d6f2555a10c153c033f835ec0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 24 Nov 2021 14:24:35 +0100 Subject: [PATCH 012/109] remove proposal for batch get event api as is unused and unimplemented --- proposals/2675-aggregations-server.md | 29 ++++++--------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 1899cb144b2..734a7c15dd9 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -118,26 +118,6 @@ three thumbsup reaction annotations, one replace, and one reference. } ``` -#### Batch API for fetching events with bundled relations - -To refresh events, we need an API to load arbitrary events from the room in -bulk, which the CS API doesn't currently provide. We propose extending GET -`{roomId}/event/{eventId}` to accept a list of event IDs on the URL, e.g: - -`POST /_matrix/client/r0/rooms/{roomId}/event` -```json -{ - "event_ids": [ - "$12345676321:matrix.org", - "$12345321432:matrix.org" - ] -} -``` - -...which returns an array of events with the given IDs. - - XXX: Is this implemented in Synapse yet? - #### Paginating relations and aggregations A single event can have lots of associated relations, and we do not want to @@ -320,11 +300,14 @@ all possible bundled aggregations to the client. The server could tell the client the event IDs of events which predate the gap which received relations during the gap. This means that the client could invalidate its copy of those events (if any) and then requery them -(including their bundled relations) from the server if/when needed using the proposed extension of the `/event` API for batch requests. +(including their bundled relations) from the server if/when needed, +for example using an extension of the `/event` API for batch requests. The server could do this with a new `stale_events` field of each room object in the sync response. The `stale_events` field would list all the event IDs prior to the gap which had updated relations during the gap. The event IDs -would be grouped by relation type, and paginated as per the normal Matrix pagination model. +would be grouped by relation type, +and paginated as per the normal Matrix pagination model. -This was originally part of this MSC but left out to limit the scope to what is implemented at the time of writing. \ No newline at end of file +This was originally part of this MSC but left out to limit the scope +to what is implemented at the time of writing. \ No newline at end of file From 7de182c50f5dd390f24766f7e9a5c5eb104c293f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 24 Nov 2021 14:47:18 +0100 Subject: [PATCH 013/109] attempt to clarify relations vs aggregations --- proposals/2675-aggregations-server.md | 77 ++++++++++++++++++--------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 734a7c15dd9..338f79ece1b 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -45,38 +45,60 @@ called with a `since` token, and that have `limited: false` in the portion of response for the given room) as normal discrete Matrix events. These are called "unbundled relation events". -#### Bundled relations +#### Aggregation -Other than during non-gappy incremental syncs, an aggregate view of relation -events should be bundled into the unsigned data of the event they relate to, -rather than sending un-bundled individual relation events. This is called a -bundled relation (or bundled aggregation), and by sending a summary of the -aggregations, avoids us having to always send lots of individual unbundled -relation events individually to the client. +Relation events can be aggregated per `rel_type` by the server. +The format of the aggregated value (hereafter called "aggregation") +in the bundle depends on the relation type. -The following client-server APIs should bundle relations in the `unsigned` property of events they return: +Some `rel_type`s might additionally group the aggregations by the `key` property +in the relation and aggregate to an array, +others might aggregate to a single object or any other value really. + +##### Bundled aggregation + +Other than during non-gappy incremental syncs, events that have other events +relate to it should bundle the aggregation of those related events +in the `m.relations` property of their unsigned data. These are called +bundled aggregations, and by sending a summary of the relations, +avoids us having to always send lots of individual unbundled relation events +to the client. + +Here's an example of what that can look like for some ficticious `rel_type`s: + +```json +{ + "event_id": "abc", + "unsigned": { + "m.relations": { + "some_rel_type": { "some_prop": true }, // aggregation for some_rel_type + "other_rel_type": { "other_prop": false }, // aggregation for other_rel_type + } + } +} +``` + +The following client-server APIs should bundle aggregations +in the `unsigned` property of events they return: - `/rooms/{roomId}/messages` - `/rooms/{roomId}/context` - `/rooms/{roomId}/event/{eventId}` - - `/sync`, only for room sections in the response where `limited` field is `true`; this amounts to all rooms in the response if the `since` request parameter was not passed, also known as an initial sync. + - `/sync`, only for room sections in the response where `limited` field + is `true`; this amounts to all rooms in the response if + the `since` request parameter was not passed, also known as an initial sync. - `/relations`, as proposed in this MSC. -Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle relations. +Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required +to bundle aggregations. -The bundled relations are grouped according to their `rel_type`, and then -paginated within each group using Matrix's defined pagination idiom of `count`, +The bundled aggregations are grouped according to their `rel_type`. +For relation types that aggregate to an array, future MSCs could opt to +paginate within each group using Matrix's defined pagination idiom of `count`, `limited` and `chunk` fields - respectively giving the total number of elements in the list, whether that list has been truncated, and an array of -elements in the list. - -The format of the aggregated value in the bundle depends on the relation type. - -`m.reference` list the `event_id` and event `type` of the events which -reference that event. - -The formats for other relation types may be defined in the proposals that -define the relation types. +elements in the list. Only the first page is bundled, pagination of subsequent +pages happens through the `/aggregations` API that is defined in this MSC. For instance, the below example shows an event with five bundled relations: three thumbsup reaction annotations, one replace, and one reference. @@ -118,7 +140,7 @@ three thumbsup reaction annotations, one replace, and one reference. } ``` -#### Paginating relations and aggregations +#### Paginating relations A single event can have lots of associated relations, and we do not want to overload the client by including them all in a bundle. Instead, we provide two @@ -158,9 +180,12 @@ The endpoint does not have any trailing slashes. edits. Either we specialcase it for edits, or we just have the client go call /event to grab the contents of the original? -The `/aggregations` API lets you iterate over **bundled** relations, and within them. +#### Paginating aggregations + +The `/aggregations` API lets you iterate over aggregations for the relations +of a given event, and the unbundled relations within them. -To iterate over the bundled relations for an event (optionally filtering by +To iterate over the aggregations for an event (optionally filtering by relation type and target event type): ``` @@ -220,7 +245,7 @@ GET /_matrix/client/r0/rooms/!asd:matrix.org/aggregations/$1cd23476/m.annotation ### End to end encryption -Since the server has to be able to bundle related events, structural +Since the server has to be able to aggregate relation events, structural information about relations must be visible to the server, and so the `m.relates_to` field must be included in the plaintext. @@ -237,7 +262,7 @@ a 404. As clients only receive unbundled events through /sync, they need to locally aggregate these unbundled events for their parent event, on top of any server-side aggregation that might have already happened, to get a complete -picture of the aggregated relations for a given parent event, as a client +picture of the aggregations for a given parent event, as a client might not be aware of all relations for an event. Local aggregation should thus also take the `m.relation` data in the `unsigned` of the parent event into account if it has been sent already. The aggregation algorithm is the From 143a70ea9739a924f29ab15c5af6f6264f6ac1fb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 12:32:24 +0100 Subject: [PATCH 014/109] clarify pagination and align it with synapse impl already in the wild --- proposals/2675-aggregations-server.md | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 338f79ece1b..fdad998c177 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -93,12 +93,14 @@ Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle aggregations. The bundled aggregations are grouped according to their `rel_type`. + For relation types that aggregate to an array, future MSCs could opt to -paginate within each group using Matrix's defined pagination idiom of `count`, -`limited` and `chunk` fields - respectively giving the total number of -elements in the list, whether that list has been truncated, and an array of -elements in the list. Only the first page is bundled, pagination of subsequent -pages happens through the `/aggregations` API that is defined in this MSC. +paginate within each group using Matrix's defined pagination idiom of +`next_batch` and `chunk` - respectively giving a pagination token if there are +more aggregations, and an array of elements in the list. Only the first page +is bundled, pagination of subsequent pages happens through the `/aggregations` +API that is defined in this MSC. The maximum amount of aggregations bundled +before the list is truncated is determined freely by the server. For instance, the below example shows an event with five bundled relations: three thumbsup reaction annotations, one replace, and one reference. @@ -116,9 +118,7 @@ three thumbsup reaction annotations, one replace, and one reference. "origin_server_ts": 1562763768320, "count": 3 } - ], - "limited": false, - "count": 1 + ] }, "m.reference": { "chunk": [ @@ -127,8 +127,7 @@ three thumbsup reaction annotations, one replace, and one reference. "event_id": "$some_event_id" } ], - "limited": false, - "count": 1 + "next_batch": "abc123", }, "m.replace": { "event_id": "$edit_event_id", @@ -154,7 +153,7 @@ associated with an event in standard topological order. You can optionally filter by a given type of relation and event type: ``` -GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]] +GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&to=token][&limit=amount] ``` ```json @@ -173,6 +172,9 @@ GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{even The endpoint does not have any trailing slashes. +The `from`, `to` and `limit` query parameters are used for pagination, and work +just like described for the `/messages` endpoint. + FIXME: we need to spell out that this API should return the original message when paginating over `m.replace` relations for a given message. Synapse currently looks to include this as an `original_event` field alongside @@ -189,7 +191,7 @@ To iterate over the aggregations for an event (optionally filtering by relation type and target event type): ``` -GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?filter=id] +GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?from=token][&to=token][&limit=amount] ``` ```json @@ -209,6 +211,9 @@ GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{ The endpoint does not have any trailing slashes. +The `from`, `to` and `limit` query parameters are used for pagination, and work +just like described for the `/messages` endpoint. + Trying to iterate over an relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error M_INVALID_REL_TYPE. From ad159f4a0e64b36fc7a594b009b9eb93a9e8fb08 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 12:33:08 +0100 Subject: [PATCH 015/109] conciseness --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index fdad998c177..abf6e8347ad 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -79,7 +79,7 @@ Here's an example of what that can look like for some ficticious `rel_type`s: ``` The following client-server APIs should bundle aggregations -in the `unsigned` property of events they return: +with events they return: - `/rooms/{roomId}/messages` - `/rooms/{roomId}/context` From 948f7cd96255074d3617f8895bba1a2347d9b1ae Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 12:38:01 +0100 Subject: [PATCH 016/109] better headers --- proposals/2675-aggregations-server.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index abf6e8347ad..6a20ef00489 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -139,7 +139,7 @@ three thumbsup reaction annotations, one replace, and one reference. } ``` -#### Paginating relations +### Querying relations A single event can have lots of associated relations, and we do not want to overload the client by including them all in a bundle. Instead, we provide two @@ -148,6 +148,8 @@ way to `/messages`, except using `next_batch` and `prev_batch` names (in line with `/sync` API). Clients can start paginating either from the earliest or latest events using the `dir` param. +#### Paginating relations + The `/relations` API lets you iterate over all the **unbundled** relations associated with an event in standard topological order. You can optionally filter by a given type of relation and event type: From 5d7b4047078c6aeeb5fc3a9db4712a8dc3edc851 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 14:06:45 +0100 Subject: [PATCH 017/109] clarify that relations are always returned, contrary to aggregations --- proposals/2675-aggregations-server.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 6a20ef00489..ff470d455c3 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -57,8 +57,10 @@ others might aggregate to a single object or any other value really. ##### Bundled aggregation +Relations are first and foremost normal matrix events, and are returned by all +endpoints that return events. Other than during non-gappy incremental syncs, events that have other events -relate to it should bundle the aggregation of those related events +relate to it should additionally bundle the aggregation of those related events in the `m.relations` property of their unsigned data. These are called bundled aggregations, and by sending a summary of the relations, avoids us having to always send lots of individual unbundled relation events From e8aca3e34c41c771e6110ad5840111235310dbe3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 15:55:41 +0100 Subject: [PATCH 018/109] document the limitation of the event type not being known in e2ee rooms --- proposals/2675-aggregations-server.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index ff470d455c3..43e7e5f9221 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -258,6 +258,11 @@ Since the server has to be able to aggregate relation events, structural information about relations must be visible to the server, and so the `m.relates_to` field must be included in the plaintext. +The `/relations` and `/aggregations` endpoint allow filtering by event type, +which for encrypted rooms will be `m.room.encrypted`, rendering this filtering +less useful for encrypted rooms. Aggregations that take the event type into +account of the relation will suffer from the same limitation. + A future MSC may define a method for encrypting certain parts of the `m.relates_to` field that may contain sensitive information. From 657617f1eb31d8fc17d4d4682b53d005e0988c73 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 15:58:38 +0100 Subject: [PATCH 019/109] specify that redacted relations are not aggregated --- proposals/2675-aggregations-server.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 43e7e5f9221..7d3a4fb93ef 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -268,6 +268,10 @@ A future MSC may define a method for encrypting certain parts of the ### Redactions +Redacted relations should not be taken into consideration in +bundled aggregations or aggregations returned from `/aggregations`, +nor should they be returned from `/relations`. + Trying to call `/relations` or `/aggregations` on a redacted message must return a 404. From ffa3995e64ab3787e99292416e691f255fba7023 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 16:03:34 +0100 Subject: [PATCH 020/109] remove type in (non-binding) example as synapse doesn't do this --- proposals/2675-aggregations-server.md | 1 - 1 file changed, 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7d3a4fb93ef..9a42883ed70 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -125,7 +125,6 @@ three thumbsup reaction annotations, one replace, and one reference. "m.reference": { "chunk": [ { - "type": "m.room.message", "event_id": "$some_event_id" } ], From 561cfc39ba1924906f398d93abb34e14c97a6551 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 16:06:56 +0100 Subject: [PATCH 021/109] mention that these are just examples --- proposals/2675-aggregations-server.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 9a42883ed70..26045eda70f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -107,6 +107,10 @@ before the list is truncated is determined freely by the server. For instance, the below example shows an event with five bundled relations: three thumbsup reaction annotations, one replace, and one reference. +These are just non-normative examples of what the aggregation for these +relation types could look like, but their MSCs might end up with +a different shape, take these with a grain of salt. + ```json { ..., From 42221ab43fa9dfbd517c1dccc8e976a3259fc67d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 16:19:48 +0100 Subject: [PATCH 022/109] clarify that this is a non-normative example --- proposals/2675-aggregations-server.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 26045eda70f..74ac78495cf 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -201,13 +201,16 @@ relation type and target event type): GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?from=token][&to=token][&limit=amount] ``` +This is just non-normative example of what the aggregation for this +relation types could look like, but its MSCs might end up with +a different shape, take this with a grain of salt. + ```json { "chunk": [ { "type": "m.reaction", "key": "👍", - "origin_server_ts": 1562763768320, "count": 5, } ], From 037cab3dc6f00c8749436f8462d76fef13ad6dbf Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 16:22:14 +0100 Subject: [PATCH 023/109] Update proposals/2675-aggregations-server.md Co-authored-by: David Baker --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 74ac78495cf..a59ad68a616 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -224,7 +224,7 @@ The endpoint does not have any trailing slashes. The `from`, `to` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. -Trying to iterate over an relation type which does not use an aggregation key +Trying to iterate over a relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error M_INVALID_REL_TYPE. From d7aa3ed04fc9539ab91756e31927f6c1debee7ba Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 25 Nov 2021 16:28:45 +0100 Subject: [PATCH 024/109] add http method for endpoint list --- proposals/2675-aggregations-server.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index a59ad68a616..7be287cecad 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -83,13 +83,13 @@ Here's an example of what that can look like for some ficticious `rel_type`s: The following client-server APIs should bundle aggregations with events they return: - - `/rooms/{roomId}/messages` - - `/rooms/{roomId}/context` - - `/rooms/{roomId}/event/{eventId}` - - `/sync`, only for room sections in the response where `limited` field + - `GET /rooms/{roomId}/messages` + - `GET /rooms/{roomId}/context` + - `GET /rooms/{roomId}/event/{eventId}` + - `GET /sync`, only for room sections in the response where `limited` field is `true`; this amounts to all rooms in the response if the `since` request parameter was not passed, also known as an initial sync. - - `/relations`, as proposed in this MSC. + - `GET /relations`, as proposed in this MSC. Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle aggregations. From 30cf5f84103449e1e8718bb4247f624c70f79e6b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 26 Nov 2021 11:19:09 +0100 Subject: [PATCH 025/109] line break --- proposals/2675-aggregations-server.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7be287cecad..4379544093b 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -17,7 +17,8 @@ relationships and maintain an correct view. Instead, this proposal seeks to solve this problem by defining APIs to let the server calculate the aggregations on behalf of the client, and so bundle the -related events with the original event where appropriate. It also proposes an API to let clients paginate through all relations of an event. +related events with the original event where appropriate. It also proposes an +API to let clients paginate through all relations of an event. This proposal is one in a series of proposals that defines a mechanism for events to relate to each other. Together, these proposals replace From ee152e090d9731f525a01e200c7923974f42c3e2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 26 Nov 2021 11:20:07 +0100 Subject: [PATCH 026/109] remove "unbundled relations" term, it's just confusing instead use relation events, with the bundled form now called aggregation also restructure the headings so we have on section about aggregations and another one about querying relation events --- proposals/2675-aggregations-server.md | 137 ++++++++++++-------------- 1 file changed, 64 insertions(+), 73 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4379544093b..77d046861fa 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -37,16 +37,7 @@ events to relate to each other. Together, these proposals replace ## Proposal -### Receiving relations - -#### Unbundled relation events - -Relations are received during non-gappy incremental syncs (that is, syncs -called with a `since` token, and that have `limited: false` in the portion of -response for the given room) as normal discrete Matrix events. These are -called "unbundled relation events". - -#### Aggregation +### Aggregations Relation events can be aggregated per `rel_type` by the server. The format of the aggregated value (hereafter called "aggregation") @@ -56,15 +47,13 @@ Some `rel_type`s might additionally group the aggregations by the `key` property in the relation and aggregate to an array, others might aggregate to a single object or any other value really. -##### Bundled aggregation +#### Bundled aggregations -Relations are first and foremost normal matrix events, and are returned by all -endpoints that return events. Other than during non-gappy incremental syncs, events that have other events -relate to it should additionally bundle the aggregation of those related events +relate to it should bundle the aggregation of those related events in the `m.relations` property of their unsigned data. These are called bundled aggregations, and by sending a summary of the relations, -avoids us having to always send lots of individual unbundled relation events +avoids us having to always send lots of individual relation events to the client. Here's an example of what that can look like for some ficticious `rel_type`s: @@ -145,55 +134,10 @@ a different shape, take these with a grain of salt. } ``` -### Querying relations - -A single event can have lots of associated relations, and we do not want to -overload the client by including them all in a bundle. Instead, we provide two -new APIs in order to paginate over the relations, which behave in a similar -way to `/messages`, except using `next_batch` and `prev_batch` names (in line -with `/sync` API). Clients can start paginating either from the earliest or -latest events using the `dir` param. - -#### Paginating relations - -The `/relations` API lets you iterate over all the **unbundled** relations -associated with an event in standard topological order. You can optionally -filter by a given type of relation and event type: - -``` -GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&to=token][&limit=amount] -``` - -```json -{ - "chunk": [ - { - "type": "m.reaction", - "sender": "...", - "content": { } - } - ], - "next_batch": "some_token", - "prev_batch": "some_token" -} -``` - -The endpoint does not have any trailing slashes. - -The `from`, `to` and `limit` query parameters are used for pagination, and work -just like described for the `/messages` endpoint. - - FIXME: we need to spell out that this API should return the original message - when paginating over `m.replace` relations for a given message. Synapse - currently looks to include this as an `original_event` field alongside - `chunk` on all relations, which feels very redundant when we only need it for - edits. Either we specialcase it for edits, or we just have the client go - call /event to grab the contents of the original? - #### Paginating aggregations The `/aggregations` API lets you iterate over aggregations for the relations -of a given event, and the unbundled relations within them. +of a given event, and the discrete relation events within them. To iterate over the aggregations for an event (optionally filtering by relation type and target event type): @@ -229,8 +173,8 @@ Trying to iterate over a relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error M_INVALID_REL_TYPE. -To iterate over the unbundled relations within a specific bundled relation, you -use the following API form, identifying the bundle based on its `key` +To iterate over the discrete relation events within a specific bundled relation, +you use the following API form, identifying the bundle based on its `key` (therefore this only applies to `m.annotation`, as it is the only current `rel_type` which groups relations via `key`). @@ -259,6 +203,53 @@ GET /_matrix/client/r0/rooms/!asd:matrix.org/aggregations/$1cd23476/m.annotation ``` + +### Querying relations + +A single event can have lots of associated relations, and we do not want to +overload the client by including them all bundled with the related-to event +like with do for aggregations. Instead, we provide two +new APIs in order to paginate over the relations, which behave in a similar +way to `/messages`, except using `next_batch` and `prev_batch` names (in line +with `/sync` API). Clients can start paginating either from the earliest or +latest events using the `dir` param. + +#### Paginating relations + +The `/relations` API lets you iterate over all the discrete relation events +associated with an event in standard topological order. You can optionally +filter by a given type of relation and event type: + +``` +GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&to=token][&limit=amount] +``` + +```json +{ + "chunk": [ + { + "type": "m.reaction", + "sender": "...", + "content": { } + } + ], + "next_batch": "some_token", + "prev_batch": "some_token" +} +``` + +The endpoint does not have any trailing slashes. + +The `from`, `to` and `limit` query parameters are used for pagination, and work +just like described for the `/messages` endpoint. + + FIXME: we need to spell out that this API should return the original message + when paginating over `m.replace` relations for a given message. Synapse + currently looks to include this as an `original_event` field alongside + `chunk` on all relations, which feels very redundant when we only need it for + edits. Either we specialcase it for edits, or we just have the client go + call /event to grab the contents of the original? + ### End to end encryption Since the server has to be able to aggregate relation events, structural @@ -284,13 +275,13 @@ a 404. ### Local echo -As clients only receive unbundled events through /sync, they need to locally -aggregate these unbundled events for their parent event, on top of any -server-side aggregation that might have already happened, to get a complete -picture of the aggregations for a given parent event, as a client -might not be aware of all relations for an event. Local aggregation should -thus also take the `m.relation` data in the `unsigned` of the parent event -into account if it has been sent already. The aggregation algorithm is the +As clients only receive discrete relation events through /sync, +they need to locally aggregate these relation events for their parent event, +on top of any server-side aggregation that might have already happened, +to get a complete picture of the aggregations for a given parent event, +as a client might not be aware of all relations for an event. Local aggregation +should thus also take the `m.relation` data in the `unsigned` of the parent +event into account if it has been sent already. The aggregation algorithm is the same as the one described here for the server. For the best possible user experience, clients should also include unsent @@ -329,9 +320,9 @@ common case for rapidly fixing a typo in a msg which is still in flight!) How do you handle ignored users? * Information about relations sent from ignored users must never be sent to - the client, either in bundled or unbundled form. This is to let you block - someone from harassing you with emoji reactions (or using edits as a - side-channel to harass you). + the client, either in aggregations or discrete relation events. + This is to let you block someone from harassing you with emoji reactions + (or using edits as a side-channel to harass you). What does it mean to call /context on a relation? * We should probably just return the root event for now, and then refine it in From 483224a21c347526cf36805d1de7ab2c1156c939 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 26 Nov 2021 11:28:12 +0100 Subject: [PATCH 027/109] some more restructuring of text after changing doc structure --- proposals/2675-aggregations-server.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 77d046861fa..78262328098 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -134,7 +134,7 @@ a different shape, take these with a grain of salt. } ``` -#### Paginating aggregations +### Querying aggregations The `/aggregations` API lets you iterate over aggregations for the relations of a given event, and the discrete relation events within them. @@ -169,7 +169,7 @@ The endpoint does not have any trailing slashes. The `from`, `to` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. -Trying to iterate over a relation type which does not use an aggregation key +Trying to iterate over an relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error M_INVALID_REL_TYPE. @@ -202,19 +202,15 @@ GET /_matrix/client/r0/rooms/!asd:matrix.org/aggregations/$1cd23476/m.annotation } ``` - - ### Querying relations A single event can have lots of associated relations, and we do not want to overload the client by including them all bundled with the related-to event -like with do for aggregations. Instead, we provide two -new APIs in order to paginate over the relations, which behave in a similar -way to `/messages`, except using `next_batch` and `prev_batch` names (in line -with `/sync` API). Clients can start paginating either from the earliest or -latest events using the `dir` param. - -#### Paginating relations +like we do for aggregations. Instead, we provide a new `/relations` API in +order to paginate over the relations, which behaves in a similar way to +`/messages`, except using `next_batch` and `prev_batch` names +(in line with `/sync` API). Clients can start paginating either from the +earliest or latest events using the `dir` param. The `/relations` API lets you iterate over all the discrete relation events associated with an event in standard topological order. You can optionally From 16723da6771ba6ac3ef0641b6c16d4c2abd2fbc5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 26 Nov 2021 11:37:26 +0100 Subject: [PATCH 028/109] mention original_event for m.replace relations --- proposals/2675-aggregations-server.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 78262328098..0544f1957b2 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -239,12 +239,10 @@ The endpoint does not have any trailing slashes. The `from`, `to` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. - FIXME: we need to spell out that this API should return the original message - when paginating over `m.replace` relations for a given message. Synapse - currently looks to include this as an `original_event` field alongside - `chunk` on all relations, which feels very redundant when we only need it for - edits. Either we specialcase it for edits, or we just have the client go - call /event to grab the contents of the original? +Note that [MSC2676](https://github.com/matrix-org/matrix-doc/pull/2676) +adds the related-to event in `original_event` property of the response. +This way the full history (e.g. also the first, original event) of the event +is obtained without further requests. See that MSC for further details. ### End to end encryption From 8e532ac1e2cfbf978223aa11e7644e1408c26521 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 29 Nov 2021 15:32:43 +0100 Subject: [PATCH 029/109] remove dir param as it is unused and unimplemented --- proposals/2675-aggregations-server.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 0544f1957b2..bc9b407f865 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -209,10 +209,9 @@ overload the client by including them all bundled with the related-to event like we do for aggregations. Instead, we provide a new `/relations` API in order to paginate over the relations, which behaves in a similar way to `/messages`, except using `next_batch` and `prev_batch` names -(in line with `/sync` API). Clients can start paginating either from the -earliest or latest events using the `dir` param. +(in line with `/sync` API). -The `/relations` API lets you iterate over all the discrete relation events +The `/relations` API returns discrete relation events associated with an event in standard topological order. You can optionally filter by a given type of relation and event type: From 6cf4d58ec6af6d27a84456ceee29eb81e2a5cae5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 29 Nov 2021 16:03:40 +0100 Subject: [PATCH 030/109] clarify that relating pending events should happen by transaction_id --- proposals/2675-aggregations-server.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index bc9b407f865..a5c36c32867 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -300,11 +300,12 @@ referred to should be de-aggregated from the relations of the target of the relation. Similar to a relation, when the sending of the redaction fails or is cancelled, the relation should be aggregated again. -To support creating relations for pending events, clients will need a way for -events to relate to one another before the `event_id` of the parent event is -known. When the parent event receives its remote echo, the target event id -(`m.relates_to`.`event_id`) of any relations in the send queue will need to be -set the newly received `event_id`. +Clients can locally relate pending events by their `transaction_id`. +When the target event receives its `event_id` (either receives the remote echo, +or receives the `event_id` from the `/send` response, +whichever comes first), the target event id (`m.relates_to`.`event_id`) of +any relations in the send queue will +need to be set the newly received `event_id`. Particularly, please remember to let users edit unsent messages (as this is a common case for rapidly fixing a typo in a msg which is still in flight!) From b0fbee12a1a350e9adc6f3c671dc6725fde22ec6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 29 Nov 2021 16:41:29 +0100 Subject: [PATCH 031/109] remove unimplemented /aggregations/{eventID}//{eventType}/{key} endpoint --- proposals/2675-aggregations-server.md | 29 --------------------------- 1 file changed, 29 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index a5c36c32867..09c3f62f343 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -173,35 +173,6 @@ Trying to iterate over an relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error M_INVALID_REL_TYPE. -To iterate over the discrete relation events within a specific bundled relation, -you use the following API form, identifying the bundle based on its `key` -(therefore this only applies to `m.annotation`, as it is the only current -`rel_type` which groups relations via `key`). - -``` -GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}/${relationType}/{eventType}/{key} -``` - -e.g. - -``` -GET /_matrix/client/r0/rooms/!asd:matrix.org/aggregations/$1cd23476/m.annotation/m.reaction/👍 -``` - -```json -{ - "chunk": [ - { - "type": "m.reaction", - "sender": "...", - "content": { } - }, - ], - "next_batch": "some_token", - "prev_batch": "some_token" -} -``` - ### Querying relations A single event can have lots of associated relations, and we do not want to From 53a30fca83fd4ebab5070ea934bcf38beb50b871 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 11:11:05 +0100 Subject: [PATCH 032/109] Update proposals/2675-aggregations-server.md Co-authored-by: Patrick Cloke --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 09c3f62f343..76eaf42e36f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -171,7 +171,7 @@ just like described for the `/messages` endpoint. Trying to iterate over an relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error -M_INVALID_REL_TYPE. +`M_INVALID_REL_TYPE`. ### Querying relations From f959119ff21871c76de27ad4384dccfd7e6a2e6a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 12:00:38 +0100 Subject: [PATCH 033/109] mention that the server might not be aware of all the relations --- proposals/2675-aggregations-server.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 76eaf42e36f..cb5a9bd5bdf 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -182,8 +182,10 @@ order to paginate over the relations, which behaves in a similar way to `/messages`, except using `next_batch` and `prev_batch` names (in line with `/sync` API). -The `/relations` API returns discrete relation events -associated with an event in standard topological order. You can optionally +The `/relations` API returns the discrete relation events +associated with an event that the server is aware of +in standard topological order. Note that events may be missing, +see [limitations](#servers-might-not-be-aware-of-all-relations-of-an-event). You can optionally filter by a given type of relation and event type: ``` @@ -283,17 +285,30 @@ common case for rapidly fixing a typo in a msg which is still in flight!) ## Edge cases -How do you handle ignored users? +### How do you handle ignored users? + * Information about relations sent from ignored users must never be sent to the client, either in aggregations or discrete relation events. This is to let you block someone from harassing you with emoji reactions (or using edits as a side-channel to harass you). -What does it mean to call /context on a relation? +### What does it mean to call /context on a relation? + * We should probably just return the root event for now, and then refine it in future for threading? * XXX: what does synapse do here? +## Limitations + +### Servers might not be aware of all relations of an event + +The response of `/relations` might be incomplete because the homeserver +potentially doesn't have the full DAG of the room. The federation API doens't +have an equivalent of the `/relations` API, so has no way but to fetch the +full DAG over federation to assure itself that it is aware of all relations. + +[MSC2836](https://github.com/matrix-org/matrix-doc/blob/kegan/msc/threading/proposals/2836-threading.md#making-relationships) also makes mention of this issue. + ## Future extensions ### Handling limited (gappy) syncs From dead29300ed3557f6e38d70b8dbf797e3a691a32 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:41:14 +0100 Subject: [PATCH 034/109] clarify that redacted events should still return their relations and aggregations respectively --- proposals/2675-aggregations-server.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index cb5a9bd5bdf..1ca85d7330d 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -236,8 +236,9 @@ Redacted relations should not be taken into consideration in bundled aggregations or aggregations returned from `/aggregations`, nor should they be returned from `/relations`. -Trying to call `/relations` or `/aggregations` on a redacted message must return -a 404. +Requesting `/relations` or `/aggregations` on a redacted event should +still return any existing relation events, and aggregations respectively. +This is in line with other APIs like `/context` and `/messages`. ### Local echo From 7299a8c13ca6353a9175dd9034e1ad5731502c03 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:42:41 +0100 Subject: [PATCH 035/109] remove /context edge case, it should not be special-cased --- proposals/2675-aggregations-server.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 1ca85d7330d..72b8a584944 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -293,12 +293,6 @@ common case for rapidly fixing a typo in a msg which is still in flight!) This is to let you block someone from harassing you with emoji reactions (or using edits as a side-channel to harass you). -### What does it mean to call /context on a relation? - - * We should probably just return the root event for now, and then refine it in - future for threading? - * XXX: what does synapse do here? - ## Limitations ### Servers might not be aware of all relations of an event From 37db9846795ab987b5d5c892e16214a6b3dbff83 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:43:57 +0100 Subject: [PATCH 036/109] Update proposals/2675-aggregations-server.md Co-authored-by: Patrick Cloke --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 72b8a584944..4d80f88020d 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -13,7 +13,7 @@ message they respond to, etc. It is possible to treat relations as normal events and aggregate them clientside, but to do so comprehensively could be very resource intensive, as the client would need to spider all possible events in a room to find -relationships and maintain an correct view. +relationships and maintain a correct view. Instead, this proposal seeks to solve this problem by defining APIs to let the server calculate the aggregations on behalf of the client, and so bundle the From 36fb70b58485de0956869bf52ce2a5ecf3c9e84c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:44:06 +0100 Subject: [PATCH 037/109] Update proposals/2675-aggregations-server.md Co-authored-by: Patrick Cloke --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4d80f88020d..14903e078be 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -137,7 +137,7 @@ a different shape, take these with a grain of salt. ### Querying aggregations The `/aggregations` API lets you iterate over aggregations for the relations -of a given event, and the discrete relation events within them. +of a given event. To iterate over the aggregations for an event (optionally filtering by relation type and target event type): From 061a1046436e4bf31abcb4e8b353f07f51e63db5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:44:15 +0100 Subject: [PATCH 038/109] Update proposals/2675-aggregations-server.md Co-authored-by: Patrick Cloke --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 14903e078be..3b1295232e5 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -242,7 +242,7 @@ This is in line with other APIs like `/context` and `/messages`. ### Local echo -As clients only receive discrete relation events through /sync, +As clients only receive discrete relation events through `/sync`, they need to locally aggregate these relation events for their parent event, on top of any server-side aggregation that might have already happened, to get a complete picture of the aggregations for a given parent event, From bf9340e1d32a4303ff588bbf0491d7682bc35311 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:47:12 +0100 Subject: [PATCH 039/109] bad example, replies doesn't use relations --- proposals/2675-aggregations-server.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 3b1295232e5..59ebc377468 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -7,8 +7,7 @@ Clients typically need to track the related events alongside the original event they relate to, in order to correctly display them. For instance, reaction events need to be aggregated together by summing and be shown next to the event they react to; edits need to be aggregated together by replacing the -original event and subsequent edits; replies need to be indented after the -message they respond to, etc. +original event and subsequent edits, etc. It is possible to treat relations as normal events and aggregate them clientside, but to do so comprehensively could be very resource intensive, as From c8533ecef20b386e1554799ee8493dfb9081a123 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:49:07 +0100 Subject: [PATCH 040/109] clarify that we dont bundle discrete events --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 59ebc377468..e03b09578fa 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -16,7 +16,7 @@ relationships and maintain a correct view. Instead, this proposal seeks to solve this problem by defining APIs to let the server calculate the aggregations on behalf of the client, and so bundle the -related events with the original event where appropriate. It also proposes an +aggregated data with the original event where appropriate. It also proposes an API to let clients paginate through all relations of an event. This proposal is one in a series of proposals that defines a mechanism for From 51bc1da11a0752f83b27c2362adf96fa1a4b7eac Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:49:55 +0100 Subject: [PATCH 041/109] clarify that we dont bundle discrete events, again --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index e03b09578fa..b314c00a6f6 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -26,7 +26,7 @@ events to relate to each other. Together, these proposals replace * [MSC2674](https://github.com/matrix-org/matrix-doc/pull/2674) defines a standard shape for indicating events which relate to other events. * This proposal defines APIs to let the server calculate the aggregations on - behalf of the client, and so bundle the related events with the original + behalf of the client, and so bundle the aggregated data with the original event where appropriate. * [MSC2676](https://github.com/matrix-org/matrix-doc/pull/2676) defines how users can edit messages using this mechanism. From 7559275137ac1d17003161c6e9161f55a659b2ee Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:51:34 +0100 Subject: [PATCH 042/109] improve example --- proposals/2675-aggregations-server.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index b314c00a6f6..5be5a59db9c 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -62,8 +62,8 @@ Here's an example of what that can look like for some ficticious `rel_type`s: "event_id": "abc", "unsigned": { "m.relations": { - "some_rel_type": { "some_prop": true }, // aggregation for some_rel_type - "other_rel_type": { "other_prop": false }, // aggregation for other_rel_type + "some_rel_type": { "some_aggregated_prop": true }, + "other_rel_type": { "other_aggregated_prop": 5 }, } } } From c475bb932dcaf5c3dc066eab8a1378ff25f579fe Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:55:18 +0100 Subject: [PATCH 043/109] clarify this MSC does not use a prefix --- proposals/2675-aggregations-server.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 5be5a59db9c..83231dc26f7 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -325,4 +325,10 @@ would be grouped by relation type, and paginated as per the normal Matrix pagination model. This was originally part of this MSC but left out to limit the scope -to what is implemented at the time of writing. \ No newline at end of file +to what is implemented at the time of writing. + +## No unstable prefix + +Implementations of this MSC should not use any prefix, +as this MSC tries to document relation support without a prefix already +being used in the wider matrix ecosystem. \ No newline at end of file From 872d3f529b9d60c46bff558ec30816815dd974e1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:57:04 +0100 Subject: [PATCH 044/109] better english --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 83231dc26f7..78de001a9b6 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -97,7 +97,7 @@ For instance, the below example shows an event with five bundled relations: three thumbsup reaction annotations, one replace, and one reference. These are just non-normative examples of what the aggregation for these -relation types could look like, but their MSCs might end up with +relation types could look like, and their MSCs might end up with a different shape, take these with a grain of salt. ```json From 7119947f40ea928d94c49bfb66872f46d2431a01 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 19:59:03 +0100 Subject: [PATCH 045/109] clarify pagination in example --- proposals/2675-aggregations-server.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 78de001a9b6..15a8f1dc2ed 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -94,7 +94,8 @@ API that is defined in this MSC. The maximum amount of aggregations bundled before the list is truncated is determined freely by the server. For instance, the below example shows an event with five bundled relations: -three thumbsup reaction annotations, one replace, and one reference. +three thumbsup reaction annotations, one replace, and a truncated list +of references, of which only one is bundled (because `next_batch` is present). These are just non-normative examples of what the aggregation for these relation types could look like, and their MSCs might end up with From 0d7b5251860251e50ce6170d4b37ec7bf3bbeb0d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 20:00:25 +0100 Subject: [PATCH 046/109] better english --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 15a8f1dc2ed..49469be9058 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -147,7 +147,7 @@ GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{ ``` This is just non-normative example of what the aggregation for this -relation types could look like, but its MSCs might end up with +relation types could look like, and its MSCs might end up with a different shape, take this with a grain of salt. ```json From 764d785e1971b69992373fed9eb7ad01a6d33eb0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 20:03:27 +0100 Subject: [PATCH 047/109] remove contradication: m.reference doesn't support pagination but example mentions it --- proposals/2675-aggregations-server.md | 31 ++++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 49469be9058..7822fd63c39 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -94,8 +94,9 @@ API that is defined in this MSC. The maximum amount of aggregations bundled before the list is truncated is determined freely by the server. For instance, the below example shows an event with five bundled relations: -three thumbsup reaction annotations, one replace, and a truncated list -of references, of which only one is bundled (because `next_batch` is present). +one replace, one reference and three thumbsup reaction annotations, +with more aggregated reactions available to paginate in +through `/aggregations` as `next_batch` is present.. These are just non-normative examples of what the aggregation for these relation types could look like, and their MSCs might end up with @@ -106,6 +107,18 @@ a different shape, take these with a grain of salt. ..., "unsigned": { "m.relations": { + "m.replace": { + "event_id": "$edit_event_id", + "origin_server_ts": 1562763768320, + "sender": "@bruno1:localhost" + }, + "m.reference": { + "chunk": [ + { + "event_id": "$some_event_id" + } + ], + }, "m.annotation": { "chunk": [ { @@ -114,20 +127,8 @@ a different shape, take these with a grain of salt. "origin_server_ts": 1562763768320, "count": 3 } + "next_batch": "abc123", ] - }, - "m.reference": { - "chunk": [ - { - "event_id": "$some_event_id" - } - ], - "next_batch": "abc123", - }, - "m.replace": { - "event_id": "$edit_event_id", - "origin_server_ts": 1562763768320, - "sender": "@bruno1:localhost" } } } From 26376de490efb855fe97bc4e962651be57b605af Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 20:04:53 +0100 Subject: [PATCH 048/109] double punctuation --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7822fd63c39..347e0741bc4 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -96,7 +96,7 @@ before the list is truncated is determined freely by the server. For instance, the below example shows an event with five bundled relations: one replace, one reference and three thumbsup reaction annotations, with more aggregated reactions available to paginate in -through `/aggregations` as `next_batch` is present.. +through `/aggregations` as `next_batch` is present. These are just non-normative examples of what the aggregation for these relation types could look like, and their MSCs might end up with From 382bb1d200db2f5b697a055439a8cfe634e844cb Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 20:08:46 +0100 Subject: [PATCH 049/109] clarify that only the bundled aggregation limit for truncation can't be set by the client, /aggregations does have a limit param --- proposals/2675-aggregations-server.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 347e0741bc4..5eb97e49c57 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -93,6 +93,10 @@ is bundled, pagination of subsequent pages happens through the `/aggregations` API that is defined in this MSC. The maximum amount of aggregations bundled before the list is truncated is determined freely by the server. +Note that the client *can* determine the page size when calling +`/aggregations` through the `limit` request parameter, the offset is solely +determined by the `next_batch` token. + For instance, the below example shows an event with five bundled relations: one replace, one reference and three thumbsup reaction annotations, with more aggregated reactions available to paginate in From a0af57336c27289adf18f60c9bb53fd4caf3accd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 20:16:24 +0100 Subject: [PATCH 050/109] move e2ee limitation to limitations section --- proposals/2675-aggregations-server.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 5eb97e49c57..a63cfd9996c 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -227,11 +227,6 @@ Since the server has to be able to aggregate relation events, structural information about relations must be visible to the server, and so the `m.relates_to` field must be included in the plaintext. -The `/relations` and `/aggregations` endpoint allow filtering by event type, -which for encrypted rooms will be `m.room.encrypted`, rendering this filtering -less useful for encrypted rooms. Aggregations that take the event type into -account of the relation will suffer from the same limitation. - A future MSC may define a method for encrypting certain parts of the `m.relates_to` field that may contain sensitive information. @@ -309,6 +304,13 @@ full DAG over federation to assure itself that it is aware of all relations. [MSC2836](https://github.com/matrix-org/matrix-doc/blob/kegan/msc/threading/proposals/2836-threading.md#making-relationships) also makes mention of this issue. +### Event type based aggregation and filtering won't work well in encrypted rooms + +The `/relations` and `/aggregations` endpoint allow filtering by event type, +which for encrypted rooms will be `m.room.encrypted`, rendering this filtering +less useful for encrypted rooms. Aggregations that take the event type into +account of the relation will suffer from the same limitation. + ## Future extensions ### Handling limited (gappy) syncs From 2557d236e0500d1d06a688b81784185173a50e3e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 30 Nov 2021 20:33:00 +0100 Subject: [PATCH 051/109] clarify prefixes --- proposals/2675-aggregations-server.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index a63cfd9996c..1e97c252bef 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -148,7 +148,7 @@ To iterate over the aggregations for an event (optionally filtering by relation type and target event type): ``` -GET /_matrix/client/r0/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?from=token][&to=token][&limit=amount] ``` This is just non-normative example of what the aggregation for this @@ -194,7 +194,7 @@ see [limitations](#servers-might-not-be-aware-of-all-relations-of-an-event). Yo filter by a given type of relation and event type: ``` -GET /_matrix/client/r0/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&to=token][&limit=amount] ``` ```json @@ -335,8 +335,13 @@ and paginated as per the normal Matrix pagination model. This was originally part of this MSC but left out to limit the scope to what is implemented at the time of writing. -## No unstable prefix +## Prefix -Implementations of this MSC should not use any prefix, -as this MSC tries to document relation support without a prefix already -being used in the wider matrix ecosystem. \ No newline at end of file +While this MSC is not considered stable, the endpoints become: + + - `GET /_matrix/client/unstable/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}]` + - `GET /_matrix/client/unstable/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]]` + +None of the newly introduced identifiers should use a prefix though, as this MSC +tries to document relation support already being used in +the wider matrix ecosystem. \ No newline at end of file From c62165a0d0b81a1c776eed1bad501dc59a7c25c3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 2 Dec 2021 20:01:35 +0100 Subject: [PATCH 052/109] mention that state events never bundle aggregations --- proposals/2675-aggregations-server.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 1e97c252bef..175664df472 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -48,13 +48,15 @@ others might aggregate to a single object or any other value really. #### Bundled aggregations -Other than during non-gappy incremental syncs, events that have other events -relate to it should bundle the aggregation of those related events +Other than during non-gappy incremental syncs, timeline events that have other +events relate to it should bundle the aggregation of those related events in the `m.relations` property of their unsigned data. These are called bundled aggregations, and by sending a summary of the relations, avoids us having to always send lots of individual relation events to the client. +State events never bundle aggregations. + Here's an example of what that can look like for some ficticious `rel_type`s: ```json From e26e4657159655a1371d9cddebaced49336d4833 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 3 Dec 2021 09:31:31 +0100 Subject: [PATCH 053/109] Update proposals/2675-aggregations-server.md Co-authored-by: Patrick Cloke --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 175664df472..d81a99e55dd 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -75,7 +75,7 @@ The following client-server APIs should bundle aggregations with events they return: - `GET /rooms/{roomId}/messages` - - `GET /rooms/{roomId}/context` + - `GET /rooms/{roomId}/context/{eventId}` - `GET /rooms/{roomId}/event/{eventId}` - `GET /sync`, only for room sections in the response where `limited` field is `true`; this amounts to all rooms in the response if From 503a569c5b2932e40e73a271d03dcfe5621b053b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:00:37 +0100 Subject: [PATCH 054/109] add that the visibility of relations can derive from that of the target --- proposals/2675-aggregations-server.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index d81a99e55dd..67880b1268b 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -223,12 +223,38 @@ adds the related-to event in `original_event` property of the response. This way the full history (e.g. also the first, original event) of the event is obtained without further requests. See that MSC for further details. +### Relation visilibity + +The visibility rules (whether or not a user should receive a given event through +the client-server API) for relations events are adjusted in the MSC. +The visibility for relation events is dependent on the `rel_type`, with two options: + + - Visibility is derived from the visibility of the target event (the event + referred to by the `event_id` in the relation); the relation should only be + visible if the relation target is visible. This option means that events + can still be visible to a user after they have left the room. This has implications + for [End-to-end encryption](#end-to-end-encryption). + [`m.replace`](https://github.com/matrix-org/matrix-doc/pull/2676) and [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) relation events have this visilibilty, see those respective MSCs. + - Visibility is the same as a non-relation event. + [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) relation events have this visilibilty, see the respective MSC. + +Visibility derived from the visibility of the target event is the default; +if the MSC introducing the relation type doesn't specify any other visibility this is assumed. + +The change of visilibilty rules will require a new room version. + ### End to end encryption Since the server has to be able to aggregate relation events, structural information about relations must be visible to the server, and so the `m.relates_to` field must be included in the plaintext. +When sending relation events whose [visibility is derived from the target event](#relation-visibility), +clients should share the end-to-end encryption keys for the encrypted +relation events with all devices that could see the target event, even +if those relation events are encrypted with a different key than +the target event, and even if the user for a device has left the room since. + A future MSC may define a method for encrypting certain parts of the `m.relates_to` field that may contain sensitive information. From 049863b1774b1eb2db3b0639ae004dc8feeca852 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:06:51 +0100 Subject: [PATCH 055/109] typsos --- proposals/2675-aggregations-server.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 67880b1268b..05fdb4c47b8 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -223,10 +223,10 @@ adds the related-to event in `original_event` property of the response. This way the full history (e.g. also the first, original event) of the event is obtained without further requests. See that MSC for further details. -### Relation visilibity +### Relation visibility The visibility rules (whether or not a user should receive a given event through -the client-server API) for relations events are adjusted in the MSC. +the client-server API) for relations events are adjusted in this MSC. The visibility for relation events is dependent on the `rel_type`, with two options: - Visibility is derived from the visibility of the target event (the event From 44d04f403c4064c4d99c32dc69b513882a1fc051 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:09:13 +0100 Subject: [PATCH 056/109] be more explicit --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 05fdb4c47b8..3c25683328c 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -238,7 +238,7 @@ The visibility for relation events is dependent on the `rel_type`, with two opti - Visibility is the same as a non-relation event. [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) relation events have this visilibilty, see the respective MSC. -Visibility derived from the visibility of the target event is the default; +Visibility derived from the visibility of the target event is the default for relation events; if the MSC introducing the relation type doesn't specify any other visibility this is assumed. The change of visilibilty rules will require a new room version. From 1160b4a38e196f23be310b80fb3ec108b0b4dd05 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:25:16 +0100 Subject: [PATCH 057/109] moar rewording --- proposals/2675-aggregations-server.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 3c25683328c..4939c47c288 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -250,10 +250,10 @@ information about relations must be visible to the server, and so the `m.relates_to` field must be included in the plaintext. When sending relation events whose [visibility is derived from the target event](#relation-visibility), -clients should share the end-to-end encryption keys for the encrypted -relation events with all devices that could see the target event, even -if those relation events are encrypted with a different key than -the target event, and even if the user for a device has left the room since. +clients should ensure that the end-to-end encryption keys for the encrypted +relation events is shared with all devices that could see the target event, +even if those relation events are encrypted with a different key than +the target event, and even if the receiving user has since left the room. A future MSC may define a method for encrypting certain parts of the `m.relates_to` field that may contain sensitive information. From 0abf2ce2676877108faacdf5c22703d23180ede5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:26:24 +0100 Subject: [PATCH 058/109] keep related parts together --- proposals/2675-aggregations-server.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4939c47c288..534743a4acc 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -249,15 +249,15 @@ Since the server has to be able to aggregate relation events, structural information about relations must be visible to the server, and so the `m.relates_to` field must be included in the plaintext. +A future MSC may define a method for encrypting certain parts of the +`m.relates_to` field that may contain sensitive information. + When sending relation events whose [visibility is derived from the target event](#relation-visibility), clients should ensure that the end-to-end encryption keys for the encrypted relation events is shared with all devices that could see the target event, even if those relation events are encrypted with a different key than the target event, and even if the receiving user has since left the room. -A future MSC may define a method for encrypting certain parts of the -`m.relates_to` field that may contain sensitive information. - ### Redactions Redacted relations should not be taken into consideration in From e460a27ec2d0f4409a66f1aa8912e89337936a9a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:49:19 +0100 Subject: [PATCH 059/109] don't make a relation invisible because the target event isn't also clarify what to do with relations for which the target is invisible --- proposals/2675-aggregations-server.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 534743a4acc..94b7d962d9e 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -230,9 +230,16 @@ the client-server API) for relations events are adjusted in this MSC. The visibility for relation events is dependent on the `rel_type`, with two options: - Visibility is derived from the visibility of the target event (the event - referred to by the `event_id` in the relation); the relation should only be - visible if the relation target is visible. This option means that events - can still be visible to a user after they have left the room. This has implications + referred to by the `event_id` in the relation) under some circumstances: + the relation should be visible if the relation target event is visible to + a user but the relation event would not be visible according to regular + event history visibility rules (e.g. the user has since left in a room with + joined or invite room history visibility). + If according to regular event room history visibility rules, the relation + event would be visible to a user, then the visibility of target event + should not be considered and the relation event should be visible. + This option means that events can still be visible to a user after + they have left the room, and has implications for [End-to-end encryption](#end-to-end-encryption). [`m.replace`](https://github.com/matrix-org/matrix-doc/pull/2676) and [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) relation events have this visilibilty, see those respective MSCs. - Visibility is the same as a non-relation event. @@ -314,6 +321,11 @@ common case for rapidly fixing a typo in a msg which is still in flight!) ## Edge cases +### Ignore relation events for which the target is not visible to us. + +Clients should ignore relation events for which the target event is +not visible to them. + ### How do you handle ignored users? * Information about relations sent from ignored users must never be sent to From 58cb3effdc57521cf78c10c1a423b0d43834b584 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:50:19 +0100 Subject: [PATCH 060/109] Update proposals/2675-aggregations-server.md Co-authored-by: David Baker --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 94b7d962d9e..e2205c24ffd 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -176,7 +176,7 @@ The endpoint does not have any trailing slashes. The `from`, `to` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. -Trying to iterate over an relation type which does not use an aggregation key +Trying to iterate over a relation type which does not use an aggregation key (i.e. `m.replace` and `m.reference`) should fail with 400 and error `M_INVALID_REL_TYPE`. From de00362835056c58ced8237eab64acb1fedfc202 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 14 Dec 2021 19:53:59 +0100 Subject: [PATCH 061/109] better words --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index e2205c24ffd..e5afd4f4f33 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -239,7 +239,7 @@ The visibility for relation events is dependent on the `rel_type`, with two opti event would be visible to a user, then the visibility of target event should not be considered and the relation event should be visible. This option means that events can still be visible to a user after - they have left the room, and has implications + the user left the room, and has implications for [End-to-end encryption](#end-to-end-encryption). [`m.replace`](https://github.com/matrix-org/matrix-doc/pull/2676) and [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) relation events have this visilibilty, see those respective MSCs. - Visibility is the same as a non-relation event. From 3dcf0ceebc9792d5adad8b2bd04b4b978293b8fc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 10:06:05 +0100 Subject: [PATCH 062/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index e5afd4f4f33..31613443411 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -40,7 +40,7 @@ events to relate to each other. Together, these proposals replace Relation events can be aggregated per `rel_type` by the server. The format of the aggregated value (hereafter called "aggregation") -in the bundle depends on the relation type. +depends on the relation type. Some `rel_type`s might additionally group the aggregations by the `key` property in the relation and aggregate to an array, From 9d963114028ea67cafc3c9ce3a6c595099c4f856 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 10:10:37 +0100 Subject: [PATCH 063/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 31613443411..0af93b60a1d 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -49,7 +49,7 @@ others might aggregate to a single object or any other value really. #### Bundled aggregations Other than during non-gappy incremental syncs, timeline events that have other -events relate to it should bundle the aggregation of those related events +events relate to them should include the aggregation of those related events in the `m.relations` property of their unsigned data. These are called bundled aggregations, and by sending a summary of the relations, avoids us having to always send lots of individual relation events From 541632f5773a7ae916e0940f09bb5eef8a9fde89 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 10:10:45 +0100 Subject: [PATCH 064/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 0af93b60a1d..bf55f64fe69 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -50,8 +50,11 @@ others might aggregate to a single object or any other value really. Other than during non-gappy incremental syncs, timeline events that have other events relate to them should include the aggregation of those related events -in the `m.relations` property of their unsigned data. These are called -bundled aggregations, and by sending a summary of the relations, +in the `m.relations` property of their unsigned data. This process is +referred to as "bundling", and the aggregated relations included via +this mechanism are called "bundled aggregations". + +By sending a summary of the relations, bundling avoids us having to always send lots of individual relation events to the client. From a9943c02773c4a408b33a422b531721806b79e89 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 10:11:42 +0100 Subject: [PATCH 065/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index bf55f64fe69..c9b21a0b416 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -58,7 +58,7 @@ By sending a summary of the relations, bundling avoids us having to always send lots of individual relation events to the client. -State events never bundle aggregations. +Aggregations are never bundled into state events. Here's an example of what that can look like for some ficticious `rel_type`s: From f97df03894956ae7a2342b1fd879d6cc21199e58 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 13:57:24 +0100 Subject: [PATCH 066/109] be more precise when clients should ensure the key is shared --- proposals/2675-aggregations-server.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index c9b21a0b416..6de2ec177ba 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -263,10 +263,11 @@ A future MSC may define a method for encrypting certain parts of the `m.relates_to` field that may contain sensitive information. When sending relation events whose [visibility is derived from the target event](#relation-visibility), -clients should ensure that the end-to-end encryption keys for the encrypted -relation events is shared with all devices that could see the target event, -even if those relation events are encrypted with a different key than -the target event, and even if the receiving user has since left the room. +clients should ensure that the end-to-end encryption key for the encrypted +relation event is shared with all devices that could see the target event +if those relation events are encrypted with a different key than +the target event (e.g. after key rotation), even if the receiving user has +since left the room. ### Redactions From 798835a662e398319694951b2fb960a3fa41dd7e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 14:36:53 +0100 Subject: [PATCH 067/109] mention that ignored users can cause different aggregations for users --- proposals/2675-aggregations-server.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 6de2ec177ba..f9d3a4543f2 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -335,7 +335,9 @@ not visible to them. * Information about relations sent from ignored users must never be sent to the client, either in aggregations or discrete relation events. This is to let you block someone from harassing you with emoji reactions - (or using edits as a side-channel to harass you). + (or using edits as a side-channel to harass you). Therefor, it is possible + that different users will see different aggregations (a different last edit, + or a different reaction count) on an event. ## Limitations From fe781522ad7d9d69d47cedfe5f244efcc7d6088f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 15:08:28 +0100 Subject: [PATCH 068/109] move visibility rule changes to MSC3570 --- proposals/2675-aggregations-server.md | 44 ++++++--------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index f9d3a4543f2..feb5f803327 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -226,33 +226,6 @@ adds the related-to event in `original_event` property of the response. This way the full history (e.g. also the first, original event) of the event is obtained without further requests. See that MSC for further details. -### Relation visibility - -The visibility rules (whether or not a user should receive a given event through -the client-server API) for relations events are adjusted in this MSC. -The visibility for relation events is dependent on the `rel_type`, with two options: - - - Visibility is derived from the visibility of the target event (the event - referred to by the `event_id` in the relation) under some circumstances: - the relation should be visible if the relation target event is visible to - a user but the relation event would not be visible according to regular - event history visibility rules (e.g. the user has since left in a room with - joined or invite room history visibility). - If according to regular event room history visibility rules, the relation - event would be visible to a user, then the visibility of target event - should not be considered and the relation event should be visible. - This option means that events can still be visible to a user after - the user left the room, and has implications - for [End-to-end encryption](#end-to-end-encryption). - [`m.replace`](https://github.com/matrix-org/matrix-doc/pull/2676) and [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) relation events have this visilibilty, see those respective MSCs. - - Visibility is the same as a non-relation event. - [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) relation events have this visilibilty, see the respective MSC. - -Visibility derived from the visibility of the target event is the default for relation events; -if the MSC introducing the relation type doesn't specify any other visibility this is assumed. - -The change of visilibilty rules will require a new room version. - ### End to end encryption Since the server has to be able to aggregate relation events, structural @@ -262,13 +235,6 @@ information about relations must be visible to the server, and so the A future MSC may define a method for encrypting certain parts of the `m.relates_to` field that may contain sensitive information. -When sending relation events whose [visibility is derived from the target event](#relation-visibility), -clients should ensure that the end-to-end encryption key for the encrypted -relation event is shared with all devices that could see the target event -if those relation events are encrypted with a different key than -the target event (e.g. after key rotation), even if the receiving user has -since left the room. - ### Redactions Redacted relations should not be taken into consideration in @@ -341,6 +307,16 @@ not visible to them. ## Limitations +### Relations can be missed while not being in the room + +Relation events behave no different from other events in terms of room history visibility, +which means that some relations might not be visible to a user while he is not a invited +or has not joined the room. These events would thus also not be included in the aggregations. +This can cause for example that a user sees an incomplete +edit history or reaction count upon (re)joining a room. + +[MSC3570](https://github.com/matrix-org/matrix-doc/pull/3570) proposes to remove this limitation. + ### Servers might not be aware of all relations of an event The response of `/relations` might be incomplete because the homeserver From 17122bf9e29d37e961271f111af60cdcbd76d678 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 15:55:15 +0100 Subject: [PATCH 069/109] don't overspecify visibility limitation, allow for unspecified behaviour as synapse includes the invisible events in the aggregation --- proposals/2675-aggregations-server.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index feb5f803327..ca0602e176f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -310,12 +310,13 @@ not visible to them. ### Relations can be missed while not being in the room Relation events behave no different from other events in terms of room history visibility, -which means that some relations might not be visible to a user while he is not a invited -or has not joined the room. These events would thus also not be included in the aggregations. -This can cause for example that a user sees an incomplete -edit history or reaction count upon (re)joining a room. +which means that some relations might not be visible to a user while they are not invited +or has not joined the room. This can cause a user to see an incomplete edit history or reaction count +based on discrete relation events upon (re)joining a room. -[MSC3570](https://github.com/matrix-org/matrix-doc/pull/3570) proposes to remove this limitation. +Ideally the server would not include these events in aggregations, as it would mean breaking +the room history visibility rules, but this MSC defers addressing this limitation and +specifying the exact server behaviour to [MSC3570](https://github.com/matrix-org/matrix-doc/pull/3570). ### Servers might not be aware of all relations of an event From ba59c436479d34162cb1cd4a5a8bc1c55c937e4c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 16:25:24 +0100 Subject: [PATCH 070/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index ca0602e176f..0c55daee1ff 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -94,7 +94,7 @@ For relation types that aggregate to an array, future MSCs could opt to paginate within each group using Matrix's defined pagination idiom of `next_batch` and `chunk` - respectively giving a pagination token if there are more aggregations, and an array of elements in the list. Only the first page -is bundled, pagination of subsequent pages happens through the `/aggregations` +is bundled; pagination of subsequent pages happens through the `/aggregations` API that is defined in this MSC. The maximum amount of aggregations bundled before the list is truncated is determined freely by the server. From 68b302ef6ca556b40c2733267ef836ddb6336240 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 16:26:33 +0100 Subject: [PATCH 071/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 0c55daee1ff..7b9530997f0 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -109,7 +109,7 @@ through `/aggregations` as `next_batch` is present. These are just non-normative examples of what the aggregation for these relation types could look like, and their MSCs might end up with -a different shape, take these with a grain of salt. +a different shape, so take these with a grain of salt. ```json { From d182b9ac6573f88f0e4f568c143269d977f70207 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 16:37:36 +0100 Subject: [PATCH 072/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7b9530997f0..66c7f55ad63 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -153,7 +153,7 @@ To iterate over the aggregations for an event (optionally filtering by relation type and target event type): ``` -GET /_matrix/client/v1/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}[/{rel_type}[/{event_type}]][?from=token][&to=token][&limit=amount] ``` This is just non-normative example of what the aggregation for this From 67d60b1c6d060e25969fed3366b28df558218dd1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 16:38:15 +0100 Subject: [PATCH 073/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 66c7f55ad63..4cb7770c496 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -38,7 +38,7 @@ events to relate to each other. Together, these proposals replace ### Aggregations -Relation events can be aggregated per `rel_type` by the server. +Relation events can be aggregated per relation type (`rel_type`) by the server. The format of the aggregated value (hereafter called "aggregation") depends on the relation type. From 71757a498f4d6da6707158abb7724675361c1b25 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 16:48:14 +0100 Subject: [PATCH 074/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4cb7770c496..851286a0b6c 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -42,7 +42,7 @@ Relation events can be aggregated per relation type (`rel_type`) by the server. The format of the aggregated value (hereafter called "aggregation") depends on the relation type. -Some `rel_type`s might additionally group the aggregations by the `key` property +Some relation types might group the aggregations by the `key` property in the relation and aggregate to an array, others might aggregate to a single object or any other value really. From 48c306300dbc7915cbbc000432c86748d23826ab Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 16:58:24 +0100 Subject: [PATCH 075/109] move non-normative note to below example --- proposals/2675-aggregations-server.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 851286a0b6c..55417ec8135 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -156,10 +156,6 @@ relation type and target event type): GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}[/{rel_type}[/{event_type}]][?from=token][&to=token][&limit=amount] ``` -This is just non-normative example of what the aggregation for this -relation types could look like, and its MSCs might end up with -a different shape, take this with a grain of salt. - ```json { "chunk": [ @@ -174,6 +170,9 @@ a different shape, take this with a grain of salt. } ``` +Again, this is a non-normative example of the aggregation for an +`m.annotation` relation type. + The endpoint does not have any trailing slashes. The `from`, `to` and `limit` query parameters are used for pagination, and work From f93143ba098bdd775179326b7922aaf0220e5ed3 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 17:13:31 +0100 Subject: [PATCH 076/109] make rel_type mandatory as the response structure doesn't allow for mixing types --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 55417ec8135..4d64253a540 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -153,7 +153,7 @@ To iterate over the aggregations for an event (optionally filtering by relation type and target event type): ``` -GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}[/{rel_type}[/{event_type}]][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{event_type}][?from=token][&to=token][&limit=amount] ``` ```json From 29fcd87a97ca074f56390c1204b5861716048400 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 17:15:28 +0100 Subject: [PATCH 077/109] fix typo/thinko --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4d64253a540..d5373127aad 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -150,7 +150,7 @@ The `/aggregations` API lets you iterate over aggregations for the relations of a given event. To iterate over the aggregations for an event (optionally filtering by -relation type and target event type): +relation type and relation event type): ``` GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{event_type}][?from=token][&to=token][&limit=amount] From 6a76e5c324da142e7c8a2782cd129b5d89151de6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 17:31:59 +0100 Subject: [PATCH 078/109] make pagination forward only as there is no use case for backwards --- proposals/2675-aggregations-server.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index d5373127aad..37883f3a29d 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -153,7 +153,7 @@ To iterate over the aggregations for an event (optionally filtering by relation type and relation event type): ``` -GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{event_type}][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{event_type}][?from=token][&limit=amount] ``` ```json @@ -166,7 +166,6 @@ GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{even } ], "next_batch": "some_token", - "prev_batch": "some_token" } ``` @@ -175,7 +174,7 @@ Again, this is a non-normative example of the aggregation for an The endpoint does not have any trailing slashes. -The `from`, `to` and `limit` query parameters are used for pagination, and work +The `from` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. Trying to iterate over a relation type which does not use an aggregation key @@ -198,7 +197,7 @@ see [limitations](#servers-might-not-be-aware-of-all-relations-of-an-event). Yo filter by a given type of relation and event type: ``` -GET /_matrix/client/v1/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&limit=amount] ``` ```json @@ -211,13 +210,12 @@ GET /_matrix/client/v1/rooms/{roomID}/relations/{eventID}[/{relationType}[/{even } ], "next_batch": "some_token", - "prev_batch": "some_token" } ``` The endpoint does not have any trailing slashes. -The `from`, `to` and `limit` query parameters are used for pagination, and work +The `from` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. Note that [MSC2676](https://github.com/matrix-org/matrix-doc/pull/2676) From f61d8dce3389191c5b8ba3eb2bb69ff010aaf148 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 17:33:48 +0100 Subject: [PATCH 079/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 37883f3a29d..9db3b0a7436 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -172,7 +172,8 @@ GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{even Again, this is a non-normative example of the aggregation for an `m.annotation` relation type. -The endpoint does not have any trailing slashes. +Note that endpoint does not have any trailing slashes: `GET /_matrix/client/v1/rooms/{roomID}/aggregations/{eventID}/` +would return aggregations of relations with an *empty* `rel_type`, which is nonsensical. The `from` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. From c65b467c92357a7c13fb0dc8e1b93e2ad7c98a36 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 17:57:43 +0100 Subject: [PATCH 080/109] add non-normative aggregation examples --- proposals/2675-aggregations-server.md | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 9db3b0a7436..aad66c8b2c1 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -46,6 +46,36 @@ Some relation types might group the aggregations by the `key` property in the relation and aggregate to an array, others might aggregate to a single object or any other value really. +Here are some non-normative examples of what aggregations can look like: + +Example [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) aggregation: +``` +{ + "latest_event": { + "content": { ... }, + ... + }, + "count": 7, + "current_user_participated": true +} +``` + +Example [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) aggregation: +``` +[ + { + "key": "👍", + "origin_server_ts": 1562763768320, + "count": 3 + }, + { + "key": "👎", + "origin_server_ts": 1562763768320, + "count": 2 + } +] +``` + #### Bundled aggregations Other than during non-gappy incremental syncs, timeline events that have other From 0717a51b73d488da33c6b34f39340329763c328b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 18:14:31 +0100 Subject: [PATCH 081/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index aad66c8b2c1..15fe5a3328f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -209,7 +209,7 @@ The `from` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. Trying to iterate over a relation type which does not use an aggregation key -(i.e. `m.replace` and `m.reference`) should fail with 400 and error +(eg. `m.replace` and `m.reference`) should fail with 400 and error `M_INVALID_REL_TYPE`. ### Querying relations From 71e4e5cb130e5ad4b2ad56029a20b3cab5ddc72d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 15 Dec 2021 18:17:26 +0100 Subject: [PATCH 082/109] use relation type rather than rel_type the former is already define as the latter in MSC 2674 --- proposals/2675-aggregations-server.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 15fe5a3328f..1237bb29778 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -38,7 +38,7 @@ events to relate to each other. Together, these proposals replace ### Aggregations -Relation events can be aggregated per relation type (`rel_type`) by the server. +Relation events can be aggregated per relation type by the server. The format of the aggregated value (hereafter called "aggregation") depends on the relation type. @@ -90,7 +90,7 @@ to the client. Aggregations are never bundled into state events. -Here's an example of what that can look like for some ficticious `rel_type`s: +Here's an example of what that can look like for some ficticious relation types: ```json { @@ -118,7 +118,7 @@ with events they return: Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle aggregations. -The bundled aggregations are grouped according to their `rel_type`. +The bundled aggregations are grouped according to their relation type. For relation types that aggregate to an array, future MSCs could opt to paginate within each group using Matrix's defined pagination idiom of From 942cfcb8d526a5c1353329fbd723255ba2d46df5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 12:41:12 +0100 Subject: [PATCH 083/109] change trailing slashes remark to event_type, rel_type is mandatory now --- proposals/2675-aggregations-server.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 1237bb29778..b9230560c0f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -202,8 +202,8 @@ GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{even Again, this is a non-normative example of the aggregation for an `m.annotation` relation type. -Note that endpoint does not have any trailing slashes: `GET /_matrix/client/v1/rooms/{roomID}/aggregations/{eventID}/` -would return aggregations of relations with an *empty* `rel_type`, which is nonsensical. +Note that endpoint does not have any trailing slashes: `GET /_matrix/client/v1/rooms/{roomID}/aggregations/$abc/m.reaction/` +would return aggregations of relations with an *empty* `event_type`, which is nonsensical. The `from` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. From b680406cbe037a18059326b9acb7cfd37e4c9a4f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 13:24:10 +0100 Subject: [PATCH 084/109] reword and split out client-side aggregation section --- proposals/2675-aggregations-server.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index b9230560c0f..5b78f3d096f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -174,6 +174,16 @@ a different shape, so take these with a grain of salt. } ``` +### Client-side aggregation + +Bundled aggregations on an event give a snapshot of what relations were know +at the time the event was received. When relations are received through `/sync`, +clients should locally aggregate (as they might have done already before +supporting this MSC) the relation on top of any bundled aggregation the server +might have sent along previously with the target event, to get an up to date +view of the aggregations for the target event. The aggregation algorithm is the +same as the one described here for the server. + ### Querying aggregations The `/aggregations` API lets you iterate over aggregations for the relations @@ -275,15 +285,6 @@ This is in line with other APIs like `/context` and `/messages`. ### Local echo -As clients only receive discrete relation events through `/sync`, -they need to locally aggregate these relation events for their parent event, -on top of any server-side aggregation that might have already happened, -to get a complete picture of the aggregations for a given parent event, -as a client might not be aware of all relations for an event. Local aggregation -should thus also take the `m.relation` data in the `unsigned` of the parent -event into account if it has been sent already. The aggregation algorithm is the -same as the one described here for the server. - For the best possible user experience, clients should also include unsent relations into the local aggregation. When adding a relation to the send queue, clients should locally aggregate it into the relations of the parent From ef57449170617aa7abcdd407fbc71cc84a52f9cc Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 13:35:34 +0100 Subject: [PATCH 085/109] rename parent event to target event, the term used elsewhere --- proposals/2675-aggregations-server.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 5b78f3d096f..43455e042a7 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -286,22 +286,22 @@ This is in line with other APIs like `/context` and `/messages`. ### Local echo For the best possible user experience, clients should also include unsent -relations into the local aggregation. When adding a relation to the send -queue, clients should locally aggregate it into the relations of the parent -event, ideally regardless of the parent event having an `event_id` already or -still being pending. If the client gives up on sending the relation for some -reason, the relation should be de-aggregated from the relations of the parent -event. If the client offers the user a possibility of manually retrying to -send the relation, it should be re-aggregated when the user does so. +relations into the client-side aggregation. When adding a relation to the send +queue, clients should locally aggregate it into the relations of the target +event, ideally regardless of the target event having an `event_id` +already or still being pending. If the client gives up on sending the relation +for some reason, the relation should be de-aggregated from the relations of +the target event. If the client offers the user a possibility of manually +retrying to send the relation, it should be re-aggregated when the user does so. De-aggregating a relation refers to rerunning the aggregation for a given -parent event while not considering the de-aggregated event any more. +target event while not considering the de-aggregated event any more. Upon receiving the remote echo for any relations, a client is likely to remove the pending event from the send queue. Here, it should also de-aggregate the -pending event from the parent event's relations, and re-aggregate the received -remote event from `/sync` to make sure the local aggregation happens with the -same event data as on the server. +pending event from the target event's relations, and re-aggregate the received +remote event from `/sync` to make sure the client-side aggregation happens with +the same event data as on the server. When adding a redaction for a relation to the send queue, the relation referred to should be de-aggregated from the relations of the target of the From 33471e6cc61699678cd0eac47738f1087eaad585 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 13:35:56 +0100 Subject: [PATCH 086/109] apply suggestion --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 43455e042a7..4429bfbf19f 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -288,7 +288,7 @@ This is in line with other APIs like `/context` and `/messages`. For the best possible user experience, clients should also include unsent relations into the client-side aggregation. When adding a relation to the send queue, clients should locally aggregate it into the relations of the target -event, ideally regardless of the target event having an `event_id` +event, ideally regardless of the target event having received an `event_id` already or still being pending. If the client gives up on sending the relation for some reason, the relation should be de-aggregated from the relations of the target event. If the client offers the user a possibility of manually From 9399b0f188b3f34001f6b8bcfad907de76f661c0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 13:37:37 +0100 Subject: [PATCH 087/109] apply suggestion --- proposals/2675-aggregations-server.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 4429bfbf19f..c1847f29a74 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -308,9 +308,9 @@ referred to should be de-aggregated from the relations of the target of the relation. Similar to a relation, when the sending of the redaction fails or is cancelled, the relation should be aggregated again. -Clients can locally relate pending events by their `transaction_id`. -When the target event receives its `event_id` (either receives the remote echo, -or receives the `event_id` from the `/send` response, +One possible way clients can locally relate pending events is by their +`transaction_id`. When the target event receives its `event_id` (either receives +the remote echo, or receives the `event_id` from the `/send` response, whichever comes first), the target event id (`m.relates_to`.`event_id`) of any relations in the send queue will need to be set the newly received `event_id`. From 6e8ff698496934684edeb5fe9f7ea935eca2f9a9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 13:45:04 +0100 Subject: [PATCH 088/109] remove pagination --- proposals/2675-aggregations-server.md | 107 ++------------------------ 1 file changed, 7 insertions(+), 100 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index c1847f29a74..44e9b9108af 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -90,20 +90,6 @@ to the client. Aggregations are never bundled into state events. -Here's an example of what that can look like for some ficticious relation types: - -```json -{ - "event_id": "abc", - "unsigned": { - "m.relations": { - "some_rel_type": { "some_aggregated_prop": true }, - "other_rel_type": { "other_aggregated_prop": 5 }, - } - } -} -``` - The following client-server APIs should bundle aggregations with events they return: @@ -119,58 +105,17 @@ Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle aggregations. The bundled aggregations are grouped according to their relation type. - -For relation types that aggregate to an array, future MSCs could opt to -paginate within each group using Matrix's defined pagination idiom of -`next_batch` and `chunk` - respectively giving a pagination token if there are -more aggregations, and an array of elements in the list. Only the first page -is bundled; pagination of subsequent pages happens through the `/aggregations` -API that is defined in this MSC. The maximum amount of aggregations bundled -before the list is truncated is determined freely by the server. - -Note that the client *can* determine the page size when calling -`/aggregations` through the `limit` request parameter, the offset is solely -determined by the `next_batch` token. - -For instance, the below example shows an event with five bundled relations: -one replace, one reference and three thumbsup reaction annotations, -with more aggregated reactions available to paginate in -through `/aggregations` as `next_batch` is present. - -These are just non-normative examples of what the aggregation for these -relation types could look like, and their MSCs might end up with -a different shape, so take these with a grain of salt. +The format of `m.relations` (here with ficticious relation types) is as follows: ```json { - ..., - "unsigned": { - "m.relations": { - "m.replace": { - "event_id": "$edit_event_id", - "origin_server_ts": 1562763768320, - "sender": "@bruno1:localhost" - }, - "m.reference": { - "chunk": [ - { - "event_id": "$some_event_id" - } - ], - }, - "m.annotation": { - "chunk": [ - { - "type": "m.reaction", - "key": "👍", - "origin_server_ts": 1562763768320, - "count": 3 - } - "next_batch": "abc123", - ] - } - } + "event_id": "abc", + "unsigned": { + "m.relations": { + "some_rel_type": { "some_aggregated_prop": true }, + "other_rel_type": { "other_aggregated_prop": 5 }, } + } } ``` @@ -184,44 +129,6 @@ might have sent along previously with the target event, to get an up to date view of the aggregations for the target event. The aggregation algorithm is the same as the one described here for the server. -### Querying aggregations - -The `/aggregations` API lets you iterate over aggregations for the relations -of a given event. - -To iterate over the aggregations for an event (optionally filtering by -relation type and relation event type): - -``` -GET /_matrix/client/v1/rooms/{room_id}/aggregations/{event_id}/{rel_type}[/{event_type}][?from=token][&limit=amount] -``` - -```json -{ - "chunk": [ - { - "type": "m.reaction", - "key": "👍", - "count": 5, - } - ], - "next_batch": "some_token", -} -``` - -Again, this is a non-normative example of the aggregation for an -`m.annotation` relation type. - -Note that endpoint does not have any trailing slashes: `GET /_matrix/client/v1/rooms/{roomID}/aggregations/$abc/m.reaction/` -would return aggregations of relations with an *empty* `event_type`, which is nonsensical. - -The `from` and `limit` query parameters are used for pagination, and work -just like described for the `/messages` endpoint. - -Trying to iterate over a relation type which does not use an aggregation key -(eg. `m.replace` and `m.reference`) should fail with 400 and error -`M_INVALID_REL_TYPE`. - ### Querying relations A single event can have lots of associated relations, and we do not want to From 803373379f05578e85713dd23ae56349f81970d5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 13:49:02 +0100 Subject: [PATCH 089/109] remove mentions of /aggregations endpoint after removing pagination --- proposals/2675-aggregations-server.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 44e9b9108af..ef760eaa7bc 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -183,11 +183,10 @@ A future MSC may define a method for encrypting certain parts of the ### Redactions Redacted relations should not be taken into consideration in -bundled aggregations or aggregations returned from `/aggregations`, -nor should they be returned from `/relations`. +bundled aggregations, nor should they be returned from `/relations`. -Requesting `/relations` or `/aggregations` on a redacted event should -still return any existing relation events, and aggregations respectively. +Requesting `/relations` on a redacted event should +still return any existing relation events. This is in line with other APIs like `/context` and `/messages`. ### Local echo @@ -265,7 +264,7 @@ full DAG over federation to assure itself that it is aware of all relations. ### Event type based aggregation and filtering won't work well in encrypted rooms -The `/relations` and `/aggregations` endpoint allow filtering by event type, +The `/relations` endpoint allows filtering by event type, which for encrypted rooms will be `m.room.encrypted`, rendering this filtering less useful for encrypted rooms. Aggregations that take the event type into account of the relation will suffer from the same limitation. @@ -298,7 +297,6 @@ to what is implemented at the time of writing. While this MSC is not considered stable, the endpoints become: - - `GET /_matrix/client/unstable/rooms/{roomID}/aggregations/{eventID}[/{relationType}][/{eventType}]` - `GET /_matrix/client/unstable/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]]` None of the newly introduced identifiers should use a prefix though, as this MSC From 3b5f05ca26998570fb83ce067be28ee50b6fe15a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 14:07:45 +0100 Subject: [PATCH 090/109] add note about not bundling into state events --- proposals/2675-aggregations-server.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index ef760eaa7bc..c48302c2000 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -88,7 +88,9 @@ By sending a summary of the relations, bundling avoids us having to always send lots of individual relation events to the client. -Aggregations are never bundled into state events. +Aggregations are never bundled into state events. This is a current +implementation detail that could be revisited later, +rather than a specific design decision. The following client-server APIs should bundle aggregations with events they return: From 513cd91b9b6b0d728da48dc187a222ede921decd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 14:24:11 +0100 Subject: [PATCH 091/109] restructure headers so more of the aggregations stuff is under section --- proposals/2675-aggregations-server.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index c48302c2000..d44ee9f3759 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -76,7 +76,7 @@ Example [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) agg ] ``` -#### Bundled aggregations +#### Bundling Other than during non-gappy incremental syncs, timeline events that have other events relate to them should include the aggregation of those related events @@ -121,7 +121,7 @@ The format of `m.relations` (here with ficticious relation types) is as follows: } ``` -### Client-side aggregation +#### Client-side aggregation Bundled aggregations on an event give a snapshot of what relations were know at the time the event was received. When relations are received through `/sync`, @@ -135,7 +135,7 @@ same as the one described here for the server. A single event can have lots of associated relations, and we do not want to overload the client by including them all bundled with the related-to event -like we do for aggregations. Instead, we provide a new `/relations` API in +like we do for aggregations. Instead, we also provide a new `/relations` API in order to paginate over the relations, which behaves in a similar way to `/messages`, except using `next_batch` and `prev_batch` names (in line with `/sync` API). From 178976a90d5f9375158a46c042c5cdb2347146ee Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 16:08:28 +0100 Subject: [PATCH 092/109] make rel_type mandatory for /relations and better wording --- proposals/2675-aggregations-server.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index d44ee9f3759..c04837a590e 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -143,11 +143,12 @@ order to paginate over the relations, which behaves in a similar way to The `/relations` API returns the discrete relation events associated with an event that the server is aware of in standard topological order. Note that events may be missing, -see [limitations](#servers-might-not-be-aware-of-all-relations-of-an-event). You can optionally -filter by a given type of relation and event type: +see [limitations](#servers-might-not-be-aware-of-all-relations-of-an-event). +You can filter by a given relation type and optionally the event type of the +relating event: ``` -GET /_matrix/client/v1/rooms/{roomID}/relations/{eventID}[/{relationType}[/{eventType}]][?from=token][&limit=amount] +GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}/{rel_type}[/{event_type}][?from=token][&limit=amount] ``` ```json From 06fcc157d1c86eec8341b6d69ca4780d3c150507 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 16:22:16 +0100 Subject: [PATCH 093/109] remove confusion that aggregations contain more info than relations --- proposals/2675-aggregations-server.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index c04837a590e..bc676be8488 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -134,8 +134,8 @@ same as the one described here for the server. ### Querying relations A single event can have lots of associated relations, and we do not want to -overload the client by including them all bundled with the related-to event -like we do for aggregations. Instead, we also provide a new `/relations` API in +overload the client by, for example, including them all bundled with the +related-to event. Instead, we also provide a new `/relations` API in order to paginate over the relations, which behaves in a similar way to `/messages`, except using `next_batch` and `prev_batch` names (in line with `/sync` API). From ea8ada343af9b9893d0b3ef4302239548d16f8f1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 16:23:38 +0100 Subject: [PATCH 094/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index bc676be8488..05f2a6efd51 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -60,7 +60,8 @@ Example [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) aggrega } ``` -Example [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) aggregation: +Example aggregation for [`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) (which +aggregates relations into a list of objects, grouped by `key`). ``` [ { From 6cdf9e7a31d3adc287ac4b0caf2e2447411ae655 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 16:23:48 +0100 Subject: [PATCH 095/109] Update proposals/2675-aggregations-server.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/2675-aggregations-server.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 05f2a6efd51..e363ec20786 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -48,7 +48,8 @@ others might aggregate to a single object or any other value really. Here are some non-normative examples of what aggregations can look like: -Example [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) aggregation: +Example aggregation for [`m.thread`](https://github.com/matrix-org/matrix-doc/pull/3440) (which +aggregates all relations into a single object): ``` { "latest_event": { From bcf7d15fc0ae6b1c01e857ff7487c91af8ea1c21 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 16:31:00 +0100 Subject: [PATCH 096/109] mention that tokens from /sync, /messages can be used on /relations --- proposals/2675-aggregations-server.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index e363ec20786..2f7e3410e3a 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -140,7 +140,9 @@ overload the client by, for example, including them all bundled with the related-to event. Instead, we also provide a new `/relations` API in order to paginate over the relations, which behaves in a similar way to `/messages`, except using `next_batch` and `prev_batch` names -(in line with `/sync` API). +(in line with `/sync` API). Tokens from `/sync` or `/messages` can be +passed to `/relations` to only get relating events from a section of +the timeline. The `/relations` API returns the discrete relation events associated with an event that the server is aware of @@ -150,7 +152,7 @@ You can filter by a given relation type and optionally the event type of the relating event: ``` -GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}/{rel_type}[/{event_type}][?from=token][&limit=amount] +GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}/{rel_type}[/{event_type}][?from=token][&to=token][&limit=amount] ``` ```json @@ -162,6 +164,7 @@ GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}/{rel_type}[/{event_ty "content": { } } ], + "prev_batch": "some_token", "next_batch": "some_token", } ``` From 0114090529bcd70b6e3fec878089627dc28b317b Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 16 Dec 2021 16:31:39 +0100 Subject: [PATCH 097/109] try not to be overly prescriptive --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 2f7e3410e3a..79ef8f0a130 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -236,7 +236,7 @@ common case for rapidly fixing a typo in a msg which is still in flight!) ### Ignore relation events for which the target is not visible to us. -Clients should ignore relation events for which the target event is +Clients can ignore relation events for which the target event is not visible to them. ### How do you handle ignored users? From 3c77504c488d4136c45a8cef2f78007db353561a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 Dec 2021 09:56:12 +0100 Subject: [PATCH 098/109] remove edge case of ignoring events without target event, as ignoring is not always safe --- proposals/2675-aggregations-server.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 79ef8f0a130..7aa81af5d6b 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -234,11 +234,6 @@ common case for rapidly fixing a typo in a msg which is still in flight!) ## Edge cases -### Ignore relation events for which the target is not visible to us. - -Clients can ignore relation events for which the target event is -not visible to them. - ### How do you handle ignored users? * Information about relations sent from ignored users must never be sent to From 8a3d9b1b3148bd384df1da328c3cc9cf03010615 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 Dec 2021 09:59:16 +0100 Subject: [PATCH 099/109] clarify limitation for encrypted rooms --- proposals/2675-aggregations-server.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7aa81af5d6b..8a799357569 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -269,8 +269,9 @@ full DAG over federation to assure itself that it is aware of all relations. The `/relations` endpoint allows filtering by event type, which for encrypted rooms will be `m.room.encrypted`, rendering this filtering -less useful for encrypted rooms. Aggregations that take the event type into -account of the relation will suffer from the same limitation. +less useful for encrypted rooms. Aggregation algorithms that take the type of +the relating events they aggregate into account will suffer from the same +limitation. ## Future extensions From 8460f64fa7a6677f9437e99606cd10c41ec2e6dd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 17 Dec 2021 10:05:25 +0100 Subject: [PATCH 100/109] make rel_type optional again for /relations --- proposals/2675-aggregations-server.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 8a799357569..7354e8a605e 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -148,20 +148,25 @@ The `/relations` API returns the discrete relation events associated with an event that the server is aware of in standard topological order. Note that events may be missing, see [limitations](#servers-might-not-be-aware-of-all-relations-of-an-event). -You can filter by a given relation type and optionally the event type of the +You can optionally filter by a given relation type and the event type of the relating event: ``` -GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}/{rel_type}[/{event_type}][?from=token][&to=token][&limit=amount] +GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}[/{rel_type}[/{event_type}]][?from=token][&to=token][&limit=amount] ``` -```json +``` { "chunk": [ { "type": "m.reaction", "sender": "...", - "content": { } + "content": { + "m.relates_to": { + "rel_type": "m.annotation", + ... + } + } } ], "prev_batch": "some_token", From e1e25933a99fc39f20f738df1ce918341706686d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 7 Jan 2022 15:10:18 +0100 Subject: [PATCH 101/109] Update proposals/2675-aggregations-server.md Co-authored-by: Hubert Chathi --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 7354e8a605e..909ba80d4d9 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -43,7 +43,7 @@ The format of the aggregated value (hereafter called "aggregation") depends on the relation type. Some relation types might group the aggregations by the `key` property -in the relation and aggregate to an array, +in the relation and aggregate to an array, while others might aggregate to a single object or any other value really. Here are some non-normative examples of what aggregations can look like: From e72837a3c31009a465c51ab904810f7c60f203ff Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 7 Jan 2022 15:10:29 +0100 Subject: [PATCH 102/109] Update proposals/2675-aggregations-server.md Co-authored-by: Hubert Chathi --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 909ba80d4d9..91cbb489f72 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -125,7 +125,7 @@ The format of `m.relations` (here with ficticious relation types) is as follows: #### Client-side aggregation -Bundled aggregations on an event give a snapshot of what relations were know +Bundled aggregations on an event give a snapshot of what relations were known at the time the event was received. When relations are received through `/sync`, clients should locally aggregate (as they might have done already before supporting this MSC) the relation on top of any bundled aggregation the server From ae20bcdcb2f40adf70e6a61c60d047a36f92e74e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 7 Jan 2022 15:10:43 +0100 Subject: [PATCH 103/109] Update proposals/2675-aggregations-server.md Co-authored-by: Hubert Chathi --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 91cbb489f72..fa43516e01a 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -244,7 +244,7 @@ common case for rapidly fixing a typo in a msg which is still in flight!) * Information about relations sent from ignored users must never be sent to the client, either in aggregations or discrete relation events. This is to let you block someone from harassing you with emoji reactions - (or using edits as a side-channel to harass you). Therefor, it is possible + (or using edits as a side-channel to harass you). Therefore, it is possible that different users will see different aggregations (a different last edit, or a different reaction count) on an event. From 1dbe2f089a5f7b754236b935eb4486d34295e338 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 7 Jan 2022 15:11:09 +0100 Subject: [PATCH 104/109] Update proposals/2675-aggregations-server.md Co-authored-by: Hubert Chathi --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index fa43516e01a..64cd82a7590 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -254,7 +254,7 @@ common case for rapidly fixing a typo in a msg which is still in flight!) Relation events behave no different from other events in terms of room history visibility, which means that some relations might not be visible to a user while they are not invited -or has not joined the room. This can cause a user to see an incomplete edit history or reaction count +or have not joined the room. This can cause a user to see an incomplete edit history or reaction count based on discrete relation events upon (re)joining a room. Ideally the server would not include these events in aggregations, as it would mean breaking From 88892a5a3616963d66636c1f580de6b0c42febdd Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 7 Jan 2022 15:11:52 +0100 Subject: [PATCH 105/109] Update proposals/2675-aggregations-server.md Co-authored-by: Matthew Hodgson --- proposals/2675-aggregations-server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 64cd82a7590..3dc2a885266 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -268,7 +268,7 @@ potentially doesn't have the full DAG of the room. The federation API doens't have an equivalent of the `/relations` API, so has no way but to fetch the full DAG over federation to assure itself that it is aware of all relations. -[MSC2836](https://github.com/matrix-org/matrix-doc/blob/kegan/msc/threading/proposals/2836-threading.md#making-relationships) also makes mention of this issue. +[MSC2836](https://github.com/matrix-org/matrix-doc/pull/2836) provided a proposal for following relationships over federation in the "Querying relationships over federation" section via a `/_matrix/federation/v1/event_relationships` API ### Event type based aggregation and filtering won't work well in encrypted rooms From 67fa56e91b467aefc9e9c88da0ad94f7e3c055b9 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 7 Jan 2022 17:04:56 +0100 Subject: [PATCH 106/109] mention requires auth and rate-limited on /relations --- proposals/2675-aggregations-server.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 3dc2a885266..346b1c58906 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -174,7 +174,8 @@ GET /_matrix/client/v1/rooms/{roomID}/relations/{event_id}[/{rel_type}[/{event_t } ``` -The endpoint does not have any trailing slashes. +The endpoint does not have any trailing slashes. It requires authentication +and is not rate-limited. The `from` and `limit` query parameters are used for pagination, and work just like described for the `/messages` endpoint. From be6b1c7c8ebff157583a77e2f82d7d23cf3ccaaf Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 10 Jan 2022 13:57:18 +0100 Subject: [PATCH 107/109] replace hypothetical examples for bundled aggregations with non-normative ones --- proposals/2675-aggregations-server.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 346b1c58906..795b41989af 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -109,15 +109,26 @@ Deprecated APIs like `/initialSync` and `/events/{eventId}` are *not* required to bundle aggregations. The bundled aggregations are grouped according to their relation type. -The format of `m.relations` (here with ficticious relation types) is as follows: +The format of `m.relations` (here with *non-normative* examples of +the [`m.replace`](https://github.com/matrix-org/matrix-doc/pull/2676) and +[`m.annotation`](https://github.com/matrix-org/matrix-doc/pull/2677) relation +types) is as follows: ```json { "event_id": "abc", "unsigned": { "m.relations": { - "some_rel_type": { "some_aggregated_prop": true }, - "other_rel_type": { "other_aggregated_prop": 5 }, + "m.annotation": { + "key": "👍", + "origin_server_ts": 1562763768320, + "count": 3 + }, + "m.replace": { + "event_id": "$edit_event_id", + "origin_server_ts": 1562763768320, + "sender": "@alice:localhost" + }, } } } From 8f3a28a52e205484e8a0acc1f1b1862431415855 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 10 Jan 2022 14:01:26 +0100 Subject: [PATCH 108/109] move to MSC 2676 as it's specific to edits --- proposals/2675-aggregations-server.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 795b41989af..57f375ef070 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -246,9 +246,6 @@ whichever comes first), the target event id (`m.relates_to`.`event_id`) of any relations in the send queue will need to be set the newly received `event_id`. -Particularly, please remember to let users edit unsent messages (as this is a -common case for rapidly fixing a typo in a msg which is still in flight!) - ## Edge cases ### How do you handle ignored users? From ae7dc261d613d345abeea35c4bf90a6ffd3ca33e Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 10 Jan 2022 15:31:17 +0100 Subject: [PATCH 109/109] dont repeat how local echo using transaction_id works --- proposals/2675-aggregations-server.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/proposals/2675-aggregations-server.md b/proposals/2675-aggregations-server.md index 57f375ef070..5808dbec008 100644 --- a/proposals/2675-aggregations-server.md +++ b/proposals/2675-aggregations-server.md @@ -239,12 +239,10 @@ referred to should be de-aggregated from the relations of the target of the relation. Similar to a relation, when the sending of the redaction fails or is cancelled, the relation should be aggregated again. -One possible way clients can locally relate pending events is by their -`transaction_id`. When the target event receives its `event_id` (either receives -the remote echo, or receives the `event_id` from the `/send` response, -whichever comes first), the target event id (`m.relates_to`.`event_id`) of -any relations in the send queue will -need to be set the newly received `event_id`. +If the target event is still pending and hasn't received its `event_id` yet, +clients can locally relate relation events to their target by using +`transaction_id` like they already do for detecting remote echos when sending +events. ## Edge cases