-
Notifications
You must be signed in to change notification settings - Fork 401
MSC4192: Comparison of proposals for ignoring invites #4192
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. Further proposals added since this the comparison was written: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
# MSC4192: 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. | ||
|
||
|
||
## [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. | ||
|
||
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. | ||
|
||
|
||
## [MSC3847] – Ignoring invites with policy rooms | ||
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 never really thought about expressing this as moderation policy lists but I actually love it. This is 100% in the spirit of Matrix as a protocol, where we can share our views of who to ignore and consciously choose to opt-in. There is the question over which room should your own personal blocklists go, to which profiles as rooms would be the obvious candidate if it ever landed. 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. Cat also likes the policy based solution and well Cat would say that the personal blocklist should be written to a dedicated MSC3784 policy room but said room can be mapped to via whatever profile system you prefer. This comes with the benefit of maintaining backwards compatibility with tooling that is only focused on policy manipulation. Plus it allows trivially having multiple personal lists. This allows stuff like private and public opinions and friends only. Since i might not want to share that i dislike X but i might be fine with sharing i dislike Y. Yes Policy based ofc has privacy implications but its also very matrix to do this stuff in this way. Edit: Since this topic came up organically i think it might be time to look at writing a Server Side applied version of a Policy based MSC. |
||
|
||
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 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`. | ||
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. Given how complex push rules are to implement correctly, I have zero desire to reproduce this here. The complexity issue should be mentioned as a negative. 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. How would you say the complexity compares to the policy list proposal above? My hunch is the policy lists could appear less complex only because they currently have fewer matching and action constructs. If the invite rules proposal would be stripped down to be on par feature-wise, would you still consider it a lot more complex to implement? I'm not necessarily in favor of this proposal. Just trying to make sure I'm not discounting it unfairly. 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. @kegsay You can read the full MSC3659 spec for more details. It's just a list of rules which are evaluated in series. I've implemented the spec myself and the implementation is not that complicated. Even if it comparatively complicated, compared to |
||
|
||
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" | ||
}] | ||
} | ||
} | ||
``` | ||
|
||
Similar to [MSC3847] glob expressions as well as block-list and allow-list | ||
configurations are supported. | ||
|
||
|
||
## [MSC4264] – Tokens for Contacting Accounts | ||
|
||
This proposal adapts the subaddressing functionality known from email to | ||
Matrix IDs. Users manage a set of "tokens" which are extensions of their | ||
MXIDs, e.g. in the form `@localpart::token:domain`. Invites are only processed | ||
when they include a valid token. | ||
|
||
|
||
## 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] | [MSC4264] | | ||
|----------------------|-----------|-----------|---------------|---------------------|-----------|---------------| | ||
| Ignore room | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | | ||
| Ignore user | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | | ||
| Ignore server | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | | ||
| Glob matching | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | | ||
| Client-side | ❌ | ✅ | ✅ (optional) | ✅ | ❌ | ✅ (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 | ||
[MSC4264]: https://github.com/matrix-org/matrix-spec-proposals/pull/4264 |
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.
With a combination of SCT and T&S hat, I think there are two separate problems which might help lead to a path forward:
For the first, prototyping the desirable constraints with MSC4155 I feel is best - the object is extensible, and can be experimented with quickly. Later, we can add fields to incorporate policy lists (a la MSC3847) to make configurations sharable/even more extensible. The "plan" would be to land MSC4155, expand upon it via MSCs, then land MSC3847 with modifications to account for MSC4155+extensions behaviour. We would also ideally have an extension MSC to introduce the difference between "ignore" and "block", which I might write up to clarify the concept in Matrix generally.
For the second, I think MSC2270 is the most generic as it doesn't just deal with invites: it deals with rooms more generally. This can enable a feature where someone can be nominally joined to a room, but otherwise elect to not see contents. For example, as an out-of-hours measure: events continue flowing through to the room, but the user doesn't see them until 8am on Monday. (We would have to refine the way ignoring works through another MSC to fully make that possible, though).
MSC3840 I think accomplishes features from both columns, but I'm not sure we actually want to combine these two features as it further leads to confusion about what "ignore" can mean. I'd recommend closing this one in favour of other MSCs, though taking the semantics and considering them for extensions on top of the other MSCs.
MSC3659 is neat, but I think might be a bit complicated to drive/get wired up to a user interface. Buckets of conditions (like MSC4155) are easier to represent to users than sequences.
MSC4264 I'm considering as adjacent to the problem space for now, especially because it needs a lot more thought and consideration for how invites overall should work. The effort in this comparison is more, in my opinion, to reduce harm from the existing system's mechanics over designing new mechanics.
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.
MSC4283 now exists to distinguish between ignore and block.
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.
From a quick read through @turt2live's plan sounds reasonable!