From f2db9f9bb9ed8171642a101ca340c6926016c95a Mon Sep 17 00:00:00 2001 From: David Teller Date: Wed, 13 Jul 2022 18:33:20 +0200 Subject: [PATCH 1/6] MSC3847: Ignoring invites with policy rooms --- ...3847-ignoring-invites-with-policy-rooms.md | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 proposals/3847-ignoring-invites-with-policy-rooms.md diff --git a/proposals/3847-ignoring-invites-with-policy-rooms.md b/proposals/3847-ignoring-invites-with-policy-rooms.md new file mode 100644 index 000000000..fd77f0038 --- /dev/null +++ b/proposals/3847-ignoring-invites-with-policy-rooms.md @@ -0,0 +1,137 @@ +# MSC3847: Ignoring invites using individual policy rooms + +Receiving unwanted invites is something that users currently need to live +with on the Matrix network. To alleviate this, Matrix needs a mechanism to +let users specify that they are not interested in invites from specific +users or towards specific rooms. + +In this proposal, we introduce the necessary extensions to let users do +this and to let clients perform filtering of unwanted invites. + +We proceed as follows: + +1. We build upon the mechanism of policy rooms, defined in MSC2313, and define +a user's individual policy room, which may be created on behalf of the user by +a Matrix client, and which is shared across all devices and clients of the user. +2. We build upon the mechanism of recommendations, also defined in MSC2313, +and create a new recommendation for ignoring invites from a specific user, from +a specific server or towards a specific room. + + +## Proposal + +### Background + +MSC2313 defines policy rooms. A policy room is a room in which rules such +as the following may be published: + +```jsonc +{ + "type": "m.policy.rule.user", // Or `m.policy.rule.server` or `m.policy.rule.room`. + "state_key": "rule_1", // Arbitrary. + "content": { + "entity": "@alice:example.org", + "recommendation": "m.ban", + "reason": "undesirable behaviour" + } +} +``` + +Policy rooms are designed to be associated with entire servers, communities, +individual rooms or individual users, but there is no specification in MSC2313 +clarifying how to associate an issuer with a policy room. + +### Associating a policy room with a user + +For individual users, we introduce a new event `m.policies`, designed +to be used as part of account data. This event has content: + +| Content | Type | Description | +|---------|------|-------------| +| `room` | Room ID or Alias | The main room in which a user may publish policies to be applied on their behalf. | + +We expect that future MSCs will expand upon this event `m.policies` and add +other rooms where policies are published by other users or communities but +that the current user also wish to apply, e.g. for distributing trust. This +is, however, beyond the scope of the current proposal. + +The expected behavior is that if a user Alice has a `m.policies` with `room` R, +then: + +- whenever Alice issues a new policy from their client or another trusted agent, + this policy will be stored in room R; +- any client or trusted agent acting on behalf of Alice will monitor room R for + new policies and apply the recommendations on behalf of Alice. + +### A recommendation for ignoring invites + +We expand the **`enum`** `recommendation` with the following value + +| Value | Description | +|---------|-------------| +| `m.invites.ignore` | The user's client should not display any invite from/to the entity specified in `entity`. | + +In particular, if Alice has a policy with `recommendation` `m.invites.ignore`: + +- if `type` is `m.policy.rule.user` and `entity` is Bob's User ID, Alice's clients will not display any invite issued by Bob; +- if `type` is `m.policy.rule.room` and `entity` is the Room ID or alias of room Bobroom, Alice's clients will not display any invite issued to Bobroom; +- if `type` is `m.policy.rule.server` and `entity` is the server name of server Bobverse, Alice's clients will not display any invite issued from any account from Bobverse or towards a room alias on the Bobverse. + +### Client behaviour + +If a new policy `m.invites.ignore` appears in Alice's individual policy room: + +- any pending invite currently displayed that matches the `entity` is removed from display; +- any incoming invite that matches the `entity` is not displayed among invites. + +However, clients are expected to offer the ability to look at any ignored invite, +in a manner similar to a trashcan/recycle bin/undelete mechanism for desktop file +systems. + +Similarly, if a policy `m.invites.ignore` is redacted/amended, clients should show any +invite that doesn't match any `m.invites.ignore` entity anymore. + +### Server behavior + +As recommended in MSC2313, if a policy `m.ban` appears in Alice's individual policy room: + +- if `type` is `m.policy.rule.user`, ignore any message or invite from the user `entity`, as per `m.ignored_users`; +- if `type` is `m.policy.rule.room`, ignore any message in the room or invite from the room `entity`; +- if `type` is `m.policy.rule.server`, ignore any message in any room on server `entity`, any message from any user on server `entity`, any invite towards any room on server `entity`, any invite from any user on server `entity`. + +## Potential issues + +### Number of events + +There is a risk that the list of ignored invites of some users may grow a lot, which might have +performance impact, both during initial sync and during filtering. We believe that this risk is +limited. If necessary, clients may decide to cleanup ignored invites after some time. + +### Sync size + +With this proposal, any invite ignored with `m.invites.ignore` will still show up at each `/sync`. +In time, this can grow expensive. + +If necessary, clients may decide to convert ignored invites into rejected invites or `m.ban` +after a while. + +## Alternatives + +### Server-side filtering + +Just as `m.ignored_users_list` is handled mostly on the server, we could handle `m.invites.ignore` +largely on the server. However, this would make it much harder to undo erroneous ignores (i.e. +implementing some sort of recovery from trashcan) on the client. + +So we prefer handling things on the client, even if this may require more traffic. + +## Security considerations + +Can't think of any right now. + +## Unstable prefix + +During testing: + +- `m.invites.ignore` should be prefixed `org.matrix.msc3847.invites.ignore`; +- `m.policies` should be prefixed `org.matrix.msc3847.policies`. From 05c57cc5384471c3c17d21f479507851030c8c98 Mon Sep 17 00:00:00 2001 From: David Teller Date: Fri, 15 Jul 2022 08:52:25 +0200 Subject: [PATCH 2/6] WIP: Applying feedback --- ...3847-ignoring-invites-with-policy-rooms.md | 81 +++++++++++-------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/proposals/3847-ignoring-invites-with-policy-rooms.md b/proposals/3847-ignoring-invites-with-policy-rooms.md index fd77f0038..a41f20ed6 100644 --- a/proposals/3847-ignoring-invites-with-policy-rooms.md +++ b/proposals/3847-ignoring-invites-with-policy-rooms.md @@ -22,8 +22,8 @@ a specific server or towards a specific room. ### Background -MSC2313 defines policy rooms. A policy room is a room in which rules such -as the following may be published: +[Matrix specs define policy rooms](https://spec.matrix.org/v1.3/client-server-api/#moderation-policy-lists). +A policy room is a room in which rules such as the following may be published: ```jsonc { @@ -38,48 +38,50 @@ as the following may be published: ``` Policy rooms are designed to be associated with entire servers, communities, -individual rooms or individual users, but there is no specification in MSC2313 +individual rooms or individual users, but there is no specification clarifying how to associate an issuer with a policy room. -### Associating a policy room with a user +### Associating policy rooms to a user For individual users, we introduce a new event `m.policies`, designed to be used as part of account data. This event has content: | Content | Type | Description | |---------|------|-------------| -| `room` | Room ID or Alias | The main room in which a user may publish policies to be applied on their behalf. | +| `m.ignore.invites` | `Policies` | A list of rooms in which policies should be understood as "ignore invite" lists. | -We expect that future MSCs will expand upon this event `m.policies` and add -other rooms where policies are published by other users or communities but -that the current user also wish to apply, e.g. for distributing trust. This -is, however, beyond the scope of the current proposal. +We expect that future MSCs will expand upon this event `m.policies` and +add further fields with other lists of rooms in which policies should be +understood differently. This is, however, beyond the scope of the current +MSC. -The expected behavior is that if a user Alice has a `m.policies` with `room` R, -then: +We also expect that future MSCs will expand upon this event `m.policies` +to add semantics in other positions than account data, e.g. community rooms. +This is also beyond the scope of the current MSC. -- whenever Alice issues a new policy from their client or another trusted agent, - this policy will be stored in room R; -- any client or trusted agent acting on behalf of Alice will monitor room R for - new policies and apply the recommendations on behalf of Alice. +Where `Policies` is defined as: -### A recommendation for ignoring invites +| Content | Type | Description | +|-------------|------|-------------| +| `target` | Room ID or Alias | A room in which to issue new policies. | +| `sources` | Room ID or Alias []| A list of rooms from which to apply new policies. Should generally include `target`. | -We expand the **`enum`** `recommendation` with the following value +The expected behavior is that: -| Value | Description | -|---------|-------------| -| `m.invites.ignore` | The user's client should not display any invite from/to the entity specified in `entity`. | +- if a user Alice has a `m.policies` with key `m.ignore.invites` and `target` R, + then whenever Alice issues a new policy to ignore invites from their client + or another trusted agent, this policy will be stored in room R. -In particular, if Alice has a policy with `recommendation` `m.invites.ignore`: +- if a user Alice has a `m.policies` with key `m.ignore.invites` and `sources` + containing room R, any client or trusted agent acting on behalf of Alice will + monitor room R for new policies and apply the recommendations on behalf of Alice, + interpreting such policies as "ignore invites". -- if `type` is `m.policy.rule.user` and `entity` is Bob's User ID, Alice's clients will not display any invite issued by Bob; -- if `type` is `m.policy.rule.room` and `entity` is the Room ID or alias of room Bobroom, Alice's clients will not display any invite issued to Bobroom; -- if `type` is `m.policy.rule.server` and `entity` is the server name of server Bobverse, Alice's clients will not display any invite issued from any account from Bobverse or towards a room alias on the Bobverse. ### Client behaviour -If a new policy `m.invites.ignore` appears in Alice's individual policy room: +If a user Alice has a `m.policies` with key `m.ignore.invites` and `sources` containing +room R *and* if a new policy `m.ban` appears in R: - any pending invite currently displayed that matches the `entity` is removed from display; - any incoming invite that matches the `entity` is not displayed among invites. @@ -88,12 +90,14 @@ However, clients are expected to offer the ability to look at any ignored invite in a manner similar to a trashcan/recycle bin/undelete mechanism for desktop file systems. -Similarly, if a policy `m.invites.ignore` is redacted/amended, clients should show any -invite that doesn't match any `m.invites.ignore` entity anymore. +Similarly, if a policy `m.ignore` in a `m.ignore.invites` room is redacted/amended, +clients should show any invite that doesn't match any `m.ignore.invites` & `m.ban` +entities anymore. ### Server behavior -As recommended in MSC2313, if a policy `m.ban` appears in Alice's individual policy room: +As recommended in Matrix spec, if a user Alice has a `m.policies` with key +`m.ignore.invites` and `sources` containing room R *and* if a policy `m.ban` is present in R: - if `type` is `m.policy.rule.user`, ignore any message or invite from the user `entity`, as per `m.ignored_users`; - if `type` is `m.policy.rule.room`, ignore any message in the room or invite from the room `entity`; @@ -109,21 +113,29 @@ limited. If necessary, clients may decide to cleanup ignored invites after some ### Sync size -With this proposal, any invite ignored with `m.invites.ignore` will still show up at each `/sync`. -In time, this can grow expensive. +With this proposal, any invite ignored with `m.ignore.invites` will still show up at each `/sync`. +In time, this can grow expensive. This is, however, necessary to be able to un-ignore invites +from the client. -If necessary, clients may decide to convert ignored invites into rejected invites or `m.ban` -after a while. +We plan to file a followup MSC to introduce a `m.policies` key `m.drop.invites`, which will +ask the server to simply not send the invites during the next `/sync` operations. ## Alternatives +### Rejecting invites + +A client could of course reject invites instead of ignoring them. However, experience shows that +spam/bullying tools monitor invite rejections to send invite spam. This entire MSC is meant to +offer an alternative mechanism that would close this gap and let users ignore invites without +notifying the sender. + ### Server-side filtering Just as `m.ignored_users_list` is handled mostly on the server, we could handle `m.invites.ignore` largely on the server. However, this would make it much harder to undo erroneous ignores (i.e. implementing some sort of recovery from trashcan) on the client. -So we prefer handling things on the client, even if this may require more traffic. +Consequently, we prefer handling things on the client, even if this may require more traffic. ## Security considerations @@ -133,5 +145,6 @@ Can't think of any right now. During testing: -- `m.invites.ignore` should be prefixed `org.matrix.msc3847.invites.ignore`; +- `m.ignore.invites` should be prefixed `org.matrix.msc3847.ignore.invites`; - `m.policies` should be prefixed `org.matrix.msc3847.policies`. + From 3903d4381d7d4181c1329032eddd7817c6d30a14 Mon Sep 17 00:00:00 2001 From: David Teller Date: Fri, 15 Jul 2022 09:30:13 +0200 Subject: [PATCH 3/6] WIP: Wait a minute, there is no server side anymore --- proposals/3847-ignoring-invites-with-policy-rooms.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/proposals/3847-ignoring-invites-with-policy-rooms.md b/proposals/3847-ignoring-invites-with-policy-rooms.md index a41f20ed6..74a8b92b6 100644 --- a/proposals/3847-ignoring-invites-with-policy-rooms.md +++ b/proposals/3847-ignoring-invites-with-policy-rooms.md @@ -90,18 +90,14 @@ However, clients are expected to offer the ability to look at any ignored invite in a manner similar to a trashcan/recycle bin/undelete mechanism for desktop file systems. -Similarly, if a policy `m.ignore` in a `m.ignore.invites` room is redacted/amended, +Similarly, if a policy `m.ban` in a `m.ignore.invites` room is redacted/amended, clients should show any invite that doesn't match any `m.ignore.invites` & `m.ban` entities anymore. ### Server behavior -As recommended in Matrix spec, if a user Alice has a `m.policies` with key -`m.ignore.invites` and `sources` containing room R *and* if a policy `m.ban` is present in R: - -- if `type` is `m.policy.rule.user`, ignore any message or invite from the user `entity`, as per `m.ignored_users`; -- if `type` is `m.policy.rule.room`, ignore any message in the room or invite from the room `entity`; -- if `type` is `m.policy.rule.server`, ignore any message in any room on server `entity`, any message from any user on server `entity`, any invite towards any room on server `entity`, any invite from any user on server `entity`. +None at this stage. While implementation details may differ, key `m.ignore.invites` is +designed *a priori* to be executed entirely client-side. ## Potential issues From 6c8477f3dee6be74ce083dea18aab64ef3df14eb Mon Sep 17 00:00:00 2001 From: David Teller Date: Wed, 20 Jul 2022 12:19:32 +0200 Subject: [PATCH 4/6] WIP: Applied feedback --- ...3847-ignoring-invites-with-policy-rooms.md | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/proposals/3847-ignoring-invites-with-policy-rooms.md b/proposals/3847-ignoring-invites-with-policy-rooms.md index 74a8b92b6..0c1d018b2 100644 --- a/proposals/3847-ignoring-invites-with-policy-rooms.md +++ b/proposals/3847-ignoring-invites-with-policy-rooms.md @@ -10,10 +10,10 @@ this and to let clients perform filtering of unwanted invites. We proceed as follows: -1. We build upon the mechanism of policy rooms, defined in MSC2313, and define +1. We build upon the mechanism of policy rooms, introduced in [MSC2313](https://github.com/matrix-org/matrix-doc/pull/2313), and define a user's individual policy room, which may be created on behalf of the user by a Matrix client, and which is shared across all devices and clients of the user. -2. We build upon the mechanism of recommendations, also defined in MSC2313, +2. We build upon the mechanism of recommendations, also introduced in [MSC2313](https://github.com/matrix-org/matrix-doc/pull/2313), and create a new recommendation for ignoring invites from a specific user, from a specific server or towards a specific room. @@ -63,8 +63,8 @@ Where `Policies` is defined as: | Content | Type | Description | |-------------|------|-------------| -| `target` | Room ID or Alias | A room in which to issue new policies. | -| `sources` | Room ID or Alias []| A list of rooms from which to apply new policies. Should generally include `target`. | +| `target` | Room ID | A room in which to issue new policies. | +| `sources` | Room ID [] | A list of rooms from which to apply new policies. Should generally include `target`. | The expected behavior is that: @@ -94,6 +94,9 @@ Similarly, if a policy `m.ban` in a `m.ignore.invites` room is redacted/amended, clients should show any invite that doesn't match any `m.ignore.invites` & `m.ban` entities anymore. +If the client detects that one of the rooms has been upgraded, it should follow +the tombstone to the new room. + ### Server behavior None at this stage. While implementation details may differ, key `m.ignore.invites` is @@ -135,7 +138,16 @@ Consequently, we prefer handling things on the client, even if this may require ## Security considerations -Can't think of any right now. +### Room aliases +We have decided to specify room IDs rather than room aliases as room aliases can, in some circumstances, +be forged by malicious users/administrators. + +### Trust +If the administrator of a policy room R is malicious, they can use this room to specify that all invites, +or some specific good invites, should be ignored. A user who uses R as a `source` will therefore not see +some invites that they would otherwise see. + +In other words, using a room as source requires trusting the administrator of that room. ## Unstable prefix From c08c9aea95df544720b151b935471aa991f564b6 Mon Sep 17 00:00:00 2001 From: David Teller Date: Wed, 20 Jul 2022 13:43:52 +0200 Subject: [PATCH 5/6] WIP --- proposals/3847-ignoring-invites-with-policy-rooms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/3847-ignoring-invites-with-policy-rooms.md b/proposals/3847-ignoring-invites-with-policy-rooms.md index 0c1d018b2..fe3a22daa 100644 --- a/proposals/3847-ignoring-invites-with-policy-rooms.md +++ b/proposals/3847-ignoring-invites-with-policy-rooms.md @@ -78,7 +78,7 @@ The expected behavior is that: interpreting such policies as "ignore invites". -### Client behaviour +### Suggested client behaviour If a user Alice has a `m.policies` with key `m.ignore.invites` and `sources` containing room R *and* if a new policy `m.ban` appears in R: From 7af95c1f4edca5e63fd37351d499ad075ff18fb6 Mon Sep 17 00:00:00 2001 From: David Teller Date: Thu, 8 Sep 2022 17:09:08 +0200 Subject: [PATCH 6/6] WIP: Expanding policy rules to individual events --- proposals/3847-ignoring-invites-with-policy-rooms.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/proposals/3847-ignoring-invites-with-policy-rooms.md b/proposals/3847-ignoring-invites-with-policy-rooms.md index fe3a22daa..a92261d47 100644 --- a/proposals/3847-ignoring-invites-with-policy-rooms.md +++ b/proposals/3847-ignoring-invites-with-policy-rooms.md @@ -77,6 +77,14 @@ The expected behavior is that: monitor room R for new policies and apply the recommendations on behalf of Alice, interpreting such policies as "ignore invites". +### Expanding recommendations to individual events + +Policy lists define three scopes `m.policy.rule.user` for rules that deal with users, +`m.policy.rule.room` for rules that deals with rooms and `m.policy.rule.server` for +rules that deal with servers. + +We expand these lists with a fourth scope `m.policy.rule.event` for rules that deal +with individual events, in this case ignoring a specific invite. ### Suggested client behaviour @@ -154,5 +162,6 @@ In other words, using a room as source requires trusting the administrator of th During testing: - `m.ignore.invites` should be prefixed `org.matrix.msc3847.ignore.invites`; -- `m.policies` should be prefixed `org.matrix.msc3847.policies`. +- `m.policies` should be prefixed `org.matrix.msc3847.policies`; +- `m.policy.rule.event` should be prefixed `org.matrix.msc3847.policy.rule.event`.