-
Notifications
You must be signed in to change notification settings - Fork 380
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
MSC2674: Event Relationships #2674
Changes from 38 commits
9e8460f
3415262
c00e4f4
e4c16fa
35fb00c
db6213b
2229975
d9ffb2c
bc1df59
18cac1a
3e6e566
62036f1
c667a08
e90f31e
fd13748
5eaf2de
157a097
71d9668
b590a4c
0cd38d1
6665bc1
00ce39e
f41b78c
6c2e2e0
5170cc1
075ea46
99a2729
76a4116
eb9033a
4388dea
cd180b6
533b8e8
138ca8c
9c6d282
e1309e1
5ec656d
8cfda4d
f24945e
46d1bff
8e12152
12fdf55
57cfb55
e027133
7cca8ac
12bdf05
feb3377
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
# MSC2674: Event relationships | ||
|
||
It's common to want to send events in Matrix which relate to existing events - | ||
for instance, reactions, edits and even replies/threads. | ||
|
||
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). | ||
|
||
* This proposal defines a standard shape for indicating events which relate to | ||
other events. | ||
* [MSC2675](https://github.com/matrix-org/matrix-doc/pull/2675) 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. | ||
* [MSC2676](https://github.com/matrix-org/matrix-doc/pull/2676) defines how | ||
users can edit messages using this mechanism. | ||
* [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. | ||
* [MSC3267](https://github.com/matrix-org/matrix-doc/pull/3267) defines how events | ||
can make a reference to other events. | ||
* [MSC3389](https://github.com/matrix-org/matrix-doc/pull/3389) defines changes to | ||
the redaction algorithm, to preserve the type and target id of a relation. | ||
|
||
|
||
## Proposal | ||
|
||
This proposal introduces the concept of relations, which can be used to | ||
associate new information with an existing event. | ||
|
||
A relationship is an object with a field `rel_type`, which is a string describing the type of relation, | ||
and a field `event_id`, which is a string that represents the event_id of the target of this relation. | ||
Both of those fields are required. An event is said to contain a relationship if their `content` contains | ||
turt2live marked this conversation as resolved.
Show resolved
Hide resolved
|
||
a relationship with all the required fields under the `m.relates_to` key. If any of these conditions is not met, | ||
clients and servers should treat the event as if it does not contain a relationship. | ||
bwindels marked this conversation as resolved.
Show resolved
Hide resolved
richvdh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Here's a (partial) example of an event relating to another event: | ||
|
||
```json | ||
{ | ||
"content": { | ||
"m.relates_to": { | ||
"rel_type": "m.replace", | ||
"event_id": "$abc:server.tld" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
All the information about the relationship lives under the `m.relates_to` key. | ||
|
||
If it helps, you can think of relations as a "subject verb object" triple, | ||
where the subject is the relation event itself; the verb is the `rel_type` | ||
field of the `m.relates_to` and the object is the `event_id` field. | ||
|
||
We consciously do not support multiple different relations within a single event, | ||
uhoreg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
in order to keep the API simple. Another MSC, | ||
like [MSC 3051](https://github.com/matrix-org/matrix-doc/pull/3051), | ||
can propose a change to add support for multiple relations if it turns out that | ||
this would facilitate certain use cases. | ||
|
||
Relations do not yet replace the | ||
[reply mechanism currently defined in the spec](https://matrix.org/docs/spec/client_server/r0.6.1#rich-replies). | ||
|
||
### Relation types | ||
|
||
This MSC does not define any value for `rel_type`, but rather defines the generic | ||
framework that different kinds of relations have in common and that other MSCs can | ||
build on. Future definitions for values of `rel_type` should describe *how* the server | ||
should aggregate relations on the target event | ||
(as proposed in [MSC 2675](https://github.com/matrix-org/matrix-doc/pull/2675)). | ||
The goal is to make each `rel_type` as broadly useful as possible, | ||
and to keep the number of types for a server implementation to support down to a minimum. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would appreciate some input here, as I think this might be the most contested part of the MSC; approaches that go somewhat against this rule of thumb have been proposed in other MSCs. My biggest doubt here is that the server endpoint in MSC 2675 to get relations for an event won't be able to filter by these subtypes, so if clients want to make use of that API, they might be forced to fetch more relations than they really need for their use case (e.g. fetch all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my opinion the server doesn't need to know all the aggregation types to calculate aggregations, see also my comment here: #2675 (comment) So it would make most sense to have specific rel_types for specific use cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this a topic for debate in #2675 anyway? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @richvdh I think this MSC should provide some guidance on how a relationship verb should be chosen. Otherwise we just end up using m.reference everywhere or alternativey m.highly_specific_thing |
||
|
||
Multiple client use cases may be served by a single `rel_type` if they require aggregation | ||
in a similar manner. To further specify how a relation should be displayed in the client, | ||
MSCs may define additional fields in `m.relates_to` for specific values of `rel_type`. | ||
|
||
Any values here should abide the | ||
[general guidelines for identifiers](https://github.com/matrix-org/matrix-doc/pull/3171). | ||
|
||
### Sending relations | ||
|
||
Related events are normal Matrix events, and can be sent by the normal `/send` | ||
API. | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The server should postprocess relations if needed before sending them into a | ||
room, as defined by the relationship type. For example, a relationship type | ||
might only allow a user to send one related message to a given event. | ||
|
||
### Receiving relations | ||
|
||
Relations are received like other non-state events, with `/sync`, | ||
`/messages` and `/context`, as normal discrete Matrix events. As explained | ||
in the limitations, clients may be unaware of some relations using just these endpoints. | ||
|
||
[MSC2675](https://github.com/matrix-org/matrix-doc/pull/2675) defines ways in | ||
which the server may aid clients in processing relations by aggregating the | ||
events. | ||
|
||
### Redactions | ||
|
||
Events with a relation may be redacted like any other event. | ||
|
||
[MSC3389](https://github.com/matrix-org/matrix-doc/pull/3389) proposes that | ||
the redaction algorithm should preserve the type and target id of a relation. | ||
|
||
However, event relationships can still be used in existing room versions, but | ||
the user experience may be worse if redactions are performed. | ||
|
||
## Potential issues | ||
|
||
### Federation considerations | ||
|
||
We have a problem with resynchronising relations after a gap in federation: | ||
We have no way of knowing that an edit happened in the gap to one of the events | ||
we already have. So, we'll show inconsistent data until we backfill the gap. | ||
turt2live marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* We could write this off as a limitation. | ||
* Or we could make *ALL* relations a DAG, so we can spot holes at the next | ||
relation, and go walk the DAG to pull in the missing relations? Then, the | ||
next relation for an event could pull in any of the missing relations. | ||
Socially this probably doesn't work as reactions will likely drop off over | ||
time, so by the time your server comes back there won't be any more reactions | ||
pulling the missing ones in. | ||
* Could we also ask the server, after a gap, to provide all the relations which | ||
happened during the gap to events whose root preceeded the gap. | ||
* "Give me all relations which happened between this set of | ||
forward-extremities when I lost sync, and the point i've rejoined the DAG, | ||
for events which preceeded the gap"? | ||
* Would be hard to auth all the relations which this api coughed up. | ||
* We could auth them based only the auth events of the relation, except we | ||
lose the context of the nearby DAG which we'd have if it was a normal | ||
backfilled event. | ||
* As a result it would be easier for a server to retrospectively lie about | ||
events on behalf of its users. | ||
* This probably isn't the end of the world, plus it's more likely to be | ||
consistent than if we leave a gap. | ||
* i.e. it's better to consistent with a small chance of being maliciously | ||
wrong, than inconsistent with a guaranteed chance of being innocently | ||
wrong. | ||
* We'd need to worry about pagination. | ||
* This is probably the best solution, but can also be added as a v2. | ||
* In practice this seems to not be an issue, which is worth complicating | ||
the s-s API over. Clients very rarely jump over the federation gap to an edit. | ||
In most cases they scroll up, which backfills the server and we have all the | ||
edits, when we reach the event before the gap. | ||
|
||
## Limitations | ||
|
||
Based solely on this MSC, relations are only received as discrete events in | ||
the timeline, so clients may only have an incomplete image of all the relations | ||
with an event if they do not fill gaps (syncs with a since token that have | ||
`limited: true` set in the sync response for a room) in the timeline. | ||
|
||
In practice, this has proven not to be too big of a problem, as reactions | ||
(as proposed in [MSC 2677](https://github.com/matrix-org/matrix-doc/pull/2677)) | ||
tend to be posted close after the target event in the timeline. | ||
|
||
A more complete solution to this has been deferred to | ||
[MSC2675](https://github.com/matrix-org/matrix-doc/pull/2675). | ||
|
||
bwindels marked this conversation as resolved.
Show resolved
Hide resolved
|
||
## Tradeoffs | ||
|
||
### Event shape | ||
|
||
Shape of | ||
|
||
```json | ||
"content": { | ||
"m.relates_to": { | ||
"m.reference": { | ||
"event_id": "$another:event.com" | ||
} | ||
} | ||
} | ||
``` | ||
versus | ||
|
||
```json | ||
"content": { | ||
"m.relates_to": { | ||
"rel_type": "m.reference", | ||
"event_id": "$another:event.com" | ||
} | ||
} | ||
``` | ||
|
||
The reasons to go with `rel_type` is: | ||
* This format is now in use in the wider matrix ecosystem without a prefix, | ||
in spite of the original MSC 1849 not being merged. This situation is not ideal | ||
but we still don't want to break compatibility with several clients. | ||
* We don't need the extra indirection to let multiple relations apply to a given pair of | ||
events, as that should be expressed as separate relation events. | ||
* If we want 'adverbs' to apply to 'verbs' in the subject-verb-object triples which | ||
relations form, then we apply it as mixins to the relation data itself rather than trying | ||
to construct subject-verb-verb-object sentences. | ||
* We decided to not adopt the format used by `m.in_reply_to` as it allows for multiple relations | ||
and is hence overly flexible. Also, the relation type of `m.in_reply_to` is also overly specific | ||
turt2live marked this conversation as resolved.
Show resolved
Hide resolved
|
||
judged by the guidelines for `rel_type`s laid out in this MSC. Having replies use the same | ||
format as relations is postponed to a later MSC, but it would likely involve replies | ||
adopting the relation format with a more broadly useful `rel_type` (possibly the `m.reference` | ||
type proposed in [MSC3267](https://github.com/matrix-org/matrix-doc/pull/3267)), | ||
rather than relations adopting the replies format. | ||
|
||
## Historical context | ||
|
||
pik's MSC441 has: | ||
|
||
Define the JSON schema for the aggregation event, so the server can work out | ||
which fields should be aggregated. | ||
|
||
```json | ||
"type": "m.room._aggregation.emoticon", | ||
"content": { | ||
"emoticon": "::smile::", | ||
"msgtype": "?", | ||
"target_id": "$another:event.com" | ||
} | ||
``` | ||
|
||
These would then be aggregated, based on target_id, and returned as annotations on | ||
the source event in an `aggregation_data` field: | ||
|
||
```json | ||
"content": { | ||
... | ||
"aggregation_data": { | ||
"m.room._aggregation.emoticon": { | ||
"aggregation_data": [ | ||
{ | ||
"emoticon": "::smile::", | ||
"event_id": "$14796538949JTYis:pik-test", | ||
"sender": "@pik:pik-test" | ||
} | ||
], | ||
"latest_event_id": "$14796538949JTYis:pik-test" | ||
} | ||
} | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Someone mentioned to me that the target event must also be in the same room, but that doesn't seem to be captured in this MSC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clients don't always do that, i.e. when forwarding messages. It would make sense to require that without a room_id though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can leave relating to events in other rooms up to another MSC, and for now say it must be the same room.
I don't think any client currently forwards an event? Replies, yes, and once those make use of relations as proposed here, the correct thing to do would probably be either define relating to events in other rooms in a new MSC or remove the reply relation. Wdyt?