Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spec /relations and aggregations #1062

Merged
merged 31 commits into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1d70a8d
Commit to show changes to rich replies section
turt2live May 5, 2022
03c4638
Move rich replies to a module
turt2live May 5, 2022
01cd76e
Add remainder of MSC2674
turt2live May 14, 2022
ff03381
Pivot away from MSC3440: Threads
turt2live May 14, 2022
b319d2f
Add changelog entries so far
turt2live May 14, 2022
9e7929c
Make a note for why we have aggregations/relations if nothing uses it
turt2live May 14, 2022
29c9465
Outright remove threads references
turt2live May 17, 2022
1435d06
Define MSC2675
turt2live May 18, 2022
7a92cf5
Define MSC3666
turt2live May 18, 2022
76e3611
Add note for rich replies?
turt2live May 18, 2022
2063d11
Update content/client-server-api/_index.md
turt2live May 27, 2022
109bfb2
Clarify how ignoring works for aggregations.
turt2live May 27, 2022
0d35037
Try to clarify redactions a bit
turt2live May 27, 2022
532b06b
Clarify using parent/child language
turt2live May 27, 2022
9fa50a7
Add missing bits of MSC2675
turt2live May 27, 2022
753fd81
Add changelog for aggregations
turt2live May 27, 2022
d9004d7
Appease the linters
turt2live May 27, 2022
42e5c4d
Update data/api/client-server/relations.yaml
turt2live May 27, 2022
f8d667a
Apply suggestions from code review
turt2live Jun 2, 2022
315b327
Apply suggestions from code review
turt2live Jun 2, 2022
2cc631e
Try to clarify the return of /relations
turt2live Jun 2, 2022
b5b6fd9
Fix required attribute
turt2live Jun 2, 2022
09422a3
Fix wording round 1
turt2live Jun 7, 2022
0f65b2f
Try to fix pagination
turt2live Jun 7, 2022
340f9e5
Copy/paste the endpoint to make Open API happy
turt2live Jun 7, 2022
c02e1f1
Fix code block examples for rich replies
turt2live Jun 7, 2022
b509444
Apply suggestions from code review
turt2live Jun 8, 2022
5bb8b3e
Apply suggestions on all 3 endpoints
turt2live Jun 8, 2022
13a43c0
Fix description of relationships API
turt2live Jun 8, 2022
a00e70e
Fix warning about server-side aggregation/bundling
turt2live Jun 8, 2022
50b4811
Merge remote-tracking branch 'origin/travis/spec/aggregations' into t…
turt2live Jun 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelogs/client_server/newsfragments/1062.feature.1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Relax the restrictions on Rich Replies, as per [MSC3676](https://github.com/matrix-org/matrix-spec-proposals/pull/3676).
1 change: 1 addition & 0 deletions changelogs/client_server/newsfragments/1062.feature.2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Describe a structured system for event relationships, as per [MSC2674](https://github.com/matrix-org/matrix-spec-proposals/pull/2674).
204 changes: 204 additions & 0 deletions content/client-server-api/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,16 @@ There are several APIs provided to `GET` events for a room:

### Sending events to a room

{{% boxes/note %}}
{{% added-in v="1.3" %}}

Servers might need to post-process some events if they
[relate to](#forming-relationships-between-events) another event. The event's
relationship type (`rel_type`) determines any restrictions which might apply,
such as the user only being able to send one event of a given type in relation
to another.
{{% /boxes/note %}}

{{% http-api spec="client-server" api="room_state" %}}

**Examples**
Expand Down Expand Up @@ -1831,6 +1841,198 @@ the topic to be removed from the room.

{{% http-api spec="client-server" api="redaction" %}}

### Forming relationships between events

{{% changed-in v="1.3" %}}
richvdh marked this conversation as resolved.
Show resolved Hide resolved

In some cases it is desirable to logically associate one event's contents with
another event's contents. For example, when replying to a message, editing an
event, or simply looking to add context for an event's purpose.
turt2live marked this conversation as resolved.
Show resolved Hide resolved

Relationships are defined as part of an event's `content`. Any event can relate
to any other event, however the relationship itself might have restrictions
depending on its `rel_type`. Those restrictions are described by the relationship
type in this specification, if any exist.

The relationship is stored under the `m.relates_to` key of `content`, referencing
the "parent" event. Both the event with `m.relates_to` and the event targeted by
`m.relates_to` MUST exist in the same room.

{{% boxes/note %}}
For simplicity, a single type of relationship is permitted on an event at a time.
A future MSC might change this if a use case arises.
{{% /boxes/note %}}

{{% boxes/note %}}
An event with `m.relates_to` can relate to another event with `m.relates_to`,
forming a sort of chain of events.
{{% /boxes/note %}}

{{% boxes/note %}}
To allow the server to aggregate and find relations on events, the `m.relates_to`
key of an event must be included in the plaintext copy of the event. It cannot
be exclusively recorded in the encrypted payload of an event.
{{% /boxes/note %}}

{{% boxes/warning %}}
If an encrypted event contains an `m.relates_to` in its payload, it should be
ignored and instead favour the plaintext `m.relates_to` copy (including when there
is no plaintext copy).
{{% /boxes/warning %}}

`m.relates_to` is described as follows:
turt2live marked this conversation as resolved.
Show resolved Hide resolved

{{% definition path="api/client-server/definitions/m.relates_to" %}}

#### Relationship types

This specification describes the following relationship types:

* [Rich replies](#rich-replies) (**Note**: uses a different relations structure than
described here)

{{% boxes/note %}}
This specification does not currently define any relation type which requires
aggregation or has restrictions, however [namespaced](/appendices#identifier-grammar)
relationship types might have these restrictions.
turt2live marked this conversation as resolved.
Show resolved Hide resolved

Future versions of this specification are expected to require certain behaviours
or aggregation of related events.
{{% /boxes/note %}}

#### Aggregations

{{% added-in v="1.3" %}}
richvdh marked this conversation as resolved.
Show resolved Hide resolved

Some relationships are "aggregated" by the server depending on their relationship
type. This can allow a set of related events to be summarised as a subset of values.
turt2live marked this conversation as resolved.
Show resolved Hide resolved

For example, a relationship might define an extra `key` field which, when used with
the appropriate `rel_type`, would mean that the client receives a total count for
the number of times that `key` was used in a relationship.

The actual aggregation format depends on the relationship type.

{{% boxes/note %}}
This specification does not currently describe any relation types which require
aggregation, however [namespaced](/appendices#identifier-grammar) relationship
types might have aggregation behaviour.
{{% /boxes/note %}}

When aggregations are summarised on an event, it is known as a "bundled aggregation"
richvdh marked this conversation as resolved.
Show resolved Hide resolved
or "bundle" for simplicity. The act of doing this is "bundling".
turt2live marked this conversation as resolved.
Show resolved Hide resolved

The bundle for an event is found under the `unsigned` field of the event, when that
event is served to the client through the APIs listed below. The field, `m.relations`,
is an object with a key of the relationship type and value being the bundle itself.

For example (unimportant fields not included):

```json
{
"event_id": "$my_event",
"unsigned": {
"m.relations": {
"org.example.possible_annotations": [
{
"key": "👍",
"origin_server_ts": 1562763768320,
"count": 3
},
{
"key": "👎",
"origin_server_ts": 1562763768320,
"count": 1
}
],
"org.example.possible_thread": {
"current_server_participated": true,
"count": 7,
"latest_event": {
"event_id": "$another_event",
"content": {
"body": "Hello world"
}
}
}
}
}
}
```

Note how the `org.example.possible_annotations` bundle is an array compared to the
`org.example.possible_thread` bundle where the server is summarising the state of
the relationship in a single object. Both are valid bundles, and their exact types
depend on the relationship type.

The endpoints where the server *should* include the `m.relations` unsigned field are:
turt2live marked this conversation as resolved.
Show resolved Hide resolved

* [`GET /rooms/{roomId}/messages`](#get_matrixclientv3roomsroomidmessages)
* [`GET /rooms/{roomId}/context/{eventId}`](#get_matrixclientv3roomsroomidcontexteventid)
* [`GET /rooms/{roomId}/event/{eventId}`](#get_matrixclientv3roomsroomideventeventid)
* [`GET /rooms/{roomId}/relations`](#get_matrixclientv3roomsroomidrelations)
richvdh marked this conversation as resolved.
Show resolved Hide resolved
* [`GET /sync`](#get_matrixclientv3sync) when the relevant section has a `limited` value
of `true`.
* [`POST /search`](#post_matrixclientv3search) for any matching events under `room_events`.

{{% boxes/note %}}
The server is **not** required to return bundles/aggregations on deprecated endpoints
turt2live marked this conversation as resolved.
Show resolved Hide resolved
such as `/initialSync`.
{{% /boxes/note %}}

While this functionality allows the client to see what was known to the server at the
time of handling, the client should continue to aggregate locally if it is aware of
the relationship type's behaviour. For example, a client might increment a `count`
on a related event's bundle if it saw a new event which referenced that event.

{{% boxes/warning %}}
The bundle provided by the server only includes events which were known at the time
the event was *received*. This can mean that in a single `/sync` response an event
will have a bundle and more events which qualify for that aggregation: in this case,
the client *should* aggregate the events which are "after" the event in question on
its own, as the server will not have considered them.
turt2live marked this conversation as resolved.
Show resolved Hide resolved
{{% /boxes/warning %}}

{{% boxes/note %}}
Events from [ignored users](#ignoring-users) do not appear in the bundle or aggregation.
Clients will need to de-aggregate the events sent by ignored users to avoid them being
considered in counts. Similarly, servers must ensure they do not consider events from
turt2live marked this conversation as resolved.
Show resolved Hide resolved
ignored users when preparing a bundle for the client.
{{% /boxes/note %}}

When an event is redacted, the relations attached to it remain. However, when an event
which uses a relation is redacted then the relation is broken. Thus, the server needs
to de-aggregate or disassociate an event from its parent when it is redacted. Clients
with local aggregation should do the same.
turt2live marked this conversation as resolved.
Show resolved Hide resolved

It is suggested that clients perform local echo on aggregations. For instance, aggregating
turt2live marked this conversation as resolved.
Show resolved Hide resolved
the event into a bundle optimistically until the server returns a failure or the client
gives up on sending the event, at which point the event should be de-aggregated and an
error or similar shown. The client should be cautious to not aggregate an event twice if
it has already optimistically aggregated the event. Clients are encouraged to take this
a step further to additionally track related events which target unsent/pending events,
likely using the transaction ID as a temporary event ID until a proper event ID is known.

{{% boxes/warning %}}
Due to history visibility restrictions, related events might not be visible to the user
if they are in a section of history the user cannot see. This can mean inaccurate bundles
turt2live marked this conversation as resolved.
Show resolved Hide resolved
for events that are "out of range".

Additionally, if the server is missing portions of the room history then it may not be
able to accurately aggregate the events.
{{% /boxes/warning %}}

#### API

To retrieve relations for an event from the server, the client can call the following
endpoint with relevant information. The endpoint does not aggregate the events and is
instead paginated: clients can perform local aggregation if needed.
turt2live marked this conversation as resolved.
Show resolved Hide resolved

This endpoint is particularly useful if the client has lost context on the bundle for
an event and needs to rebuild/verify it.

{{% http-api spec="client-server" api="relations" %}}

## Rooms

### Types
Expand Down Expand Up @@ -2212,6 +2414,7 @@ that profile.
| Module / Profile | Web | Mobile | Desktop | CLI | Embedded |
|------------------------------------------------------------|-----------|----------|----------|----------|----------|
| [Instant Messaging](#instant-messaging) | Required | Required | Required | Required | Optional |
| [Rich replies](#rich-replies) | Optional | Optional | Optional | Optional | Optional |
| [Direct Messaging](#direct-messaging) | Required | Required | Required | Required | Optional |
| [Mentions](#user-room-and-group-mentions) | Required | Required | Required | Optional | Optional |
| [Presence](#presence) | Required | Required | Required | Required | Optional |
Expand Down Expand Up @@ -2291,6 +2494,7 @@ applications, they are not intended to be fully-fledged communication
systems.

{{% cs-module name="instant_messaging" %}}
{{% cs-module name="rich_replies" %}}
{{% cs-module name="voip_events" %}}
{{% cs-module name="typing_notifications" %}}
{{% cs-module name="receipts" %}}
Expand Down
Loading