Skip to content
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
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
285 changes: 285 additions & 0 deletions proposals/xxxx-ignoring-invites.md
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
Copy link
Contributor

@Gnuxie Gnuxie Sep 13, 2024

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?

Copy link
Contributor

@Gnuxie Gnuxie Sep 13, 2024

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.

Copy link
Contributor

@Gnuxie Gnuxie Sep 13, 2024

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).

Copy link
Contributor Author

@Johennes Johennes Sep 16, 2024

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe they would conceptually support the homeserver injecting a certain base configuration

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.

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?

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.

Copy link
Contributor Author

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:

  • Let users manage who can invite them (this is what I originally had in mind when writing this up and what the existing proposals largely focus on)
  • Let users share their invite configurations with each other?
  • Let users share their invite configurations with their server?
  • Let servers share default or recommended invite configurations with their users?
  • Let servers share invite configurations with each other?
  • Maybe others?


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