-
Notifications
You must be signed in to change notification settings - Fork 401
MSC3659: Invite Rules #3659
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
MSC3659: Invite Rules #3659
Changes from 7 commits
85b4989
1da1061
3fbaaa1
4c777e9
635b8e3
c118a1d
89dda60
13eeb22
641257c
4fdd734
1fdbf98
d3c3ddd
f8cd199
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
# MSC3659 - Invite Rules | ||
|
||
This MSC proposes the creation of an optional account data state which allows users to control how invites directed at them | ||
are processed by their homeserver. | ||
|
||
*Homeservers may choose to ignore an Invitee's invite rules *if* the Inviter is a homeserver admin.* | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Proposal | ||
|
||
### Glossery | ||
- Inviter: The matrix user which has created the invite request. | ||
- Invitee: The matrix user which is receiving the invite request. | ||
- Invite request: An invite that the homeserver is to process. For Synapse, this would be handled by [`on_invite_request`](https://github.com/matrix-org/synapse/blob/develop/synapse/handlers/federation.py#L752). | ||
|
||
### `m.invite_rules` | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
An invite rules state contains one required key. | ||
- `"rules"`: An Array of `RuleItem`s. The Array should contain no more than 127 entries. | ||
|
||
*Homeservers may wish to implement a smaller maximum, if so that maximum should be no smaller than 8* | ||
|
||
*Homeservers may also wish to exceed the defined maximum, doing so is allowed, but at their own peril.* | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### `RuleItemAction` | ||
A String-Enum that defines an action that the ruleset evaluator is to perform. | ||
|
||
* `"allow"`: Allow the invite request, breaks from ruleset evaluation. | ||
* `"deny"`: Reject the invite request. | ||
* `"continue"`: Do not take any action and continue ruleset evaluation. | ||
|
||
*Ruleset evaluation is performed before an invite request is acknowledged by the homeserver, invite rejection here refers to rejecting the invite request in the form of returning a HTTP error to the Inviter's homeserver. Not to reject an invite request which has already been acknowledged (visible to the Invitee) by the homeserver.* | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### `RuleItem` | ||
A RuleItem defines a Rule that can test against an invite request. | ||
|
||
- `"type"`: Required String-Enum, must be one of the defined types below. | ||
- `"pass":` A required `RuleItemAction` that will be performed if the rule evaluates as True | ||
- `"fail":` A required `RuleItemAction` that will be performed if the rule evaluates as False | ||
|
||
##### `m.user` | ||
Validates as True if the Inviter MXID is equal to the defined `"user_id"` | ||
- `"user_id"`: Required String, a valid user id. | ||
|
||
##### `m.shared_room` | ||
Validates as True if the Inviter and Invitee are in the defined `"room_id"`. | ||
- `"room_id"`: Required String, a valid room id. | ||
|
||
##### `m.target_room` | ||
Validation depends on the keys defined. Either `"room_id"` or `"room_type"` must be defined. | ||
- `"room_id"`: Optional String, a valid room id. Rule evaluates as True if the target room id is equal to the defined `room_id`. | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- `"room_type"`: Optional String-Enum. | ||
- `"room_type": "is-direct-room"`: Rule evaluates as True if the Invitee's membership state in the target room has `"is_direct"` set to True. | ||
- `"room_type": "is-space"`: Rule evaluates as True if the target room's `m.room.create` `type` is `"m.space"` | ||
- `"room_type": "is-room"`: Rule evaluates as True if the target room is not a direct room or a space. | ||
|
||
##### `m.invite_rule` | ||
Evaluation is dependant on the defined `"rule"`. | ||
* `"rule"`: An `InviteRule`. | ||
|
||
#### `InviteRule` | ||
A String-Enum. | ||
|
||
* `"any"`: Always evaluates as True. | ||
* `"has-shared-room"`: Evaluates as True if the Inviter shares at least one room with the Invitee. | ||
* `"has-direct-room"`: Evaluates as True if the Inviter has an active room defined in the Invitee's `m.direct` account data state. *Active is defined as "if both the Invitee and Inviter are present".* | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* `"none"`: Always evaluates as False. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the point of this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
#### Evaluation | ||
|
||
* The Inviter attempts to create an invite request to the Invitee: | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* If the `"m.invite_rules"` account data state exists, then: | ||
* If `"rules"` is defined, then for each `RuleItem`: | ||
* Evaluate the `RuleItem` and save either the `"pass"` or `"fail"` `RuleItemAction` depending on the result. | ||
* If the `RuleItemAction` is: | ||
* `"allow"`, then: Break from the invite rules loop. | ||
* `"deny"`, then: Respond with `M_FORBIDDEN`. | ||
* `"continue"`, then: Continue for each. | ||
|
||
*If the rules loop is iterated through without any action taken, it is treated as `"allow"`.* | ||
|
||
Implementations may wish to utilise result caching where applicable to improve performance. Such as for rules that may require comparing the joined rooms of each user. | ||
|
||
*Such cache would be storing the resulting `Boolean` returned during `RuleItem` evaluation, **not** the `RuleItemAction` which is picked from the defined `"pass"` or `"fail"` keys.* | ||
Comment on lines
+73
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this performance note is worth including in the spec. Implementations can come to it on their own. |
||
|
||
#### Invite Rejection | ||
If an invite is to be rejected, the homeserver *should* respond with M_FORBIDDEN, and the error message: "This user is not permitted to send invites to this server/user" | ||
|
||
#### Example | ||
The following example will allow any invites from `@bob:example.com` or members of `!a:example.com`, deny any invites from `@alice:example.com`, and allow direct invites from any user who shares at least one room with the Invitee. | ||
|
||
```js | ||
{ | ||
"type": "m.invite_rules", | ||
"content": { | ||
"rules": [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if simple linear logic is enough here. For example what if I want to allow members of space to invite me to rooms in that space. Or what if I want people I share rooms with to be able to DM me but not invite me to a public room? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are edgecases which the rules system can't account for but it's the best compromise between giving the user enough control to be useful, and not overcomplicating the specification. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this could be helped by adding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about adding |
||
{ | ||
"type": "m.user", | ||
"user_id": "@bob:example.com", | ||
"pass": "allow", | ||
"fail": "continue" | ||
}, | ||
{ | ||
"type": "m.user", | ||
"user_id": "@alice:example.com", | ||
"pass": "deny", | ||
"fail": "continue" | ||
}, | ||
{ | ||
"type": "m.shared_room", | ||
"room_id": "!a:example.com", | ||
"pass": "allow", | ||
"fail": "continue" | ||
}, | ||
{ | ||
"type": "m.invite_rule", | ||
"rule": "has-shared-room", | ||
"pass": "continue", | ||
"fail": "deny" | ||
}, | ||
{ | ||
"type": "m.target_room", | ||
"room_type": "is-direct-room", | ||
"pass": "allow", | ||
"fail": "deny" | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
|
||
## Alternatives | ||
Currently, there is no way outside of homeserver-wide restrictions (mjolnir, anti-spam plugins), for users to control who can send them invites. While users can ignore single users to prevent them from sending them invites, this does little since a malicious user simply create another matrix account. | ||
|
||
## Potential Issues | ||
There is a potential denial of service for the `has-shared-room` and `has-direct-room` invite rules, as they require searching through all rooms a user is in, which could be a lot. This heavily depends on the homeserver's internals of course. | ||
|
||
The `"rules"` Array's defined maximum may not be suitable for resource-strained, or particularly large homeservers. Homeservers should make the maximum rules configurable for the homeserver admin. | ||
|
||
As homeservers may set a custom rule limit, clients currently have no reliable way of knowing that limit. Some way of signalling the limit to the client should be looked into | ||
joshqou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Unstable prefix | ||
While this MSC is in development, implementations of this MSC should use the state type `org.matrix.msc3659.invite_rules` |
Uh oh!
There was an error while loading. Please reload this page.