diff --git a/changelogs/client_server/newsfragments/1099.feature b/changelogs/client_server/newsfragments/1099.feature new file mode 100644 index 000000000..632a1c463 --- /dev/null +++ b/changelogs/client_server/newsfragments/1099.feature @@ -0,0 +1 @@ +Add support for a new `knock_restricted` join rule in supported room versions, as per [MSC3787](https://github.com/matrix-org/matrix-spec-proposals/pull/3787). \ No newline at end of file diff --git a/changelogs/room_versions/newsfragments/1099.clarification b/changelogs/room_versions/newsfragments/1099.clarification new file mode 100644 index 000000000..272aec3e0 --- /dev/null +++ b/changelogs/room_versions/newsfragments/1099.clarification @@ -0,0 +1 @@ +Clarify that room versions 1 through 9 accept stringy power levels, as noted by [MSC3667](https://github.com/matrix-org/matrix-spec-proposals/pull/3667). \ No newline at end of file diff --git a/changelogs/room_versions/newsfragments/1099.feature.1 b/changelogs/room_versions/newsfragments/1099.feature.1 new file mode 100644 index 000000000..d8fabdba7 --- /dev/null +++ b/changelogs/room_versions/newsfragments/1099.feature.1 @@ -0,0 +1 @@ +Add room version 10 as per [MSC3604](https://github.com/matrix-org/matrix-spec-proposals/pull/3604). \ No newline at end of file diff --git a/changelogs/room_versions/newsfragments/1099.feature.2 b/changelogs/room_versions/newsfragments/1099.feature.2 new file mode 100644 index 000000000..b89704b8c --- /dev/null +++ b/changelogs/room_versions/newsfragments/1099.feature.2 @@ -0,0 +1 @@ +Enforce integer power levels in room version 10 as per [MSC3667](https://github.com/matrix-org/matrix-spec-proposals/pull/3667). \ No newline at end of file diff --git a/changelogs/room_versions/newsfragments/1099.feature.3 b/changelogs/room_versions/newsfragments/1099.feature.3 new file mode 100644 index 000000000..b10228de7 --- /dev/null +++ b/changelogs/room_versions/newsfragments/1099.feature.3 @@ -0,0 +1 @@ +Add a `knock_restricted` join rule supported by room version 10 as per [MSC3787](https://github.com/matrix-org/matrix-spec-proposals/pull/3787). \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/1099.clarification b/changelogs/server_server/newsfragments/1099.clarification new file mode 100644 index 000000000..76ce98497 --- /dev/null +++ b/changelogs/server_server/newsfragments/1099.clarification @@ -0,0 +1 @@ +Clarify the historical handling of non-integer power levels. \ No newline at end of file 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 %}} -| 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/v1-deprecated-formatting-off-spec.md b/content/rooms/fragments/v1-deprecated-formatting-off-spec.md new file mode 100644 index 000000000..1cf7d49fa --- /dev/null +++ b/content/rooms/fragments/v1-deprecated-formatting-off-spec.md @@ -0,0 +1,13 @@ +--- +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. + +{{% 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..054c05069 --- /dev/null +++ b/content/rooms/fragments/v1-stringy-power-levels.md @@ -0,0 +1,43 @@ +--- +toc_hide: true +--- + +##### `m.room.power_levels` events accept values as strings + +In order to maintain backwards compatibility with early implementations, +each of the integer-valued properties within +[`m.room.power_levels`](/client-server-api#mroompower_levels) events can +be encoded as strings instead of integers. This includes the nested values +within the `events`, `notifications` and `users` properties. +For example, the following is a valid `m.room.power_levels` event in this room version: + +```json +{ + "content": { + "ban": "50", + "events": { + "m.room.power_levels": "100" + }, + "events_default": "0", + "state_default": "50", + "users": { + "@example:localhost": "100" + }, + "users_default": "0" + }, + "origin_server_ts": 1432735824653, + "room_id": "!jEsUZKDJdhlrceRyVU:example.org", + "sender": "@example:example.org", + "state_key": "", + "type": "m.room.power_levels" +} +``` + +When the value is representative of an integer, they must be the following format: + +* a single base 10 integer, no float values or decimal points, optionally with + any number of leading zeroes (`"100"`, `"000100"`); +* optionally prefixed with a single `-` or `+` character before the integer (`"+100"`, + `"-100"`). +* optionally with any number of leading or trailing whitespace characters (`" 100 "`, + `" 00100 "`, `" +100 "`, `" -100 "`); diff --git a/content/rooms/fragments/v9-redactions.md b/content/rooms/fragments/v9-redactions.md new file mode 100644 index 000000000..3247c59f8 --- /dev/null +++ b/content/rooms/fragments/v9-redactions.md @@ -0,0 +1,51 @@ +--- +toc_hide: true +--- + +{{% added-in this=true %}} `m.room.member` events 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. + +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/v1.md b/content/rooms/v1.md index a69e3d5d0..3d3e97383 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 event content schemas + +{{% 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/v10.md b/content/rooms/v10.md new file mode 100644 index 000000000..63a2e5297 --- /dev/null +++ b/content/rooms/v10.md @@ -0,0 +1,277 @@ +--- +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. 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. + +## 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 it was not possible to use +the two mechanisms together. This room version adds a new +`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. + +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. + +### Event format + +The event format is unchanged by this room version. See [below](#event-format-1) +for details on the current event format. + +#### Deprecated event content schemas + +While this room version does not change the event format specifically, some +deprecated behaviours are strictly no longer supported. + +##### Values in `m.room.power_levels` events must be integers + +In other room versions, such as [v9](/rooms/v9/#mroompower_levels-events-accept-values-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. + +### 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. {{< 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 + 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. {{< 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. + 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. {{< 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 either of the keys `events` or `notifications` in `content` + are present and not a dictionary with 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`, + `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 +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" %}} + +### 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/v2.md b/content/rooms/v2.md index cdc59190f..274e0ea09 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 event content schemas + +{{% 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..8dd261e8c 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 event content schemas + +{{% 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..c329f3420 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 event content schemas + +{{% 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..25147e9e5 100644 --- a/content/rooms/v5.md +++ b/content/rooms/v5.md @@ -51,6 +51,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated event content schemas + +{{% 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..0e2e70dc6 100644 --- a/content/rooms/v6.md +++ b/content/rooms/v6.md @@ -212,6 +212,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated event content schemas + +{{% 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..5960c1980 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 @@ -205,6 +205,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated event content schemas + +{{% 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..2a8cf1255 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 @@ -110,6 +110,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated event content schemas + +{{% 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..d4da72de8 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 @@ -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" withVersioning="true" %}} ## Server implementation components @@ -102,6 +54,12 @@ completeness. {{% rver-fragment name="v4-event-format" %}} +#### Deprecated event content schemas + +{{% 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 f70e89942..12d4bc45a 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -432,6 +432,16 @@ unspecified. For an `m.room.member` state event, the user given by the `state_key` of the event. +{{% boxes/warning %}} +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 The rules governing whether an event is authorized depends on a set of diff --git a/data/event-schemas/schema/m.room.join_rules.yaml b/data/event-schemas/schema/m.room.join_rules.yaml index dbac60d56..d5f8eb2de 100644 --- a/data/event-schemas/schema/m.room.join_rules.yaml +++ b/data/event-schemas/schema/m.room.join_rules.yaml @@ -12,6 +12,10 @@ description: | * `restricted` - anyone able to satisfy at least one of the allow conditions is able to join the room without prior action. Otherwise, an invite is required. Only available in rooms [which support the join rule](/rooms/#feature-matrix). + * `knock_restricted` - a user can request an invite using the same functions offered + by the `knock` join rule, or can attempt to join having satisfied an allow condition + per the `restricted` join rule. Only available in rooms + [which support the join rule](/rooms/#feature-matrix). * `private` - reserved without implementation. No significant meaning. properties: content: