|
|
|
@ -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"<sup id="a1">[1](#f1)</sup>).
|
|
|
|
|
|
|
|
|
|
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"<sup id="a1">[1](#f1)</sup>).
|
|
|
|
|
|
|
|
|
|
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<sup
|
|
|
|
|
id="a2">[2](#f2)</sup>. 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.<sup id="a3">[3](#f3)</sup>
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
<a id="f2"/>[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)
|
|
|
|
|
|
|
|
|
|
<a id="f3"/>[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)
|
|
|
|
|