diff --git a/proposals/1772-groups-as-rooms.md b/proposals/1772-groups-as-rooms.md index 4a0d7aed..76520b92 100644 --- a/proposals/1772-groups-as-rooms.md +++ b/proposals/1772-groups-as-rooms.md @@ -187,7 +187,8 @@ TODO: this could also be done via pinned messages. Failing that ### Managing power levels via spaces -XXX: this section still in progress +TODO: much of this is orthogonal to the headline feature of "spaces", and +should be moved to a separate MSC. One use-case for spaces is to help manage power levels across a group of rooms. For example: "Jim has just joined the management team at my company. He @@ -234,21 +235,21 @@ key which is an ordered list, for example: ```js { - "type": "m.room.power_level_mappings", - "state_key": "", - "content": { - "mappings": [ - { - "space": "!mods:example.org", - "via": ["example.org"], - "power_level": 50 - }, - { - "space": "!users:example.org", - "via": ["example.org"], - "power_level": 1 - } - ] + "type": "m.room.power_level_mappings", + "state_key": "", + "content": { + "mappings": [ + { + "space": "!mods:example.org", + "via": ["example.org"], + "power_level": 50 + }, + { + "space": "!users:example.org", + "via": ["example.org"], + "power_level": 1 + } + ] } } ``` @@ -283,22 +284,97 @@ access to it is itself restricted via `power_levels`. This could be enforced by the admin bot so that no `m.room.power_levels` events are generated unless `power_level_mappings` is appropriately restricted. -### Membership restrictions +### Restricting room membership based on space membership A desirable feature is to give room admins the power to restrict membership of -their room based on the membership of spaces (for example, "only members of the -#doglovers space can join this room"[1](#f1)). - -XXX can we maybe do this with invites generated on demand? If not, we probably -need some sort of "silent invite" state for each user, +their room based on the membership of spaces (for example, "members of the +#doglovers space can join this room without an invitation"[1](#f1)). -By implication, when a user leaves the required space, they should be ejected -from the room. +We could represent the allowed spaces with additional content in the +`m.room.join_rules` event. For example: -XXX: how do we implement the ejection? We could leave it up to the ejectee's -server, but what happens if it doesn't play the game? So we probably need to -enact a ban... but then, which server has responisiblity, and which user is used? +```js +{ + "type": "m.room.join_rules", + "state_key": "", + "content": { + "join_rule": "public", + "allowed_spaces": [ + { + "space": "!mods:example.org", + "via": ["example.org"], + }, + { + "space": "!users:example.org", + "via": ["example.org"], + } + ] + } +} +``` +XXX: would it be better to put it in a separate event? Doing so would probably +require us to come up with a new `join_rule` state to tell servers to go and +look for the allowed spaces. + +The `allowed_spaces` key applies a restriction to the `public` join rule, so +that only users in those spaces should be allowed to join. Additionally, users +who have received an explicit `invite` event are allowed to join[2](#f2). If the `allowed_spaces` key is an empty list (or not a +list at all), no users are allowed to join without an invite. + +Unlike the regular `invite` join rule, the restriction cannot be enforced over +federation by event authorization, so servers in the room are trusted not to +allow invalid users to join.[3](#f3) + +When a server receives a `/join` request from a client or a +`/make_join`/`/send_join` request from a server, the request should only be +permitted if the user has a valid invite or is in one of the listed spaces +(established by peeking). + +XXX: redacting the join_rules above will reset the room to public, which feels dangerous? + +A new room version is not absolutely required here, but may be advisable to +ensure that servers that do not support `allowed_spaces` do not join the room +(and would also allow us to tweak the redaction rules to avoid the foot-gun). + +#### Kicking users out when they leave the allowed_space + +In the above example, suppose `@bob:server.example` leaves `!users:example.org`: +they should be removed from the room. One option is to leave the departure up +to Bob's server `server.example`, but this places a relatively high level of trust +in that server. Additionally, if `server.example` were offline, other users in +the room would still see Bob in the room (and their servers would attempt to +send message traffic to it). + +Instead, we make the removal the responsibility of the room's admin bot (see +above): the bot is expected to peek into any `allowed_spaces` and kick any +users who are members of the room and leave the union of the allowed +spaces. + +(XXX: should users in a space be kicked when that space is removed from the +`allowed_spaces` list? We think not, by analogy with what happens when you +switch the join rules from `public` to `invite`.) + +One problem here is that it will lead to users who joined via an invite being +kicked. For example: + * `@bob:server.example` creates an invite-only room. + * Later, the `join_rules` are switched to `public`, with an `allowed_space` of + `!users:example.org`, of which Bob happens to be a member. + * Later still, Bob leaves `!users:example.org`. + * Bob is kicked from his own room. + +Fixing this is thorny. Some sort of annotation on the membership events might +help. but it's unclear what the desired semantics are: + + * Assuming that users in a given space are *not* kicked when that space is + removed from `allowed_spaces`, are those users then given a pass to remain + in the room indefinitely? What happens if the space is added back to + `allowed_spaces` and *then* the user leaves it? + + * Suppose a user joins a room via a space (SpaceA). Later, SpaceB is added to + the `allowed_spaces` list and SpaceA is removed. What should happen when the + user leaves SpaceB? Are they exempt from the kick? ## Future extensions @@ -370,6 +446,13 @@ These dependencies are shared with profiles-as-rooms * The peek server has significant power. TODO: expand. +* The `allowed_spaces` feature places increased trust in the servers in the + room. We consider this acceptable: if you don't want evil servers randomly + joining spurious users into your rooms, then a) don't let evil servers in + your room in the first place, b) don't use `allowed_spaces` lists, given the + expansion increases the attack surface anyway by letting members in other + rooms dictate who's allowed into your room". + ## Tradeoffs * If the membership of a space would be large (for example: an organisation of @@ -442,3 +525,14 @@ of the '#catlovers' space" is less useful since (a) users in the banned space could simply leave it at any time; (b) this functionality is already somewhat provided by [Moderation policy lists](https://matrix.org/docs/spec/client_server/r0.6.1#moderation-policy-lists). [↩](#a1) + +[2]: Note that there is nothing stopping users sending and +receiving invites in `public` rooms today, and they work as you might +expect. The only difference is that you are not *required* to hold an `invite` +when joining the room. [↩](#a2) + +[3]: This is a marginal decrease in security from the current +situation with invite-only rooms. Currently, a misbehaving server can allow +unauthorized users to join an invite-only room by first issuing an invite to +that user. In theory that can be prevented by raising the PL required to send +an invite, but in practice that is rarely done. [↩](#a2)