-
Notifications
You must be signed in to change notification settings - Fork 389
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
MSC4115: membership information on events #4115
Merged
Merged
Changes from 12 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
2545ccf
Proposal for membership information on events
richvdh 191e182
unstable prefix
richvdh b63d565
typo
richvdh 6b0776c
Update proposals/4115-membership-on-events.md
richvdh 3ab18b5
Update MSC4115
richvdh bbcedf8
spleling
richvdh 7142bc3
Return state *after* the event
richvdh a282730
Clarificatoins to scope of MSC
richvdh 283a7e9
List of endpoints is incomplete
richvdh 638d299
RFC2119 keywords
richvdh 6ef6feb
Remove non-issue potential issue
richvdh 6db3b97
Expand on why doing it client side doesn't work
richvdh b297b8b
Update proposals/4115-membership-on-events.md
richvdh 8b880df
Update proposals/4115-membership-on-events.md
richvdh ed20d83
Update proposals/4115-membership-on-events.md
richvdh 9323f48
fix formatting
richvdh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# MSC4115: membership metadata on events | ||
|
||
## Background | ||
|
||
Consider the following Event DAG: | ||
|
||
```mermaid | ||
graph BT; | ||
B[Bob joins]; | ||
B-->A; | ||
C-->A; | ||
D-->B; | ||
D-->C; | ||
``` | ||
|
||
Bob has joined a room, but at the same time, another user has sent a message | ||
`C`. | ||
|
||
Depending on the configuration of the room, Bob's server may serve the event | ||
`C` to Bob's client. However, if the room is encrypted, Bob will not be on the | ||
recipient list for `C` and the sender will not share the message key with Bob, | ||
even though, in an absolute time reference, `C` may have been sent at a later | ||
timestamp than Bob's join. | ||
richvdh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Unfortunately, there is no way for Bob's client to reliably distinguish events | ||
such as `A` and `C` that were sent "before" he joined (and he should therefore | ||
not expect to decrypt) from those such as `D` that were sent later. | ||
andybalaam marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
(Aside: there are two parts to a complete resolution of this "forked-DAG" | ||
problem. The first part is making sure that the *sender* of an encrypted event | ||
has a clear idea of who was a member at the point of the event; the second part | ||
is making sure that the *recipient* knows whether or not they were a member at | ||
the point of the event and should therefore expect to receive keys for it. This | ||
MSC deals only with the second part. The whole situation is discussed in more | ||
detail at https://github.com/element-hq/element-meta/issues/2268.) | ||
|
||
A similar scenario can arise even in the absence of a forked DAG: clients | ||
see events sent when the user was not in the room if the room has [History | ||
Visibility](https://spec.matrix.org/v1.10/client-server-api/#room-history-visibility) | ||
set to `shared`. (This is fairly common even in encrypted rooms, partly because | ||
that is the default state for new rooms even using the `private_chat` preset | ||
for the [`/createRoom`](https://spec.matrix.org/v1.10/client-server-api/#post_matrixclientv3createroom) | ||
request, and also because history-sharing solutions such as | ||
[MSC3061](https://github.com/matrix-org/matrix-spec-proposals/pull/3061) rely | ||
on it.) | ||
|
||
As a partial solution to the forked-DAG problem, which will also solve the | ||
problem of historical message visibility, we propose a mechanism for servers to | ||
inform clients of their room membership at each event. | ||
|
||
## Proposal | ||
|
||
The `unsigned` structure contains data added to an event by a homeserver when | ||
serving an event over the client-server API. (See | ||
[specification](https://spec.matrix.org/v1.9/client-server-api/#definition-clientevent)). | ||
|
||
We propose adding a new optional property, `membership`. If returned by the | ||
server, it MUST contain the membership of the user making the request, | ||
according to the state of the room at the time of the event being returned. If | ||
the user had no membership at that point (ie, they had yet to join or be | ||
invited), `membership` is set to `leave`. Any changes caused by the event | ||
itself (ie, if the event itself is a `m.room.member` event for the requesting | ||
user) are *included*. | ||
dbkr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
In other words: servers MUST follow the following algorithm when populating | ||
the `unsigned.membership` property on an event E and serving it to a user Alice: | ||
|
||
1. Consider the room state just *after* event E landed (accounting for E | ||
itself, but not any other events in the DAG which are not ancestors of E). | ||
2. Within the state, find the event M with type `m.room.member` and `state_key` | ||
set to Alice's user ID. | ||
3. * If no such event exists, set `membership` to `leave`. | ||
* Otherwise, set `membership` to the value of the `membership` property of | ||
the content of M. | ||
|
||
It is recommended that homeservers SHOULD populate the new property wherever | ||
practical, but they MAY omit it if necessary (for example, if calculating the | ||
value is expensive, servers might choose to only implement it in encrypted | ||
rooms). Clients MUST in any case treat the new property as optional. | ||
|
||
For the avoidance of doubt, the new `membership` property is added to all | ||
Client-Server API endpoints that return events, including, but not limited to, | ||
[`/sync`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3sync), | ||
[`/messages`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3roomsroomidmessages), | ||
[`/state`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3roomsroomidstate), | ||
and deprecated endpoints such as | ||
[`/events`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3events) | ||
and | ||
[`/initialSync`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3events). | ||
|
||
|
||
Example event including the new property: | ||
|
||
```json | ||
{ | ||
"content": { | ||
"membership": "join" | ||
}, | ||
"event_id": "$26RqwJMLw-yds1GAH_QxjHRC1Da9oasK0e5VLnck_45", | ||
"origin_server_ts": 1632489532305, | ||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org", | ||
"sender": "@example:example.org", | ||
"state_key": "@user:example.org", | ||
"type": "m.room.member", | ||
"unsigned": { | ||
"age": 1567437, | ||
"membership": "leave", | ||
KitsuneRal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"redacted_because": { | ||
"content": { | ||
"reason": "spam" | ||
}, | ||
"event_id": "$Nhl3rsgHMjk-DjMJANawr9HHAhLg4GcoTYrSiYYGqEE", | ||
"origin_server_ts": 1632491098485, | ||
"redacts": "$26RqwJMLw-yds1GAH_QxjHRC1Da9oasK0e5VLnck_45", | ||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org", | ||
"sender": "@moderator:example.org", | ||
"type": "m.room.redaction", | ||
"unsigned": { | ||
"membership": "leave", | ||
"age": 1257 | ||
} | ||
} | ||
} | ||
} | ||
richvdh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
## Potential issues | ||
|
||
None foreseen. | ||
|
||
## Alternatives | ||
|
||
1. https://github.com/element-hq/element-meta/issues/2268#issuecomment-1904069895 | ||
proposes use of a Bloom filter — or possibly several Bloom filters — to | ||
mitigate this problem in a more general way. It is the opinion of the author of | ||
this MSC that there is room for both approaches. | ||
|
||
2. We could attempt to calculate the membership state on the client side. This | ||
might help in a majority of cases, but it will be unreliable in the presence | ||
of forked DAGs. It would require clients ti implement the [state resolution | ||
richvdh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
algorithm](https://spec.matrix.org/v1.10/rooms/v11/#state-resolution), which | ||
would be prohibitively complicated for most clients. | ||
|
||
## Security considerations | ||
|
||
None foreseen. | ||
|
||
## Unstable prefix | ||
|
||
While this proposal is in development, the name `io.element.msc4115.membership` | ||
MUST be used in place of `membership`. | ||
|
||
## Dependencies | ||
|
||
None. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Implementation requirements: