From f443b3d5a9afac3095b14a72ec471ba06f4cc78b Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 24 May 2022 17:38:08 +0100 Subject: [PATCH 01/23] Clarification on historical power level handling --- content/server-server-api.md | 102 +++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/content/server-server-api.md b/content/server-server-api.md index 24b6a889a..203974b68 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -68,17 +68,17 @@ Server names are resolved to an IP address and port to connect to, and have various conditions affecting which certificates and `Host` headers to send. The process overall is as follows: -1. If the hostname is an IP literal, then that IP address should be +1. If the hostname is an IP literal, then that IP address should be used, together with the given port number, or 8448 if no port is given. The target server must present a valid certificate for the IP address. The `Host` header in the request should be set to the server name, including the port if the server name included one. -2. If the hostname is not an IP literal, and the server name includes +2. If the hostname is not an IP literal, and the server name includes an explicit port, resolve the IP address using AAAA or A records. Requests are made to the resolved IP address and given port with a `Host` header of the original server name (with port). The target server must present a valid certificate for the hostname. -3. If the hostname is not an IP literal, a regular HTTPS request is +3. If the hostname is not an IP literal, a regular HTTPS request is made to `https:///.well-known/matrix/server`, expecting the schema defined later in this section. 30x redirects should be followed, however redirection loops should be avoided. Responses @@ -95,20 +95,20 @@ to send. The process overall is as follows: to step 4. If the response is valid, the `m.server` property is parsed as `[:]` and processed as follows: - - If `` is an IP literal, then that IP address + - If `` is an IP literal, then that IP address should be used together with the `` or 8448 if no port is provided. The target server must present a valid TLS certificate for the IP address. Requests must be made with a `Host` header containing the IP address, including the port if one was provided. - - If `` is not an IP literal, and + - If `` is not an IP literal, and `` is present, an IP address is discovered by looking up an AAAA or A record for ``. The resulting IP address is used, alongside the ``. Requests must be made with a `Host` header of `:`. The target server must present a valid certificate for ``. - - If `` is not an IP literal and no + - If `` is not an IP literal and no `` is present, an SRV record is looked up for `_matrix._tcp.`. This may result in another hostname (to be resolved using AAAA or A records) and port. @@ -116,19 +116,19 @@ to send. The process overall is as follows: a `Host` header containing the ``. The target server must present a valid certificate for ``. - - If no SRV record is found, an IP address is resolved using AAAA + - If no SRV record is found, an IP address is resolved using AAAA or A records. Requests are then made to the resolve IP address and a port of 8448, using a `Host` header of ``. The target server must present a valid certificate for ``. -4. If the `/.well-known` request resulted in an error response, a +4. If the `/.well-known` request resulted in an error response, a server is found by resolving an SRV record for `_matrix._tcp.`. This may result in a hostname (to be resolved using AAAA or A records) and port. Requests are made to the resolved IP address and port, using 8448 as a default port, with a `Host` header of ``. The target server must present a valid certificate for ``. -5. If the `/.well-known` request returned an error response, and the +5. If the `/.well-known` request returned an error response, and the SRV record was not found, an IP address is resolved using AAAA and A records. Requests are made to the resolved IP address using port 8448 and a `Host` header containing the ``. The target @@ -137,6 +137,7 @@ to send. The process overall is as follows: {{% boxes/note %}} The reasons we require `` rather than `` for SRV delegation are: + 1. DNS is insecure (not all domains have DNSSEC), so the target of the delegation must prove that it is a valid delegate for `` via TLS. 2. Consistency with the recommendations in [RFC6125](https://datatracker.ietf.org/doc/html/rfc6125#section-6.2.1) @@ -356,17 +357,17 @@ specification](/rooms). Whenever a server receives an event from a remote server, the receiving server must ensure that the event: -1. Is a valid event, otherwise it is dropped. For an event to be valid, it +1. Is a valid event, otherwise it is dropped. For an event to be valid, it must contain a `room_id`, and it must comply with the event format of that [room version](/rooms). -2. Passes signature checks, otherwise it is dropped. -3. Passes hash checks, otherwise it is redacted before being processed +2. Passes signature checks, otherwise it is dropped. +3. Passes hash checks, otherwise it is redacted before being processed further. -4. Passes authorization rules based on the event's auth events, +4. Passes authorization rules based on the event's auth events, otherwise it is rejected. -5. Passes authorization rules based on the state before the event, +5. Passes authorization rules based on the state before the event, otherwise it is rejected. -6. Passes authorization rules based on the current state of the room, +6. Passes authorization rules based on the current state of the room, otherwise it is "soft failed". Further details of these checks, and how to handle failures, are @@ -394,6 +395,25 @@ unspecified. For an `m.room.member` state event, the user given by the `state_key` of the event. +**Historical String Power Levels** \ + +In order to maintain backwards compatibility with early implementations, +power levels can optionally be represented in string format instead of +integer format. A homeserver must be prepared to deal with this by parsing +the power level from a string. In these cases, the following formatting of the +power level string is allowed: + +- a single Base10 integer, no float values or decimal points, optionally with leading zeroes; +- optionally with leading or trailing whitespace characters; +- optionally prefixed with a single `-` or `+` character before the integer but after leading whitespace padding. + +{{% boxes/warning %}} +This behaviour is preserved strictly for backward compatibility only. A +homeserver should take reasonable precautions to prevent users from +sending new power level events with string values and must never +populate the default power levels in a room as string values. +{{% /boxes/warning %}} + #### Authorization rules The rules governing whether an event is authorized depends on a set of @@ -418,14 +438,14 @@ the following subset of the room state: - If type is `m.room.member`: - - The target's current `m.room.member` event, if any. - - If `membership` is `join` or `invite`, the current + - The target's current `m.room.member` event, if any. + - If `membership` is `join` or `invite`, the current `m.room.join_rules` event, if any. - - If membership is `invite` and `content` contains a + - If membership is `invite` and `content` contains a `third_party_invite` property, the current `m.room.third_party_invite` event with `state_key` matching `content.third_party_invite.signed.token`, if any. - - If `content.join_authorised_via_users_server` is present, + - If `content.join_authorised_via_users_server` is present, and the [room version supports restricted rooms](/rooms/#feature-matrix), then the `m.room.member` event with `state_key` matching `content.join_authorised_via_users_server`. @@ -1101,22 +1121,22 @@ of `M_FORBIDDEN`. The following endpoint prefixes MUST be protected: -- `/_matrix/federation/v1/send` (on a per-PDU basis) -- `/_matrix/federation/v1/make_join` -- `/_matrix/federation/v1/make_leave` -- `/_matrix/federation/v1/send_join` -- `/_matrix/federation/v2/send_join` -- `/_matrix/federation/v1/send_leave` -- `/_matrix/federation/v2/send_leave` -- `/_matrix/federation/v1/invite` -- `/_matrix/federation/v2/invite` -- `/_matrix/federation/v1/make_knock` -- `/_matrix/federation/v1/send_knock` -- `/_matrix/federation/v1/state` -- `/_matrix/federation/v1/state_ids` -- `/_matrix/federation/v1/backfill` -- `/_matrix/federation/v1/event_auth` -- `/_matrix/federation/v1/get_missing_events` +- `/_matrix/federation/v1/send` (on a per-PDU basis) +- `/_matrix/federation/v1/make_join` +- `/_matrix/federation/v1/make_leave` +- `/_matrix/federation/v1/send_join` +- `/_matrix/federation/v2/send_join` +- `/_matrix/federation/v1/send_leave` +- `/_matrix/federation/v2/send_leave` +- `/_matrix/federation/v1/invite` +- `/_matrix/federation/v2/invite` +- `/_matrix/federation/v1/make_knock` +- `/_matrix/federation/v1/send_knock` +- `/_matrix/federation/v1/state` +- `/_matrix/federation/v1/state_ids` +- `/_matrix/federation/v1/backfill` +- `/_matrix/federation/v1/event_auth` +- `/_matrix/federation/v1/get_missing_events` ## Signing Events @@ -1157,11 +1177,11 @@ redacted copy. The signatures expected on an event are: -- The `sender`'s server, unless the invite was created as a result of +- The `sender`'s server, unless the invite was created as a result of 3rd party invite. The sender must already match the 3rd party invite, and the server which actually sends the event may be a different server. -- For room versions 1 and 2, the server which created the `event_id`. +- For room versions 1 and 2, the server which created the `event_id`. Other room versions do not track the `event_id` over federation and therefore do not need a signature from those servers. @@ -1183,12 +1203,12 @@ some room versions. See the [room version specification](/rooms) for more information. It is calculated as follows. -1. The event is put through the redaction algorithm. -2. The `signatures`, `age_ts`, and `unsigned` properties are removed +1. The event is put through the redaction algorithm. +2. The `signatures`, `age_ts`, and `unsigned` properties are removed from the event, if present. -3. The event is converted into [Canonical +3. The event is converted into [Canonical JSON](/appendices#canonical-json). -4. A sha256 hash is calculated on the resulting JSON object. +4. A sha256 hash is calculated on the resulting JSON object. ### Calculating the content hash for an event From 6b175d66655110f3578dbfab218b1a8c01b32c8c Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 24 May 2022 17:40:14 +0100 Subject: [PATCH 02/23] Revert "Clarification on historical power level handling" This reverts commit f443b3d5a9afac3095b14a72ec471ba06f4cc78b. --- content/server-server-api.md | 102 ++++++++++++++--------------------- 1 file changed, 41 insertions(+), 61 deletions(-) diff --git a/content/server-server-api.md b/content/server-server-api.md index 203974b68..24b6a889a 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -68,17 +68,17 @@ Server names are resolved to an IP address and port to connect to, and have various conditions affecting which certificates and `Host` headers to send. The process overall is as follows: -1. If the hostname is an IP literal, then that IP address should be +1. If the hostname is an IP literal, then that IP address should be used, together with the given port number, or 8448 if no port is given. The target server must present a valid certificate for the IP address. The `Host` header in the request should be set to the server name, including the port if the server name included one. -2. If the hostname is not an IP literal, and the server name includes +2. If the hostname is not an IP literal, and the server name includes an explicit port, resolve the IP address using AAAA or A records. Requests are made to the resolved IP address and given port with a `Host` header of the original server name (with port). The target server must present a valid certificate for the hostname. -3. If the hostname is not an IP literal, a regular HTTPS request is +3. If the hostname is not an IP literal, a regular HTTPS request is made to `https:///.well-known/matrix/server`, expecting the schema defined later in this section. 30x redirects should be followed, however redirection loops should be avoided. Responses @@ -95,20 +95,20 @@ to send. The process overall is as follows: to step 4. If the response is valid, the `m.server` property is parsed as `[:]` and processed as follows: - - If `` is an IP literal, then that IP address + - If `` is an IP literal, then that IP address should be used together with the `` or 8448 if no port is provided. The target server must present a valid TLS certificate for the IP address. Requests must be made with a `Host` header containing the IP address, including the port if one was provided. - - If `` is not an IP literal, and + - If `` is not an IP literal, and `` is present, an IP address is discovered by looking up an AAAA or A record for ``. The resulting IP address is used, alongside the ``. Requests must be made with a `Host` header of `:`. The target server must present a valid certificate for ``. - - If `` is not an IP literal and no + - If `` is not an IP literal and no `` is present, an SRV record is looked up for `_matrix._tcp.`. This may result in another hostname (to be resolved using AAAA or A records) and port. @@ -116,19 +116,19 @@ to send. The process overall is as follows: a `Host` header containing the ``. The target server must present a valid certificate for ``. - - If no SRV record is found, an IP address is resolved using AAAA + - If no SRV record is found, an IP address is resolved using AAAA or A records. Requests are then made to the resolve IP address and a port of 8448, using a `Host` header of ``. The target server must present a valid certificate for ``. -4. If the `/.well-known` request resulted in an error response, a +4. If the `/.well-known` request resulted in an error response, a server is found by resolving an SRV record for `_matrix._tcp.`. This may result in a hostname (to be resolved using AAAA or A records) and port. Requests are made to the resolved IP address and port, using 8448 as a default port, with a `Host` header of ``. The target server must present a valid certificate for ``. -5. If the `/.well-known` request returned an error response, and the +5. If the `/.well-known` request returned an error response, and the SRV record was not found, an IP address is resolved using AAAA and A records. Requests are made to the resolved IP address using port 8448 and a `Host` header containing the ``. The target @@ -137,7 +137,6 @@ to send. The process overall is as follows: {{% boxes/note %}} The reasons we require `` rather than `` for SRV delegation are: - 1. DNS is insecure (not all domains have DNSSEC), so the target of the delegation must prove that it is a valid delegate for `` via TLS. 2. Consistency with the recommendations in [RFC6125](https://datatracker.ietf.org/doc/html/rfc6125#section-6.2.1) @@ -357,17 +356,17 @@ specification](/rooms). Whenever a server receives an event from a remote server, the receiving server must ensure that the event: -1. Is a valid event, otherwise it is dropped. For an event to be valid, it +1. Is a valid event, otherwise it is dropped. For an event to be valid, it must contain a `room_id`, and it must comply with the event format of that [room version](/rooms). -2. Passes signature checks, otherwise it is dropped. -3. Passes hash checks, otherwise it is redacted before being processed +2. Passes signature checks, otherwise it is dropped. +3. Passes hash checks, otherwise it is redacted before being processed further. -4. Passes authorization rules based on the event's auth events, +4. Passes authorization rules based on the event's auth events, otherwise it is rejected. -5. Passes authorization rules based on the state before the event, +5. Passes authorization rules based on the state before the event, otherwise it is rejected. -6. Passes authorization rules based on the current state of the room, +6. Passes authorization rules based on the current state of the room, otherwise it is "soft failed". Further details of these checks, and how to handle failures, are @@ -395,25 +394,6 @@ unspecified. For an `m.room.member` state event, the user given by the `state_key` of the event. -**Historical String Power Levels** \ - -In order to maintain backwards compatibility with early implementations, -power levels can optionally be represented in string format instead of -integer format. A homeserver must be prepared to deal with this by parsing -the power level from a string. In these cases, the following formatting of the -power level string is allowed: - -- a single Base10 integer, no float values or decimal points, optionally with leading zeroes; -- optionally with leading or trailing whitespace characters; -- optionally prefixed with a single `-` or `+` character before the integer but after leading whitespace padding. - -{{% boxes/warning %}} -This behaviour is preserved strictly for backward compatibility only. A -homeserver should take reasonable precautions to prevent users from -sending new power level events with string values and must never -populate the default power levels in a room as string values. -{{% /boxes/warning %}} - #### Authorization rules The rules governing whether an event is authorized depends on a set of @@ -438,14 +418,14 @@ the following subset of the room state: - If type is `m.room.member`: - - The target's current `m.room.member` event, if any. - - If `membership` is `join` or `invite`, the current + - The target's current `m.room.member` event, if any. + - If `membership` is `join` or `invite`, the current `m.room.join_rules` event, if any. - - If membership is `invite` and `content` contains a + - If membership is `invite` and `content` contains a `third_party_invite` property, the current `m.room.third_party_invite` event with `state_key` matching `content.third_party_invite.signed.token`, if any. - - If `content.join_authorised_via_users_server` is present, + - If `content.join_authorised_via_users_server` is present, and the [room version supports restricted rooms](/rooms/#feature-matrix), then the `m.room.member` event with `state_key` matching `content.join_authorised_via_users_server`. @@ -1121,22 +1101,22 @@ of `M_FORBIDDEN`. The following endpoint prefixes MUST be protected: -- `/_matrix/federation/v1/send` (on a per-PDU basis) -- `/_matrix/federation/v1/make_join` -- `/_matrix/federation/v1/make_leave` -- `/_matrix/federation/v1/send_join` -- `/_matrix/federation/v2/send_join` -- `/_matrix/federation/v1/send_leave` -- `/_matrix/federation/v2/send_leave` -- `/_matrix/federation/v1/invite` -- `/_matrix/federation/v2/invite` -- `/_matrix/federation/v1/make_knock` -- `/_matrix/federation/v1/send_knock` -- `/_matrix/federation/v1/state` -- `/_matrix/federation/v1/state_ids` -- `/_matrix/federation/v1/backfill` -- `/_matrix/federation/v1/event_auth` -- `/_matrix/federation/v1/get_missing_events` +- `/_matrix/federation/v1/send` (on a per-PDU basis) +- `/_matrix/federation/v1/make_join` +- `/_matrix/federation/v1/make_leave` +- `/_matrix/federation/v1/send_join` +- `/_matrix/federation/v2/send_join` +- `/_matrix/federation/v1/send_leave` +- `/_matrix/federation/v2/send_leave` +- `/_matrix/federation/v1/invite` +- `/_matrix/federation/v2/invite` +- `/_matrix/federation/v1/make_knock` +- `/_matrix/federation/v1/send_knock` +- `/_matrix/federation/v1/state` +- `/_matrix/federation/v1/state_ids` +- `/_matrix/federation/v1/backfill` +- `/_matrix/federation/v1/event_auth` +- `/_matrix/federation/v1/get_missing_events` ## Signing Events @@ -1177,11 +1157,11 @@ redacted copy. The signatures expected on an event are: -- The `sender`'s server, unless the invite was created as a result of +- The `sender`'s server, unless the invite was created as a result of 3rd party invite. The sender must already match the 3rd party invite, and the server which actually sends the event may be a different server. -- For room versions 1 and 2, the server which created the `event_id`. +- For room versions 1 and 2, the server which created the `event_id`. Other room versions do not track the `event_id` over federation and therefore do not need a signature from those servers. @@ -1203,12 +1183,12 @@ some room versions. See the [room version specification](/rooms) for more information. It is calculated as follows. -1. The event is put through the redaction algorithm. -2. The `signatures`, `age_ts`, and `unsigned` properties are removed +1. The event is put through the redaction algorithm. +2. The `signatures`, `age_ts`, and `unsigned` properties are removed from the event, if present. -3. The event is converted into [Canonical +3. The event is converted into [Canonical JSON](/appendices#canonical-json). -4. A sha256 hash is calculated on the resulting JSON object. +4. A sha256 hash is calculated on the resulting JSON object. ### Calculating the content hash for an event From 7fd54c43c5f83bd6426bcac1e6d554b70a1205a4 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 24 May 2022 17:40:47 +0100 Subject: [PATCH 03/23] Clean up --- .../newsfragments/1082.clarification | 1 + content/server-server-api.md | 102 +++++++++++------- 2 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 changelogs/server_server/newsfragments/1082.clarification diff --git a/changelogs/server_server/newsfragments/1082.clarification b/changelogs/server_server/newsfragments/1082.clarification new file mode 100644 index 000000000..2a420f522 --- /dev/null +++ b/changelogs/server_server/newsfragments/1082.clarification @@ -0,0 +1 @@ +Clarifies the historical handling of non-integer power levels. \ No newline at end of file diff --git a/content/server-server-api.md b/content/server-server-api.md index 24b6a889a..f026879f2 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -68,17 +68,17 @@ Server names are resolved to an IP address and port to connect to, and have various conditions affecting which certificates and `Host` headers to send. The process overall is as follows: -1. If the hostname is an IP literal, then that IP address should be +1. If the hostname is an IP literal, then that IP address should be used, together with the given port number, or 8448 if no port is given. The target server must present a valid certificate for the IP address. The `Host` header in the request should be set to the server name, including the port if the server name included one. -2. If the hostname is not an IP literal, and the server name includes +2. If the hostname is not an IP literal, and the server name includes an explicit port, resolve the IP address using AAAA or A records. Requests are made to the resolved IP address and given port with a `Host` header of the original server name (with port). The target server must present a valid certificate for the hostname. -3. If the hostname is not an IP literal, a regular HTTPS request is +3. If the hostname is not an IP literal, a regular HTTPS request is made to `https:///.well-known/matrix/server`, expecting the schema defined later in this section. 30x redirects should be followed, however redirection loops should be avoided. Responses @@ -95,20 +95,20 @@ to send. The process overall is as follows: to step 4. If the response is valid, the `m.server` property is parsed as `[:]` and processed as follows: - - If `` is an IP literal, then that IP address + - If `` is an IP literal, then that IP address should be used together with the `` or 8448 if no port is provided. The target server must present a valid TLS certificate for the IP address. Requests must be made with a `Host` header containing the IP address, including the port if one was provided. - - If `` is not an IP literal, and + - If `` is not an IP literal, and `` is present, an IP address is discovered by looking up an AAAA or A record for ``. The resulting IP address is used, alongside the ``. Requests must be made with a `Host` header of `:`. The target server must present a valid certificate for ``. - - If `` is not an IP literal and no + - If `` is not an IP literal and no `` is present, an SRV record is looked up for `_matrix._tcp.`. This may result in another hostname (to be resolved using AAAA or A records) and port. @@ -116,19 +116,19 @@ to send. The process overall is as follows: a `Host` header containing the ``. The target server must present a valid certificate for ``. - - If no SRV record is found, an IP address is resolved using AAAA + - If no SRV record is found, an IP address is resolved using AAAA or A records. Requests are then made to the resolve IP address and a port of 8448, using a `Host` header of ``. The target server must present a valid certificate for ``. -4. If the `/.well-known` request resulted in an error response, a +4. If the `/.well-known` request resulted in an error response, a server is found by resolving an SRV record for `_matrix._tcp.`. This may result in a hostname (to be resolved using AAAA or A records) and port. Requests are made to the resolved IP address and port, using 8448 as a default port, with a `Host` header of ``. The target server must present a valid certificate for ``. -5. If the `/.well-known` request returned an error response, and the +5. If the `/.well-known` request returned an error response, and the SRV record was not found, an IP address is resolved using AAAA and A records. Requests are made to the resolved IP address using port 8448 and a `Host` header containing the ``. The target @@ -137,6 +137,7 @@ to send. The process overall is as follows: {{% boxes/note %}} The reasons we require `` rather than `` for SRV delegation are: + 1. DNS is insecure (not all domains have DNSSEC), so the target of the delegation must prove that it is a valid delegate for `` via TLS. 2. Consistency with the recommendations in [RFC6125](https://datatracker.ietf.org/doc/html/rfc6125#section-6.2.1) @@ -356,17 +357,17 @@ specification](/rooms). Whenever a server receives an event from a remote server, the receiving server must ensure that the event: -1. Is a valid event, otherwise it is dropped. For an event to be valid, it +1. Is a valid event, otherwise it is dropped. For an event to be valid, it must contain a `room_id`, and it must comply with the event format of that [room version](/rooms). -2. Passes signature checks, otherwise it is dropped. -3. Passes hash checks, otherwise it is redacted before being processed +2. Passes signature checks, otherwise it is dropped. +3. Passes hash checks, otherwise it is redacted before being processed further. -4. Passes authorization rules based on the event's auth events, +4. Passes authorization rules based on the event's auth events, otherwise it is rejected. -5. Passes authorization rules based on the state before the event, +5. Passes authorization rules based on the state before the event, otherwise it is rejected. -6. Passes authorization rules based on the current state of the room, +6. Passes authorization rules based on the current state of the room, otherwise it is "soft failed". Further details of these checks, and how to handle failures, are @@ -394,6 +395,25 @@ unspecified. For an `m.room.member` state event, the user given by the `state_key` of the event. +**Historical String Power Levels** \ + + In order to maintain backwards compatibility with early implementations, + power levels can optionally be represented in string format instead of + integer format. A homeserver must be prepared to deal with this by parsing + the power level from a string. In these cases, the following formatting of the + power level string is allowed: + +- a single Base10 integer, no float values or decimal points, optionally with leading zeroes; +- optionally with leading or trailing whitespace characters; +- optionally prefixed with a single `-` or `+` character before the integer but after leading whitespace padding. + + {{% boxes/warning %}} + This behaviour is preserved strictly for backward compatibility only. A + homeserver should take reasonable precautions to prevent users from + sending new power level events with string values and must never + populate the default power levels in a room as string values. + {{% /boxes/warning %}} + #### Authorization rules The rules governing whether an event is authorized depends on a set of @@ -418,14 +438,14 @@ the following subset of the room state: - If type is `m.room.member`: - - The target's current `m.room.member` event, if any. - - If `membership` is `join` or `invite`, the current + - The target's current `m.room.member` event, if any. + - If `membership` is `join` or `invite`, the current `m.room.join_rules` event, if any. - - If membership is `invite` and `content` contains a + - If membership is `invite` and `content` contains a `third_party_invite` property, the current `m.room.third_party_invite` event with `state_key` matching `content.third_party_invite.signed.token`, if any. - - If `content.join_authorised_via_users_server` is present, + - If `content.join_authorised_via_users_server` is present, and the [room version supports restricted rooms](/rooms/#feature-matrix), then the `m.room.member` event with `state_key` matching `content.join_authorised_via_users_server`. @@ -1101,22 +1121,22 @@ of `M_FORBIDDEN`. The following endpoint prefixes MUST be protected: -- `/_matrix/federation/v1/send` (on a per-PDU basis) -- `/_matrix/federation/v1/make_join` -- `/_matrix/federation/v1/make_leave` -- `/_matrix/federation/v1/send_join` -- `/_matrix/federation/v2/send_join` -- `/_matrix/federation/v1/send_leave` -- `/_matrix/federation/v2/send_leave` -- `/_matrix/federation/v1/invite` -- `/_matrix/federation/v2/invite` -- `/_matrix/federation/v1/make_knock` -- `/_matrix/federation/v1/send_knock` -- `/_matrix/federation/v1/state` -- `/_matrix/federation/v1/state_ids` -- `/_matrix/federation/v1/backfill` -- `/_matrix/federation/v1/event_auth` -- `/_matrix/federation/v1/get_missing_events` +- `/_matrix/federation/v1/send` (on a per-PDU basis) +- `/_matrix/federation/v1/make_join` +- `/_matrix/federation/v1/make_leave` +- `/_matrix/federation/v1/send_join` +- `/_matrix/federation/v2/send_join` +- `/_matrix/federation/v1/send_leave` +- `/_matrix/federation/v2/send_leave` +- `/_matrix/federation/v1/invite` +- `/_matrix/federation/v2/invite` +- `/_matrix/federation/v1/make_knock` +- `/_matrix/federation/v1/send_knock` +- `/_matrix/federation/v1/state` +- `/_matrix/federation/v1/state_ids` +- `/_matrix/federation/v1/backfill` +- `/_matrix/federation/v1/event_auth` +- `/_matrix/federation/v1/get_missing_events` ## Signing Events @@ -1157,11 +1177,11 @@ redacted copy. The signatures expected on an event are: -- The `sender`'s server, unless the invite was created as a result of +- The `sender`'s server, unless the invite was created as a result of 3rd party invite. The sender must already match the 3rd party invite, and the server which actually sends the event may be a different server. -- For room versions 1 and 2, the server which created the `event_id`. +- For room versions 1 and 2, the server which created the `event_id`. Other room versions do not track the `event_id` over federation and therefore do not need a signature from those servers. @@ -1183,12 +1203,12 @@ some room versions. See the [room version specification](/rooms) for more information. It is calculated as follows. -1. The event is put through the redaction algorithm. -2. The `signatures`, `age_ts`, and `unsigned` properties are removed +1. The event is put through the redaction algorithm. +2. The `signatures`, `age_ts`, and `unsigned` properties are removed from the event, if present. -3. The event is converted into [Canonical +3. The event is converted into [Canonical JSON](/appendices#canonical-json). -4. A sha256 hash is calculated on the resulting JSON object. +4. A sha256 hash is calculated on the resulting JSON object. ### Calculating the content hash for an event From 666baf6159e99cb592c3620f2b5a77b57dbeb4b3 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 24 May 2022 17:43:43 +0100 Subject: [PATCH 04/23] Let us try this again not using VS Code --- content/server-server-api.md | 105 +++++++++++++++++------------------ 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/content/server-server-api.md b/content/server-server-api.md index f026879f2..3b428230f 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -68,17 +68,17 @@ Server names are resolved to an IP address and port to connect to, and have various conditions affecting which certificates and `Host` headers to send. The process overall is as follows: -1. If the hostname is an IP literal, then that IP address should be +1. If the hostname is an IP literal, then that IP address should be used, together with the given port number, or 8448 if no port is given. The target server must present a valid certificate for the IP address. The `Host` header in the request should be set to the server name, including the port if the server name included one. -2. If the hostname is not an IP literal, and the server name includes +2. If the hostname is not an IP literal, and the server name includes an explicit port, resolve the IP address using AAAA or A records. Requests are made to the resolved IP address and given port with a `Host` header of the original server name (with port). The target server must present a valid certificate for the hostname. -3. If the hostname is not an IP literal, a regular HTTPS request is +3. If the hostname is not an IP literal, a regular HTTPS request is made to `https:///.well-known/matrix/server`, expecting the schema defined later in this section. 30x redirects should be followed, however redirection loops should be avoided. Responses @@ -95,20 +95,20 @@ to send. The process overall is as follows: to step 4. If the response is valid, the `m.server` property is parsed as `[:]` and processed as follows: - - If `` is an IP literal, then that IP address + - If `` is an IP literal, then that IP address should be used together with the `` or 8448 if no port is provided. The target server must present a valid TLS certificate for the IP address. Requests must be made with a `Host` header containing the IP address, including the port if one was provided. - - If `` is not an IP literal, and + - If `` is not an IP literal, and `` is present, an IP address is discovered by looking up an AAAA or A record for ``. The resulting IP address is used, alongside the ``. Requests must be made with a `Host` header of `:`. The target server must present a valid certificate for ``. - - If `` is not an IP literal and no + - If `` is not an IP literal and no `` is present, an SRV record is looked up for `_matrix._tcp.`. This may result in another hostname (to be resolved using AAAA or A records) and port. @@ -116,19 +116,19 @@ to send. The process overall is as follows: a `Host` header containing the ``. The target server must present a valid certificate for ``. - - If no SRV record is found, an IP address is resolved using AAAA + - If no SRV record is found, an IP address is resolved using AAAA or A records. Requests are then made to the resolve IP address and a port of 8448, using a `Host` header of ``. The target server must present a valid certificate for ``. -4. If the `/.well-known` request resulted in an error response, a +4. If the `/.well-known` request resulted in an error response, a server is found by resolving an SRV record for `_matrix._tcp.`. This may result in a hostname (to be resolved using AAAA or A records) and port. Requests are made to the resolved IP address and port, using 8448 as a default port, with a `Host` header of ``. The target server must present a valid certificate for ``. -5. If the `/.well-known` request returned an error response, and the +5. If the `/.well-known` request returned an error response, and the SRV record was not found, an IP address is resolved using AAAA and A records. Requests are made to the resolved IP address using port 8448 and a `Host` header containing the ``. The target @@ -137,7 +137,6 @@ to send. The process overall is as follows: {{% boxes/note %}} The reasons we require `` rather than `` for SRV delegation are: - 1. DNS is insecure (not all domains have DNSSEC), so the target of the delegation must prove that it is a valid delegate for `` via TLS. 2. Consistency with the recommendations in [RFC6125](https://datatracker.ietf.org/doc/html/rfc6125#section-6.2.1) @@ -357,17 +356,17 @@ specification](/rooms). Whenever a server receives an event from a remote server, the receiving server must ensure that the event: -1. Is a valid event, otherwise it is dropped. For an event to be valid, it +1. Is a valid event, otherwise it is dropped. For an event to be valid, it must contain a `room_id`, and it must comply with the event format of that [room version](/rooms). -2. Passes signature checks, otherwise it is dropped. -3. Passes hash checks, otherwise it is redacted before being processed +2. Passes signature checks, otherwise it is dropped. +3. Passes hash checks, otherwise it is redacted before being processed further. -4. Passes authorization rules based on the event's auth events, +4. Passes authorization rules based on the event's auth events, otherwise it is rejected. -5. Passes authorization rules based on the state before the event, +5. Passes authorization rules based on the state before the event, otherwise it is rejected. -6. Passes authorization rules based on the current state of the room, +6. Passes authorization rules based on the current state of the room, otherwise it is "soft failed". Further details of these checks, and how to handle failures, are @@ -397,22 +396,22 @@ the event. **Historical String Power Levels** \ - In order to maintain backwards compatibility with early implementations, - power levels can optionally be represented in string format instead of - integer format. A homeserver must be prepared to deal with this by parsing - the power level from a string. In these cases, the following formatting of the - power level string is allowed: +In order to maintain backwards compatibility with early implementations, +power levels can optionally be represented in string format instead of +integer format. A homeserver must be prepared to deal with this by parsing +the power level from a string. In these cases, the following formatting of the +power level string is allowed: - a single Base10 integer, no float values or decimal points, optionally with leading zeroes; - optionally with leading or trailing whitespace characters; - optionally prefixed with a single `-` or `+` character before the integer but after leading whitespace padding. - {{% boxes/warning %}} - This behaviour is preserved strictly for backward compatibility only. A - homeserver should take reasonable precautions to prevent users from - sending new power level events with string values and must never - populate the default power levels in a room as string values. - {{% /boxes/warning %}} +{{% boxes/warning %}} +This behaviour is preserved strictly for backward compatibility only. A +homeserver should take reasonable precautions to prevent users from +sending new power level events with string values and must never +populate the default power levels in a room as string values. +{{% /boxes/warning %}} #### Authorization rules @@ -438,14 +437,14 @@ the following subset of the room state: - If type is `m.room.member`: - - The target's current `m.room.member` event, if any. - - If `membership` is `join` or `invite`, the current + - The target's current `m.room.member` event, if any. + - If `membership` is `join` or `invite`, the current `m.room.join_rules` event, if any. - - If membership is `invite` and `content` contains a + - If membership is `invite` and `content` contains a `third_party_invite` property, the current `m.room.third_party_invite` event with `state_key` matching `content.third_party_invite.signed.token`, if any. - - If `content.join_authorised_via_users_server` is present, + - If `content.join_authorised_via_users_server` is present, and the [room version supports restricted rooms](/rooms/#feature-matrix), then the `m.room.member` event with `state_key` matching `content.join_authorised_via_users_server`. @@ -1121,22 +1120,22 @@ of `M_FORBIDDEN`. The following endpoint prefixes MUST be protected: -- `/_matrix/federation/v1/send` (on a per-PDU basis) -- `/_matrix/federation/v1/make_join` -- `/_matrix/federation/v1/make_leave` -- `/_matrix/federation/v1/send_join` -- `/_matrix/federation/v2/send_join` -- `/_matrix/federation/v1/send_leave` -- `/_matrix/federation/v2/send_leave` -- `/_matrix/federation/v1/invite` -- `/_matrix/federation/v2/invite` -- `/_matrix/federation/v1/make_knock` -- `/_matrix/federation/v1/send_knock` -- `/_matrix/federation/v1/state` -- `/_matrix/federation/v1/state_ids` -- `/_matrix/federation/v1/backfill` -- `/_matrix/federation/v1/event_auth` -- `/_matrix/federation/v1/get_missing_events` +- `/_matrix/federation/v1/send` (on a per-PDU basis) +- `/_matrix/federation/v1/make_join` +- `/_matrix/federation/v1/make_leave` +- `/_matrix/federation/v1/send_join` +- `/_matrix/federation/v2/send_join` +- `/_matrix/federation/v1/send_leave` +- `/_matrix/federation/v2/send_leave` +- `/_matrix/federation/v1/invite` +- `/_matrix/federation/v2/invite` +- `/_matrix/federation/v1/make_knock` +- `/_matrix/federation/v1/send_knock` +- `/_matrix/federation/v1/state` +- `/_matrix/federation/v1/state_ids` +- `/_matrix/federation/v1/backfill` +- `/_matrix/federation/v1/event_auth` +- `/_matrix/federation/v1/get_missing_events` ## Signing Events @@ -1177,11 +1176,11 @@ redacted copy. The signatures expected on an event are: -- The `sender`'s server, unless the invite was created as a result of +- The `sender`'s server, unless the invite was created as a result of 3rd party invite. The sender must already match the 3rd party invite, and the server which actually sends the event may be a different server. -- For room versions 1 and 2, the server which created the `event_id`. +- For room versions 1 and 2, the server which created the `event_id`. Other room versions do not track the `event_id` over federation and therefore do not need a signature from those servers. @@ -1203,12 +1202,12 @@ some room versions. See the [room version specification](/rooms) for more information. It is calculated as follows. -1. The event is put through the redaction algorithm. -2. The `signatures`, `age_ts`, and `unsigned` properties are removed +1. The event is put through the redaction algorithm. +2. The `signatures`, `age_ts`, and `unsigned` properties are removed from the event, if present. -3. The event is converted into [Canonical +3. The event is converted into [Canonical JSON](/appendices#canonical-json). -4. A sha256 hash is calculated on the resulting JSON object. +4. A sha256 hash is calculated on the resulting JSON object. ### Calculating the content hash for an event From a5a4c1f1f81bf7d8d3a8c040049232c0b2483f7d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Tue, 24 May 2022 17:46:02 +0100 Subject: [PATCH 05/23] Markdown is full of mysteries --- content/server-server-api.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/server-server-api.md b/content/server-server-api.md index 3b428230f..0e2ffcdc0 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -395,7 +395,6 @@ For an `m.room.member` state event, the user given by the `state_key` of the event. **Historical String Power Levels** \ - In order to maintain backwards compatibility with early implementations, power levels can optionally be represented in string format instead of integer format. A homeserver must be prepared to deal with this by parsing From 3dd5bee5ef4c229d4a0e8a6a35e3d73404bcdbb6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 13:48:27 -0600 Subject: [PATCH 06/23] Move stringy power levels to room versions --- .../v1-deprecated-formatting-off-spec.md | 9 ++++++++ .../fragments/v1-stringy-power-levels.md | 15 +++++++++++++ content/rooms/v1.md | 6 +++++ content/rooms/v2.md | 6 +++++ content/rooms/v3.md | 6 +++++ content/rooms/v4.md | 6 +++++ content/rooms/v5.md | 6 +++++ content/rooms/v6.md | 6 +++++ content/rooms/v7.md | 6 +++++ content/rooms/v8.md | 6 +++++ content/rooms/v9.md | 6 +++++ content/server-server-api.md | 22 ++++++------------- 12 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 content/rooms/fragments/v1-deprecated-formatting-off-spec.md create mode 100644 content/rooms/fragments/v1-stringy-power-levels.md diff --git a/content/rooms/fragments/v1-deprecated-formatting-off-spec.md b/content/rooms/fragments/v1-deprecated-formatting-off-spec.md new file mode 100644 index 000000000..2c5cb4779 --- /dev/null +++ b/content/rooms/fragments/v1-deprecated-formatting-off-spec.md @@ -0,0 +1,9 @@ +Events sent into rooms of this version can have formats which are different +from their normal schema. Those cases are documented here. + +{{% boxes/warning %}} +The behaviour described here is preserved strictly for backwards compatibility +only. A homeserver should take reasonable precautions to prevent users from +sending these so-called "malformed" events, and must never rely on the behaviours +described here as a default. +{{% /boxes/warning %}} diff --git a/content/rooms/fragments/v1-stringy-power-levels.md b/content/rooms/fragments/v1-stringy-power-levels.md new file mode 100644 index 000000000..abfd5dc9b --- /dev/null +++ b/content/rooms/fragments/v1-stringy-power-levels.md @@ -0,0 +1,15 @@ +##### Power levels accepted as strings + +In order to maintain backwards compatibility with early implementations, +power levels can optionally be represented in string format instead of +integer format. A homeserver must be prepared to deal with this by parsing +the power level from a string. In these cases, the following formatting of the +power level string is allowed: + +* a single Base10 integer, no float values or decimal points, optionally with + any number of leading zeroes (`"100"`, `"000100"`); +* optionally with any number of leading or trailing whitespace characters (`" 100 "`, + `" 00100 "`); +* optionally prefixed with a single `-` or `+` character before the integer + but after leading whitespace padding (`" +100 "`, `" -100 "`, `"+100"`, + `"-100"`). diff --git a/content/rooms/v1.md b/content/rooms/v1.md index a69e3d5d0..392c20f16 100644 --- a/content/rooms/v1.md +++ b/content/rooms/v1.md @@ -48,6 +48,12 @@ Events in version 1 rooms have the following structure: {{% definition path="api/server-server/definitions/pdu" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### Authorization rules {{% rver-fragment name="v1-auth-rules" %}} diff --git a/content/rooms/v2.md b/content/rooms/v2.md index cdc59190f..c468cff86 100644 --- a/content/rooms/v2.md +++ b/content/rooms/v2.md @@ -46,6 +46,12 @@ Events in rooms of this version have the following structure: {{% definition path="api/server-server/definitions/pdu" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### Authorization rules {{% rver-fragment name="v1-auth-rules" %}} diff --git a/content/rooms/v3.md b/content/rooms/v3.md index 310c66250..b4c1af56a 100644 --- a/content/rooms/v3.md +++ b/content/rooms/v3.md @@ -81,6 +81,12 @@ The complete structure of a event in a v3 room is shown below. {{% definition path="api/server-server/definitions/pdu_v3" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### Authorization rules {{% added-in this=true %}} `m.room.redaction` events are no longer diff --git a/content/rooms/v4.md b/content/rooms/v4.md index 01c695bac..79a5b5329 100644 --- a/content/rooms/v4.md +++ b/content/rooms/v4.md @@ -69,6 +69,12 @@ the changes in this room version. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### Authorization rules {{% rver-fragment name="v3-auth-rules" %}} diff --git a/content/rooms/v5.md b/content/rooms/v5.md index b4283071e..438c1171b 100644 --- a/content/rooms/v5.md +++ b/content/rooms/v5.md @@ -51,6 +51,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### Authorization rules {{% rver-fragment name="v3-auth-rules" %}} diff --git a/content/rooms/v6.md b/content/rooms/v6.md index cb87082c0..c0735af55 100644 --- a/content/rooms/v6.md +++ b/content/rooms/v6.md @@ -212,6 +212,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### State resolution {{% rver-fragment name="v2-state-res" %}} diff --git a/content/rooms/v7.md b/content/rooms/v7.md index 2ada06f78..c22b4dcf4 100644 --- a/content/rooms/v7.md +++ b/content/rooms/v7.md @@ -205,6 +205,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### State resolution {{% rver-fragment name="v2-state-res" %}} diff --git a/content/rooms/v8.md b/content/rooms/v8.md index 50a1f065f..060142b46 100644 --- a/content/rooms/v8.md +++ b/content/rooms/v8.md @@ -110,6 +110,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### State resolution {{% rver-fragment name="v2-state-res" %}} diff --git a/content/rooms/v9.md b/content/rooms/v9.md index 285a7640f..c32fc2765 100644 --- a/content/rooms/v9.md +++ b/content/rooms/v9.md @@ -102,6 +102,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + ### Authorization rules {{% rver-fragment name="v8-auth-rules" %}} diff --git a/content/server-server-api.md b/content/server-server-api.md index 0e2ffcdc0..a35b4ea9a 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -394,22 +394,14 @@ unspecified. For an `m.room.member` state event, the user given by the `state_key` of the event. -**Historical String Power Levels** \ -In order to maintain backwards compatibility with early implementations, -power levels can optionally be represented in string format instead of -integer format. A homeserver must be prepared to deal with this by parsing -the power level from a string. In these cases, the following formatting of the -power level string is allowed: - -- a single Base10 integer, no float values or decimal points, optionally with leading zeroes; -- optionally with leading or trailing whitespace characters; -- optionally prefixed with a single `-` or `+` character before the integer but after leading whitespace padding. - {{% boxes/warning %}} -This behaviour is preserved strictly for backward compatibility only. A -homeserver should take reasonable precautions to prevent users from -sending new power level events with string values and must never -populate the default power levels in a room as string values. +Some [room versions](/rooms) accept power level values to be represented as +strings rather than integers. This is strictly for backwards compatibility. +A homeserver should take reasonable precautions to prevent users from sending +new power level events with string values (eg: by rejecting the API request), +and must never populate the default power levels in a room as string values. + +See the [room version specification](/rooms) for more information. {{% /boxes/warning %}} #### Authorization rules From b2fa4e59895a186b8d092b17c837a13cef51293f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 13:53:26 -0600 Subject: [PATCH 07/23] Describe range --- content/rooms/fragments/v1-stringy-power-levels.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/rooms/fragments/v1-stringy-power-levels.md b/content/rooms/fragments/v1-stringy-power-levels.md index abfd5dc9b..57b5ff1f6 100644 --- a/content/rooms/fragments/v1-stringy-power-levels.md +++ b/content/rooms/fragments/v1-stringy-power-levels.md @@ -13,3 +13,8 @@ power level string is allowed: * optionally prefixed with a single `-` or `+` character before the integer but after leading whitespace padding (`" +100 "`, `" -100 "`, `"+100"`, `"-100"`). + +{{% boxes/note %}} +The integer represented by the string must still be within the `[-2^53, 2^53)` +range accepted by normal, non-string, power level values. +{{% /boxes/note %}} From be12f1e2e6a53b9c34cd5cdf4619f2569f0e20ac Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:15:25 -0600 Subject: [PATCH 08/23] Fix minor issues with previous room version stuff --- content/rooms/fragments/v1-deprecated-formatting-off-spec.md | 4 ++++ content/rooms/fragments/v1-stringy-power-levels.md | 4 ++++ content/rooms/v7.md | 2 +- content/rooms/v8.md | 2 +- content/rooms/v9.md | 2 +- 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/content/rooms/fragments/v1-deprecated-formatting-off-spec.md b/content/rooms/fragments/v1-deprecated-formatting-off-spec.md index 2c5cb4779..1cf7d49fa 100644 --- a/content/rooms/fragments/v1-deprecated-formatting-off-spec.md +++ b/content/rooms/fragments/v1-deprecated-formatting-off-spec.md @@ -1,3 +1,7 @@ +--- +toc_hide: true +--- + Events sent into rooms of this version can have formats which are different from their normal schema. Those cases are documented here. diff --git a/content/rooms/fragments/v1-stringy-power-levels.md b/content/rooms/fragments/v1-stringy-power-levels.md index 57b5ff1f6..f07aa2ea3 100644 --- a/content/rooms/fragments/v1-stringy-power-levels.md +++ b/content/rooms/fragments/v1-stringy-power-levels.md @@ -1,3 +1,7 @@ +--- +toc_hide: true +--- + ##### Power levels accepted as strings In order to maintain backwards compatibility with early implementations, diff --git a/content/rooms/v7.md b/content/rooms/v7.md index c22b4dcf4..6656b911b 100644 --- a/content/rooms/v7.md +++ b/content/rooms/v7.md @@ -1,7 +1,7 @@ --- title: Room Version 7 type: docs -weight: 60 +weight: 70 --- This room version builds on [version 6](/rooms/v6) to introduce knocking diff --git a/content/rooms/v8.md b/content/rooms/v8.md index 060142b46..32523aa1e 100644 --- a/content/rooms/v8.md +++ b/content/rooms/v8.md @@ -1,7 +1,7 @@ --- title: Room Version 8 type: docs -weight: 60 +weight: 80 --- This room version builds on [version 7](/rooms/v7) to introduce a new diff --git a/content/rooms/v9.md b/content/rooms/v9.md index c32fc2765..95ea83f8f 100644 --- a/content/rooms/v9.md +++ b/content/rooms/v9.md @@ -1,7 +1,7 @@ --- title: Room Version 9 type: docs -weight: 60 +weight: 90 --- This room version builds on [version 8](/rooms/v8) to add additional redaction From 16e7383ddb4175101644e9deed19eed20587b79b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:15:34 -0600 Subject: [PATCH 09/23] Copy/paste v9 into v10 --- content/rooms/_index.md | 11 +-- content/rooms/fragments/v9-redactions.md | 53 ++++++++++++++ content/rooms/v10.md | 90 ++++++++++++++++++++++++ content/rooms/v9.md | 50 +------------ 4 files changed, 151 insertions(+), 53 deletions(-) create mode 100644 content/rooms/fragments/v9-redactions.md create mode 100644 content/rooms/v10.md diff --git a/content/rooms/_index.md b/content/rooms/_index.md index f946cb611..ac93e69e0 100644 --- a/content/rooms/_index.md +++ b/content/rooms/_index.md @@ -36,10 +36,11 @@ Alternatively, consider flipping the column/row organization to be features up top and versions on the left. --> -| Feature \ Version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -|-------------------|---|---|---|---|---|---|---|---|---| -| **Knocking** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | -| **Restricted join rules** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | +| Feature \ Version | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | +|-------------------|---|---|---|---|---|---|---|---|---|----| +| **Knocking** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | +| **Restricted join rules** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ✔ | ✔ | +| **`knock_restricted` join rule** | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔ | ## Complete list of room versions @@ -73,6 +74,8 @@ The available room versions are: of another room to join without invite. - [Version 9](/rooms/v9) - **Stable**. Builds on v8 to fix issues when redacting some membership events. +- [Version 10](/rooms/v10) - **Stable**. Enforces integer-only power levels + and adds `knock_restricted` join rule. ## Room version grammar diff --git a/content/rooms/fragments/v9-redactions.md b/content/rooms/fragments/v9-redactions.md new file mode 100644 index 000000000..ad45d78aa --- /dev/null +++ b/content/rooms/fragments/v9-redactions.md @@ -0,0 +1,53 @@ +--- +toc_hide: true +--- + +{{% added-in this=true %}} `m.room.member` now keep `join_authorised_via_users_server` +in addition to other keys in `content` when being redacted. + +{{% boxes/rationale %}} +Without the `join_authorised_via_users_server` property, redacted join events +can become invalid when verifying the auth chain of a given event, thus creating +a split-brain scenario where the user is able to speak from one server's +perspective but most others will continually reject their events. + +This can theoretically be worked around with a rejoin to the room, being careful +not to use the faulty events as `prev_events`, though instead it is encouraged +to use v9 rooms over v8 rooms to outright avoid the situation. + +[Issue #3373](https://github.com/matrix-org/matrix-doc/issues/3373) has further +information. +{{% /boxes/rationale %}} + +The full redaction algorithm follows. + +{{% rver-fragment name="v3-handling-redactions" %}} + +Upon receipt of a redaction event, the server must strip off any keys +not in the following list: + +- `event_id` +- `type` +- `room_id` +- `sender` +- `state_key` +- `content` +- `hashes` +- `signatures` +- `depth` +- `prev_events` +- `prev_state` +- `auth_events` +- `origin` +- `origin_server_ts` +- `membership` + +The content object must also be stripped of all keys, unless it is one +of one of the following event types: + +- `m.room.member` allows keys `membership`, `join_authorised_via_users_server`. +- `m.room.create` allows key `creator`. +- `m.room.join_rules` allows keys `join_rule`, `allow`. +- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, + `kick`, `redact`, `state_default`, `users`, `users_default`. +- `m.room.history_visibility` allows key `history_visibility`. \ No newline at end of file diff --git a/content/rooms/v10.md b/content/rooms/v10.md new file mode 100644 index 000000000..2fafe7248 --- /dev/null +++ b/content/rooms/v10.md @@ -0,0 +1,90 @@ +--- +title: Room Version 10 +type: docs +weight: 100 +--- + +This room version builds on [version 9](/rooms/v9) to enforce that power level +values be integers, and to introduce a new `knock_restricted` join rule, allowing +prospective members to more easily join such a room. + +## Client considerations + +This room version adds a new `knock_restricted` join rule to allow prospective +members of a room join either through knocking (introduced in [room version 7](/rooms/v7)) +or through "join restrictions" (introduced in [room version 8](/rooms/v8) and +refined in [room version 9](/rooms/v9)). + +Clients should render the new join rule accordingly for such rooms. + +Clients which implement the redaction algorithm locally should refer to the +[redactions](#redactions) section below for a full overview. + +## Server implementation components + +{{% boxes/warning %}} +The information contained in this section is strictly for server +implementors. Applications which use the Client-Server API are generally +unaffected by the intricacies contained here. The section above +regarding client considerations is the resource that Client-Server API +use cases should reference. +{{% /boxes/warning %}} + +[Room version 7](/rooms/v7) added "knocking" and [room version 8](/rooms/v8) +added "join restrictions" (refined by [room version 9](/rooms/v9)) - both allow +prospective members an avenue to join, however both could not be used at the +same time due to how the join rules work. This room version adds a new +`knock_restricted` join rule as a mix of the two behaviours (first match wins). + +This room version additionally requires that values in the power levels event +be integers and not string representations, unlike other room versions. + +Room version 10 is based upon room version 9 with the following considerations. + +### TODO + +* Auth rules +* Stringy power levels + +## Unchanged from v9 + +The following sections have not been modified since v9, but are included for +completeness. + +### Redactions + +{{% rver-fragment name="v9-redactions" %}} + +### Handling redactions + +{{% rver-fragment name="v3-handling-redactions" %}} + +### Event IDs + +{{% rver-fragment name="v4-event-ids" %}} + +### Event format + +{{% rver-fragment name="v4-event-format" %}} + +#### Deprecated formatting + +{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} + +{{% rver-fragment name="v1-stringy-power-levels" %}} + +### Authorization rules + +{{% rver-fragment name="v8-auth-rules" %}} + +### State resolution + +{{% rver-fragment name="v2-state-res" %}} + +### Canonical JSON + +{{% rver-fragment name="v6-canonical-json" %}} + +### Signing key validity period + +{{% rver-fragment name="v5-signing-requirements" %}} diff --git a/content/rooms/v9.md b/content/rooms/v9.md index 95ea83f8f..96851e73e 100644 --- a/content/rooms/v9.md +++ b/content/rooms/v9.md @@ -17,55 +17,7 @@ Clients which implement the redaction algorithm locally should refer to the ### Redactions -{{% added-in this=true %}} `m.room.member` now keep `join_authorised_via_users_server` -in addition to other keys in `content` when being redacted. - -{{% boxes/rationale %}} -Without the `join_authorised_via_users_server` property, redacted join events -can become invalid when verifying the auth chain of a given event, thus creating -a split-brain scenario where the user is able to speak from one server's -perspective but most others will continually reject their events. - -This can theoretically be worked around with a rejoin to the room, being careful -not to use the faulty events as `prev_events`, though instead it is encouraged -to use v9 rooms over v8 rooms to outright avoid the situation. - -[Issue #3373](https://github.com/matrix-org/matrix-doc/issues/3373) has further -information. -{{% /boxes/rationale %}} - -The full redaction algorithm follows. - -{{% rver-fragment name="v3-handling-redactions" %}} - -Upon receipt of a redaction event, the server must strip off any keys -not in the following list: - -- `event_id` -- `type` -- `room_id` -- `sender` -- `state_key` -- `content` -- `hashes` -- `signatures` -- `depth` -- `prev_events` -- `prev_state` -- `auth_events` -- `origin` -- `origin_server_ts` -- `membership` - -The content object must also be stripped of all keys, unless it is one -of one of the following event types: - -- `m.room.member` allows keys `membership`, `join_authorised_via_users_server`. -- `m.room.create` allows key `creator`. -- `m.room.join_rules` allows keys `join_rule`, `allow`. -- `m.room.power_levels` allows keys `ban`, `events`, `events_default`, - `kick`, `redact`, `state_default`, `users`, `users_default`. -- `m.room.history_visibility` allows key `history_visibility`. +{{% rver-fragment name="v9-redactions" %}} ## Server implementation components From 3d500196e89ca365e2ff801057c5d93d5c9b7446 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:36:33 -0600 Subject: [PATCH 10/23] Describe deprecated formatting --- content/rooms/v10.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/content/rooms/v10.md b/content/rooms/v10.md index 2fafe7248..b302c6498 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -41,10 +41,24 @@ be integers and not string representations, unlike other room versions. Room version 10 is based upon room version 9 with the following considerations. -### TODO +### Event format + +The event format is unchanged by this room version. See [below](#event-format-1) +for details on the current event format. + +#### Deprecated formatting + +While this room version does not change the event format specifically, some +deprecated behaviours are strictly no longer supported. + +##### Power levels must be integers -* Auth rules -* Stringy power levels +In other room versions, such as [v9](/rooms/v9/#power-levels-accepted-as-strings), +power levels could be represented as strings for backwards compatibility. + +This backwards compatibility is removed in this room version - power levels MUST NOT +be represented as strings within this room version. Power levels which are not +correctly structured are rejected under the authorization rules below. ## Unchanged from v9 @@ -67,12 +81,6 @@ completeness. {{% rver-fragment name="v4-event-format" %}} -#### Deprecated formatting - -{{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} - -{{% rver-fragment name="v1-stringy-power-levels" %}} - ### Authorization rules {{% rver-fragment name="v8-auth-rules" %}} From 1f3dc21432d68826ea59d44b4ee85dc673ca950c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:37:13 -0600 Subject: [PATCH 11/23] Paste unmodified auth rules from v8 into v10 --- content/rooms/v10.md | 165 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 161 insertions(+), 4 deletions(-) diff --git a/content/rooms/v10.md b/content/rooms/v10.md index b302c6498..d3c387a58 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -60,6 +60,167 @@ This backwards compatibility is removed in this room version - power levels MUST be represented as strings within this room version. Power levels which are not correctly structured are rejected under the authorization rules below. +### Authorization rules + +Events must be signed by the server denoted by the `sender` key. + +`m.room.redaction` events are not explicitly part of the auth rules. +They are still subject to the minimum power level rules, but should always +fall into "10. Otherwise, allow". Instead of being authorized at the time +of receipt, they are authorized at a later stage: see the +[Redactions](#redactions) section below for more information. + +The types of state events that affect authorization are: + +- [`m.room.create`](/client-server-api#mroomcreate) +- [`m.room.member`](/client-server-api#mroommember) +- [`m.room.join_rules`](/client-server-api#mroom) +- [`m.room.power_levels`](/client-server-api#mroompower_levels) +- [`m.room.third_party_invite`](/client-server-api#mroomthird_party_invite) + +{{% boxes/note %}} +Power levels are inferred from defaults when not explicitly supplied. +For example, mentions of the `sender`'s power level can also refer to +the default power level for users in the room. +{{% /boxes/note %}} + +The rules are as follows: + +1. If type is `m.room.create`: + 1. If it has any previous events, reject. + 2. If the domain of the `room_id` does not match the domain of the + `sender`, reject. + 3. If `content.room_version` is present and is not a recognised + version, reject. + 4. If `content` has no `creator` field, reject. + 5. Otherwise, allow. +2. Reject if event has `auth_events` that: + 1. have duplicate entries for a given `type` and `state_key` pair + 2. have entries whose `type` and `state_key` don't match those + specified by the [auth events + selection](/server-server-api#auth-events-selection) + algorithm described in the server specification. +3. If event does not have a `m.room.create` in its `auth_events`, + reject. +4. If type is `m.room.member`: + 1. If no `state_key` key or `membership` key in `content`, reject. + 2. If `content` has a `join_authorised_via_users_server` + key: + 1. If the event is not validly signed by the homeserver of the user ID denoted + by the key, reject. + 3. If `membership` is `join`: + 1. If the only previous event is an `m.room.create` and the + `state_key` is the creator, allow. + 2. If the `sender` does not match `state_key`, reject. + 3. If the `sender` is banned, reject. + 4. If the `join_rule` is `invite` or `knock` then allow if + membership state is `invite` or `join`. + 5. If the `join_rule` is `restricted`: + 1. If membership state is `join` or `invite`, allow. + 2. If the `join_authorised_via_users_server` key in `content` + is not a user with sufficient permission to invite other + users, reject. + 3. Otherwise, allow. + 6. If the `join_rule` is `public`, allow. + 7. Otherwise, reject. + 4. If `membership` is `invite`: + 1. If `content` has `third_party_invite` key: + 1. If *target user* is banned, reject. + 2. If `content.third_party_invite` does not have a `signed` + key, reject. + 3. If `signed` does not have `mxid` and `token` keys, + reject. + 4. If `mxid` does not match `state_key`, reject. + 5. If there is no `m.room.third_party_invite` event in the + current room state with `state_key` matching `token`, + reject. + 6. If `sender` does not match `sender` of the + `m.room.third_party_invite`, reject. + 7. If any signature in `signed` matches any public key in + the `m.room.third_party_invite` event, allow. The public + keys are in `content` of `m.room.third_party_invite` as: + 1. A single public key in the `public_key` field. + 2. A list of public keys in the `public_keys` field. + 8. Otherwise, reject. + 2. If the `sender`'s current membership state is not `join`, + reject. + 3. If *target user*'s current membership state is `join` or + `ban`, reject. + 4. If the `sender`'s power level is greater than or equal to + the *invite level*, allow. + 5. Otherwise, reject. + 5. If `membership` is `leave`: + 1. If the `sender` matches `state_key`, allow if and only if + that user's current membership state is `invite`, `join`, + or `knock`. + 2. If the `sender`'s current membership state is not `join`, + reject. + 3. If the *target user*'s current membership state is `ban`, + and the `sender`'s power level is less than the *ban level*, + reject. + 4. If the `sender`'s power level is greater than or equal to + the *kick level*, and the *target user*'s power level is + less than the `sender`'s power level, allow. + 5. Otherwise, reject. + 6. If `membership` is `ban`: + 1. If the `sender`'s current membership state is not `join`, + reject. + 2. If the `sender`'s power level is greater than or equal to + the *ban level*, and the *target user*'s power level is less + than the `sender`'s power level, allow. + 3. Otherwise, reject. + 7. If `membership` is `knock`: + 1. If the `join_rule` is anything other than `knock`, reject. + 2. If `sender` does not match `state_key`, reject. + 3. If the `sender`'s current membership is not `ban`, `invite`, + or `join`, allow. + 4. Otherwise, reject. + 8. Otherwise, the membership is unknown. Reject. +5. If the `sender`'s current membership state is not `join`, reject. +6. If type is `m.room.third_party_invite`: + 1. Allow if and only if `sender`'s current power level is greater + than or equal to the *invite level*. +7. If the event type's *required power level* is greater than the + `sender`'s power level, reject. +8. If the event has a `state_key` that starts with an `@` and does not + match the `sender`, reject. +9. If type is `m.room.power_levels`: + 1. If `users` key in `content` is not a dictionary with keys that + are valid user IDs with values that are integers (or a string + that is an integer), reject. + 2. If there is no previous `m.room.power_levels` event in the room, + allow. + 3. For the keys `users_default`, `events_default`, `state_default`, + `ban`, `redact`, `kick`, `invite` check if they were added, + changed or removed. For each found alteration: + 1. If the current value is higher than the `sender`'s current + power level, reject. + 2. If the new value is higher than the `sender`'s current power + level, reject. + 4. For each entry being added, changed or removed in both the + `events`, `users`, and `notifications` keys: + 1. If the current value is higher than the `sender`'s current + power level, reject. + 2. If the new value is higher than the `sender`'s current power + level, reject. + 5. For each entry being changed under the `users` key, other than + the `sender`'s own entry: + 1. If the current value is equal to the `sender`'s current + power level, reject. + 6. Otherwise, allow. +10. Otherwise, allow. + +{{% boxes/note %}} +Some consequences of these rules: + +- Unless you are a member of the room, the only permitted operations + (apart from the initial create/join) are: joining a public room; + accepting or rejecting an invitation to a room. +- To unban somebody, you must have power level greater than or equal + to both the kick *and* ban levels, *and* greater than the target + user's power level. +{{% /boxes/note %}} + ## Unchanged from v9 The following sections have not been modified since v9, but are included for @@ -81,10 +242,6 @@ completeness. {{% rver-fragment name="v4-event-format" %}} -### Authorization rules - -{{% rver-fragment name="v8-auth-rules" %}} - ### State resolution {{% rver-fragment name="v2-state-res" %}} From 017461823b43ec2df43bdaa07515e1342deb6b15 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:38:16 -0600 Subject: [PATCH 12/23] Move 9.1 to 9.3, add 9.1 and 9.2 for integer enforcement --- content/rooms/v10.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/content/rooms/v10.md b/content/rooms/v10.md index d3c387a58..2cc2bc443 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -185,9 +185,16 @@ The rules are as follows: 8. If the event has a `state_key` that starts with an `@` and does not match the `sender`, reject. 9. If type is `m.room.power_levels`: - 1. If `users` key in `content` is not a dictionary with keys that - are valid user IDs with values that are integers (or a string - that is an integer), reject. + 1. {{< added-in this="true" >}} + If any of the keys `users_default`, `events_default`, `state_default`, + `ban`, `redact`, `kick`, or `invite` in `content` are present and + not an integer, reject. + 2. {{< added-in this="true" >}} + If any of the keys `users`, `events`, or `notifications` in `content` + are present and not a dictionary with string keys and values that + are integers, reject. + 3. If `users` key in `content` is not a dictionary with keys that + are valid user IDs with values that are integers, reject. 2. If there is no previous `m.room.power_levels` event in the room, allow. 3. For the keys `users_default`, `events_default`, `state_default`, From 0eec78d8d6cf420d5094ba48f1042e00cc02c893 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:43:44 -0600 Subject: [PATCH 13/23] Add knock_restricted to v10 auth --- content/rooms/v10.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/content/rooms/v10.md b/content/rooms/v10.md index 2cc2bc443..7569ab8e3 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -15,7 +15,17 @@ members of a room join either through knocking (introduced in [room version 7](/ or through "join restrictions" (introduced in [room version 8](/rooms/v8) and refined in [room version 9](/rooms/v9)). -Clients should render the new join rule accordingly for such rooms. +Clients should render the new join rule accordingly for such rooms. For example: + +``` +This room is: +[ ] Public +[x] Private + +Join rules (disabled when Public): +[x] Allow members of `#space:example.org` to join +[x] Allow knocking +``` Clients which implement the redaction algorithm locally should refer to the [redactions](#redactions) section below for a full overview. @@ -115,7 +125,8 @@ The rules are as follows: 3. If the `sender` is banned, reject. 4. If the `join_rule` is `invite` or `knock` then allow if membership state is `invite` or `join`. - 5. If the `join_rule` is `restricted`: + 5. {{< changed-in this="true" >}} + If the `join_rule` is `restricted` or `knock_restricted`: 1. If membership state is `join` or `invite`, allow. 2. If the `join_authorised_via_users_server` key in `content` is not a user with sufficient permission to invite other @@ -170,7 +181,9 @@ The rules are as follows: than the `sender`'s power level, allow. 3. Otherwise, reject. 7. If `membership` is `knock`: - 1. If the `join_rule` is anything other than `knock`, reject. + 1. {{< changed-in this="true" >}} + If the `join_rule` is anything other than `knock` or + `knock_restricted`, reject. 2. If `sender` does not match `state_key`, reject. 3. If the `sender`'s current membership is not `ban`, `invite`, or `join`, allow. From 41ed640130ee0119b8fa2c1d3b3e404f9cfa0123 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:45:33 -0600 Subject: [PATCH 14/23] Misc cleanup and clarification for fragments --- content/rooms/fragments/v9-redactions.md | 3 --- content/rooms/v10.md | 4 +++- content/rooms/v9.md | 3 +++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/content/rooms/fragments/v9-redactions.md b/content/rooms/fragments/v9-redactions.md index ad45d78aa..936a56d85 100644 --- a/content/rooms/fragments/v9-redactions.md +++ b/content/rooms/fragments/v9-redactions.md @@ -2,9 +2,6 @@ toc_hide: true --- -{{% added-in this=true %}} `m.room.member` now keep `join_authorised_via_users_server` -in addition to other keys in `content` when being redacted. - {{% boxes/rationale %}} Without the `join_authorised_via_users_server` property, redacted join events can become invalid when verifying the auth chain of a given event, thus creating diff --git a/content/rooms/v10.md b/content/rooms/v10.md index 7569ab8e3..7d5ced052 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -44,7 +44,9 @@ use cases should reference. added "join restrictions" (refined by [room version 9](/rooms/v9)) - both allow prospective members an avenue to join, however both could not be used at the same time due to how the join rules work. This room version adds a new -`knock_restricted` join rule as a mix of the two behaviours (first match wins). +`knock_restricted` join rule as a mix of the two behaviours, allowing a user to +join the room if they meet either the `restricted` join rule criteria or the +`knock` join rule criteria - whichever function they're attempting to use. This room version additionally requires that values in the power levels event be integers and not string representations, unlike other room versions. diff --git a/content/rooms/v9.md b/content/rooms/v9.md index 96851e73e..23fe729b6 100644 --- a/content/rooms/v9.md +++ b/content/rooms/v9.md @@ -17,6 +17,9 @@ Clients which implement the redaction algorithm locally should refer to the ### Redactions +{{% added-in this=true %}} `m.room.member` now keep `join_authorised_via_users_server` +in addition to other keys in `content` when being redacted. + {{% rver-fragment name="v9-redactions" %}} ## Server implementation components From 5e3175a094b85efed0b71153bb22f89c309de0ec Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 30 May 2022 14:54:09 -0600 Subject: [PATCH 15/23] Describe `knock_restricted` client changes --- content/client-server-api/_index.md | 25 +++++++++++++++++++ .../schema/m.room.join_rules.yaml | 4 +++ 2 files changed, 29 insertions(+) diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index da19a7de5..63a58babf 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -1969,6 +1969,13 @@ room listed in the join rules. If the server cannot verify membership for any of the listed rooms then you can only join with an invite. Note that this rule is only expected to work in room versions [which support it](/rooms/#feature-matrix). +{{% added-in v="1.3" %}} `knock_restricted` +This room can be joined as though it was `restricted` *or* `knock`. If you +interact with the room using knocking, the `knock` rule takes effect whereas +trying to join the room without an invite applies the `restricted` join rule. +Note that this rule is only expected to work in room versions +[which support it](/rooms/#feature-matrix). + The allowable state transitions of membership are: ![membership-flow-diagram](/diagrams/membership.png) @@ -1984,6 +1991,15 @@ The allowable state transitions of membership are: ##### Knocking on rooms {{% added-in v="1.1" %}} +{{% changed-in v="1.3" %}} + +{{% boxes/note %}} +As of `v1.3`, it is possible to knock on a [restricted room](#restricted-rooms) +if the room supports and is using the `knock_restricted` join rule. + +Note that `knock_restricted` is only expected to work in room versions +[which support it](/rooms/#feature-matrix). +{{% /boxes/note %}}