Skip to content

Commit 712dd41

Browse files
richvdhara4nclokep
authored
MSC4115: membership information on events (#4115)
* Proposal for membership information on events * unstable prefix * typo * Update proposals/4115-membership-on-events.md Co-authored-by: Matthew Hodgson <[email protected]> * Update MSC4115 * Make the new property *optional*. * Describe linear-DAG situation. * Mention client-side calculation as an alternative. * spleling * Return state *after* the event This is much easier to calculate in Synapse. * Clarificatoins to scope of MSC * List of endpoints is incomplete * RFC2119 keywords * Remove non-issue potential issue * Expand on why doing it client side doesn't work * Update proposals/4115-membership-on-events.md Co-authored-by: Patrick Cloke <[email protected]> * Update proposals/4115-membership-on-events.md * Update proposals/4115-membership-on-events.md * fix formatting --------- Co-authored-by: Matthew Hodgson <[email protected]> Co-authored-by: Patrick Cloke <[email protected]>
1 parent b9cdd78 commit 712dd41

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# MSC4115: membership metadata on events
2+
3+
## Background
4+
5+
Consider the following Event DAG:
6+
7+
```mermaid
8+
graph BT;
9+
B[Bob joins];
10+
B-->A;
11+
C-->A;
12+
D-->B;
13+
D-->C;
14+
```
15+
16+
Bob has joined a room, but at the same time, another user has sent a message
17+
`C`.
18+
19+
Depending on the configuration of the room, Bob's server may serve the event
20+
`C` to Bob's client. However, if the room is encrypted, Bob will not be on the
21+
recipient list for `C` and the sender will not share the message key with Bob,
22+
even though, in an absolute time reference, `C` may have been sent at a later
23+
timestamp than Bob's join.
24+
25+
Unfortunately, there is no way for Bob's client to reliably distinguish events
26+
such as `A` and `C` that were sent "before" he joined (and he should therefore
27+
not expect to decrypt) from those such as `D` that were sent later.
28+
29+
(Aside: there are two parts to a complete resolution of this "forked-DAG"
30+
problem. The first part is making sure that the *sender* of an encrypted event
31+
has a clear idea of who was a member at the point of the event; the second part
32+
is making sure that the *recipient* knows whether or not they were a member at
33+
the point of the event and should therefore expect to receive keys for it. This
34+
MSC deals only with the second part. The whole situation is discussed in more
35+
detail at https://github.com/element-hq/element-meta/issues/2268.)
36+
37+
A similar scenario can arise even in the absence of a forked DAG: clients
38+
see events sent when the user was not in the room if the room has [History
39+
Visibility](https://spec.matrix.org/v1.10/client-server-api/#room-history-visibility)
40+
set to `shared`. (This is fairly common even in encrypted rooms, partly because
41+
that is the default state for new rooms even using the `private_chat` preset
42+
for the [`/createRoom`](https://spec.matrix.org/v1.10/client-server-api/#post_matrixclientv3createroom)
43+
request, and also because history-sharing solutions such as
44+
[MSC3061](https://github.com/matrix-org/matrix-spec-proposals/pull/3061) rely
45+
on it.)
46+
47+
As a partial solution to the forked-DAG problem, which will also solve the
48+
problem of historical message visibility, we propose a mechanism for servers to
49+
inform clients of their room membership at each event.
50+
51+
## Proposal
52+
53+
The `unsigned` structure contains data added to an event by a homeserver when
54+
serving an event over the client-server API. (See
55+
[specification](https://spec.matrix.org/v1.9/client-server-api/#definition-clientevent)).
56+
57+
We propose adding a new optional property, `membership`. If returned by the
58+
server, it MUST contain the membership of the user making the request,
59+
according to the state of the room at the time of the event being returned. If
60+
the user had no membership at that point (ie, they had yet to join or be
61+
invited), `membership` is set to `leave`. Any changes caused by the event
62+
itself (ie, if the event itself is a `m.room.member` event for the requesting
63+
user) are *included*.
64+
65+
In other words: servers MUST follow the following algorithm when populating
66+
the `unsigned.membership` property on an event E and serving it to a user Alice:
67+
68+
1. Consider the room state just *after* event E landed (accounting for E
69+
itself, but not any other events in the DAG which are not ancestors of E).
70+
2. Within the state, find the event M with type `m.room.member` and `state_key`
71+
set to Alice's user ID.
72+
3. * If no such event exists, set `membership` to `leave`.
73+
* Otherwise, set `membership` to the value of the `membership` property of
74+
the content of M.
75+
76+
It is recommended that homeservers SHOULD populate the new property wherever
77+
practical, but they MAY omit it if necessary (for example, if calculating the
78+
value is expensive, servers might choose to only implement it in encrypted
79+
rooms). Clients MUST in any case treat the new property as optional.
80+
81+
For the avoidance of doubt, the new `membership` property is added to all
82+
Client-Server API endpoints that return events, including, but not limited to,
83+
[`/sync`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3sync),
84+
[`/messages`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3roomsroomidmessages),
85+
[`/state`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3roomsroomidstate),
86+
and deprecated endpoints such as
87+
[`/events`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3events)
88+
and
89+
[`/initialSync`](https://spec.matrix.org/v1.9/client-server-api/#get_matrixclientv3events).
90+
91+
92+
Example event including the new property, as seen in the response to a request made by `@user:example.org`:
93+
94+
```json5
95+
{
96+
"content": {
97+
"membership": "join"
98+
},
99+
"event_id": "$26RqwJMLw-yds1GAH_QxjHRC1Da9oasK0e5VLnck_45",
100+
"origin_server_ts": 1632489532305,
101+
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
102+
"sender": "@example:example.org",
103+
"state_key": "@example:example.org",
104+
"type": "m.room.member",
105+
"unsigned": {
106+
"age": 1567437,
107+
// @user:example.org's membership at the time this event was sent
108+
"membership": "leave",
109+
"redacted_because": {
110+
"content": {
111+
"reason": "spam"
112+
},
113+
"event_id": "$Nhl3rsgHMjk-DjMJANawr9HHAhLg4GcoTYrSiYYGqEE",
114+
"origin_server_ts": 1632491098485,
115+
"redacts": "$26RqwJMLw-yds1GAH_QxjHRC1Da9oasK0e5VLnck_45",
116+
"room_id": "!jEsUZKDJdhlrceRyVU:example.org",
117+
"sender": "@moderator:example.org",
118+
"type": "m.room.redaction",
119+
"unsigned": {
120+
// @user:example.org's membership at the time the redaction was sent
121+
"membership": "join",
122+
"age": 1257
123+
}
124+
}
125+
}
126+
}
127+
```
128+
129+
## Potential issues
130+
131+
None foreseen.
132+
133+
## Alternatives
134+
135+
1. https://github.com/element-hq/element-meta/issues/2268#issuecomment-1904069895
136+
proposes use of a Bloom filter — or possibly several Bloom filters — to
137+
mitigate this problem in a more general way. It is the opinion of the author of
138+
this MSC that there is room for both approaches.
139+
140+
2. We could attempt to calculate the membership state on the client side. This
141+
might help in a majority of cases, but it will be unreliable in the presence
142+
of forked DAGs. It would require clients to implement the [state resolution
143+
algorithm](https://spec.matrix.org/v1.10/rooms/v11/#state-resolution), which
144+
would be prohibitively complicated for most clients.
145+
146+
## Security considerations
147+
148+
None foreseen.
149+
150+
## Unstable prefix
151+
152+
While this proposal is in development, the name `io.element.msc4115.membership`
153+
MUST be used in place of `membership`.
154+
155+
## Dependencies
156+
157+
None.

0 commit comments

Comments
 (0)