Skip to content

MSC4301: Event capability negotiation between clients #4301

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
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
115 changes: 115 additions & 0 deletions proposals/4301-event-capability-negotiation.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation requirements:

  • Sending client
  • Receiving client (with support)
  • Receiving client (without support)

Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# MSC4301: Event capability negotiation between clients

Matrix allows clients to exchange both built-in and custom events with other clients in rooms. There
is, however, no way for a client to understand what types of events the other clients in a room are
able to understand. This is problematic as a compatibility mismatch means that the recipient user
might only be able to see a fallback representation of an event or, in the worst case, nothing at
all. At the same time, the sender is left wholly unaware of the recipient's experience.
Comment on lines +3 to +7
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This problem area is discussed a lot, usually in the context of extensible events. I'm concerned that this MSC opens up pandora's box again by trying to add a negotiation layer on top of a compatibility layer - this proposal needs a strong rationale for why extensible events is insufficient beyond "it can sometimes result in fallback", which is by design.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this proposal needs a strong rationale for why extensible events is insufficient beyond "it can sometimes result in fallback", which is by design.

This is really it though.

We're using Matrix in the healthcare sector and in some cases it's simply not acceptable to rely on fallback representations. The events to be sent might contain complex medical data that cannot feasibly be condensed into a useful fallback and where the sender requires guarantees that the content will actually be understood because health depends on it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho a combination of extensible events and m.status.response would be sufficient. We could add an information like allow_fallback: Boolean or don't add a fallback at all in the extensible event. Then the receiver could answer with an m.status.response so the sender would get notified about displaying issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For many cases a fallback would be sufficient. E. g. a DICOM event could have an image and file fallback, so the user would get a preview (image fallback) and could download the DICOM (file fallback) and open it in an external software.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are good points. I suppose in essence the only thing this proposal adds over #4300 is the shortcut of figuring out if an event type will be understood before actually sending the event.

Not having to send the event if the recipient is known to not support it is probably only a meaningful benefit if you're sending extremely large data.

However, being able to downgrade to another event type that the recipient understands feels harder to do with just #4300. What I'm trying to hedge against are cases where there are multiple historic versions of an event type (similar to how some of the email message types here had several versions).


[MSC4300] partially addresses this problem by enabling clients to communicate the result of
processing a specific event back to the sender. This lets senders determine after the fact whether
the events they have sent were understood by other clients or not.

The present proposal goes a step further and introduces a scheme for clients to query whether other
clients understand an event type *ahead* of actually sending that event. This allows clients to
efficiently negotiate compatible event types resulting in the best possible experience for all
participants.

## Proposal

A new room event type `m.request.event_capability` is introduced to request supported event types
from other clients. These capability requests may be time-sensitive and, in the best case, result in
a capability response from each participating device. For this reason, the processing status request
/ response mechanism from [MSC4300] is reused. `m.request.event_capability` has the following
properties in `content`:

- `m.request.status` (object, required): Generic information about the request as per [MSC4300].
- `m.request.event_capability` (object, required): Information about the event capability request.
- `types` (array, required): A list of event types for which the sender wishes to request support.

``` json5
{
"type": "m.request.event_capability",
"event_id": "$1",
"content": {
// Properties from MSC4300
"m.request.status": {
"from_device": "RJYKSTBOIE",
"lifetime": 90_000, // 90s
},
// I'd like to send any of these event types into this room.
// Which of these do you understand?
"m.request.event_capability": {
"types": [
"m.pizza.margherita",
"m.pizza.salami",
"m.pizza.hawaii"
]
}
}
}
```

Recipient clients MAY respond to `m.request.event_capability` within its lifetime with the
`m.response.status` event from [MSC4300] and the following additional properties in `content`:

- `m.response.event_capability` (object, required): Information about the event capability response
- `types` (array, required): The subset of event types from `m.request.event_capability` that the
sending device is able to understand.

``` json5
{
"type": "m.response.status",
"content": {
// Properties from MSC4300
"m.response.status": {
"from_device": "EIOBTSKYJR",
"status": "success",
"messages": [{
"type": "info",
"m.text": [{ "body": "Refusing to recognise Hawaii as a Pizza style!" }]
}]
},
"m.relates_to": {
"event_id": "$1",
"rel_type": "m.reference",
},
// These are the event types I understand.
"m.response.event_capability": {
"types": [
"m.pizza.margherita",
"m.pizza.salami",
]
}
}
}
```

## Potential issues

None.

## Alternatives

Instead of querying event capabilities ad-hoc, clients could statically advertise the types of
events that they are able to understand, for instance, via profiles or state events in a room. This
would simplify looking up capabilities but comes with its own technical challenges such as scoping
profiles to devices and rooms or being able to send state events in a room.

## Security considerations

The concerns and remedies around leaking metadata from [MSC4300] apply to this proposal as well.

## Unstable prefix

While this MSC is not considered stable, `m.request.event_capability` (the event type) and
`m.response.event_capability` should be referred to as `de.gematik.msc4301.request.event_capability`
and `de.gematik.msc4301.response.event_capability`, respectively. Properties inherited from
[MSC4300] have their own prefixing requirements.

## Dependencies

This proposal builds on [MSC4300] which at the time of writing has not yet been accepted into the
spec.

[MSC4300]: https://github.com/matrix-org/matrix-spec-proposals/pull/4300