6.8 KiB
Joining upgraded private rooms
Although most rooms which require an upgrade will be public, there are already cases where private (invite-only) rooms are upgraded. There is also the lingering possibility of a bug being found in the various algorithms which run a room that require private rooms to be upgraded as well.
Currently when a room is upgraded all members need to rejoin manually. This is fine for public rooms because the users can click a button and it takes them over to the new room to join. For private rooms however, the members of the old room need to be manually invited.
This limitation in upgrades has caused some grief for those who have tried to upgrade private rooms already. While migrating membership transparently (auto-joining) would be ideal, this proposal is meant to fill the gap for private rooms while the harder problem of migrating membership is thought out more thoroughly. This proposal does not aim to solve transparent migration of membership.
This proposal is also an idea for how to solve this based largely on the author's work on MSC2213. It could be completely flawed.
Proposal
In a future room version, a new state event is introduced to track the previous membership events for a given room. This new state event acts like a "soft invite" where a user can be allowed into the room without getting hit with an explicit invite.
The new state event, m.room.previous_member
, mirrors the existing m.room.member
event. The state_key
is the affected user and the content
has the same definition
as the m.room.member
event.
When a room is upgraded to a version which supports this proposal, the server is
expected to clone the state_key
and content
of the old room's m.room.member
events into m.room.previous_member
events. The sender
of the old m.room.member
event is specified as previous_sender
under content
, overwriting the key if
it was present in the m.room.member
event's content
. Servers can skip membership
events which won't result in the user being able to join the new room, such as
kicks, bans, and plain leaves. It is instead recommended that the server copy bans
over to the new room as regular m.room.member
events.
m.room.previous_member
carries its own set of auth rules for acceptance:
- If there is no
state_key
key, nomembership
incontent
, or noprevious_sender
incontent
, reject. - If
membership
is not a validm.room.member
membership, reject. - If the
sender
is not the room creator, reject. - If the
sender
does not have permission to invite users, reject. This includes the room creator no longer being a member of the room themselves. - If the
sender
and thestate_key
are the same, reject.
third_party_event
in the content
of m.room.previous_member
is not validated
and serves only audit purposes.
The redaction rules for m.room.member
are copied for m.room.previous_member
, with
the addition of preserving previous_sender
in content
. Although the previous_sender
does not serve a protocol purpose, it is metadata important for the audit trail of the
room.
Servers for these previous membership events are not expected to receive them over federation until they actually join the room.
m.room.previous_member
is only used in the auth rules when a user is attempting to
join the room. For all other scenarios (such as sending messages), the auth rules must
continue to look for an appropriate m.room.member
event. The rules for handling joins
in the new room are as follows:
- If the user has an
m.room.member
state event in the room, use that instead of them.room.previous_member
event. Stop processing these new rules and use the rules for handling a join with am.room.member
event instead. - If the
m.room.create
event does not have apredecessor
in itscontent
, reject. - If the
m.room.previous_member
membership
isinvite
, process the join as though the user was invited (allow am.room.member
withmembership
ofjoin
). - If the
m.room.previous_member
membership
isjoin
, process the join as though the user was already joined (allow am.room.member
event to take its place). - If the
m.room.previous_member
membership
isban
, process the join as though the user was banned (reject). - If the
m.room.previous_member
membership
isleave
, process the join as though the user has left the room (for example, reject if the room is invite-only).
m.room.member
events use their own auth rules even when they replace a m.room.previous_member
event. For example, a user cannot introduce an m.room.member
event with membership
of ban
unless the user has permission to ban users, even if the m.room.previous_member
event had a membership
of ban
as well.
Security considerations
This effectively gives the room creator the power to invite users until the end of time. However, this is no different than any other user's ability to invite members to a room in the vast majority of rooms today. The only difference is that the room creator is able to lie about the previous membership of a user with no verification that it is accurate.
Clients should be skeptical of m.room.previous_member
events and largely treat them as
invites.
Servers could additionally forget (intentionally or otherwise) to include valid members. This is treated similar to the semantics of not inviting someone to your private room, and should have the same social consequences (forever being disappointed in the person who didn't invite you to the party).
Alternative solutions / known problems
There's many solutions to this kind of problem. For example, we could change the auth
rules to allow a room creator to set membership
of join
on m.room.member
events
without the target user being involved. This results in very complicated auth rules
however, as it would be possible for any room creator to craft a room which automatically
joins users without them having been in a relevant previous room. This would be bad.
This solution is not meant to be the silver bullet to the problem of automatically transferring membership to the new room. It is just meant to alleviate a pain point in upgrades while a better solution can be created.
Another problem with this proposal is that users are not told they are invited to this new room. This is a designed feature of this proposal to prevent unnecessary notifications to target users (they already get one that a room was upgraded, so another that they are invited to a room would be confusing). Servers can of course ignore this proposal and just spam invites if they wanted to.
To further clarify: because these events are treated very similar to invites, it is possible to "kick" or ban a user from a room to prevent them from joining. This proposal does not revoke an admin/moderator's ability to stop someone from joining/accepting their invite.