-
Notifications
You must be signed in to change notification settings - Fork 380
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
MSC4192: Comparison of proposals for ignoring invites #4192
Draft
Johennes
wants to merge
3
commits into
matrix-org:main
Choose a base branch
from
Johennes:johannes/ignoring-invites-meta
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
# Comparison of proposals for ignoring invites | ||
|
||
Matrix supports ignoring specific users via the eponymous [module] and the | ||
`m.ignored_user_list` account data event. | ||
|
||
```json5 | ||
{ | ||
"type": "m.ignored_user_list" | ||
"content": { | ||
"ignored_users": { | ||
"@someone:example.org": {} | ||
} | ||
}, | ||
} | ||
``` | ||
|
||
Servers MUST NOT forward invites from ignored users to clients. For the | ||
purposes of ignoring invites, this feature is, however, quite limiting | ||
because: | ||
|
||
* Ignoring users also hides their events in existing rooms which might not | ||
be desirable | ||
* There's no support for globs or wildcards | ||
* The module only supports block-list but no allow-list semantics | ||
* Users cannot review or unignore specific ignored invites | ||
* There's no built-in concept of sharing ignore lists between users | ||
|
||
Several attempts at designing a scheme for ignoring invites specifically | ||
have been made so far. This documents provides a brief comparison of the | ||
different proposals and serves as an entry point for further research. | ||
|
||
|
||
## [MSC2270] – Proposal for ignoring invites | ||
|
||
A new account data event `m.ignored_room_list` is introduced. The event | ||
has the exact same semantics as `m.ignored_user_list` but tracks room IDs | ||
rather than user IDs. | ||
|
||
```json5 | ||
{ | ||
"type": "m.ignored_room_list" | ||
"content": { | ||
"ignored_rooms": { | ||
"!something:example.org": {} | ||
} | ||
}, | ||
} | ||
``` | ||
|
||
A key drawback of this scheme is that it's not possible to blanketly ignore | ||
invites from specific users or servers. Spammers could, therefore, send | ||
invites repeatedly. | ||
|
||
Additionally, the ignore list is subject to the 64 KiB event size limit. | ||
|
||
|
||
## [MSC3840] – Ignore invites | ||
|
||
A new account data event `m.ignored_invites` is introduced. The event has | ||
separate fields for ignoring invites: | ||
|
||
- From specific users | ||
- From specific servers | ||
- Into specific rooms | ||
- Into specific rooms by specific users | ||
|
||
```json5 | ||
{ | ||
"type": "m.ignored_invites" | ||
"content": { | ||
"ignored_user_ids": { | ||
"@someone:example.org": { | ||
"ts": 1726138169160, | ||
"reason": "..." | ||
}, | ||
}, | ||
"ignored_servers": { | ||
"example.org": { | ||
"ts": 1726138169160, | ||
"reason": "..." | ||
}, | ||
}, | ||
"ignored_room_ids": { | ||
"!something:example.org": { | ||
"ts": 1726138169160, | ||
"reason": "..." | ||
}, | ||
}, | ||
"ignored_invites": { | ||
"!something:example.org": { | ||
"@someone:example.org": { | ||
"ts": 1726138169160, | ||
"reason": "..." | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
A key improvement over [MSC2270] is the ability to ignore entire users | ||
and servers. | ||
|
||
Similar to [MSC2270], however, the ignore configuration is still subject | ||
to the 64 KiB event size limit. | ||
|
||
Contrary to `m.ignored_user_list` and [MSC2270], `m.ignored_invites` is | ||
handled exclusively on the client side. This allows users to review and | ||
unignore ignored invites but also means that ignored invites will be | ||
repeated in `/sync` which can cause performance issues over time. | ||
|
||
|
||
## [MSC4155]: Invite filtering | ||
|
||
A new account data event `m.invite_permission_config` is introduced to | ||
maintain a configuration for invite filtering with: | ||
|
||
- A global default to allow / block all invites | ||
- Per-user & per-server exceptions that override the default | ||
|
||
```json5 | ||
{ | ||
"type": "m.invite_permission_config", | ||
"content": { | ||
"default": "allow | block", | ||
"user_exceptions": { | ||
"@someone:example.org": {}, | ||
... | ||
}, | ||
"server_exceptions": { | ||
"example.org": {}, | ||
... | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Similar to [MSC3840], this scheme allows to ignore entire users and servers. | ||
A key advantage though is the ability to create both block-list and allow-list | ||
configurations. | ||
|
||
Unlike [MSC3840], processing the ignore configuration can happen on either the | ||
client or the server. | ||
|
||
Similar to [MSC2270] and [MSC3840], the ignore configuration is subject to | ||
the 64 KiB event size limit. | ||
|
||
|
||
## [MSC3847] – Ignoring invites with policy rooms | ||
|
||
The invite filtering configuration is tracked in [moderation policy lists]. | ||
These are already part of the spec and allow formulating glob rules against | ||
users, rooms and servers via state events in a policy room. | ||
|
||
```json5 | ||
{ | ||
"type": "m.policy.rule.user | m.policy.rule.room | m.policy.rule.server", | ||
"state_key": "...arbitrary...", | ||
"content": { | ||
"entity": "@someone:example.org | !abcdefg:example.org | example.org | *example.org", | ||
"reason": "...", | ||
"recommendation": "m.ban" | ||
} | ||
} | ||
``` | ||
|
||
Users can hook into policy rooms for invite filtering via a new account data | ||
event `m.policies` which defines: | ||
|
||
- A room into which the user will write their own custom policy rules (`target`) | ||
- A list of policy rooms to be executed against invites (`sources`). This | ||
should generally include `target` but may also list other rooms such as | ||
policy rooms recommended by the home server. | ||
|
||
```json5 | ||
{ | ||
"type": "m.policies", | ||
"content": { | ||
"m.ignore.invites": { | ||
"target": "!my-policies:example.org", | ||
"sources": [ | ||
"!my-policies:example.org", | ||
"!bobs-policies:example.org" | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Unlike the previous proposals, the ignore configuration is not subject to | ||
the 64 KiB event size limit because each policy rule is stored in a separate | ||
event. | ||
|
||
Additionally, ignore configurations can easily be shared and reused across | ||
different users. | ||
|
||
Another key advantage is the ability to match users, rooms and servers against | ||
glob expressions. This could probably be added into the other proposals as well, | ||
however. | ||
|
||
Similar to [MSC3840], the ignore configuration is processed exclusively on the | ||
client which comes with the same advantages and disadvantages. | ||
|
||
Finally, when combined with [MSC4150], this scheme also allows for allow-list | ||
configurations. | ||
|
||
|
||
## [MSC3659] – Invite Rules | ||
|
||
A system akin to push rules is defined. Rules are stored as a flat list | ||
in a new account data event `m.invite_rules`. | ||
|
||
Each rule has a type that is accompanied with additional data to determines | ||
how the rule matches against invites. Rule types include: | ||
|
||
- `m.user`, accompanied with a field `user_id` that matches against a user | ||
ID glob expression | ||
- `m.target_room_id`, accompanied with a field `room_id` that matches against | ||
a room ID glob expression | ||
- `m.shared_room`, accompanied with a field `room_id` that matches if the | ||
inviter and invitee already share a specific room | ||
|
||
Each rule is accompanied with two actions. One is to be executed if the rule | ||
matches, the other if the rule fails. Actions must have one of the values | ||
`allow`, `deny` and `continue`. `allow` and `deny` permit and reject the | ||
invite, respectively, and terminate the rulelist evaluation. `continue` skips | ||
ahead to the next rule in the list. | ||
|
||
```json5 | ||
{ | ||
"type": "m.invite_rules", | ||
"content": { | ||
"rules": [{ | ||
"type": "m.user", | ||
"user_id": "*:badguys.com", | ||
"pass": "deny", | ||
"fail": "continue" | ||
}, { | ||
"type": "m.target_room_id", | ||
"room_id": "*:badguys.com", | ||
"pass": "deny", | ||
"fail": "continue" | ||
}, { | ||
"type": "m.user", | ||
"user_id": "@someone:example.org", | ||
"pass": "allow", | ||
"fail": "continue" | ||
}] | ||
} | ||
} | ||
``` | ||
|
||
Unlike [MSC3847], the ignore configuration is subject to the 64 KiB event size | ||
limit because all rules are stored in a single event. | ||
|
||
Similar to [MSC3847], however, glob expressions as well as block-list and | ||
allow-list configurations are supported. | ||
|
||
|
||
## Summary | ||
|
||
The table below compares the proposals in terms of different features. It's | ||
worth noting that some features such as glob matching could easily be extended | ||
to all proposals. | ||
|
||
| | [MSC2270] | [MSC3840] | [MSC4155] | [MSC3847] | [MSC3659] | | ||
|----------------------|-----------|-----------|---------------|---------------------|-----------| | ||
| Ignore room | ✅ | ✅ | ❌ | ✅ | ✅ | | ||
| Ignore user | ❌ | ✅ | ✅ | ✅ | ✅ | | ||
| Ignore server | ❌ | ✅ | ✅ | ✅ | ✅ | | ||
| Glob matching | ❌ | ❌ | ❌ | ✅ | ✅ | | ||
| Can exceed 64 KiB | ❌ | ❌ | ❌ | ✅ | ❌ | | ||
| Client-side | ❌ | ✅ | ✅ (optional) | ✅ | ❌ | | ||
| Block-list semantics | ✅ | ✅ | ✅ | ✅ | ✅ | | ||
| Allow-list semantics | ❌ | ❌ | ✅ | ✅ (with [MSC4150]) | ✅ | | ||
|
||
|
||
[moderation policy lists]: https://spec.matrix.org/v1.11/client-server-api/#moderation-policy-lists | ||
[module]: https://spec.matrix.org/v1.10/client-server-api/#ignoring-users | ||
[MSC2270]: https://github.com/matrix-org/matrix-spec-proposals/pull/2270 | ||
[MSC3659]: https://github.com/matrix-org/matrix-spec-proposals/pull/3659 | ||
[MSC3840]: https://github.com/matrix-org/matrix-spec-proposals/pull/3840 | ||
[MSC3847]: https://github.com/matrix-org/matrix-spec-proposals/pull/3847 | ||
[MSC4150]: https://github.com/matrix-org/matrix-spec-proposals/pull/4150 | ||
[MSC4155]: https://github.com/matrix-org/matrix-spec-proposals/pull/4155 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something that's kind of missing from the review is that most of these proposals focus on how a user can filter invitations from their client to filter them from one device or from
/sync
across their devices. The focus is on what an individual user can do, for their own experience and no one else's. There obviously needs to be a way to ignore invitations, but advanced filtering such as globs or rules could be missing the point. If Matrix users are having to set these advanced systems up, and everyone has to do that individually, then that's no good. The bar is too high, and that's a lot of duplicated work that everyone is doing.The reason for that is because there's no dedicated moderation team in Matrix. If this was a normal social network then there would be a team that would be fed information each time a user rejects an invitation and from that they would be able to generate the metrics to be able to create these complex rules. That would then be applied system wide for all users of the network.
So how do we get an equivalent to that in Matrix that works?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So to an extent, homeservers can already collect data whenever one of their resident users rejects an invitation. And tools can in theory be developed to protect resident users from those invitations. But there's a problem with this because the targets of the invitations on single user homeservers and small homeservers will get exposed to the invitations before there's enough data to protect everyone on the server who is a target.
So there obviously needs to be some collaboration between homeservers if this route was to be explored. Fortunately policy lists are great at that and could be reused, but they would have to be discoverable automatically to be effective and also not accidentally leak unnecessary information, such as who the target of the invitation was.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other route is to skip the homeserver entirely, and have users publish data about the invitations that they have rejected directly (but again, there needs to be consideration about how not to leak unnecessary information and at the minimum identifiers will have to be hashed). The good news there is that the upcoming profiles MSC4133 actually provides an avenue for personal policy lists to be discoverable (which i must stress has been a major blocker for things like this before).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the input, these are good thoughts.
My focus writing this up was definitely on the end user taking action. gematik is currently using MSC4155 in a private federation to let e.g. doctor's decide what patients, other doctors, etc. are allowed to contact them. The other proposals mostly focus on the invitee taking action, too, though.
Since all of the proposals depend on account data in some form, I believe they would conceptually support the homeserver injecting a certain base configuration – just like you're getting default push rules from the server. We'd just have to put modifying the account data event behind an API.
In order not to let the scope explode, I'm wondering if we should make a separation here. This proposal could focus on providing capabilities for users to set up personalized invite filtering and for servers to inject default configurations. The topic of sharing invite spam information among servers could then be handled separately in other proposals?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If your server is a corporation with their own rules to follow, this makes total sense. However, I somewhat strongly feel that this must not be applied universally for all servers (like push rules are today). A core part of Matrix is that you have the agency to choose which filter bubbles you're taking part in, and it should be visible to the end user.
I don't think this is a good separation of concerns because well, they concern the same thing. Say we do this and decide to implement MSC3659 – Invite Rules - for whatever reason. Months later, we want to share the rules with others. Oh no. Now we have two similar but not quite the same systems dealing with allow/blocklists for different categories of things, when if we had a holistic view from the start we may not have made the same decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Point taken. Maybe we should clarify what exactly we want to solve for here:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not so sure, it should make sense everywhere. There should be defaults because a majority of users will never play around with the settings much. That does not mean that power users shouldn't be able to customize or deviate from the default though.