MSC2674: Event Relationships (#2674)
* initial version of event relationship MSC * fix MSC numbers * clarifications * mention multiple relations per event might be useful, but postpone for a future MSC * mention MSC 3051 for proposed multiple relations * remove send_relation endpoint * move e2ee section under sending relations * mention limitation of leaving server-side aggregations out for now * remove mentions of m.reference, we'll sort that out in another MSC * whitespace * argument why m.relates_to should be preserved by redactions more general but still give example of redacted edits * deal with this in the comments * clarify the conditions to meet for a relation * mention specifically that this does not replace replies (yet) * clarify how general rel_types should be * clarify that gaps may cause clients to be unaware of some relations * Update proposals/2674-event-relationships.md Co-authored-by: DeepBlueV7.X <nicolas.werner@hotmail.de> * Update proposals/2674-event-relationships.md Co-authored-by: DeepBlueV7.X <nicolas.werner@hotmail.de> * make wording clearer and move to bottom of section * remove this as references are not defined here anymore * clearer wording * move edge cases to other relevant mscs * clarify that a goal of sticking to this format is backwards compat. * mention MSC 3267, to which m.reference has been extracted * Update proposals/2674-event-relationships.md Co-authored-by: Hubert Chathi <hubert@uhoreg.ca> * Update proposals/2674-event-relationships.md Co-authored-by: Hubert Chathi <hubert@uhoreg.ca> * Update proposals/2674-event-relationships.md Co-authored-by: Matthew Hodgson <matthew@arasphere.net> * Update proposals/2674-event-relationships.md Co-authored-by: Matthew Hodgson <matthew@arasphere.net> * Update proposals/2674-event-relationships.md Co-authored-by: Travis Ralston <travpc@gmail.com> * wrap lines * better wording * this is singular, really * add example of event shape * specify how invalid relations should be treated by the redaction algorithm * fix typo * split up redactions changes in separate MSC * also add new msc to introduction * reword why not adopt m.in_reply_to * remove guidelines how to pick rel_type * mention that the target event must exist in the same room * spell out the conscious (subject, object, verb) triple idea. * Spelling Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * remove paragraph saying what server should accept * Revert "remove paragraph saying what server should accept" This reverts commit e0271331b2e7dee236349aa63eec3cec7369e361. * further specify that a server should reject invalid relations through the cs api * linebreak Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: Bruno Windels <bruno@windels.cloud> Co-authored-by: DeepBlueV7.X <nicolas.werner@hotmail.de> Co-authored-by: Matthew Hodgson <matthew@arasphere.net> Co-authored-by: Travis Ralston <travpc@gmail.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>pull/977/head
parent
ac98c8c08c
commit
9654bf19b3
@ -0,0 +1,250 @@
|
||||
# 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 event of this relation.
|
||||
The target event must exist in the same room as the relating event is sent.
|
||||
Both of those fields are required. An event is said to contain a relationship if its `content` contains
|
||||
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.
|
||||
Servers should reject events not meeting these conditions with an HTTP 400 error when
|
||||
they are received via the client-server API.
|
||||
|
||||
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,
|
||||
in order to keep the API simple. This means that if event A relates to event B
|
||||
in two different ways you would send two events to describe the two relations,
|
||||
rather than bundling them into a single event. 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
|
||||
|
||||
Any values for `rel_type` should abide the
|
||||
[general guidelines for identifiers](https://github.com/matrix-org/matrix-doc/pull/3171).
|
||||
|
||||
The `rel_type` property determines how an event relates to another and can be used
|
||||
by clients to determine how and in what context a relation should be displayed.
|
||||
|
||||
[MSC 2675](https://github.com/matrix-org/matrix-doc/pull/2675) proposes to also interpret the `rel_type` server-side.
|
||||
|
||||
It is left up to the discretion of other MSCs building on this one whether they introduce
|
||||
`rel_type`s that are specific to their use case or that can serve a broad range
|
||||
of use cases. MSCs may define additional properties on the relation object for a given `rel_type`.
|
||||
|
||||
Currently, a few `rel_type`s are already proposed. Here's a non-exhaustive list:
|
||||
|
||||
- `m.replace` in [MSC 2676](https://github.com/matrix-org/matrix-doc/pull/2676).
|
||||
- `m.annotation` in [MSC 2677](https://github.com/matrix-org/matrix-doc/pull/2677).
|
||||
- `m.reference` in [MSC 3267](https://github.com/matrix-org/matrix-doc/pull/3267).
|
||||
- `m.thread` in [MSC 3440](https://github.com/matrix-org/matrix-doc/pull/3440).
|
||||
|
||||
|
||||
### Sending relations
|
||||
|
||||
Related events are normal Matrix events, and can be sent by the normal `/send`
|
||||
API.
|
||||
|
||||
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.
|
||||
* 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).
|
||||
|
||||
## 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
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue