From cb83c5a76ee3317903039c78f3047f1f4760b159 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 14 Feb 2025 07:06:21 -0500 Subject: [PATCH 01/67] Clarify which rooms are returned from /hierarchy (#2064) Signed-off-by: Patrick Cloke Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- .../client_server/newsfragments/2064.clarification | 1 + data/api/client-server/space_hierarchy.yaml | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2064.clarification diff --git a/changelogs/client_server/newsfragments/2064.clarification b/changelogs/client_server/newsfragments/2064.clarification new file mode 100644 index 00000000..17cc2890 --- /dev/null +++ b/changelogs/client_server/newsfragments/2064.clarification @@ -0,0 +1 @@ +Clarify which rooms are returned from `/hierarchy`. diff --git a/data/api/client-server/space_hierarchy.yaml b/data/api/client-server/space_hierarchy.yaml index 6329495c..3a4a14a5 100644 --- a/data/api/client-server/space_hierarchy.yaml +++ b/data/api/client-server/space_hierarchy.yaml @@ -88,7 +88,18 @@ paths: properties: rooms: type: array - description: The rooms for the current page, with the current filters. + description: |- + The rooms for the current page, with the current filters. + + The server should return any rooms where at least one of the following conditions is true: + + * The requesting user is currently a member (their [room membership](#room-membership) is `join`). + * The requesting user already has permission to join, i.e. one of the following: + * The user's room membership is `invite`. + * The room's [join rules](#mroomjoin_rules) are set to `public`. + * The room's join rules are set to [`restricted`](#restricted-rooms), provided the user meets one of the specified conditions. + * The room is "knockable" (the room's join rules are set to `knock`, or `knock_restricted`, in a room version that supports those settings). + * The room's [`m.room.history_visibility`](#room-history-visibility) is set to `world_readable`. items: allOf: - $ref: definitions/public_rooms_chunk.yaml From eedecf863a100986ff1833d100538b88bba330ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 25 Feb 2025 21:34:23 +0100 Subject: [PATCH 02/67] Clarify that join rules must be in auth events for knock events (#2063) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- changelogs/server_server/newsfragments/2063.clarification | 1 + content/server-server-api.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/server_server/newsfragments/2063.clarification diff --git a/changelogs/server_server/newsfragments/2063.clarification b/changelogs/server_server/newsfragments/2063.clarification new file mode 100644 index 00000000..4e3df516 --- /dev/null +++ b/changelogs/server_server/newsfragments/2063.clarification @@ -0,0 +1 @@ +Clarify that `m.join_rules` should be in the `auth_events` of an `m.room.member` event with a `membership` of `knock`. \ No newline at end of file diff --git a/content/server-server-api.md b/content/server-server-api.md index 8e99c431..65494f80 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -537,7 +537,7 @@ 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 + - If `membership` is `join`, `invite` or `knock`, the current `m.room.join_rules` event, if any. - If membership is `invite` and `content` contains a `third_party_invite` property, the current From 10587366e9eb831f36aadc8911a661a46a7895d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 25 Feb 2025 22:00:32 +0100 Subject: [PATCH 03/67] =?UTF-8?q?For=20room=20versions=206=20and=207,=20cl?= =?UTF-8?q?arify=20that=20events=20with=20rejected=20auth=20eve=E2=80=A6?= =?UTF-8?q?=20(#2065)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other room versions were updated in #1103 and #1137, but not these ones. Signed-off-by: Kévin Commaille --- .../newsfragments/2065.clarification | 1 + content/rooms/v6.md | 18 ++++++++++++------ content/rooms/v7.md | 18 ++++++++++++------ 3 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 changelogs/room_versions/newsfragments/2065.clarification diff --git a/changelogs/room_versions/newsfragments/2065.clarification b/changelogs/room_versions/newsfragments/2065.clarification new file mode 100644 index 00000000..e7fc9f20 --- /dev/null +++ b/changelogs/room_versions/newsfragments/2065.clarification @@ -0,0 +1 @@ +For room versions 6 and 7, clarify in the authorization rules that `m.federate` must be checked and that events with rejected auth events must be rejected, for parity with all the other room versions. diff --git a/content/rooms/v6.md b/content/rooms/v6.md index b2a5f024..72007d97 100644 --- a/content/rooms/v6.md +++ b/content/rooms/v6.md @@ -88,14 +88,20 @@ The rules are as follows: version, reject. 4. If `content` has no `creator` property, 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 +2. Considering the event's `auth_events`: + 1. If there are duplicate entries for a given `type` and `state_key` pair, + reject. + 2. If there are 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. + algorithm described in the server specification, reject. + 3. If there are entries which were themselves rejected under the [checks + performed on receipt of a + PDU](/server-server-api/#checks-performed-on-receipt-of-a-pdu), reject. + 4. If there is no `m.room.create` event among the entries, reject. +3. If the `content` of the `m.room.create` event in the room state has the + property `m.federate` set to `false`, and the `sender` domain of the event + does not match the `sender` domain of the create event, reject. 4. If type is `m.room.member`: 1. If there is no `state_key` property, or no `membership` property in `content`, reject. diff --git a/content/rooms/v7.md b/content/rooms/v7.md index 216646d3..ba711c55 100644 --- a/content/rooms/v7.md +++ b/content/rooms/v7.md @@ -74,14 +74,20 @@ The rules are as follows: version, reject. 4. If `content` has no `creator` property, 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 +2. Considering the event's `auth_events`: + 1. If there are duplicate entries for a given `type` and `state_key` pair, + reject. + 2. If there are 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. + algorithm described in the server specification, reject. + 3. If there are entries which were themselves rejected under the [checks + performed on receipt of a + PDU](/server-server-api/#checks-performed-on-receipt-of-a-pdu), reject. + 4. If there is no `m.room.create` event among the entries, reject. +3. If the `content` of the `m.room.create` event in the room state has the + property `m.federate` set to `false`, and the `sender` domain of the event + does not match the `sender` domain of the create event, reject. 4. If type is `m.room.member`: 1. If there is no `state_key` property, or no `membership` property in `content`, reject. From ae06f3747087a2569bffc137b3c670e90b54df7d Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 25 Feb 2025 17:11:50 -0500 Subject: [PATCH 04/67] fix typos in m.room_key.withheld (#2080) * fix typos * add changelog --- changelogs/client_server/newsfragments/2080.clarification | 1 + data/event-schemas/schema/m.room_key.withheld.yaml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2080.clarification diff --git a/changelogs/client_server/newsfragments/2080.clarification b/changelogs/client_server/newsfragments/2080.clarification new file mode 100644 index 00000000..ca5f3aea --- /dev/null +++ b/changelogs/client_server/newsfragments/2080.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. \ No newline at end of file diff --git a/data/event-schemas/schema/m.room_key.withheld.yaml b/data/event-schemas/schema/m.room_key.withheld.yaml index 797b51f9..1acca546 100644 --- a/data/event-schemas/schema/m.room_key.withheld.yaml +++ b/data/event-schemas/schema/m.room_key.withheld.yaml @@ -48,8 +48,8 @@ properties: session_id: type: string description: |- - Required of `code` is not `m.no_olm`. The session ID of the key - that this event is aboutis for. + Required if `code` is not `m.no_olm`. The session ID of the key + that this event is about. sender_key: type: string description: |- From 60339adb2d4df2d9ed480cf7cff270652d71a59c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:08:42 +0100 Subject: [PATCH 05/67] Refactor PDU definitions to reduce duplication (#2070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First of all, all PDU definitions were based on the v1 PDU definition with a few fields overwritten to change the format with needed. While that works when rendering the spec, this is semantically incorrect because it means that the objects must match both schemas, which is impossible. So now we make a base with only the common fields, and we add the others as needed by the room version. Note that there is no more "unsigned PDU" definition since it is not used directly, and hashes and signatures are the same across all versions. Signed-off-by: Kévin Commaille --- .../newsfragments/2070.clarification | 1 + content/rooms/v1.md | 2 +- content/rooms/v2.md | 2 +- .../auth_events_prev_events_v4.yaml | 45 ++++++++++++ .../{ => components}/event_hash.yaml | 0 .../pdu_base.yaml} | 60 +++++----------- data/api/server-server/definitions/pdu.yaml | 45 ------------ .../api/server-server/definitions/pdu_v1.yaml | 70 +++++++++++++++++++ .../server-server/definitions/pdu_v11.yaml | 53 +------------- .../api/server-server/definitions/pdu_v3.yaml | 22 +----- .../api/server-server/definitions/pdu_v4.yaml | 33 ++------- .../definitions/unsigned_pdu.yaml | 28 -------- .../auth_events_prev_events_v4.json | 10 +++ .../examples/components/pdu_base.json | 21 ++++++ data/api/server-server/examples/pdu.json | 11 --- .../{unsigned_pdu_base.json => pdu_v1.json} | 17 ++--- data/api/server-server/examples/pdu_v11.json | 19 +---- data/api/server-server/examples/pdu_v3.json | 10 +-- data/api/server-server/examples/pdu_v4.json | 15 ++-- .../examples/pdu_v4_join_membership.json | 5 +- .../server-server/examples/unsigned_pdu.json | 4 -- 21 files changed, 190 insertions(+), 283 deletions(-) create mode 100644 changelogs/room_versions/newsfragments/2070.clarification create mode 100644 data/api/server-server/definitions/components/auth_events_prev_events_v4.yaml rename data/api/server-server/definitions/{ => components}/event_hash.yaml (100%) rename data/api/server-server/definitions/{unsigned_pdu_base.yaml => components/pdu_base.yaml} (63%) delete mode 100644 data/api/server-server/definitions/pdu.yaml create mode 100644 data/api/server-server/definitions/pdu_v1.yaml delete mode 100644 data/api/server-server/definitions/unsigned_pdu.yaml create mode 100644 data/api/server-server/examples/components/auth_events_prev_events_v4.json create mode 100644 data/api/server-server/examples/components/pdu_base.json delete mode 100644 data/api/server-server/examples/pdu.json rename data/api/server-server/examples/{unsigned_pdu_base.json => pdu_v1.json} (52%) delete mode 100644 data/api/server-server/examples/unsigned_pdu.json diff --git a/changelogs/room_versions/newsfragments/2070.clarification b/changelogs/room_versions/newsfragments/2070.clarification new file mode 100644 index 00000000..7d0208cd --- /dev/null +++ b/changelogs/room_versions/newsfragments/2070.clarification @@ -0,0 +1 @@ +Refactor PDU definitions to reduce duplication. diff --git a/content/rooms/v1.md b/content/rooms/v1.md index 1b950f11..773d7caa 100644 --- a/content/rooms/v1.md +++ b/content/rooms/v1.md @@ -51,7 +51,7 @@ inconsistencies may occur. Events in version 1 rooms have the following structure: -{{% definition path="api/server-server/definitions/pdu" %}} +{{% definition path="api/server-server/definitions/pdu_v1" %}} #### Deprecated event content schemas diff --git a/content/rooms/v2.md b/content/rooms/v2.md index f9980261..f0ea1ac7 100644 --- a/content/rooms/v2.md +++ b/content/rooms/v2.md @@ -49,7 +49,7 @@ completeness. Events in rooms of this version have the following structure: -{{% definition path="api/server-server/definitions/pdu" %}} +{{% definition path="api/server-server/definitions/pdu_v1" %}} #### Deprecated event content schemas diff --git a/data/api/server-server/definitions/components/auth_events_prev_events_v4.yaml b/data/api/server-server/definitions/components/auth_events_prev_events_v4.yaml new file mode 100644 index 00000000..fabfef82 --- /dev/null +++ b/data/api/server-server/definitions/components/auth_events_prev_events_v4.yaml @@ -0,0 +1,45 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +type: object +description: |- + The auth_events and prev_events fields of PDUs for room version 4 + and beyond. +properties: + auth_events: + type: array + items: + type: string + description: Event ID. + description: |- + Event IDs for the authorization events that would + allow this event to be in the room. + + Must contain less than or equal to 10 events. Note that if the relevant + auth event selection rules are used, this restriction should never be + encountered. + example: ["$URLsafe-base64EncodedHash", "$Another_Event"] + prev_events: + type: array + items: + type: string + description: Event ID. + description: |- + Event IDs for the most recent events in the room + that the homeserver was aware of when it made this event. + + Must contain less than or equal to 20 events. + example: ["$URLsafe-base64EncodedHash", "$Another_Event"] +required: + - auth_events + - prev_events diff --git a/data/api/server-server/definitions/event_hash.yaml b/data/api/server-server/definitions/components/event_hash.yaml similarity index 100% rename from data/api/server-server/definitions/event_hash.yaml rename to data/api/server-server/definitions/components/event_hash.yaml diff --git a/data/api/server-server/definitions/unsigned_pdu_base.yaml b/data/api/server-server/definitions/components/pdu_base.yaml similarity index 63% rename from data/api/server-server/definitions/unsigned_pdu_base.yaml rename to data/api/server-server/definitions/components/pdu_base.yaml index a2ec9552..4b676c8f 100644 --- a/data/api/server-server/definitions/unsigned_pdu_base.yaml +++ b/data/api/server-server/definitions/components/pdu_base.yaml @@ -12,10 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. type: object -title: Unsigned Persistent Data Unit -description: An unsigned persistent data unit (event) -example: - $ref: "../examples/unsigned_pdu_base.json" +description: Common fields for all PDU versions properties: room_id: type: string @@ -44,23 +41,6 @@ properties: type: object description: The content of the event. example: {"key": "value"} - prev_events: - type: array - description: |- - Event IDs and reference hashes for the most recent events in the room - that the homeserver was aware of when it made this event. - - Must contain less than or equal to 20 events. - items: - type: array - maxItems: 2 - minItems: 2 - items: - anyOf: - - type: string - title: Event ID - example: "$abc123:matrix.org" - - $ref: "event_hash.yaml" depth: type: integer description: |- @@ -68,25 +48,22 @@ properties: maximum value for an integer (2^63 - 1). If the room's depth is already at the limit, the depth must be set to the limit. example: 12 - auth_events: - type: array + hashes: + $ref: "event_hash.yaml" + signatures: + type: object description: |- - Event IDs and reference hashes for the authorization events that would - allow this event to be in the room. - - Must contain less than or equal to 10 events. Note that if the relevant - auth event selection rules are used, this restriction should never be - encountered. - items: - type: array - maxItems: 2 - minItems: 2 - items: - anyOf: - - type: string - title: Event ID - example: "$abc123:matrix.org" - - $ref: "event_hash.yaml" + Signatures for the PDU, following the algorithm specified in [Signing Events](/server-server-api/#signing-events). + example: { + "example.com": { + "ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent" + } + } + additionalProperties: + type: object + title: Server Signatures + additionalProperties: + type: string unsigned: type: object title: UnsignedData @@ -99,12 +76,11 @@ properties: description: The number of milliseconds that have passed since this message was sent. example: 4612 required: - - event_id - room_id - sender - origin_server_ts - type - content - - prev_events - depth - - auth_events + - hashes + - signatures diff --git a/data/api/server-server/definitions/pdu.yaml b/data/api/server-server/definitions/pdu.yaml deleted file mode 100644 index 00b83321..00000000 --- a/data/api/server-server/definitions/pdu.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2018 New Vector Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -type: object -title: Persistent Data Unit -description: A persistent data unit (event) for room versions 1 and 2. -example: - $ref: "../examples/pdu.json" -allOf: - - $ref: "unsigned_pdu.yaml" - - type: object - properties: - redacts: - type: string - description: For redaction events, the ID of the event being redacted. - example: "$def456:matrix.org" - hashes: - $ref: "event_hash.yaml" - signatures: - type: object - description: |- - Signatures for the PDU, following the algorithm specified in [Signing Events](/server-server-api/#signing-events). - example: { - "example.com": { - "ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent" - } - } - additionalProperties: - type: object - title: Server Signatures - additionalProperties: - type: string - required: - - hashes - - signatures diff --git a/data/api/server-server/definitions/pdu_v1.yaml b/data/api/server-server/definitions/pdu_v1.yaml new file mode 100644 index 00000000..b9ba8cc1 --- /dev/null +++ b/data/api/server-server/definitions/pdu_v1.yaml @@ -0,0 +1,70 @@ +# Copyright 2018 New Vector Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +type: object +title: Persistent Data Unit +description: A persistent data unit (event) for room versions 1 and 2. +example: + $ref: "../examples/pdu_v1.json" +allOf: + - $ref: "components/pdu_base.yaml" + - type: object + properties: + event_id: + type: string + description: The event ID for the PDU. + example: "$a4ecee13e2accdadf56c1025:example.com" + redacts: + type: string + description: For redaction events, the ID of the event being redacted. + example: "$def456:matrix.org" + auth_events: + type: array + description: |- + Event IDs and reference hashes for the authorization events that would + allow this event to be in the room. + + Must contain less than or equal to 10 events. Note that if the relevant + auth event selection rules are used, this restriction should never be + encountered. + items: + type: array + maxItems: 2 + minItems: 2 + items: + anyOf: + - type: string + title: Event ID + example: "$abc123:matrix.org" + - $ref: "components/event_hash.yaml" + prev_events: + type: array + description: |- + Event IDs and reference hashes for the most recent events in the room + that the homeserver was aware of when it made this event. + + Must contain less than or equal to 20 events. + items: + type: array + maxItems: 2 + minItems: 2 + items: + anyOf: + - type: string + title: Event ID + example: "$abc123:matrix.org" + - $ref: "components/event_hash.yaml" + required: + - event_id + - auth_events + - prev_events diff --git a/data/api/server-server/definitions/pdu_v11.yaml b/data/api/server-server/definitions/pdu_v11.yaml index 60f9b3ac..a3db6ee9 100644 --- a/data/api/server-server/definitions/pdu_v11.yaml +++ b/data/api/server-server/definitions/pdu_v11.yaml @@ -17,53 +17,6 @@ description: A persistent data unit (event) for room version 11 and beyond. example: $ref: "../examples/pdu_v11.json" allOf: - # v11 is the v4 event, but without redacts. Copy the auth_events/prev_events - # from pdu_v4.yaml and hashes and signatures from pdu_v3.yaml. - - $ref: "unsigned_pdu_base.yaml" - - type: object - properties: - auth_events: - type: array - items: - type: string - description: Event ID. - description: |- - Event IDs for the authorization events that would - allow this event to be in the room. - - Must contain less than or equal to 10 events. Note that if the relevant - auth event selection rules are used, this restriction should never be - encountered. - example: ["$URLsafe-base64EncodedHash", "$Another_Event"] - prev_events: - type: array - items: - type: string - description: Event ID. - description: |- - Event IDs for the most recent events in the room - that the homeserver was aware of when it made this event. - - Must contain less than or equal to 20 events. - example: ["$URLsafe-base64EncodedHash", "$Another_Event"] - hashes: - $ref: "event_hash.yaml" - signatures: - type: object - description: |- - Signatures for the PDU, following the algorithm specified in [Signing Events](/server-server-api/#signing-events). - example: { - "example.com": { - "ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent" - } - } - additionalProperties: - type: object - title: Server Signatures - additionalProperties: - type: string - required: - - auth_events - - prev_events - - hashes - - signatures + # v11 is the v4 event, but without redacts. + - $ref: "components/pdu_base.yaml" + - $ref: "components/auth_events_prev_events_v4.yaml" \ No newline at end of file diff --git a/data/api/server-server/definitions/pdu_v3.yaml b/data/api/server-server/definitions/pdu_v3.yaml index e801518c..69d8900c 100644 --- a/data/api/server-server/definitions/pdu_v3.yaml +++ b/data/api/server-server/definitions/pdu_v3.yaml @@ -13,11 +13,11 @@ # limitations under the License. type: object title: Persistent Data Unit -description: A persistent data unit (event) for room version 3 and beyond. +description: A persistent data unit (event) for room version 3. example: $ref: "../examples/pdu_v3.json" allOf: - - $ref: "unsigned_pdu_base.yaml" + - $ref: "components/pdu_base.yaml" - type: object properties: redacts: @@ -48,24 +48,6 @@ allOf: Must contain less than or equal to 20 events. example: ["$base64EncodedHash", "$AnotherEvent"] - hashes: - $ref: "event_hash.yaml" - signatures: - type: object - description: |- - Signatures for the PDU, following the algorithm specified in [Signing Events](/server-server-api/#signing-events). - example: { - "example.com": { - "ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent" - } - } - additionalProperties: - type: object - title: Server Signatures - additionalProperties: - type: string required: - auth_events - prev_events - - hashes - - signatures diff --git a/data/api/server-server/definitions/pdu_v4.yaml b/data/api/server-server/definitions/pdu_v4.yaml index d22956c6..e859ee86 100644 --- a/data/api/server-server/definitions/pdu_v4.yaml +++ b/data/api/server-server/definitions/pdu_v4.yaml @@ -13,41 +13,16 @@ # limitations under the License. type: object title: Persistent Data Unit -description: A persistent data unit (event) for room version 4 and beyond. +description: |- + A persistent data unit (event) for room versions 4, 5, 6, 7, 8, 9 and 10. example: $ref: "../examples/pdu_v4.json" allOf: - - $ref: "pdu_v3.yaml" + - $ref: "components/pdu_base.yaml" + - $ref: "components/auth_events_prev_events_v4.yaml" - type: object properties: redacts: type: string description: For redaction events, the ID of the event being redacted. example: "$def_456-oldevent" - auth_events: - type: array - items: - type: string - description: Event ID. - description: |- - Event IDs for the authorization events that would - allow this event to be in the room. - - Must contain less than or equal to 10 events. Note that if the relevant - auth event selection rules are used, this restriction should never be - encountered. - example: ["$URLsafe-base64EncodedHash", "$Another_Event"] - prev_events: - type: array - items: - type: string - description: Event ID. - description: |- - Event IDs for the most recent events in the room - that the homeserver was aware of when it made this event. - - Must contain less than or equal to 20 events. - example: ["$URLsafe-base64EncodedHash", "$Another_Event"] - required: - - auth_events - - prev_events diff --git a/data/api/server-server/definitions/unsigned_pdu.yaml b/data/api/server-server/definitions/unsigned_pdu.yaml deleted file mode 100644 index a27a21cd..00000000 --- a/data/api/server-server/definitions/unsigned_pdu.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2018-2019 New Vector Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -type: object -title: Unsigned Persistent Data Unit -description: An unsigned persistent data unit (event) -example: - $ref: "../examples/unsigned_pdu.json" -allOf: - - $ref: "unsigned_pdu_base.yaml" - - type: object - properties: - event_id: - type: string - description: The event ID for the PDU. - example: "$a4ecee13e2accdadf56c1025:example.com" - required: - - event_id diff --git a/data/api/server-server/examples/components/auth_events_prev_events_v4.json b/data/api/server-server/examples/components/auth_events_prev_events_v4.json new file mode 100644 index 00000000..3a203b49 --- /dev/null +++ b/data/api/server-server/examples/components/auth_events_prev_events_v4.json @@ -0,0 +1,10 @@ +{ + "auth_events": [ + "$urlsafe_base64_encoded_eventid", + "$a-different-event-id" + ], + "prev_events": [ + "$urlsafe_base64_encoded_eventid", + "$a-different-event-id" + ] +} \ No newline at end of file diff --git a/data/api/server-server/examples/components/pdu_base.json b/data/api/server-server/examples/components/pdu_base.json new file mode 100644 index 00000000..448aeafa --- /dev/null +++ b/data/api/server-server/examples/components/pdu_base.json @@ -0,0 +1,21 @@ +{ + "room_id": "!UcYsUzyxTGDxLBEvLy:example.org", + "sender": "@alice:example.com", + "origin_server_ts": 1404838188000, + "depth": 12, + "type": "m.room.message", + "content": { + "key": "value" + }, + "hashes": { + "sha256": "thishashcoversallfieldsincasethisisredacted" + }, + "signatures": { + "example.com": { + "ed25519:key_version": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" + } + }, + "unsigned": { + "age": 4612 + } +} diff --git a/data/api/server-server/examples/pdu.json b/data/api/server-server/examples/pdu.json deleted file mode 100644 index 81981b23..00000000 --- a/data/api/server-server/examples/pdu.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$ref": "unsigned_pdu.json", - "hashes": { - "sha256": "thishashcoversallfieldsincasethisisredacted" - }, - "signatures": { - "example.com": { - "ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" - } - } -} \ No newline at end of file diff --git a/data/api/server-server/examples/unsigned_pdu_base.json b/data/api/server-server/examples/pdu_v1.json similarity index 52% rename from data/api/server-server/examples/unsigned_pdu_base.json rename to data/api/server-server/examples/pdu_v1.json index 079ee1ea..4e80ca52 100644 --- a/data/api/server-server/examples/unsigned_pdu_base.json +++ b/data/api/server-server/examples/pdu_v1.json @@ -1,25 +1,16 @@ { - "room_id": "!UcYsUzyxTGDxLBEvLy:example.org", - "sender": "@alice:example.com", - "origin_server_ts": 1404838188000, - "depth": 12, + "$ref": "components/pdu_base.json", + "event_id": "$a4ecee13e2accdadf56c1025:example.com", "auth_events": [ [ "$af232176:example.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"} ] ], - "type": "m.room.message", "prev_events": [ [ "$af232176:example.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"} ] - ], - "content": { - "key": "value" - }, - "unsigned": { - "age": 4612 - } -} + ] +} \ No newline at end of file diff --git a/data/api/server-server/examples/pdu_v11.json b/data/api/server-server/examples/pdu_v11.json index 292f38a0..bbdcf433 100644 --- a/data/api/server-server/examples/pdu_v11.json +++ b/data/api/server-server/examples/pdu_v11.json @@ -1,19 +1,6 @@ { - "$ref": "unsigned_pdu_base.json", - "hashes": { - "sha256": "thishashcoversallfieldsincasethisisredacted" - }, - "signatures": { - "example.com": { - "ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" - } - }, - "auth_events": [ - "$urlsafe_base64_encoded_eventid", - "$a-different-event-id" - ], - "prev_events": [ - "$urlsafe_base64_encoded_eventid", - "$a-different-event-id" + "allOf": [ + { "$ref": "components/pdu_base.json" }, + { "$ref": "components/auth_events_prev_events_v4.json" } ] } diff --git a/data/api/server-server/examples/pdu_v3.json b/data/api/server-server/examples/pdu_v3.json index acffdf26..6d2f5244 100644 --- a/data/api/server-server/examples/pdu_v3.json +++ b/data/api/server-server/examples/pdu_v3.json @@ -1,13 +1,5 @@ { - "$ref": "unsigned_pdu_base.json", - "hashes": { - "sha256": "thishashcoversallfieldsincasethisisredacted" - }, - "signatures": { - "example.com": { - "ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" - } - }, + "$ref": "components/pdu_base.json", "auth_events": [ "$base64encodedeventid", "$adifferenteventid" diff --git a/data/api/server-server/examples/pdu_v4.json b/data/api/server-server/examples/pdu_v4.json index 3c2f0e22..ae25d537 100644 --- a/data/api/server-server/examples/pdu_v4.json +++ b/data/api/server-server/examples/pdu_v4.json @@ -1,12 +1,7 @@ { - "$ref": "pdu_v3.json", - "auth_events": [ - "$urlsafe_base64_encoded_eventid", - "$a-different-event-id" - ], - "prev_events": [ - "$urlsafe_base64_encoded_eventid", - "$a-different-event-id" - ], - "redacts": "$some-old_event" + "allOf": [ + { "$ref": "components/pdu_base.json" }, + { "$ref": "components/auth_events_prev_events_v4.json" }, + { "redacts": "$some-old_event" } + ] } diff --git a/data/api/server-server/examples/pdu_v4_join_membership.json b/data/api/server-server/examples/pdu_v4_join_membership.json index 1057ea94..23f69e81 100644 --- a/data/api/server-server/examples/pdu_v4_join_membership.json +++ b/data/api/server-server/examples/pdu_v4_join_membership.json @@ -1,8 +1,5 @@ { - "$ref": "unsigned_pdu_base.json", - "hashes": { - "sha256": "thishashcoversallfieldsincasethisisredacted" - }, + "$ref": "components/pdu_base.json", "signatures": { "example.com": { "ed25519:key_version": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" diff --git a/data/api/server-server/examples/unsigned_pdu.json b/data/api/server-server/examples/unsigned_pdu.json deleted file mode 100644 index b886a365..00000000 --- a/data/api/server-server/examples/unsigned_pdu.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$ref": "unsigned_pdu_base.json", - "event_id": "$a4ecee13e2accdadf56c1025:example.com" -} From dfc61ffc71ab0af1b58517ae40ce4b6f4521064e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:14:42 +0100 Subject: [PATCH 06/67] Fix parsing of nested slices in resolve-refs and resolve-allof partials (#2069) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- changelogs/internal/newsfragments/2069.clarification | 1 + layouts/partials/json-schema/resolve-allof.html | 8 ++++++++ layouts/partials/json-schema/resolve-refs.html | 8 ++++++++ 3 files changed, 17 insertions(+) create mode 100644 changelogs/internal/newsfragments/2069.clarification diff --git a/changelogs/internal/newsfragments/2069.clarification b/changelogs/internal/newsfragments/2069.clarification new file mode 100644 index 00000000..2ad407fb --- /dev/null +++ b/changelogs/internal/newsfragments/2069.clarification @@ -0,0 +1 @@ +Fix parsing of nested slices in `resolve-refs` and `resolve-allof` partials. diff --git a/layouts/partials/json-schema/resolve-allof.html b/layouts/partials/json-schema/resolve-allof.html index b8b81e7d..61a03c3f 100644 --- a/layouts/partials/json-schema/resolve-allof.html +++ b/layouts/partials/json-schema/resolve-allof.html @@ -24,6 +24,14 @@ {{ range $original }} {{ $resolved := partial "json-schema/resolve-allof" . }} + {{ if reflect.IsSlice $resolved }} + {{/* + If $resolved is a slice, `append` will add the items of $resolved to + $ret, but we want to add $resolved itself to $ret, so we always wrap + it into another slice. + */}} + {{ $resolved = slice $resolved }} + {{ end }} {{ $ret = $ret | append $resolved }} {{ end }} {{ else if reflect.IsMap $original }} diff --git a/layouts/partials/json-schema/resolve-refs.html b/layouts/partials/json-schema/resolve-refs.html index 9a36e413..7479498a 100644 --- a/layouts/partials/json-schema/resolve-refs.html +++ b/layouts/partials/json-schema/resolve-refs.html @@ -69,6 +69,14 @@ {{ range $schema }} {{ $resolved := partial "json-schema/resolve-refs" (dict "schema" . "path" $path) }} + {{ if reflect.IsSlice $resolved }} + {{/* + If $resolved is a slice, `append` will add the items of $resolved to + $result_slice, but we want to add $resolved itself to $result_slice, + so we wrap it into another slice. + */}} + {{ $resolved = slice $resolved }} + {{ end }} {{ $result_slice = $result_slice | append $resolved }} {{ end }} From 844dd6f8aefd301c18643488ef101d38c18c9be9 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 4 Mar 2025 18:18:27 +0100 Subject: [PATCH 07/67] Clients can choose which history visibility options they offer to users when creating rooms (#2072) Signed-off-by: Johannes Marbach --- changelogs/client_server/newsfragments/2072.clarification | 1 + content/client-server-api/modules/history_visibility.md | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2072.clarification diff --git a/changelogs/client_server/newsfragments/2072.clarification b/changelogs/client_server/newsfragments/2072.clarification new file mode 100644 index 00000000..ddb9a536 --- /dev/null +++ b/changelogs/client_server/newsfragments/2072.clarification @@ -0,0 +1 @@ +Clients can choose which history visibility options they offer to users when creating rooms. diff --git a/content/client-server-api/modules/history_visibility.md b/content/client-server-api/modules/history_visibility.md index b0d333ab..04487bdb 100644 --- a/content/client-server-api/modules/history_visibility.md +++ b/content/client-server-api/modules/history_visibility.md @@ -43,11 +43,8 @@ setting at that time was more restrictive. #### Client behaviour -Clients that implement this module MUST present to the user the possible -options for setting history visibility when creating a room. - -Clients may want to display a notice that their events may be read by -non-joined people if the value is set to `world_readable`. +Clients may want to display a notice that events may be read by +non-joined people if the history visibility is set to `world_readable`. #### Server behaviour From 4ff9a851e683b14b150b5941fb28b988e17242e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:43:27 +0100 Subject: [PATCH 08/67] Add link to git commit for unstable changelog too (#2078) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- changelogs/internal/newsfragments/2078.clarification | 1 + layouts/docs/changelog.html | 12 ++++++++++-- scripts/generate-changelog.sh | 12 +++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 changelogs/internal/newsfragments/2078.clarification diff --git a/changelogs/internal/newsfragments/2078.clarification b/changelogs/internal/newsfragments/2078.clarification new file mode 100644 index 00000000..d9285d5a --- /dev/null +++ b/changelogs/internal/newsfragments/2078.clarification @@ -0,0 +1 @@ +Add link to the git commit for the unstable changelog. diff --git a/layouts/docs/changelog.html b/layouts/docs/changelog.html index b23c8074..94fa55a3 100644 --- a/layouts/docs/changelog.html +++ b/layouts/docs/changelog.html @@ -31,9 +31,17 @@

{{ .Title }}

- {{ if ne $version "unstable" -}} - {{ $commitLink := printf "https://github.com/matrix-org/matrix-spec/tree/%s" $version -}} + {{ $rev := $version }} + {{ if eq $version "unstable" -}} + {{- /* + Extract the git SHA from the frontmatter of the changelog, where + it was stashed by `generate-changelog.sh`. + */ -}} + {{ $rev = .Params.commit -}} + {{ end -}} + {{ $commitLink := printf "https://github.com/matrix-org/matrix-spec/tree/%s" $rev -}} + {{ if ne $version "unstable" }} {{ end -}} {{ $checklist := .OutputFormats.Get "checklist" -}} diff --git a/scripts/generate-changelog.sh b/scripts/generate-changelog.sh index 678af60f..9c80b059 100755 --- a/scripts/generate-changelog.sh +++ b/scripts/generate-changelog.sh @@ -44,8 +44,18 @@ outputs: - html - checklist date: $(date -Idate) ---- EOF + + # Add the commit hash for the unstable versions. It is used to generate a + # link to the commit on the repository. + if [ "$VERSION" == "vUNSTABLE" ]; then + echo "params:" + echo " commit: $(git rev-parse --short HEAD)" + fi + + # Close the frontmatter. + echo "---" + # Remove trailing whitespace (such as our intentionally blank RST headings) sed -e "s/[ ]*$//" rendered.md } > ../content/changelog/$FILENAME From 3adbfa30da98f2cee9d46fd96cf3b0eff3a31c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:44:59 +0100 Subject: [PATCH 09/67] Look for examples in all possible locations (#2076) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We used to only look for examples in a few (sometimes arbitrary) places, and we didn't support showing several examples in most cases. This is intended to fix this. In the process we try to deduplicate code to make sure that we use the same logic everywhere. Signed-off-by: Kévin Commaille --- .../internal/newsfragments/2076.clarification | 1 + .../newsfragments/2076.clarification | 1 + data/api/server-server/invites-v1.yaml | 16 --- data/api/server-server/invites-v2.yaml | 19 ---- data/api/server-server/joins-v2.yaml | 1 - data/api/server-server/knocks.yaml | 1 - layouts/partials/events/example.html | 8 +- .../partials/json-schema/resolve-example.html | 46 -------- .../json-schema/resolve-examples.html | 71 ++++++++++++ .../openapi/render-media-type-objects.html | 104 ++++++++++++++++++ layouts/partials/openapi/render-request.html | 59 +--------- .../partials/openapi/render-responses.html | 68 +----------- layouts/partials/render-example.html | 40 +++++++ layouts/shortcodes/definition.html | 11 +- 14 files changed, 226 insertions(+), 220 deletions(-) create mode 100644 changelogs/internal/newsfragments/2076.clarification create mode 100644 changelogs/server_server/newsfragments/2076.clarification delete mode 100644 layouts/partials/json-schema/resolve-example.html create mode 100644 layouts/partials/json-schema/resolve-examples.html create mode 100644 layouts/partials/openapi/render-media-type-objects.html create mode 100644 layouts/partials/render-example.html diff --git a/changelogs/internal/newsfragments/2076.clarification b/changelogs/internal/newsfragments/2076.clarification new file mode 100644 index 00000000..3cf1fb94 --- /dev/null +++ b/changelogs/internal/newsfragments/2076.clarification @@ -0,0 +1 @@ +Support more locations for examples in OpenAPI definitions and JSON schemas. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/2076.clarification b/changelogs/server_server/newsfragments/2076.clarification new file mode 100644 index 00000000..b3cad0d2 --- /dev/null +++ b/changelogs/server_server/newsfragments/2076.clarification @@ -0,0 +1 @@ +Remove an erroneous `room_id` field in a few examples. diff --git a/data/api/server-server/invites-v1.yaml b/data/api/server-server/invites-v1.yaml index c328f05e..7d241c37 100644 --- a/data/api/server-server/invites-v1.yaml +++ b/data/api/server-server/invites-v1.yaml @@ -75,22 +75,6 @@ paths: example: $ref: ../../event-schemas/examples/invite_room_state.json type: object - example: { - "room_id": "!somewhere:example.org", - "type": "m.room.member", - "state_key": "@joe:elsewhere.com", - "origin": "example.org", - "origin_server_ts": 1549041175876, - "sender": "@someone:example.org", - "content": { - "membership": "invite" - }, - "signatures": { - "example.com": { - "ed25519:key_version": "SomeSignatureHere" - }, - } - } required: true responses: "200": diff --git a/data/api/server-server/invites-v2.yaml b/data/api/server-server/invites-v2.yaml index 8984b6d1..f42c8eea 100644 --- a/data/api/server-server/invites-v2.yaml +++ b/data/api/server-server/invites-v2.yaml @@ -78,25 +78,6 @@ paths: required: - room_version - event - example: { - "room_version": "2", - "event": { - "room_id": "!somewhere:example.org", - "type": "m.room.member", - "state_key": "@joe:elsewhere.com", - "origin": "example.org", - "origin_server_ts": 1549041175876, - "sender": "@someone:example.org", - "content": { - "membership": "invite" - }, - "signatures": { - "example.com": { - "ed25519:key_version": "SomeSignatureHere" - }, - } - } - } required: true responses: "200": diff --git a/data/api/server-server/joins-v2.yaml b/data/api/server-server/joins-v2.yaml index bb45b1be..91e6a83e 100644 --- a/data/api/server-server/joins-v2.yaml +++ b/data/api/server-server/joins-v2.yaml @@ -140,7 +140,6 @@ paths: - type - content example: { - "room_id": "!somewhere:example.org", "type": "m.room.member", "state_key": "@someone:example.org", "origin": "example.org", diff --git a/data/api/server-server/knocks.yaml b/data/api/server-server/knocks.yaml index cba9d32b..01bfa637 100644 --- a/data/api/server-server/knocks.yaml +++ b/data/api/server-server/knocks.yaml @@ -270,7 +270,6 @@ paths: - type - content example: { - "room_id": "!somewhere:example.org", "type": "m.room.member", "state_key": "@someone:example.org", "origin": "example.org", diff --git a/layouts/partials/events/example.html b/layouts/partials/events/example.html index 90752fbd..c24cd66b 100644 --- a/layouts/partials/events/example.html +++ b/layouts/partials/events/example.html @@ -13,10 +13,4 @@ {{ $path := delimit (slice "event-schemas/examples" .name) "/" }} {{ $example_content := partial "json-schema/resolve-refs" (dict "schema" .schema "path" $path) }} -{{ $example_json := jsonify (dict "indent" " ") $example_content }} -{{ $example_json = replace $example_json "\\u003c" "<" }} -{{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }} - -```json -{{ $example_json }} -``` +{{ partial "render-example" (dict "example" $example_content) }} diff --git a/layouts/partials/json-schema/resolve-example.html b/layouts/partials/json-schema/resolve-example.html deleted file mode 100644 index 8fa98400..00000000 --- a/layouts/partials/json-schema/resolve-example.html +++ /dev/null @@ -1,46 +0,0 @@ -{{/* - - For complex objects, example content is sometimes attached to the - object's individual properties (and subproperties...), so to get - a complete example for the whole object we need to iterate through - its properties (and subproperties...) and assemble them. - - That's what this template does. - -*/}} - -{{ $this_object := . }} - -{{ $example := $this_object.example }} - -{{ if not $example }} - - {{ if eq $this_object.type "object" }} - {{ $example = dict }} - - {{ range $key, $property := $this_object.properties}} - {{ $this_property_example := partial "json-schema/resolve-example" $property }} - {{ if $this_property_example }} - {{ $example = merge (dict $key $this_property_example) $example }} - {{ end }} - {{ end }} - - {{ else if eq $this_object.type "array" }} - - {{/* the "items" within an array can either be an object (where we have a - list of items which match the schema), or a list (for tuple - validation, where each item has a different schema). - - TODO: support tuple validation here. - */}} - {{ if reflect.IsMap $this_object.items }} - {{ $items_example := partial "json-schema/resolve-example" $this_object.items }} - {{ if $items_example }} - {{ $example = slice $items_example }} - {{ end }} - {{ end }} - {{ end }} - -{{ end }} - -{{ return $example }} diff --git a/layouts/partials/json-schema/resolve-examples.html b/layouts/partials/json-schema/resolve-examples.html new file mode 100644 index 00000000..dd126540 --- /dev/null +++ b/layouts/partials/json-schema/resolve-examples.html @@ -0,0 +1,71 @@ +{{/* + + Find examples in the given JSON schema. + + Tries to find examples in the `examples` and `example` keys of the schema + first. + + If it doesn't succeed, iterates through the properties and subproperties to + collect their examples, to merge them into a complete example for the whole + object. + + Parameter: the JSON schema to extract the examples from. + +*/}} + +{{ $this_object := . }} +{{ $examples := slice }} + +{{ if $this_object.examples }} + {{/* This is an array of examples, we can just use it */}} + {{ $examples = $this_object.examples }} +{{ else if $this_object.example }} + {{ $examples = slice $this_object.example }} +{{ else }} + {{/* Resolve the nested examples */}} + {{ if eq $this_object.type "object" }} + {{ $example := dict }} + + {{ range $key, $property := $this_object.properties}} + {{ $this_property_examples := partial "json-schema/resolve-examples" $property }} + {{/* + It would be too complex to handle several nested examples, + just use the first one. + */}} + {{ with index $this_property_examples 0 }} + {{ $example = merge (dict $key .) $example }} + {{ end }} + {{ end }} + + {{/* + Add the assembled example to the list if either (a) the example is + non-empty, or (b) the object itself is meant to be empty (so an + empty example is correct). + */}} + {{ if (or $example (not $this_object.properties)) }} + {{ $examples = slice $example }} + {{ end }} + + {{ else if eq $this_object.type "array" }} + + {{/* the "items" within an array can either be an object (where we have a + list of items which match the schema), or a list (for tuple + validation, where each item has a different schema). + + TODO: support tuple validation here. + */}} + {{ if reflect.IsMap $this_object.items }} + {{ $items_examples := partial "json-schema/resolve-examples" $this_object.items }} + {{/* + It would be too complex to handle several nested examples, + just use the first one. + */}} + {{ with index $items_examples 0 }} + {{ $examples = slice (slice .) }} + {{ end }} + {{ end }} + {{ end }} + +{{ end }} + +{{ return $examples }} diff --git a/layouts/partials/openapi/render-media-type-objects.html b/layouts/partials/openapi/render-media-type-objects.html new file mode 100644 index 00000000..7c48320e --- /dev/null +++ b/layouts/partials/openapi/render-media-type-objects.html @@ -0,0 +1,104 @@ +{{/* + + Render a map of [Media Type Objects](https://spec.openapis.org/oas/v3.1.1#media-type-object). + This map can be found as the `content` field of requests and responses. + + Parameters: + + * `content`: A map of MIME type to Media Type Object + * `kind`: the kind of object that is rendered, either `request` or `response`. + * `anchor_base`: a prefix to add to the HTML anchors generated for each object + + This template renders: + + * Object tables if the map contains an `application/json` MIME type, or a + table with the MIME types and the corresponding description of the object. + * The examples of the Media Type Objects. + +*/}} + +{{/* + Request and response bodies can have several content types. If there is a + JSON type, we display that; otherwise we just show the content types and + descriptions. +*/}} +{{ $json_body := index .content "application/json" }} +{{ if $json_body }} + {{/* + Display the JSON schemas + */}} + + {{ $schema := $json_body.schema }} + + {{/* + All this is to work out how to express the content of the response + in the case where it is an array. + */}} + {{ if eq $schema.type "array" }} + {{ $type_of := "" }} + {{ if $schema.items.anyOf }} + {{ $types := slice }} + {{ range $schema.items.anyOf }} + {{ if .title }} + {{ $types = $types | append .title}} + {{ else }} + {{ $types = $types | append .type }} + {{ end }} + {{ end }} + {{ $type_of = delimit $types ", "}} + {{ else }} + {{ $type_of = $schema.items.title }} + {{ end }} +

Array of {{ $type_of }}.

+ {{ end }} + + {{/* + Render object tables for any objects referenced in the request/response. + + This will be a no-op for request/response body types which aren't + objects or arrays. + */}} + {{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" .anchor_base) }} + {{ range $additional_types }} + {{ partial "openapi/render-object-table" . }} + {{ end }} +{{ else }} + {{/* + Show the content types and description. + */}} + {{ partial "openapi/render-content-type" (dict "content_types" .content) }} +{{ end }} + +{{/* + Show all the examples. +*/}} +{{ if eq .kind "request" }} +

Request body example

+{{ end }} + +{{ range $mime, $body := .content }} + {{ $examples := slice }} + + {{/* + Find the examples to display, with the following priority: + + 1. The `examples` field + 2. The `example` field + 3. The examples in the `schema` field + */}} + {{ if $body.examples }} + {{/* This is a map of string to Example Object */}} + {{ range $key, $example := $body.examples }} + {{/* The example is in the `value` field of the object */}} + {{ $examples = $examples | append (slice $example.value) }} + {{ end }} + {{ else if $body.example }} + {{ $examples = slice $body.example }} + {{ else if $body.schema }} + {{ $examples = partial "json-schema/resolve-examples" $body.schema }} + {{ end }} + + {{ range $examples }} + {{ partial "render-example" (dict "example" . "mime" $mime) }} + {{ end }} +{{ end }} diff --git a/layouts/partials/openapi/render-request.html b/layouts/partials/openapi/render-request.html index 80b352c6..88749cbf 100644 --- a/layouts/partials/openapi/render-request.html +++ b/layouts/partials/openapi/render-request.html @@ -33,65 +33,8 @@ {{ if $request_body }}

Request body

- {{/* - A request can have several content types. - */}} - {{ $json_body := index $request_body.content "application/json" }} - {{ if $json_body }} - {{/* - Display the JSON schemas - */}} - {{ $schema := $json_body.schema }} - {{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor) }} - {{ range $additional_types }} - {{ partial "openapi/render-object-table" . }} - {{ end }} - {{ else }} - {{/* - Show the content types and description. - */}} - {{ partial "openapi/render-content-type" (dict "content_types" $request_body.content) }} - {{ end }} - -

Request body example

- {{/* - Show all the examples. - */}} - {{ range $mime, $body := $request_body.content }} - {{ $example := dict }} - - {{ if $body.schema }} - {{ $example = partial "json-schema/resolve-example" $body.schema }} - {{ end }} - - {{ if and (eq ($example | len) 0) $body.example }} - {{/* - If no example was generated from the schema, fallback to the - main example. - */}} - {{ $example = $body.example }} - {{ end }} - - {{ if eq $mime "application/json" }} - {{ $example_json := jsonify (dict "indent" " ") $example }} - {{ $example_json = replace $example_json "\\u003c" "<" }} - {{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }} -```json -{{ $example_json }} -``` - {{ else }} - {{ $example = $example | safeHTML }} - {{/* - We need to set a language for the code otherwise the styling - is different than other examples. - */}} -```json -{{ $example }} -``` - {{ end }} - - {{ end }} + {{ partial "openapi/render-media-type-objects" (dict "content" $request_body.content "kind" "request" "anchor_base" $anchor) }} {{ end }} {{ else }} diff --git a/layouts/partials/openapi/render-responses.html b/layouts/partials/openapi/render-responses.html index 084e9481..0e7f1324 100644 --- a/layouts/partials/openapi/render-responses.html +++ b/layouts/partials/openapi/render-responses.html @@ -59,72 +59,6 @@ {{ partial "openapi/render-object-table" (dict "title" "Headers" "properties" $headers_dict) }} {{ end }} - {{/* - A response can have several content types. - */}} - {{ $json_body := index $response.content "application/json" }} - {{ if $json_body }} - {{/* - Display the JSON schemas - */}} - - {{ $schema := $json_body.schema }} - - {{/* - All this is to work out how to express the content of the response - in the case where it is an array. - */}} - {{ if eq $schema.type "array" }} - {{ $type_of := "" }} - {{ if $schema.items.anyOf }} - {{ $types := slice }} - {{ range $schema.items.anyOf }} - {{ if .title }} - {{ $types = $types | append .title}} - {{ else }} - {{ $types = $types | append .type }} - {{ end }} - {{ end }} - {{ $type_of = delimit $types ", "}} - {{ else }} - {{ $type_of = $schema.items.title }} - {{ end }} -

Array of {{ $type_of }}.

- {{ end }} - - - {{/* - render object tables for any objects referenced in the - response. (This will be a no-op for response types which aren't - objects or arrays.) - */}} - {{ $additional_types := partial "json-schema/resolve-additional-types" (dict "schema" $schema "anchor_base" $anchor) }} - {{ range $additional_types }} - {{ partial "openapi/render-object-table" . }} - {{ end }} - - {{/* - render an example. currently this is only supported for arrays and objects. - */}} - {{ if or (eq $schema.type "object") (eq $schema.type "array") }} - {{ $example := partial "json-schema/resolve-example" $schema }} - {{ if $json_body.examples }} - {{ $example = $json_body.examples.response.value }} - {{ end }} - - {{ $example_json := jsonify (dict "indent" " ") $example }} - {{ $example_json = replace $example_json "\\u003c" "<" }} - {{ $example_json = replace $example_json "\\u003e" ">" | safeHTML }} - -```json -{{ $example_json }} -``` - {{ end }} - {{ else }} - {{/* - Show the content types and description. - */}} - {{ partial "openapi/render-content-type" (dict "content_types" $response.content) }} - {{ end }} + {{ partial "openapi/render-media-type-objects" (dict "content" $response.content "kind" "response" "anchor_base" $anchor) }} {{ end }} {{ end }} diff --git a/layouts/partials/render-example.html b/layouts/partials/render-example.html new file mode 100644 index 00000000..1f6c18fb --- /dev/null +++ b/layouts/partials/render-example.html @@ -0,0 +1,40 @@ +{{/* + + Renders an example to be included in HTML, with support for pretty-printing + JSON. + + Parameters: + + * `example`: the example + * `mime`: the mime type of the example. Used to pretty-print JSON and for + syntax highlighting. If it is not provided, it is assumed to be + `application/json`. + +*/}} + +{{ $example := .example }} + +{{/* + We need to convert the mime type to a recognized language. + For simplicity we only support JSON, which is also the default. Other mime + types are not highlighted. +*/}} +{{ $language := "json" }} + +{{ if (and .mime (ne .mime "application/json")) }} + {{/* + `no-highlight` treats the value as plain text, but still styles the code + block like the ones with proper syntax highlighting. + */}} + {{ $language = "no-highlight" }} +{{ end }} + +{{ if eq $language "json" }} + {{ $example = jsonify (dict "indent" " ") $example }} + {{ $example = replace $example "\\u003c" "<" }} + {{ $example = replace $example "\\u003e" ">" }} +{{ end }} + +```{{ $language }} +{{ $example | safeHTML }} +``` diff --git a/layouts/shortcodes/definition.html b/layouts/shortcodes/definition.html index 10ad0e87..1a9643d9 100644 --- a/layouts/shortcodes/definition.html +++ b/layouts/shortcodes/definition.html @@ -58,13 +58,14 @@ {{ partial "openapi/render-object-table" . }} {{end}} +{{ $examples := partial "json-schema/resolve-examples" $definition }} +{{ if $examples }}

Examples

-{{ $example := partial "json-schema/resolve-example" $definition }} - -```json -{{ jsonify (dict "indent" " ") $example }} -``` + {{ range $examples }} + {{ partial "render-example" (dict "example" .) }} + {{ end }} +{{ end }} From 02a1aeefbcd4acde25569f80358c301a227a957e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:52:40 +0100 Subject: [PATCH 10/67] Deduplicate `RoomKeysUpdateResponse` (#2073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And add a link to the endpoint that is mentionned while we're at it. Signed-off-by: Kévin Commaille --- .../internal/newsfragments/2073.clarification | 1 + data/api/client-server/key_backup.yaml | 122 ++++-------------- 2 files changed, 27 insertions(+), 96 deletions(-) create mode 100644 changelogs/internal/newsfragments/2073.clarification diff --git a/changelogs/internal/newsfragments/2073.clarification b/changelogs/internal/newsfragments/2073.clarification new file mode 100644 index 00000000..64dbc6c4 --- /dev/null +++ b/changelogs/internal/newsfragments/2073.clarification @@ -0,0 +1 @@ +Deduplicate the definition of `RoomKeysUpdateResponse`. diff --git a/data/api/client-server/key_backup.yaml b/data/api/client-server/key_backup.yaml index 64833f6e..cd597f88 100644 --- a/data/api/client-server/key_backup.yaml +++ b/data/api/client-server/key_backup.yaml @@ -438,22 +438,7 @@ paths: content: application/json: schema: - type: object - title: RoomKeysUpdateResponse - properties: - etag: - description: |- - The new etag value representing stored keys in the backup. - See `GET /room_keys/version/{version}` for more details. - type: string - example: abcdefg - count: - description: The number of keys stored in the backup - type: integer - example: 10 - required: - - etag - - count + $ref: "#/components/schemas/RoomKeysUpdateResponse" "403": description: |- The version specified does not match the current backup version. @@ -571,22 +556,7 @@ paths: content: application/json: schema: - type: object - title: RoomKeysUpdateResponse - properties: - etag: - description: |- - The new etag value representing stored keys in the backup. - See `GET /room_keys/version/{version}` for more details. - type: string - example: abcdefg - count: - description: The number of keys stored in the backup - type: integer - example: 10 - required: - - etag - - count + $ref: "#/components/schemas/RoomKeysUpdateResponse" "404": description: The backup was not found. content: @@ -644,22 +614,7 @@ paths: content: application/json: schema: - type: object - title: RoomKeysUpdateResponse - properties: - etag: - description: |- - The new etag value representing stored keys in the backup. - See `GET /room_keys/version/{version}` for more details. - type: string - example: abcdefg - count: - description: The number of keys stored in the backup - type: integer - example: 10 - required: - - etag - - count + $ref: "#/components/schemas/RoomKeysUpdateResponse" "403": description: |- The version specified does not match the current backup version. @@ -778,22 +733,7 @@ paths: content: application/json: schema: - type: object - title: RoomKeysUpdateResponse - properties: - etag: - description: |- - The new etag value representing stored keys in the backup. - See `GET /room_keys/version/{version}` for more details. - type: string - example: abcdefg - count: - description: The number of keys stored in the backup - type: integer - example: 10 - required: - - etag - - count + $ref: "#/components/schemas/RoomKeysUpdateResponse" "404": description: The backup was not found. content: @@ -866,22 +806,7 @@ paths: content: application/json: schema: - type: object - title: RoomKeysUpdateResponse - properties: - etag: - description: |- - The new etag value representing stored keys in the backup. - See `GET /room_keys/version/{version}` for more details. - type: string - example: abcdefg - count: - description: The number of keys stored in the backup - type: integer - example: 10 - required: - - etag - - count + $ref: "#/components/schemas/RoomKeysUpdateResponse" "403": description: |- The version specified does not match the current backup version. @@ -1007,22 +932,7 @@ paths: content: application/json: schema: - type: object - title: RoomKeysUpdateResponse - properties: - etag: - description: |- - The new etag value representing stored keys in the backup. - See `GET /room_keys/version/{version}` for more details. - type: string - example: abcdefg - count: - description: The number of keys stored in the backup - type: integer - example: 10 - required: - - etag - - count + $ref: "#/components/schemas/RoomKeysUpdateResponse" "404": description: The backup was not found. content: @@ -1056,6 +966,26 @@ servers: basePath: default: /_matrix/client/v3 components: + schemas: + RoomKeysUpdateResponse: + type: object + title: RoomKeysUpdateResponse + properties: + etag: + description: |- + The new etag value representing stored keys in the backup. + + See [`GET /room_keys/version/{version}`](client-server-api/#get_matrixclientv3room_keysversionversion) + for more details. + type: string + example: abcdefg + count: + description: The number of keys stored in the backup + type: integer + example: 10 + required: + - etag + - count securitySchemes: accessTokenQuery: $ref: definitions/security.yaml#/accessTokenQuery From 1916e53f8cd4c94f18c721662e0547ecd1ca2e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:56:49 +0100 Subject: [PATCH 11/67] Deduplicate `Invite3pid` (#2074) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Deduplicate Invite3pid Signed-off-by: Kévin Commaille --- .../internal/newsfragments/2074.clarification | 1 + data/api/client-server/create_room.yaml | 27 +---------- .../definitions/invite_3pid.yaml | 45 +++++++++++++++++++ .../client-server/third_party_membership.yaml | 32 +------------ 4 files changed, 48 insertions(+), 57 deletions(-) create mode 100644 changelogs/internal/newsfragments/2074.clarification create mode 100644 data/api/client-server/definitions/invite_3pid.yaml diff --git a/changelogs/internal/newsfragments/2074.clarification b/changelogs/internal/newsfragments/2074.clarification new file mode 100644 index 00000000..4f941dd2 --- /dev/null +++ b/changelogs/internal/newsfragments/2074.clarification @@ -0,0 +1 @@ +Deduplicate the definitions of `Invite3pid`. diff --git a/data/api/client-server/create_room.yaml b/data/api/client-server/create_room.yaml index 9e36d5e8..3992fdfe 100644 --- a/data/api/client-server/create_room.yaml +++ b/data/api/client-server/create_room.yaml @@ -131,32 +131,7 @@ paths: A list of objects representing third-party IDs to invite into the room. items: - type: object - title: Invite3pid - properties: - id_server: - type: string - description: The hostname+port of the identity server which should be used for - third-party identifier lookups. - id_access_token: - type: string - description: |- - An access token previously registered with the identity server. Servers - can treat this as optional to distinguish between r0.5-compatible clients - and this specification version. - medium: - type: string - description: |- - The kind of address being passed in the address field, for example `email` - (see [the list of recognised values](/appendices/#3pid-types)). - address: - type: string - description: The invitee's third-party identifier. - required: - - id_server - - id_access_token - - medium - - address + $ref: definitions/invite_3pid.yaml room_version: type: string description: |- diff --git a/data/api/client-server/definitions/invite_3pid.yaml b/data/api/client-server/definitions/invite_3pid.yaml new file mode 100644 index 00000000..f00f15c5 --- /dev/null +++ b/data/api/client-server/definitions/invite_3pid.yaml @@ -0,0 +1,45 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +type: object +title: Invite3pid +properties: + id_server: + type: string + description: The hostname+port of the identity server which should be used for + third-party identifier lookups. + id_access_token: + type: string + description: |- + An access token previously registered with the identity server. Servers + can treat this as optional to distinguish between r0.5-compatible clients + and this specification version. + medium: + type: string + description: |- + The kind of address being passed in the address field, for example `email` + (see [the list of recognised values](/appendices/#3pid-types)). + address: + type: string + description: The invitee's third-party identifier. +required: + - id_server + - id_access_token + - medium + - address +example: { + "id_server": "matrix.org", + "id_access_token": "abc123_OpaqueString", + "medium": "email", + "address": "cheeky@monkey.com" +} \ No newline at end of file diff --git a/data/api/client-server/third_party_membership.yaml b/data/api/client-server/third_party_membership.yaml index ea366648..65148ee0 100644 --- a/data/api/client-server/third_party_membership.yaml +++ b/data/api/client-server/third_party_membership.yaml @@ -76,37 +76,7 @@ paths: content: application/json: schema: - type: object - example: { - "id_server": "matrix.org", - "id_access_token": "abc123_OpaqueString", - "medium": "email", - "address": "cheeky@monkey.com" - } - properties: - id_server: - type: string - description: The hostname+port of the identity server which should be used for - third-party identifier lookups. - id_access_token: - type: string - description: |- - An access token previously registered with the identity server. Servers - can treat this as optional to distinguish between r0.5-compatible clients - and this specification version. - medium: - type: string - description: |- - The kind of address being passed in the address field, for example - `email` (see [the list of recognised values](/appendices/#3pid-types)). - address: - type: string - description: The invitee's third-party identifier. - required: - - id_server - - id_access_token - - medium - - address + $ref: definitions/invite_3pid.yaml required: true responses: "200": From e283c35dbda8661f748cb978e6ab5493d8a03fdd Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 5 Mar 2025 15:12:15 +0100 Subject: [PATCH 12/67] Remove extra trailing quotes from sync API specs (#2091) Signed-off-by: Johannes Marbach --- changelogs/client_server/newsfragments/2091.clarification | 1 + data/api/client-server/old_sync.yaml | 2 +- data/api/client-server/room_initial_sync.yaml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2091.clarification diff --git a/changelogs/client_server/newsfragments/2091.clarification b/changelogs/client_server/newsfragments/2091.clarification new file mode 100644 index 00000000..3ccb2333 --- /dev/null +++ b/changelogs/client_server/newsfragments/2091.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/data/api/client-server/old_sync.yaml b/data/api/client-server/old_sync.yaml index 0a3c0439..118087c0 100644 --- a/data/api/client-server/old_sync.yaml +++ b/data/api/client-server/old_sync.yaml @@ -214,7 +214,7 @@ paths: - public description: |- Whether this room is visible to the `/publicRooms` API - or not." + or not. account_data: type: array description: |- diff --git a/data/api/client-server/room_initial_sync.yaml b/data/api/client-server/room_initial_sync.yaml index 130efa1c..e9ad7a63 100644 --- a/data/api/client-server/room_initial_sync.yaml +++ b/data/api/client-server/room_initial_sync.yaml @@ -96,7 +96,7 @@ paths: - public description: |- Whether this room is visible to the `/publicRooms` API - or not." + or not. account_data: type: array description: The private data that this user has attached to this room. From 7fd49a2808523b6a4436bea9a2f2dbd2c7b1b51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Thu, 20 Mar 2025 19:00:33 +0100 Subject: [PATCH 13/67] Set room version 11 as the default (#2105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Set room version 11 as the default As per MSC4239 Signed-off-by: Kévin Commaille * Add changelog Signed-off-by: Kévin Commaille --------- Signed-off-by: Kévin Commaille --- changelogs/room_versions/newsfragments/2105.feature | 1 + content/rooms/_index.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/room_versions/newsfragments/2105.feature diff --git a/changelogs/room_versions/newsfragments/2105.feature b/changelogs/room_versions/newsfragments/2105.feature new file mode 100644 index 00000000..9e13a36c --- /dev/null +++ b/changelogs/room_versions/newsfragments/2105.feature @@ -0,0 +1 @@ +Update the default room version to 11, as per [MSC4239](https://github.com/matrix-org/matrix-spec-proposals/pull/4239). diff --git a/content/rooms/_index.md b/content/rooms/_index.md index 9334c3a1..d970bfe7 100644 --- a/content/rooms/_index.md +++ b/content/rooms/_index.md @@ -52,7 +52,7 @@ stable and unstable periodically for a variety of reasons, including discovered security vulnerabilities and age. Clients should not ask room administrators to upgrade their rooms if the -room is running a stable version. Servers SHOULD use **room version 10** as +room is running a stable version. Servers SHOULD use **room version 11** as the default room version when creating new rooms. The available room versions are: From c7581356bf65607939877e37c17b28a220e0310b Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Fri, 21 Mar 2025 20:33:26 +0100 Subject: [PATCH 14/67] MSC4260: Reporting users (Client-Server API) (#2093) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * MSC4260: Reporting users (Client-Server API) Signed-off-by: Johannes Marbach * Add changelog * Update data/api/client-server/report_content.yaml Co-authored-by: Kévin Commaille <76261501+zecakeh@users.noreply.github.com> * Move option to consistently respond with 200 to user reporting endpoint * Move optional random delay to event and user reporting endpoints * Make reason required for user and room reports * Fix requiredness syntax --------- Signed-off-by: Johannes Marbach Co-authored-by: Kévin Commaille <76261501+zecakeh@users.noreply.github.com> --- .../client_server/newsfragments/2093.new | 1 + .../modules/report_content.md | 6 ++ data/api/client-server/report_content.yaml | 97 +++++++++++++++++-- 3 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2093.new diff --git a/changelogs/client_server/newsfragments/2093.new b/changelogs/client_server/newsfragments/2093.new new file mode 100644 index 00000000..28c03ffc --- /dev/null +++ b/changelogs/client_server/newsfragments/2093.new @@ -0,0 +1 @@ +Add `POST /_matrix/client/v3/users/{userId}/report` as per [MSC4260](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). \ No newline at end of file diff --git a/content/client-server-api/modules/report_content.md b/content/client-server-api/modules/report_content.md index 6f34e938..ab0e011b 100644 --- a/content/client-server-api/modules/report_content.md +++ b/content/client-server-api/modules/report_content.md @@ -29,3 +29,9 @@ is in before accepting a report. based on whether or not the reporting user is joined to the room. This is because users can be exposed to harmful content without being joined to a room. For instance, through room directories or invites. + +{{% added-in v="1.14" %}} Similarly, servers MUST NOT restrict user reports +based on whether or not the reporting user is joined to any rooms that the +reported user is joined to. This is because users can be exposed to harmful +content without being joined to a room. For instance, through user +directories or invites. diff --git a/data/api/client-server/report_content.yaml b/data/api/client-server/report_content.yaml index 654784ca..4934ef3f 100644 --- a/data/api/client-server/report_content.yaml +++ b/data/api/client-server/report_content.yaml @@ -45,7 +45,9 @@ paths: properties: reason: type: string - description: The reason the room is being reported. + description: The reason the room is being reported. May be blank. + required: + - reason required: true security: - accessTokenQuery: [] @@ -88,12 +90,11 @@ paths: Reports an event as inappropriate to the server, which may then notify the appropriate people. The caller must be joined to the room to report it. - - It might be possible for clients to deduce whether an event exists by - timing the response, as only a report for an event that does exist - will require the homeserver to check whether a user is joined to - the room. To combat this, homeserver implementations should add - a random delay when generating a response. + + Furthermore, it might be possible for clients to deduce whether a reported + event exists by timing the response. This is because only a report for an + existing event will require the homeserver to do further processing. To + combat this, homeservers MAY add a random delay when generating a response. operationId: reportEvent parameters: - in: path @@ -164,6 +165,88 @@ paths: } tags: - Reporting content + "/users/{userId}/report": + post: + x-addedInMatrixVersion: "1.14" + summary: Report a user as inappropriate. + description: |- + Reports a user as inappropriate to the server, which may then notify + the appropriate people. How such information is delivered is left up to + implementations. The caller is not required to be joined to any rooms + that the reported user is joined to. + + Clients may wish to [ignore](#ignoring-users) users after reporting them. + + Clients could infer whether a reported user exists based on the 404 response. + Homeservers that wish to conceal this information MAY return 200 responses + regardless of the existence of the reported user. + + Furthermore, it might be possible for clients to deduce whether a reported + user exists by timing the response. This is because only a report for an + existing user will require the homeserver to do further processing. To + combat this, homeservers MAY add a random delay when generating a response. + operationId: reportUser + parameters: + - in: path + name: userId + description: The user being reported. + required: true + example: "@someguy:example.com" + schema: + type: string + format: mx-user-id + pattern: "^@" + requestBody: + content: + application/json: + schema: + type: object + example: { + "reason": "this makes me sad" + } + properties: + reason: + type: string + description: The reason the room is being reported. May be blank. + required: + - reason + required: true + security: + - accessTokenQuery: [] + - accessTokenBearer: [] + responses: + "200": + description: | + The user has been reported successfully or the server chose + to not disclose whether the users exists. + content: + application/json: + schema: + type: object + examples: + response: + value: {} + "404": + description: |- + The user was not found on the homeserver. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_NOT_FOUND", + "error": "The user was not found." + } + "429": + description: This request was rate-limited. + content: + application/json: + schema: + $ref: definitions/errors/rate_limited.yaml + tags: + - Reporting content servers: - url: "{protocol}://{hostname}{basePath}" variables: From cb6d039c57d07ea489577d9234813c39e93a2243 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 25 Mar 2025 15:40:04 -0600 Subject: [PATCH 15/67] Normalize changelog --- changelogs/client_server/newsfragments/2051.clarification | 3 +-- changelogs/client_server/newsfragments/2059.removal | 2 +- changelogs/client_server/newsfragments/2093.new | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/changelogs/client_server/newsfragments/2051.clarification b/changelogs/client_server/newsfragments/2051.clarification index e8f7a70c..30cdbc73 100644 --- a/changelogs/client_server/newsfragments/2051.clarification +++ b/changelogs/client_server/newsfragments/2051.clarification @@ -1,2 +1 @@ -Document the `instance_id` field of `Protocol Instance` in the responses to -`GET /_matrix/client/v3/thirdparty/protocols` and `GET /_matrix/client/v3/thirdparty/protocol/{protocol}`. +Document the `instance_id` field of `Protocol Instance` in the responses to `GET /_matrix/client/v3/thirdparty/protocols` and `GET /_matrix/client/v3/thirdparty/protocol/{protocol}`. diff --git a/changelogs/client_server/newsfragments/2059.removal b/changelogs/client_server/newsfragments/2059.removal index 94db06f8..1075c2e0 100644 --- a/changelogs/client_server/newsfragments/2059.removal +++ b/changelogs/client_server/newsfragments/2059.removal @@ -1 +1 @@ -Remove `server_name` parameter from `/_matrix/client/v3/join/{roomIdOrAlias}` and `/_matrix/client/v3/knock/{roomIdOrAlias}` as per [MSC4213](https://github.com/matrix-org/matrix-spec-proposals/pull/4213). +Remove `server_name` parameter from `/_matrix/client/v3/join/{roomIdOrAlias}` and `/_matrix/client/v3/knock/{roomIdOrAlias}`, as per [MSC4213](https://github.com/matrix-org/matrix-spec-proposals/pull/4213). diff --git a/changelogs/client_server/newsfragments/2093.new b/changelogs/client_server/newsfragments/2093.new index 28c03ffc..931b93ae 100644 --- a/changelogs/client_server/newsfragments/2093.new +++ b/changelogs/client_server/newsfragments/2093.new @@ -1 +1 @@ -Add `POST /_matrix/client/v3/users/{userId}/report` as per [MSC4260](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). \ No newline at end of file +Add `POST /_matrix/client/v3/users/{userId}/report`, as per [MSC4260](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). \ No newline at end of file From 71ce620fc093e92b5a4ad23ea91c1cb2a09ab1b6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Mar 2025 10:23:09 -0600 Subject: [PATCH 16/67] Add a v6 event format with correct `depth` limits (#2114) * Add a v6 event format with correct `depth` limits * Changelog * numbers are hard --- .../newsfragments/2114.clarification | 1 + content/rooms/fragments/v6-event-format.md | 4 +++ content/rooms/v10.md | 2 +- content/rooms/v6.md | 11 +++--- content/rooms/v7.md | 2 +- content/rooms/v8.md | 2 +- content/rooms/v9.md | 2 +- .../definitions/components/pdu_base.yaml | 7 ---- .../api/server-server/definitions/pdu_v1.yaml | 7 ++++ .../server-server/definitions/pdu_v11.yaml | 14 ++++++-- .../api/server-server/definitions/pdu_v3.yaml | 7 ++++ .../api/server-server/definitions/pdu_v4.yaml | 7 ++++ .../api/server-server/definitions/pdu_v6.yaml | 36 +++++++++++++++++++ 13 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 changelogs/room_versions/newsfragments/2114.clarification create mode 100644 content/rooms/fragments/v6-event-format.md create mode 100644 data/api/server-server/definitions/pdu_v6.yaml diff --git a/changelogs/room_versions/newsfragments/2114.clarification b/changelogs/room_versions/newsfragments/2114.clarification new file mode 100644 index 00000000..46104473 --- /dev/null +++ b/changelogs/room_versions/newsfragments/2114.clarification @@ -0,0 +1 @@ +Clarify the maximum `depth` value for room versions 6, 7, 8, 9, 10, and 11. \ No newline at end of file diff --git a/content/rooms/fragments/v6-event-format.md b/content/rooms/fragments/v6-event-format.md new file mode 100644 index 00000000..f230ac54 --- /dev/null +++ b/content/rooms/fragments/v6-event-format.md @@ -0,0 +1,4 @@ + +Events in rooms of this version have the following structure: + +{{% definition path="api/server-server/definitions/pdu_v6" %}} diff --git a/content/rooms/v10.md b/content/rooms/v10.md index 974a0822..81daf4d6 100644 --- a/content/rooms/v10.md +++ b/content/rooms/v10.md @@ -281,7 +281,7 @@ completeness. ### Event format -{{% rver-fragment name="v4-event-format" %}} +{{% rver-fragment name="v6-event-format" %}} ### State resolution diff --git a/content/rooms/v6.md b/content/rooms/v6.md index 72007d97..2f728587 100644 --- a/content/rooms/v6.md +++ b/content/rooms/v6.md @@ -39,6 +39,13 @@ in [room version 5](/rooms/v5). [See above](#redactions). +### Event format + +{{% added-in v=6 %}} Through enforcement of [Canonical JSON](#canonical-json), +the `depth` limit has been reduced in this room version. + +{{% rver-fragment name="v6-event-format" %}} + ### Authorization rules {{% added-in v=6 %}} Rule 4, which related specifically to events @@ -229,10 +236,6 @@ completeness. {{% rver-fragment name="v4-event-ids" %}} -### Event format - -{{% rver-fragment name="v4-event-format" %}} - #### Deprecated event content schemas {{% rver-fragment name="v1-deprecated-formatting-off-spec" %}} diff --git a/content/rooms/v7.md b/content/rooms/v7.md index ba711c55..34e2a8eb 100644 --- a/content/rooms/v7.md +++ b/content/rooms/v7.md @@ -225,7 +225,7 @@ completeness. ### Event format -{{% rver-fragment name="v4-event-format" %}} +{{% rver-fragment name="v6-event-format" %}} #### Deprecated event content schemas diff --git a/content/rooms/v8.md b/content/rooms/v8.md index c6c116a8..aabf88c5 100644 --- a/content/rooms/v8.md +++ b/content/rooms/v8.md @@ -109,7 +109,7 @@ completeness. ### Event format -{{% rver-fragment name="v4-event-format" %}} +{{% rver-fragment name="v6-event-format" %}} #### Deprecated event content schemas diff --git a/content/rooms/v9.md b/content/rooms/v9.md index 582ff6b4..ac3288a1 100644 --- a/content/rooms/v9.md +++ b/content/rooms/v9.md @@ -74,7 +74,7 @@ completeness. ### Event format -{{% rver-fragment name="v4-event-format" %}} +{{% rver-fragment name="v6-event-format" %}} #### Deprecated event content schemas diff --git a/data/api/server-server/definitions/components/pdu_base.yaml b/data/api/server-server/definitions/components/pdu_base.yaml index 4b676c8f..be275611 100644 --- a/data/api/server-server/definitions/components/pdu_base.yaml +++ b/data/api/server-server/definitions/components/pdu_base.yaml @@ -41,13 +41,6 @@ properties: type: object description: The content of the event. example: {"key": "value"} - depth: - type: integer - description: |- - The maximum depth of the `prev_events`, plus one. Must be less than the - maximum value for an integer (2^63 - 1). If the room's depth is already at - the limit, the depth must be set to the limit. - example: 12 hashes: $ref: "event_hash.yaml" signatures: diff --git a/data/api/server-server/definitions/pdu_v1.yaml b/data/api/server-server/definitions/pdu_v1.yaml index b9ba8cc1..d2fb2ef9 100644 --- a/data/api/server-server/definitions/pdu_v1.yaml +++ b/data/api/server-server/definitions/pdu_v1.yaml @@ -28,6 +28,13 @@ allOf: type: string description: For redaction events, the ID of the event being redacted. example: "$def456:matrix.org" + depth: + type: integer + description: |- + The maximum depth of the `prev_events`, plus one. Must be less than the + maximum value for an integer (2^63 - 1). If the room's depth is already at + the limit, the depth must be set to the limit. + example: 12 auth_events: type: array description: |- diff --git a/data/api/server-server/definitions/pdu_v11.yaml b/data/api/server-server/definitions/pdu_v11.yaml index a3db6ee9..409b99c6 100644 --- a/data/api/server-server/definitions/pdu_v11.yaml +++ b/data/api/server-server/definitions/pdu_v11.yaml @@ -17,6 +17,16 @@ description: A persistent data unit (event) for room version 11 and beyond. example: $ref: "../examples/pdu_v11.json" allOf: - # v11 is the v4 event, but without redacts. + # v11 is the v6 event, but without redacts. - $ref: "components/pdu_base.yaml" - - $ref: "components/auth_events_prev_events_v4.yaml" \ No newline at end of file + - $ref: "components/auth_events_prev_events_v4.yaml" + - type: object + properties: + # v6 enforces Canonical JSON and therefore needs a depth limit change + depth: + type: integer + description: |- + The maximum depth of the `prev_events`, plus one. Must be less than the + maximum value for an integer (2^53 - 1). If the room's depth is already at + the limit, the depth must be set to the limit. + example: 12 \ No newline at end of file diff --git a/data/api/server-server/definitions/pdu_v3.yaml b/data/api/server-server/definitions/pdu_v3.yaml index 69d8900c..ccca717b 100644 --- a/data/api/server-server/definitions/pdu_v3.yaml +++ b/data/api/server-server/definitions/pdu_v3.yaml @@ -24,6 +24,13 @@ allOf: type: string description: For redaction events, the ID of the event being redacted. example: "$def/456+oldevent" + depth: + type: integer + description: |- + The maximum depth of the `prev_events`, plus one. Must be less than the + maximum value for an integer (2^63 - 1). If the room's depth is already at + the limit, the depth must be set to the limit. + example: 12 auth_events: type: array items: diff --git a/data/api/server-server/definitions/pdu_v4.yaml b/data/api/server-server/definitions/pdu_v4.yaml index e859ee86..2edf1b31 100644 --- a/data/api/server-server/definitions/pdu_v4.yaml +++ b/data/api/server-server/definitions/pdu_v4.yaml @@ -26,3 +26,10 @@ allOf: type: string description: For redaction events, the ID of the event being redacted. example: "$def_456-oldevent" + depth: + type: integer + description: |- + The maximum depth of the `prev_events`, plus one. Must be less than the + maximum value for an integer (2^63 - 1). If the room's depth is already at + the limit, the depth must be set to the limit. + example: 12 diff --git a/data/api/server-server/definitions/pdu_v6.yaml b/data/api/server-server/definitions/pdu_v6.yaml new file mode 100644 index 00000000..1278a6e3 --- /dev/null +++ b/data/api/server-server/definitions/pdu_v6.yaml @@ -0,0 +1,36 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +type: object +title: Persistent Data Unit +description: |- + A persistent data unit (event) for room versions 4, 5, 6, 7, 8, 9 and 10. +example: + $ref: "../examples/pdu_v4.json" +allOf: + - $ref: "components/pdu_base.yaml" + - $ref: "components/auth_events_prev_events_v4.yaml" + - type: object + properties: + redacts: + type: string + description: For redaction events, the ID of the event being redacted. + example: "$def_456-oldevent" + # v6 enforces Canonical JSON and therefore needs a depth limit change + depth: + type: integer + description: |- + The maximum depth of the `prev_events`, plus one. Must be less than the + maximum value for an integer (2^53 - 1). If the room's depth is already at + the limit, the depth must be set to the limit. + example: 12 From fe880fdaf4f7f8c4f95fe56ea5a0a1ce9498f270 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Mar 2025 10:28:55 -0600 Subject: [PATCH 17/67] v1.14 --- .../newsfragments/1506.clarification | 1 - .../newsfragments/2036.clarification | 1 - .../newsfragments/2038.clarification | 1 - .../newsfragments/2046.clarification | 1 - .../newsfragments/2047.clarification | 1 - .../newsfragments/2048.clarification | 1 - .../newsfragments/2051.clarification | 1 - .../newsfragments/2055.clarification | 1 - .../client_server/newsfragments/2059.removal | 1 - .../newsfragments/2064.clarification | 1 - .../newsfragments/2072.clarification | 1 - .../newsfragments/2080.clarification | 1 - .../newsfragments/2091.clarification | 1 - .../client_server/newsfragments/2093.new | 1 - .../internal/newsfragments/2033.clarification | 1 - .../internal/newsfragments/2041.clarification | 1 - .../internal/newsfragments/2042.clarification | 1 - .../internal/newsfragments/2045.clarification | 1 - .../internal/newsfragments/2049.clarification | 1 - .../internal/newsfragments/2061.clarification | 1 - .../internal/newsfragments/2069.clarification | 1 - .../internal/newsfragments/2073.clarification | 1 - .../internal/newsfragments/2074.clarification | 1 - .../internal/newsfragments/2076.clarification | 1 - .../internal/newsfragments/2078.clarification | 1 - .../newsfragments/2065.clarification | 1 - .../newsfragments/2066.clarification | 1 - .../newsfragments/2070.clarification | 1 - .../room_versions/newsfragments/2105.feature | 1 - .../newsfragments/2114.clarification | 1 - .../newsfragments/2050.clarification | 1 - .../newsfragments/2063.clarification | 1 - .../newsfragments/2076.clarification | 1 - config/_default/hugo.toml | 6 +- content/changelog/v1.14.md | 93 +++++++++++++++++++ 35 files changed, 96 insertions(+), 36 deletions(-) delete mode 100644 changelogs/appendices/newsfragments/1506.clarification delete mode 100644 changelogs/client_server/newsfragments/2036.clarification delete mode 100644 changelogs/client_server/newsfragments/2038.clarification delete mode 100644 changelogs/client_server/newsfragments/2046.clarification delete mode 100644 changelogs/client_server/newsfragments/2047.clarification delete mode 100644 changelogs/client_server/newsfragments/2048.clarification delete mode 100644 changelogs/client_server/newsfragments/2051.clarification delete mode 100644 changelogs/client_server/newsfragments/2055.clarification delete mode 100644 changelogs/client_server/newsfragments/2059.removal delete mode 100644 changelogs/client_server/newsfragments/2064.clarification delete mode 100644 changelogs/client_server/newsfragments/2072.clarification delete mode 100644 changelogs/client_server/newsfragments/2080.clarification delete mode 100644 changelogs/client_server/newsfragments/2091.clarification delete mode 100644 changelogs/client_server/newsfragments/2093.new delete mode 100644 changelogs/internal/newsfragments/2033.clarification delete mode 100644 changelogs/internal/newsfragments/2041.clarification delete mode 100644 changelogs/internal/newsfragments/2042.clarification delete mode 100644 changelogs/internal/newsfragments/2045.clarification delete mode 100644 changelogs/internal/newsfragments/2049.clarification delete mode 100644 changelogs/internal/newsfragments/2061.clarification delete mode 100644 changelogs/internal/newsfragments/2069.clarification delete mode 100644 changelogs/internal/newsfragments/2073.clarification delete mode 100644 changelogs/internal/newsfragments/2074.clarification delete mode 100644 changelogs/internal/newsfragments/2076.clarification delete mode 100644 changelogs/internal/newsfragments/2078.clarification delete mode 100644 changelogs/room_versions/newsfragments/2065.clarification delete mode 100644 changelogs/room_versions/newsfragments/2066.clarification delete mode 100644 changelogs/room_versions/newsfragments/2070.clarification delete mode 100644 changelogs/room_versions/newsfragments/2105.feature delete mode 100644 changelogs/room_versions/newsfragments/2114.clarification delete mode 100644 changelogs/server_server/newsfragments/2050.clarification delete mode 100644 changelogs/server_server/newsfragments/2063.clarification delete mode 100644 changelogs/server_server/newsfragments/2076.clarification create mode 100644 content/changelog/v1.14.md diff --git a/changelogs/appendices/newsfragments/1506.clarification b/changelogs/appendices/newsfragments/1506.clarification deleted file mode 100644 index 41ef5ac4..00000000 --- a/changelogs/appendices/newsfragments/1506.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that arbitrary unicode is allowed in user/room IDs and room aliases. diff --git a/changelogs/client_server/newsfragments/2036.clarification b/changelogs/client_server/newsfragments/2036.clarification deleted file mode 100644 index 9e586ae0..00000000 --- a/changelogs/client_server/newsfragments/2036.clarification +++ /dev/null @@ -1 +0,0 @@ -The `POST /_matrix/client/v3/rooms/{roomId}/initialSync` endpoint is no longer deprecated, as it is still used for peeking. diff --git a/changelogs/client_server/newsfragments/2038.clarification b/changelogs/client_server/newsfragments/2038.clarification deleted file mode 100644 index 169ca65c..00000000 --- a/changelogs/client_server/newsfragments/2038.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify wording in the `/join` endpoints' summaries and descriptions. Contributed by @HarHarLinks. diff --git a/changelogs/client_server/newsfragments/2046.clarification b/changelogs/client_server/newsfragments/2046.clarification deleted file mode 100644 index bdcce777..00000000 --- a/changelogs/client_server/newsfragments/2046.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify formats of string types. diff --git a/changelogs/client_server/newsfragments/2047.clarification b/changelogs/client_server/newsfragments/2047.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2047.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2048.clarification b/changelogs/client_server/newsfragments/2048.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2048.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2051.clarification b/changelogs/client_server/newsfragments/2051.clarification deleted file mode 100644 index 30cdbc73..00000000 --- a/changelogs/client_server/newsfragments/2051.clarification +++ /dev/null @@ -1 +0,0 @@ -Document the `instance_id` field of `Protocol Instance` in the responses to `GET /_matrix/client/v3/thirdparty/protocols` and `GET /_matrix/client/v3/thirdparty/protocol/{protocol}`. diff --git a/changelogs/client_server/newsfragments/2055.clarification b/changelogs/client_server/newsfragments/2055.clarification deleted file mode 100644 index f8d79ec9..00000000 --- a/changelogs/client_server/newsfragments/2055.clarification +++ /dev/null @@ -1 +0,0 @@ -Applying redactions is a SHOULD for clients. diff --git a/changelogs/client_server/newsfragments/2059.removal b/changelogs/client_server/newsfragments/2059.removal deleted file mode 100644 index 1075c2e0..00000000 --- a/changelogs/client_server/newsfragments/2059.removal +++ /dev/null @@ -1 +0,0 @@ -Remove `server_name` parameter from `/_matrix/client/v3/join/{roomIdOrAlias}` and `/_matrix/client/v3/knock/{roomIdOrAlias}`, as per [MSC4213](https://github.com/matrix-org/matrix-spec-proposals/pull/4213). diff --git a/changelogs/client_server/newsfragments/2064.clarification b/changelogs/client_server/newsfragments/2064.clarification deleted file mode 100644 index 17cc2890..00000000 --- a/changelogs/client_server/newsfragments/2064.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify which rooms are returned from `/hierarchy`. diff --git a/changelogs/client_server/newsfragments/2072.clarification b/changelogs/client_server/newsfragments/2072.clarification deleted file mode 100644 index ddb9a536..00000000 --- a/changelogs/client_server/newsfragments/2072.clarification +++ /dev/null @@ -1 +0,0 @@ -Clients can choose which history visibility options they offer to users when creating rooms. diff --git a/changelogs/client_server/newsfragments/2080.clarification b/changelogs/client_server/newsfragments/2080.clarification deleted file mode 100644 index ca5f3aea..00000000 --- a/changelogs/client_server/newsfragments/2080.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2091.clarification b/changelogs/client_server/newsfragments/2091.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2091.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2093.new b/changelogs/client_server/newsfragments/2093.new deleted file mode 100644 index 931b93ae..00000000 --- a/changelogs/client_server/newsfragments/2093.new +++ /dev/null @@ -1 +0,0 @@ -Add `POST /_matrix/client/v3/users/{userId}/report`, as per [MSC4260](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2033.clarification b/changelogs/internal/newsfragments/2033.clarification deleted file mode 100644 index 9d3e7596..00000000 --- a/changelogs/internal/newsfragments/2033.clarification +++ /dev/null @@ -1 +0,0 @@ -Generate the changelog release info with Hugo, rather than the changelog generation script. diff --git a/changelogs/internal/newsfragments/2041.clarification b/changelogs/internal/newsfragments/2041.clarification deleted file mode 100644 index fd9a66f7..00000000 --- a/changelogs/internal/newsfragments/2041.clarification +++ /dev/null @@ -1 +0,0 @@ -Update release steps documentation. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2042.clarification b/changelogs/internal/newsfragments/2042.clarification deleted file mode 100644 index 4abe8e4e..00000000 --- a/changelogs/internal/newsfragments/2042.clarification +++ /dev/null @@ -1 +0,0 @@ -Remove unused `release_date` from Hugo config. diff --git a/changelogs/internal/newsfragments/2045.clarification b/changelogs/internal/newsfragments/2045.clarification deleted file mode 100644 index bfe42c51..00000000 --- a/changelogs/internal/newsfragments/2045.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that v1.0 of Matrix was a release prior to the current global versioning system. diff --git a/changelogs/internal/newsfragments/2049.clarification b/changelogs/internal/newsfragments/2049.clarification deleted file mode 100644 index 5a6e90f1..00000000 --- a/changelogs/internal/newsfragments/2049.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix syntax highlighting and click-to-copy buttons for code blocks by purging less CSS. diff --git a/changelogs/internal/newsfragments/2061.clarification b/changelogs/internal/newsfragments/2061.clarification deleted file mode 100644 index 3257cef1..00000000 --- a/changelogs/internal/newsfragments/2061.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix the version of the Identity Service API when Matrix 1.0 was introduced. diff --git a/changelogs/internal/newsfragments/2069.clarification b/changelogs/internal/newsfragments/2069.clarification deleted file mode 100644 index 2ad407fb..00000000 --- a/changelogs/internal/newsfragments/2069.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix parsing of nested slices in `resolve-refs` and `resolve-allof` partials. diff --git a/changelogs/internal/newsfragments/2073.clarification b/changelogs/internal/newsfragments/2073.clarification deleted file mode 100644 index 64dbc6c4..00000000 --- a/changelogs/internal/newsfragments/2073.clarification +++ /dev/null @@ -1 +0,0 @@ -Deduplicate the definition of `RoomKeysUpdateResponse`. diff --git a/changelogs/internal/newsfragments/2074.clarification b/changelogs/internal/newsfragments/2074.clarification deleted file mode 100644 index 4f941dd2..00000000 --- a/changelogs/internal/newsfragments/2074.clarification +++ /dev/null @@ -1 +0,0 @@ -Deduplicate the definitions of `Invite3pid`. diff --git a/changelogs/internal/newsfragments/2076.clarification b/changelogs/internal/newsfragments/2076.clarification deleted file mode 100644 index 3cf1fb94..00000000 --- a/changelogs/internal/newsfragments/2076.clarification +++ /dev/null @@ -1 +0,0 @@ -Support more locations for examples in OpenAPI definitions and JSON schemas. \ No newline at end of file diff --git a/changelogs/internal/newsfragments/2078.clarification b/changelogs/internal/newsfragments/2078.clarification deleted file mode 100644 index d9285d5a..00000000 --- a/changelogs/internal/newsfragments/2078.clarification +++ /dev/null @@ -1 +0,0 @@ -Add link to the git commit for the unstable changelog. diff --git a/changelogs/room_versions/newsfragments/2065.clarification b/changelogs/room_versions/newsfragments/2065.clarification deleted file mode 100644 index e7fc9f20..00000000 --- a/changelogs/room_versions/newsfragments/2065.clarification +++ /dev/null @@ -1 +0,0 @@ -For room versions 6 and 7, clarify in the authorization rules that `m.federate` must be checked and that events with rejected auth events must be rejected, for parity with all the other room versions. diff --git a/changelogs/room_versions/newsfragments/2066.clarification b/changelogs/room_versions/newsfragments/2066.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/room_versions/newsfragments/2066.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/room_versions/newsfragments/2070.clarification b/changelogs/room_versions/newsfragments/2070.clarification deleted file mode 100644 index 7d0208cd..00000000 --- a/changelogs/room_versions/newsfragments/2070.clarification +++ /dev/null @@ -1 +0,0 @@ -Refactor PDU definitions to reduce duplication. diff --git a/changelogs/room_versions/newsfragments/2105.feature b/changelogs/room_versions/newsfragments/2105.feature deleted file mode 100644 index 9e13a36c..00000000 --- a/changelogs/room_versions/newsfragments/2105.feature +++ /dev/null @@ -1 +0,0 @@ -Update the default room version to 11, as per [MSC4239](https://github.com/matrix-org/matrix-spec-proposals/pull/4239). diff --git a/changelogs/room_versions/newsfragments/2114.clarification b/changelogs/room_versions/newsfragments/2114.clarification deleted file mode 100644 index 46104473..00000000 --- a/changelogs/room_versions/newsfragments/2114.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify the maximum `depth` value for room versions 6, 7, 8, 9, 10, and 11. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/2050.clarification b/changelogs/server_server/newsfragments/2050.clarification deleted file mode 100644 index 8c4545d3..00000000 --- a/changelogs/server_server/newsfragments/2050.clarification +++ /dev/null @@ -1 +0,0 @@ -Remove the `origin` field in `PUT /send_join` responses, because it was never sent in the first place. diff --git a/changelogs/server_server/newsfragments/2063.clarification b/changelogs/server_server/newsfragments/2063.clarification deleted file mode 100644 index 4e3df516..00000000 --- a/changelogs/server_server/newsfragments/2063.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that `m.join_rules` should be in the `auth_events` of an `m.room.member` event with a `membership` of `knock`. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/2076.clarification b/changelogs/server_server/newsfragments/2076.clarification deleted file mode 100644 index b3cad0d2..00000000 --- a/changelogs/server_server/newsfragments/2076.clarification +++ /dev/null @@ -1 +0,0 @@ -Remove an erroneous `room_id` field in a few examples. diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index 84362b3b..3ad53623 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -61,13 +61,13 @@ copyright = "The Matrix.org Foundation CIC" [params.version] # must be one of "unstable", "current", "historical" # this is used to decide whether to show a banner pointing to the current release -status = "unstable" +status = "stable" # A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner. current_version_url = "https://spec.matrix.org/latest" # The following is used when status = "stable", and is displayed in various UI elements on a released version # of the spec. -# major = "1" -# minor = "13" +major = "1" +minor = "14" # User interface configuration [params.ui] diff --git a/content/changelog/v1.14.md b/content/changelog/v1.14.md new file mode 100644 index 00000000..d5f14aba --- /dev/null +++ b/content/changelog/v1.14.md @@ -0,0 +1,93 @@ +--- +title: v1.14 Changelog +linkTitle: v1.14 +type: docs +layout: changelog +outputs: + - html + - checklist +date: 2025-03-27 +--- + +## Client-Server API + +**New Endpoints** + +- Add `POST /_matrix/client/v3/users/{userId}/report`, as per [MSC4260](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). ([#2093](https://github.com/matrix-org/matrix-spec/issues/2093)) + +**Removed Endpoints** + +- Remove `server_name` parameter from `/_matrix/client/v3/join/{roomIdOrAlias}` and `/_matrix/client/v3/knock/{roomIdOrAlias}`, as per [MSC4213](https://github.com/matrix-org/matrix-spec-proposals/pull/4213). ([#2059](https://github.com/matrix-org/matrix-spec/issues/2059)) + +**Spec Clarifications** + +- The `POST /_matrix/client/v3/rooms/{roomId}/initialSync` endpoint is no longer deprecated, as it is still used for peeking. ([#2036](https://github.com/matrix-org/matrix-spec/issues/2036)) +- Clarify wording in the `/join` endpoints' summaries and descriptions. Contributed by @HarHarLinks. ([#2038](https://github.com/matrix-org/matrix-spec/issues/2038)) +- Clarify formats of string types. ([#2046](https://github.com/matrix-org/matrix-spec/issues/2046)) +- Fix various typos throughout the specification. ([#2047](https://github.com/matrix-org/matrix-spec/issues/2047), [#2048](https://github.com/matrix-org/matrix-spec/issues/2048), [#2080](https://github.com/matrix-org/matrix-spec/issues/2080), [#2091](https://github.com/matrix-org/matrix-spec/issues/2091)) +- Document the `instance_id` field of `Protocol Instance` in the responses to `GET /_matrix/client/v3/thirdparty/protocols` and `GET /_matrix/client/v3/thirdparty/protocol/{protocol}`. ([#2051](https://github.com/matrix-org/matrix-spec/issues/2051)) +- Applying redactions is a SHOULD for clients. ([#2055](https://github.com/matrix-org/matrix-spec/issues/2055)) +- Clarify which rooms are returned from `/hierarchy`. ([#2064](https://github.com/matrix-org/matrix-spec/issues/2064)) +- Clients can choose which history visibility options they offer to users when creating rooms. ([#2072](https://github.com/matrix-org/matrix-spec/issues/2072)) + + +## Server-Server API + +**Spec Clarifications** + +- Remove the `origin` field in `PUT /send_join` responses, because it was never sent in the first place. ([#2050](https://github.com/matrix-org/matrix-spec/issues/2050)) +- Clarify that `m.join_rules` should be in the `auth_events` of an `m.room.member` event with a `membership` of `knock`. ([#2063](https://github.com/matrix-org/matrix-spec/issues/2063)) +- Remove an erroneous `room_id` field in a few examples. ([#2076](https://github.com/matrix-org/matrix-spec/issues/2076)) + + +## Application Service API + +No significant changes. + + +## Identity Service API + +No significant changes. + + +## Push Gateway API + +No significant changes. + + +## Room Versions + +**Backwards Compatible Changes** + +- Update the default room version to 11, as per [MSC4239](https://github.com/matrix-org/matrix-spec-proposals/pull/4239). ([#2105](https://github.com/matrix-org/matrix-spec/issues/2105)) + +**Spec Clarifications** + +- For room versions 6 and 7, clarify in the authorization rules that `m.federate` must be checked and that events with rejected auth events must be rejected, for parity with all the other room versions. ([#2065](https://github.com/matrix-org/matrix-spec/issues/2065)) +- Fix various typos throughout the specification. ([#2066](https://github.com/matrix-org/matrix-spec/issues/2066)) +- Refactor PDU definitions to reduce duplication. ([#2070](https://github.com/matrix-org/matrix-spec/issues/2070)) +- Clarify the maximum `depth` value for room versions 6, 7, 8, 9, 10, and 11. ([#2114](https://github.com/matrix-org/matrix-spec/issues/2114)) + + +## Appendices + +**Spec Clarifications** + +- Clarify that arbitrary unicode is allowed in user/room IDs and room aliases. ([#1506](https://github.com/matrix-org/matrix-spec/issues/1506)) + + +## Internal Changes/Tooling + +**Spec Clarifications** + +- Generate the changelog release info with Hugo, rather than the changelog generation script. ([#2033](https://github.com/matrix-org/matrix-spec/issues/2033)) +- Update release steps documentation. ([#2041](https://github.com/matrix-org/matrix-spec/issues/2041)) +- Remove unused `release_date` from Hugo config. ([#2042](https://github.com/matrix-org/matrix-spec/issues/2042)) +- Clarify that v1.0 of Matrix was a release prior to the current global versioning system. ([#2045](https://github.com/matrix-org/matrix-spec/issues/2045)) +- Fix syntax highlighting and click-to-copy buttons for code blocks by purging less CSS. ([#2049](https://github.com/matrix-org/matrix-spec/issues/2049)) +- Fix the version of the Identity Service API when Matrix 1.0 was introduced. ([#2061](https://github.com/matrix-org/matrix-spec/issues/2061)) +- Fix parsing of nested slices in `resolve-refs` and `resolve-allof` partials. ([#2069](https://github.com/matrix-org/matrix-spec/issues/2069)) +- Deduplicate the definition of `RoomKeysUpdateResponse`. ([#2073](https://github.com/matrix-org/matrix-spec/issues/2073)) +- Deduplicate the definitions of `Invite3pid`. ([#2074](https://github.com/matrix-org/matrix-spec/issues/2074)) +- Support more locations for examples in OpenAPI definitions and JSON schemas. ([#2076](https://github.com/matrix-org/matrix-spec/issues/2076)) +- Add link to the git commit for the unstable changelog. ([#2078](https://github.com/matrix-org/matrix-spec/issues/2078)) From 029be205b9e738d56e3f41b7da3ca09b78de0090 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 27 Mar 2025 10:30:02 -0600 Subject: [PATCH 18/67] -> unstable --- config/_default/hugo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index 3ad53623..3394c942 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -61,13 +61,13 @@ copyright = "The Matrix.org Foundation CIC" [params.version] # must be one of "unstable", "current", "historical" # this is used to decide whether to show a banner pointing to the current release -status = "stable" +status = "unstable" # A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner. current_version_url = "https://spec.matrix.org/latest" # The following is used when status = "stable", and is displayed in various UI elements on a released version # of the spec. -major = "1" -minor = "14" +# major = "1" +# minor = "14" # User interface configuration [params.ui] From 817ec5380f57aecc392db19e8f2c12361a12249c Mon Sep 17 00:00:00 2001 From: Kim Brose <2803622+HarHarLinks@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:19:23 +0100 Subject: [PATCH 19/67] Create funding-manifest-urls (#2115) * Create funding-manifest-urls * update funding-manifest-urls location, add news Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com> --------- Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com> --- changelogs/internal/newsfragments/2115.clarification | 1 + static/.well-known/funding-manifest-urls | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelogs/internal/newsfragments/2115.clarification create mode 100644 static/.well-known/funding-manifest-urls diff --git a/changelogs/internal/newsfragments/2115.clarification b/changelogs/internal/newsfragments/2115.clarification new file mode 100644 index 00000000..3deaf8c8 --- /dev/null +++ b/changelogs/internal/newsfragments/2115.clarification @@ -0,0 +1 @@ +Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks. diff --git a/static/.well-known/funding-manifest-urls b/static/.well-known/funding-manifest-urls new file mode 100644 index 00000000..1b14b420 --- /dev/null +++ b/static/.well-known/funding-manifest-urls @@ -0,0 +1 @@ +https://matrix.org/funding.json From 8a2c58b1b17b26f742be2e1b0aeafdd41bb5f9fc Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 28 Mar 2025 14:13:17 +0000 Subject: [PATCH 20/67] Typo "not" -> "no" (#2121) * Typo "not" -> "no" Signed-off-by: Andy Balaam --------- Signed-off-by: Andy Balaam --- changelogs/client_server/newsfragments/2121.clarification | 1 + content/client-server-api/modules/secrets.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2121.clarification diff --git a/changelogs/client_server/newsfragments/2121.clarification b/changelogs/client_server/newsfragments/2121.clarification new file mode 100644 index 00000000..3ccb2333 --- /dev/null +++ b/changelogs/client_server/newsfragments/2121.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/content/client-server-api/modules/secrets.md b/content/client-server-api/modules/secrets.md index 3e586bc4..fb997992 100644 --- a/content/client-server-api/modules/secrets.md +++ b/content/client-server-api/modules/secrets.md @@ -58,7 +58,7 @@ available on all their clients. Unless the user specifies otherwise, clients will try to use the default key to decrypt secrets. Clients that want to present a simplified interface to users by not supporting -multiple keys should use the default key if one is specified. If not default +multiple keys should use the default key if one is specified. If no default key is specified, the client may behave as if there is no key is present at all. When such a client creates a key, it should mark that key as being the default key. From 23ff7f1343ef00c61d148e84b3a26ec7826810b2 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 7 Apr 2025 14:28:00 -0600 Subject: [PATCH 21/67] Fix minor typo in content hash calculations (#2128) * Fix minor typo in content hash calculations * Changelog --- changelogs/server_server/newsfragments/2128.clarification | 1 + content/server-server-api.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/server_server/newsfragments/2128.clarification diff --git a/changelogs/server_server/newsfragments/2128.clarification b/changelogs/server_server/newsfragments/2128.clarification new file mode 100644 index 00000000..3ccb2333 --- /dev/null +++ b/changelogs/server_server/newsfragments/2128.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/content/server-server-api.md b/content/server-server-api.md index 65494f80..d93aa51f 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -1337,7 +1337,7 @@ calculated as follows. The *content hash* of an event covers the complete event including the *unredacted* contents. It is calculated as follows. -First, any existing `unsigned`, `signature`, and `hashes` members are +First, any existing `unsigned`, `signatures`, and `hashes` properties are removed. The resulting object is then encoded as [Canonical JSON](/appendices#canonical-json), and the JSON is hashed using SHA-256. From c39c7d06807d933c9584c59b9a9f9ba5b096409e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:47:21 +0200 Subject: [PATCH 22/67] Fix `/sync` example (#2077) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix sync example The same event should not appear in `state` and in the `timeline` so we cannot use the same event twice. To provide a `state` example we assume that with lazy-loading the user did not get the state event for `@example:example.org`, so we add one since they sent a message in the timeline. The events that are referenced include a `room_id`, which doesn't appear on this endpoint, so we copy them without it. Finally, the `join` event of `@alice:example.org` is wrong because the sender does not match the state key, which wouldn't pass the authorization rules. Signed-off-by: Kévin Commaille * Fix the `m.room.member.yaml` example This is a `join` event, and the `sender` doesn't match the `state_key`, so the event couldn't pass the authorization rules. Signed-off-by: Kévin Commaille * Add changelog Signed-off-by: Kévin Commaille --------- Signed-off-by: Kévin Commaille --- .../newsfragments/2077.clarification | 1 + data/api/client-server/sync.yaml | 46 +++++++++++++++++-- .../event-schemas/examples/m.room.member.yaml | 1 + 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2077.clarification diff --git a/changelogs/client_server/newsfragments/2077.clarification b/changelogs/client_server/newsfragments/2077.clarification new file mode 100644 index 00000000..2077d47f --- /dev/null +++ b/changelogs/client_server/newsfragments/2077.clarification @@ -0,0 +1 @@ +Fix the example of the `GET /sync` endpoint and the `m.room.member` example used in several places. \ No newline at end of file diff --git a/data/api/client-server/sync.yaml b/data/api/client-server/sync.yaml index 9d9a807d..e6fd7883 100644 --- a/data/api/client-server/sync.yaml +++ b/data/api/client-server/sync.yaml @@ -441,17 +441,57 @@ paths: "state": { "events": [ { - "$ref": "../../event-schemas/examples/m.room.member.yaml" + "content": { + "avatar_url": "mxc://example.org/SFHyPlCeYUSFFxlgbQYZmoEoe", + "displayname": "Example user", + "membership": "join" + }, + "event_id": "$143273976499sgjks:example.org", + "origin_server_ts": 1432735824653, + "sender": "@example:example.org", + "state_key": "@example:example.org", + "type": "m.room.member", + "unsigned": { + "age": 45603, + "membership": "join" + } } ] }, "timeline": { "events": [ { - "$ref": "../../event-schemas/examples/m.room.member.yaml" + "content": { + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Alice Margatroid", + "membership": "join", + "reason": "Looking for support" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1432735824653, + "sender": "@alice:example.org", + "state_key": "@alice:example.org", + "type": "m.room.member", + "unsigned": { + "age": 1234, + "membership": "join" + } }, { - "$ref": "../../event-schemas/examples/m.room.message$m.text.yaml" + "content": { + "body": "This is an example text message", + "format": "org.matrix.custom.html", + "formatted_body": "This is an example text message", + "msgtype": "m.text" + }, + "event_id": "$143273582443PhrSn:example.org", + "origin_server_ts": 1432735824653, + "sender": "@example:example.org", + "type": "m.room.message", + "unsigned": { + "age": 1234, + "membership": "join" + } } ], "limited": true, diff --git a/data/event-schemas/examples/m.room.member.yaml b/data/event-schemas/examples/m.room.member.yaml index 5147b258..85e9a9eb 100644 --- a/data/event-schemas/examples/m.room.member.yaml +++ b/data/event-schemas/examples/m.room.member.yaml @@ -1,6 +1,7 @@ { "$ref": "core/state_event.json", "state_key": "@alice:example.org", + "sender": "@alice:example.org", "type": "m.room.member", "content": { "membership": "join", From 65b1db721d1269936b4c9b3d4a8f0fc4250c9f94 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 15 Apr 2025 18:24:22 +0100 Subject: [PATCH 23/67] Describe behaviour when the `topic` key is falsey in a `m.room.topic` event. (#2068) We seem to have [updated this for m.room.name](https://github.com/matrix-org/matrix-spec/pull/1639) some years back but omitted it for topic. --- .../client_server/newsfragments/2068.clarification | 1 + data/event-schemas/schema/m.room.topic.yaml | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2068.clarification diff --git a/changelogs/client_server/newsfragments/2068.clarification b/changelogs/client_server/newsfragments/2068.clarification new file mode 100644 index 00000000..1b3c13e8 --- /dev/null +++ b/changelogs/client_server/newsfragments/2068.clarification @@ -0,0 +1 @@ +Clarify behaviour when the `topic` key of a `m.room.topic` event is absent, null, or empty. diff --git a/data/event-schemas/schema/m.room.topic.yaml b/data/event-schemas/schema/m.room.topic.yaml index 78a3d878..56f0caf9 100644 --- a/data/event-schemas/schema/m.room.topic.yaml +++ b/data/event-schemas/schema/m.room.topic.yaml @@ -1,7 +1,14 @@ --- allOf: - $ref: core-event-schema/state_event.yaml -description: 'A topic is a short message detailing what is currently being discussed in the room. It can also be used as a way to display extra information about the room, which may not be suitable for the room name. The room topic can also be set when creating a room using `/createRoom` with the `topic` key.' +description: |- + A topic is a short message detailing what is currently being discussed in the room. + It can also be used as a way to display extra information about the room, which may not + be suitable for the room name. + The room topic can also be set when creating a room using `/createRoom` with the `topic` key.' + + If the `topic` property is absent, null, or empty then the topic is unset. In other words, + an empty `topic` property effectively resets the room to having no topic. properties: content: properties: From 81273df88ee79e2819733ef70dfae9d715954ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:35:27 +0200 Subject: [PATCH 24/67] Adjust margins in rendered endpoints (#2081) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use consistent spacing between tables and code blocks Tables used `4 rem` which is more than the margin above a h2 title, which seems excessive. We change it to `2 rem` which matches the margin of code blocks and info boxes. We also remove the margin on the last item of a `.rendered-data` block because this is just wasted space. Signed-off-by: Kévin Commaille * Adjust spacing around h2 and h3 titles in `.rendered-data` Given that h2 titles are always preceded by an horizontal rule, we don't need a lot of space to separate them from the previous section. We also reduce the spacing when a h2 title is followed directly by a h3 title. Finally, we add a little spacing below both so that tables are less close to the title. Signed-off-by: Kévin Commaille * Add changelog Signed-off-by: Kévin Commaille --------- Signed-off-by: Kévin Commaille Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- assets/scss/_styles_project.scss | 26 ++++++++++++++----- .../internal/newsfragments/2081.clarification | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 changelogs/internal/newsfragments/2081.clarification diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index 9b020715..772b8412 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -316,13 +316,19 @@ Custom SCSS for the Matrix spec h2 { font-weight: $font-weight-bold; font-size: 1.3rem; - margin: 3rem 0 .5rem 0; + margin: 1.5rem 0 1rem 0; } h3 { font-weight: $font-weight-bold; font-size: 1.1rem; - margin: 1.5rem 0 .75rem 0; + margin: 1.5rem 0 1rem 0; + + } + + /* Reduce top margin of h3 if previous sibling is a h2 */ + h2 + h3 { + margin-top: 1rem; } hr { @@ -367,11 +373,6 @@ Custom SCSS for the Matrix spec } } - // add some space between two tables when they are right next to each other - & + table { - margin-top: 4rem; - } - caption { caption-side: top; color: $dark; @@ -443,6 +444,17 @@ Custom SCSS for the Matrix spec } } + /* Have consistent spacing around tables and examples */ + table, .highlight { + margin-top: 0; + margin-bottom: 2rem; + + /* We don't need the margin on the last child of the .rendered-data block */ + &:last-child { + margin-bottom: 0; + } + } + pre { border: 0; border-left: solid 5px $secondary; diff --git a/changelogs/internal/newsfragments/2081.clarification b/changelogs/internal/newsfragments/2081.clarification new file mode 100644 index 00000000..a4923694 --- /dev/null +++ b/changelogs/internal/newsfragments/2081.clarification @@ -0,0 +1 @@ +Adjust margins in rendered endpoints. From fca171427f11233cb1b82982ac541dd206ebbff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 22 Apr 2025 16:48:50 +0200 Subject: [PATCH 25/67] Clarifications around third-party invites (#2083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- .../newsfragments/2083.clarification | 2 + .../newsfragments/2083.clarification | 1 + .../newsfragments/2083.clarification | 2 + .../modules/third_party_invites.md | 46 ++++---- content/server-server-api.md | 44 ++++---- .../client-server/third_party_membership.yaml | 9 +- data/api/identity/v2_pubkey.yaml | 15 ++- data/api/identity/v2_store_invite.yaml | 14 ++- .../api/server-server/third_party_invite.yaml | 100 ++++-------------- .../components/signed_third_party_invite.yaml | 45 ++++++++ data/event-schemas/schema/m.room.member.yaml | 91 ++++++++-------- .../schema/m.room.third_party_invite.yaml | 48 +++++++-- data/string-formats.yaml | 5 + 13 files changed, 237 insertions(+), 185 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2083.clarification create mode 100644 changelogs/identity_service/newsfragments/2083.clarification create mode 100644 changelogs/server_server/newsfragments/2083.clarification create mode 100644 data/event-schemas/schema/components/signed_third_party_invite.yaml diff --git a/changelogs/client_server/newsfragments/2083.clarification b/changelogs/client_server/newsfragments/2083.clarification new file mode 100644 index 00000000..cc3dc3c7 --- /dev/null +++ b/changelogs/client_server/newsfragments/2083.clarification @@ -0,0 +1,2 @@ +Clarify the format of third-party invites, including the fact that identity +server public keys can be encoded using standard or URL-safe base64. diff --git a/changelogs/identity_service/newsfragments/2083.clarification b/changelogs/identity_service/newsfragments/2083.clarification new file mode 100644 index 00000000..7e5575c9 --- /dev/null +++ b/changelogs/identity_service/newsfragments/2083.clarification @@ -0,0 +1 @@ +Clarify that public keys can be encoded using standard or URL-safe base64. diff --git a/changelogs/server_server/newsfragments/2083.clarification b/changelogs/server_server/newsfragments/2083.clarification new file mode 100644 index 00000000..cc3dc3c7 --- /dev/null +++ b/changelogs/server_server/newsfragments/2083.clarification @@ -0,0 +1,2 @@ +Clarify the format of third-party invites, including the fact that identity +server public keys can be encoded using standard or URL-safe base64. diff --git a/content/client-server-api/modules/third_party_invites.md b/content/client-server-api/modules/third_party_invites.md index 9ac55f57..2fc8b82e 100644 --- a/content/client-server-api/modules/third_party_invites.md +++ b/content/client-server-api/modules/third_party_invites.md @@ -5,8 +5,8 @@ This module adds in support for inviting new members to a room where their Matrix user ID is not known, instead addressing them by a third-party identifier such as an email address. There are two flows here; one if a Matrix user ID is known for the third-party identifier, and one if -not. Either way, the client calls [`/invite`](#post_matrixclientv3roomsroomidinvite) with the details of the -third-party identifier. +not. Either way, the client calls [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite) +with the details of the third-party identifier. The homeserver asks the identity server whether a Matrix user ID is known for that identifier: @@ -37,10 +37,12 @@ A client asks a server to invite a user by their third-party identifier. #### Server behaviour -Upon receipt of an [`/invite`](#post_matrixclientv3roomsroomidinvite), the server is expected to look up the -third-party identifier with the provided identity server. If the lookup -yields a result for a Matrix User ID then the normal invite process can -be initiated. This process ends up looking like this: +Upon receipt of an [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite), +the server is expected to look up the third-party identifier with the provided +identity server by making a call to [`/_matrix/identity/v2/lookup`](/identity-service-api/#post_matrixidentityv2lookup). +If the lookup yields a result for a Matrix User ID then the normal [invite +process](/server-server-api/#inviting-to-a-room) can be initiated. This process +ends up looking like this: ``` +---------+ +-------------+ +-----------------+ @@ -66,10 +68,11 @@ be initiated. This process ends up looking like this: | | | ``` -However, if the lookup does not yield a bound User ID, the homeserver -must store the invite on the identity server and emit a valid -`m.room.third_party_invite` event to the room. This process ends up -looking like this: +However, if the lookup does not yield a bound User ID, the homeserver must store +the invite on the identity server with a call to +[`/_matrix/identity/v2/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite) +and emit a valid [`m.room.third_party_invite`](#mroomthird_party_invite) event +to the room. This process ends up looking like this: ``` +---------+ +-------------+ +-----------------+ @@ -101,15 +104,18 @@ looking like this: | | | ``` -All homeservers MUST verify the signature in the event's -`content.third_party_invite.signed` object. +The third-party user will then need to verify their identity, which results in a +request to [`/_matrix/federation/v1/3pid/onbind`](/server-server-api/#put_matrixfederationv13pidonbind) +from the identity server to the homeserver that bound the third-party identifier +to a user. The homeserver then exchanges the `m.room.third_party_invite` event +in the room for a complete [`m.room.member`](#mroommember) event with +`content.membership: invite` and a `content.third_party_invite` property for the +user that has bound the third-party identifier. If the invitee is on a different +homeserver than the inviting user, the invitee's homeserver makes a request to +[`/_matrix/federation/v1/exchange_third_party_invite/{roomId}`](/server-server-api/#put_matrixfederationv1exchange_third_party_inviteroomid). -The third-party user will then need to verify their identity, which -results in a call from the identity server to the homeserver that bound -the third-party identifier to a user. The homeserver then exchanges the -`m.room.third_party_invite` event in the room for a complete -`m.room.member` event for `membership: invite` for the user that has -bound the third-party identifier. +All homeservers MUST verify the signature in the `m.room.member` event's +`content.third_party_invite.signed` object. If a homeserver is joining a room for the first time because of an `m.room.third_party_invite`, the server which is already participating @@ -193,8 +199,8 @@ at any time - the completion is not shown in the diagram. H1 MUST verify the request from H3 to ensure the `signed` property is correct as well as the `key_validity_url` as still being valid. This is -done by making a request to the [identity server -/isvalid](/identity-service-api/#get_matrixidentityv2pubkeyisvalid) +done by making a request to the identity server's +[`/pubkey/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyisvalid) endpoint, using the provided URL rather than constructing a new one. The query string and response for the provided URL must match the Identity Service Specification. diff --git a/content/server-server-api.md b/content/server-server-api.md index d93aa51f..c82e3bee 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -970,9 +970,8 @@ the event to other servers in the room. ## Third-party invites {{% boxes/note %}} -More information about third-party invites is available in the -[Client-Server API](/client-server-api) under -the Third-party Invites module. +More information about third-party invites is available in the Client-Server API +under the [Third-party invites](/client-server-api/#third-party-invites) module. {{% /boxes/note %}} When a user wants to invite another user in a room but doesn't know the @@ -985,38 +984,41 @@ API](/identity-service-api). ### Cases where an association exists for a third-party identifier -If the third-party identifier is already bound to a Matrix ID, a lookup -request on the identity server will return it. The invite is then -processed by the inviting homeserver as a standard `m.room.member` -invite event. This is the simplest case. +If the third-party identifier is already bound to a Matrix ID, a [lookup +request](/identity-service-api/#post_matrixidentityv2lookup) on the identity +server will return it. The invite is then processed by the inviting homeserver +as a [standard `m.room.member` invite event](#inviting-to-a-room). This is the +simplest case. ### Cases where an association doesn't exist for a third-party identifier If the third-party identifier isn't bound to any Matrix ID, the inviting -homeserver will request the identity server to store an invite for this -identifier and to deliver it to whoever binds it to its Matrix ID. It -will also send an `m.room.third_party_invite` event in the room to -specify a display name, a token and public keys the identity server -provided as a response to the invite storage request. +homeserver will request the identity server to [store an invite](/identity-service-api/#invitation-storage) +for this identifier and to deliver it to whoever binds it to its Matrix ID. It +will also send an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) +event in the room to specify a display name, a token and public keys the +identity server provided as a response to the invite storage request. -When a third-party identifier with pending invites gets bound to a -Matrix ID, the identity server will send a POST request to the ID's -homeserver as described in the [Invitation -Storage](/identity-service-api#invitation-storage) -section of the Identity Service API. +When a third-party identifier with pending invites gets bound to a Matrix ID, +the identity server will send a request to the [`/3pid/onbind`](#put_matrixfederationv13pidonbind) +endpoint of the the ID's homeserver as described in the [Invitation +Storage](/identity-service-api#invitation-storage) section of the Identity +Service API. The following process applies for each invite sent by the identity server: -The invited homeserver will create an `m.room.member` invite event -containing a special `third_party_invite` section containing the token -and a signed object, both provided by the identity server. +The invited homeserver will create an [`m.room.member`](/client-server-api/#mroommember) +invite event containing a special `third_party_invite` section containing the +token and a `signed` object, both provided by the identity server. If the invited homeserver is in the room the invite came from, it can auth the event and send it. However, if the invited homeserver isn't in the room the invite came -from, it will need to request the room's homeserver to auth the event. +from, it will need to request the inviting homeserver to auth the event +at the [`/exchange_third_party_invite`](#put_matrixfederationv1exchange_third_party_inviteroomid) +endpoint. {{% http-api spec="server-server" api="third_party_invite" %}} diff --git a/data/api/client-server/third_party_membership.yaml b/data/api/client-server/third_party_membership.yaml index 65148ee0..67caa387 100644 --- a/data/api/client-server/third_party_membership.yaml +++ b/data/api/client-server/third_party_membership.yaml @@ -57,9 +57,6 @@ paths: - A signature of the token, signed with the identity server's private key - The matrix user ID who invited them to the room - - If a token is requested from the identity server, the homeserver will - append a `m.room.third_party_invite` event to the room. operationId: inviteBy3PID security: - accessTokenQuery: [] @@ -72,6 +69,8 @@ paths: example: "!d41d8cd:matrix.org" schema: type: string + format: mx-room-id + pattern: "^!" requestBody: content: application/json: @@ -90,7 +89,9 @@ paths: value: {} "403": description: |- - You do not have permission to invite the user to the room. A meaningful `errcode` and description error text will be returned. Example reasons for rejections are: + You do not have permission to invite the user to the room. A + meaningful `errcode` and description error text will be returned. + Example reasons for rejections are: - The invitee has been banned from the room. - The invitee is already a member of the room. diff --git a/data/api/identity/v2_pubkey.yaml b/data/api/identity/v2_pubkey.yaml index 2aaf5f8e..68e383a8 100644 --- a/data/api/identity/v2_pubkey.yaml +++ b/data/api/identity/v2_pubkey.yaml @@ -43,7 +43,8 @@ paths: properties: public_key: type: string - description: Unpadded Base64 encoded public key. + description: |- + [Unpadded Base64](/appendices/#unpadded-base64)-encoded public key. required: - public_key examples: @@ -74,7 +75,8 @@ paths: - in: query name: public_key required: true - description: The unpadded base64-encoded public key to check. + description: |- + The [unpadded Base64](/appendices/#unpadded-base64)-encoded public key to check. example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c schema: type: string @@ -105,7 +107,14 @@ paths: - in: query name: public_key required: true - description: The unpadded base64-encoded public key to check. + description: |- + The [unpadded Base64](/appendices/#unpadded-base64)-encoded public + key to check. + + This MUST be the exact same encoded string returned in the response + of the [`/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite) + endpoint, or found in the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) + event, so it may use the standard or URL-safe alphabets. example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c schema: type: string diff --git a/data/api/identity/v2_store_invite.yaml b/data/api/identity/v2_store_invite.yaml index 5dcd9a78..98e7e7f4 100644 --- a/data/api/identity/v2_store_invite.yaml +++ b/data/api/identity/v2_store_invite.yaml @@ -42,7 +42,7 @@ paths: (if present) from the request here. Also, the generated ephemeral public key will be listed as valid on - requests to `/_matrix/identity/v2/pubkey/ephemeral/isvalid`. + requests to [`/_matrix/identity/v2/pubkey/ephemeral/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyephemeralisvalid). Currently, invites may only be issued for 3pids of the `email` medium. @@ -70,10 +70,14 @@ paths: room_id: type: string description: The Matrix room ID to which the user is invited + format: mx-room-id + pattern: "^!" example: "!something:example.org" sender: type: string description: The Matrix user ID of the inviting user + format: mx-user-id + pattern: "^@" example: "@bob:example.com" room_alias: type: string @@ -81,12 +85,16 @@ paths: The Matrix room alias for the room to which the user is invited. This should be retrieved from the `m.room.canonical_alias` state event. + format: mx-room-alias + pattern: "^#" example: "#somewhere:example.org" room_avatar_url: type: string description: |- The Content URI for the room to which the user is invited. This should be retrieved from the `m.room.avatar` state event. + format: mx-mxc-uri + pattern: "^mxc:\\/\\/" example: mxc://example.org/s0meM3dia room_join_rules: type: string @@ -108,6 +116,8 @@ paths: type: string description: The Content URI for the avatar of the user ID initiating the invite. + format: mx-mxc-uri + pattern: "^mxc:\\/\\/" example: mxc://example.org/an0th3rM3dia room_type: type: string @@ -146,7 +156,7 @@ paths: public_key: type: string description: | - The public key, encoded using [unpadded Base64](/appendices/#unpadded-base64). + The public key, encoded using standard or URL-safe [unpadded Base64](/appendices/#unpadded-base64). key_validity_url: type: string description: | diff --git a/data/api/server-server/third_party_invite.yaml b/data/api/server-server/third_party_invite.yaml index 76a7d2ff..019aa2d4 100644 --- a/data/api/server-server/third_party_invite.yaml +++ b/data/api/server-server/third_party_invite.yaml @@ -35,6 +35,8 @@ paths: example: "!abc123:matrix.org" schema: type: string + format: mx-room-id + pattern: "^!" requestBody: content: application/json: @@ -50,16 +52,22 @@ paths: description: |- The room ID the event is for. Must match the ID given in the path. + format: mx-room-id + pattern: "^!" example: "!abc123:matrix.org" sender: type: string description: |- The user ID of the user who sent the original `m.room.third_party_invite` event. + format: mx-user-id + pattern: "^@" example: "@joe:matrix.org" state_key: type: string description: The user ID of the invited user + format: mx-user-id + pattern: "^@" example: "@someone:example.org" content: type: object @@ -82,45 +90,7 @@ paths: third-party identifier. example: alice signed: - type: object - description: |- - A block of content which has been signed, which servers can use to - verify the event. - title: Invite Signatures - properties: - signatures: - type: object - title: Signatures - additionalProperties: - type: object - additionalProperties: - type: string - description: |- - The server signatures for this event. - - The signature is calculated using the process - described at [Signing JSON](/appendices/#signing-json). - example: - magic.forest: - ed25519:3: fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg - mxid: - type: string - description: The invited matrix user ID - example: "@alice:localhost" - token: - type: string - description: The token used to verify the event - example: abc123 - required: - - signatures - - mxid - - token - example: - mxid: "@alice:localhost" - token: abc123 - signatures: - magic.forest: - ed25519:3: fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg + $ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml required: - display_name - signed @@ -215,6 +185,8 @@ paths: mxid: type: string description: The user that is now bound to the third-party identifier. + format: mx-user-id + pattern: "^@" example: "@alice:matrix.org" invites: type: array @@ -237,59 +209,23 @@ paths: mxid: type: string description: The now-bound user ID that received the invite. + format: mx-user-id + pattern: "^@" example: "@alice:matrix.org" room_id: type: string description: The room ID the invite is valid for. + format: mx-room-id + pattern: "^!" example: "!somewhere:example.org" sender: type: string description: The user ID that sent the invite. + format: mx-user-id + pattern: "^@" example: "@bob:matrix.org" - # TODO (TravisR): Make this reusable when doing IS spec changes - # also make sure it isn't lying about anything, like the key version signed: - type: object - title: Identity Server Signatures - description: |- - Signature from the identity server using a long-term private - key. - properties: - mxid: - type: string - description: |- - The user ID that has been bound to the third-party - identifier. - example: "@alice:matrix.org" - token: - type: string - # TODO: What is this actually? - description: A token. - example: Hello World - signatures: - type: object - title: Identity Server Signature - description: |- - The signature from the identity server. The `string` key - is the identity server's domain name, such as vector.im - additionalProperties: - type: object - title: Identity Server Domain Signature - description: The signature for the identity server. - properties: - ed25519:0: - type: string - description: The signature. - example: SomeSignatureGoesHere - required: - - ed25519:0 - example: - vector.im: - ed25519:0: SomeSignatureGoesHere - required: - - mxid - - token - - signatures + $ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml required: - medium - address diff --git a/data/event-schemas/schema/components/signed_third_party_invite.yaml b/data/event-schemas/schema/components/signed_third_party_invite.yaml new file mode 100644 index 00000000..b231c978 --- /dev/null +++ b/data/event-schemas/schema/components/signed_third_party_invite.yaml @@ -0,0 +1,45 @@ +title: SignedThirdPartyInvite +description: |- + A block of content which has been signed by the identity server, which + homeservers can use to verify the event. Clients should ignore this. +type: object +properties: + mxid: + description: |- + The user ID that has been bound to the third-party identifier. + type: string + format: mx-user-id + pattern: "^@" + example: "@alice:example.org" + signatures: + title: IdentityServerSignatures + description: |- + The identity server signatures for this block. This is a map of identity + server name to signing key identifier to base64-encoded signature. + + The signatures are calculated using the process described at + [Signing JSON](/appendices/#signing-json). + type: object + additionalProperties: + type: object + additionalProperties: + type: string + example: { + "magic.forest": { + "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg" + } + } + token: + description: |- + The token generated by the identity server at the + [`/store_invite`](/identity-service-api/#post_matrixidentityv2store-invite) + endpoint. + + It matches the `state_key` of the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) + event. + type: string + example: "abc123" +required: + - mxid + - signatures + - token diff --git a/data/event-schemas/schema/m.room.member.yaml b/data/event-schemas/schema/m.room.member.yaml index 8d212687..436c0145 100644 --- a/data/event-schemas/schema/m.room.member.yaml +++ b/data/event-schemas/schema/m.room.member.yaml @@ -2,17 +2,27 @@ allOf: - $ref: core-event-schema/state_event.yaml description: |- - Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (`/rooms//invite` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail. + Adjusts the membership state for a user in a room. It is preferable to use the membership APIs + (`/rooms//invite` etc) when performing membership actions rather than adjusting the + state directly as there are a restricted set of valid transformations. For example, user A cannot + force user B to join a room, and trying to force this state change directly will fail. The following membership states are specified: - - `invite` - The user has been invited to join a room, but has not yet joined it. They may not participate in the room until they join. - - `join` - The user has joined the room (possibly after accepting an invite), and may participate in it. - - `leave` - The user was once joined to the room, but has since left (possibly by choice, or possibly by being kicked). - - `ban` - The user has been banned from the room, and is no longer allowed to join it until they are un-banned from the room (by having their membership state set to a value other than `ban`). - - `knock` - The user has knocked on the room, requesting permission to participate. They may not participate in the room until they join. + - `invite` - The user has been invited to join a room, but has not yet joined it. They may not + participate in the room until they join. + - `join` - The user has joined the room (possibly after accepting an invite), and may participate + in it. + - `leave` - The user was once joined to the room, but has since left (possibly by choice, or + possibly by being kicked). + - `ban` - The user has been banned from the room, and is no longer allowed to join it until they + are un-banned from the room (by having their membership state set to a value other than `ban`). + - `knock` - The user has knocked on the room, requesting permission to participate. They may not + participate in the room until they join. - The `third_party_invite` property will be set if this invite is an `invite` event and is the successor of an `m.room.third_party_invite` event, and absent otherwise. + The `third_party_invite` property will be set if this invite is an `invite` event and is the + successor of an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) event, + and absent otherwise. This event may also include an `invite_room_state` key inside the event's `unsigned` data. If present, this contains an array of [stripped state events](/client-server-api/#stripped-state) @@ -57,63 +67,54 @@ properties: - ban type: string is_direct: - description: Flag indicating if the room containing this event was created with the intention of being a direct chat. See [Direct Messaging](/client-server-api/#direct-messaging). + description: |- + Flag indicating if the room containing this event was created with the intention of being + a direct chat. See [Direct Messaging](/client-server-api/#direct-messaging). type: boolean join_authorised_via_users_server: x-addedInMatrixVersion: "1.2" type: string description: |- - Usually found on `join` events, this field is used to denote which homeserver (through representation of a user with sufficient power level) - authorised the user's join. More information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms). + Usually found on `join` events, this field is used to denote which homeserver (through + representation of a user with sufficient power level) authorised the user's join. More + information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms). - Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules) of including this - field in further events: in particular, the event must be signed by the server which - owns the user ID in the field. When copying the membership event's `content` - (for profile updates and similar) it is therefore encouraged to exclude this - field in the copy, as otherwise the event might fail event authorization. + Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules) + of including this field in further events: in particular, the event must be signed by the + server which owns the user ID in the field. When copying the membership event's `content` + (for profile updates and similar) it is therefore encouraged to exclude this field in the + copy, as otherwise the event might fail event authorization. reason: x-addedInMatrixVersion: "1.1" type: string description: |- - Optional user-supplied text for why their membership has changed. For kicks and bans, this is typically the reason for the kick or ban. - For other membership changes, this is a way for the user to communicate their intent without having to send a message to the room, such - as in a case where Bob rejects an invite from Alice about an upcoming concert, but can't make it that day. + Optional user-supplied text for why their membership has changed. For kicks and bans, + this is typically the reason for the kick or ban. For other membership changes, this is a + way for the user to communicate their intent without having to send a message to the + room, such as in a case where Bob rejects an invite from Alice about an upcoming concert, + but can't make it that day. - Clients are not recommended to show this reason to users when receiving an invite due to the potential for spam and abuse. Hiding the - reason behind a button or other component is recommended. + Clients are not recommended to show this reason to users when receiving an invite due to + the potential for spam and abuse. Hiding the reason behind a button or other component is + recommended. third_party_invite: + title: ThirdPartyInvite + description: |- + A third-party invite, if this `m.room.member` is the successor to an + [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) + event. + type: object properties: display_name: - description: A name which can be displayed to represent the user instead of their third-party identifier + description: |- + A name which can be displayed to represent the user instead of their + third-party identifier type: string signed: - description: 'A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.' - properties: - mxid: - description: The invited matrix user ID. Must be equal to the user_id property of the event. - type: string - signatures: - description: 'A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.' - title: Signatures - type: object - additionalProperties: - type: object - additionalProperties: - type: string - token: - description: The token property of the containing third_party_invite object. - type: string - required: - - mxid - - signatures - - token - title: signed - type: object + $ref: components/signed_third_party_invite.yaml required: - display_name - signed - title: Invite - type: object required: - membership title: EventContent diff --git a/data/event-schemas/schema/m.room.third_party_invite.yaml b/data/event-schemas/schema/m.room.third_party_invite.yaml index bb4883f5..704669d2 100644 --- a/data/event-schemas/schema/m.room.third_party_invite.yaml +++ b/data/event-schemas/schema/m.room.third_party_invite.yaml @@ -1,28 +1,56 @@ --- allOf: - $ref: core-event-schema/state_event.yaml -description: "Acts as an `m.room.member` invite event, where there isn't a target user_id to invite. This event contains a token and a public key whose private key must be used to sign the token. Any user who can present that signature may use this invitation to join the target room." +description: |- + Acts as an `m.room.member` invite event, where there isn't a target user_id to + invite. This event contains a token and a public key whose private key must be + used to sign the token. Any user who can present that signature may use this + invitation to join the target room. properties: content: properties: display_name: - description: "A user-readable string which represents the user who has been invited. This should not contain the user's third-party ID, as otherwise when the invite is accepted it would leak the association between the matrix ID and the third-party ID." + description: |- + A user-readable string which represents the user who has been invited. + This should not contain the user's third-party ID, as otherwise when + the invite is accepted it would leak the association between the + matrix ID and the third-party ID. type: string key_validity_url: - description: "A URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'." + description: |- + A URL which can be fetched, with querystring public_key=public_key, to + validate whether the key has been revoked. The URL must return a JSON + object containing a boolean property named 'valid'. type: string + format: uri public_key: - description: A base64-encoded ed25519 key with which token must be signed (though a signature from any entry in public_keys is also sufficient). This exists for backwards compatibility. + description: |- + An Ed25519 key with which the token must be signed (though a signature + from any entry in `public_keys` is also sufficient). + + The key is encoded using [Unpadded Base64](/appendices/#unpadded-base64), + using the standard or URL-safe alphabets. + + This exists for backwards compatibility. type: string public_keys: description: Keys with which the token may be signed. items: properties: key_validity_url: - description: "An optional URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'. If this URL is absent, the key must be considered valid indefinitely." + description: |- + An optional URL which can be fetched, with querystring + `public_key=`, to validate whether the key has been + revoked. The URL must return a JSON object containing a boolean + property named `valid`. If this URL is absent, the key must be + considered valid indefinitely. type: string public_key: - description: A base-64 encoded ed25519 key with which token may be signed. + description: |- + An Ed25519 key with which the token may be signed. + + The key is encoded using [Unpadded Base64](/appendices/#unpadded-base64), + using the standard or URL-safe alphabets. type: string required: - public_key @@ -35,11 +63,15 @@ properties: - public_key type: object state_key: - description: 'The token, of which a signature must be produced in order to join the room.' + description: |- + The token, of which a signature must be produced in order to join the + room. type: string type: enum: - m.room.third_party_invite type: string -title: 'An invitation to a room issued to a third-party identifier, rather than a matrix user ID.' +title: |- + An invitation to a room issued to a third-party identifier, rather than a + matrix user ID. type: object diff --git a/data/string-formats.yaml b/data/string-formats.yaml index 352d21fc..fca325b9 100644 --- a/data/string-formats.yaml +++ b/data/string-formats.yaml @@ -51,6 +51,11 @@ mx-room-id: url: appendices#room-ids # regex: "^!" +mx-room-alias: + title: Room Alias + url: appendices#room-aliases + # regex: "^#" + mx-server-name: title: Server Name url: appendices#server-name From a8c326962a773f5234a08f755512d7cbae40ca30 Mon Sep 17 00:00:00 2001 From: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> Date: Thu, 8 May 2025 10:09:45 +0100 Subject: [PATCH 26/67] Add a note to the federation invite endpoints that invites can be sent twice (#2067) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... as this may be non-obvious when implementing behaviour that is triggered by an incoming invite event. See https://github.com/matrix-org/matrix-spec/issues/2062 for more context. Co-authored-by: Kévin Commaille <76261501+zecakeh@users.noreply.github.com> --- changelogs/server_server/newsfragments/2067.clarification | 1 + data/api/server-server/invites-v1.yaml | 6 +++++- data/api/server-server/invites-v2.yaml | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 changelogs/server_server/newsfragments/2067.clarification diff --git a/changelogs/server_server/newsfragments/2067.clarification b/changelogs/server_server/newsfragments/2067.clarification new file mode 100644 index 00000000..4bd8176b --- /dev/null +++ b/changelogs/server_server/newsfragments/2067.clarification @@ -0,0 +1 @@ +Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room. \ No newline at end of file diff --git a/data/api/server-server/invites-v1.yaml b/data/api/server-server/invites-v1.yaml index 7d241c37..b1771018 100644 --- a/data/api/server-server/invites-v1.yaml +++ b/data/api/server-server/invites-v1.yaml @@ -20,7 +20,7 @@ paths: put: summary: Invites a remote user to a room description: |- - Invites a remote user to a room. Once the event has been signed by both the inviting + Invites a remote user to a room. Once the event has been signed by both the inviting homeserver and the invited homeserver, it can be sent to all of the servers in the room by the inviting homeserver. @@ -32,6 +32,10 @@ paths: [room version specification](/rooms) for precise event formats. **The request and response bodies here describe the common event fields in more detail and may be missing other required fields for a PDU.** + + Also note that if the remote homeserver is already in the room, it will receive the + invite event twice; once through this endpoint, and again through a [federation + transaction](/server-server-api/#transactions). operationId: sendInviteV1 security: - signedRequest: [] diff --git a/data/api/server-server/invites-v2.yaml b/data/api/server-server/invites-v2.yaml index f42c8eea..6ac8bb3e 100644 --- a/data/api/server-server/invites-v2.yaml +++ b/data/api/server-server/invites-v2.yaml @@ -24,7 +24,7 @@ paths: This API is nearly identical to the v1 API with the exception of the request body being different, and the response format fixed. - Invites a remote user to a room. Once the event has been signed by both the inviting + Invites a remote user to a room. Once the event has been signed by both the inviting homeserver and the invited homeserver, it can be sent to all of the servers in the room by the inviting homeserver. @@ -36,6 +36,10 @@ paths: [room version specification](/rooms) for precise event formats. **The request and response bodies here describe the common event fields in more detail and may be missing other required fields for a PDU.** + + Also note that if the remote homeserver is already in the room, it will receive the + invite event twice; once through this endpoint, and again through a [federation + transaction](/server-server-api/#transactions). operationId: sendInviteV2 security: - signedRequest: [] From fe46e0c363cc285125f9a83be29f96aeb4945dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Thu, 8 May 2025 11:29:32 +0200 Subject: [PATCH 27/67] Replace Hugo shortcodes in OpenAPI output (#2088) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- .github/workflows/main.yml | 11 +- .../internal/newsfragments/2088.clarification | 1 + scripts/dump-openapi.py | 112 +++++++++++++++++- 3 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 changelogs/internal/newsfragments/2088.clarification diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 25a2fb68..daa8fb67 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,6 +2,7 @@ name: "Spec" env: HUGO_VERSION: 0.139.0 + PYTHON_VERSION: 3.13 on: push: @@ -40,7 +41,7 @@ jobs: - name: "➕ Setup Python" uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" @@ -59,7 +60,7 @@ jobs: - name: "➕ Setup Python" uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" @@ -78,7 +79,7 @@ jobs: - name: "➕ Setup Python" uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" @@ -120,7 +121,7 @@ jobs: - name: "➕ Setup Python" uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' cache-dependency-path: scripts/requirements.txt - name: "➕ Install dependencies" @@ -172,7 +173,7 @@ jobs: - name: "➕ Setup Python" uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: ${{ env.PYTHON_VERSION }} - name: "➕ Install towncrier" run: "pip install 'towncrier'" - name: "Generate changelog" diff --git a/changelogs/internal/newsfragments/2088.clarification b/changelogs/internal/newsfragments/2088.clarification new file mode 100644 index 00000000..a0e53726 --- /dev/null +++ b/changelogs/internal/newsfragments/2088.clarification @@ -0,0 +1 @@ +Replace Hugo shortcodes in OpenAPI output. diff --git a/scripts/dump-openapi.py b/scripts/dump-openapi.py index 490ac9bf..49ad9147 100755 --- a/scripts/dump-openapi.py +++ b/scripts/dump-openapi.py @@ -32,6 +32,35 @@ import yaml scripts_dir = os.path.dirname(os.path.abspath(__file__)) api_dir = os.path.join(os.path.dirname(scripts_dir), "data", "api") +# Finds a Hugo shortcode in a string. +# +# A shortcode is defined as (newlines and whitespaces for presentation purpose): +# +# {{% +# +# +# (optional ) +# +# %}} +# +# With: +# +# * : any word character and `-` and `/`. `re.ASCII` is used to only match +# ASCII characters in the name. +# * : any character except `}`, must not start or end with a +# whitespace. +shortcode_regex = re.compile(r"""\{\{\% # {{% + \s* # zero or more whitespaces + (?P[\w/-]+) # name of shortcode + (?:\s+(?P[^\s\}][^\}]+[^\s\}]))? # optional list of parameters + \s* # zero or more whitespaces + \%\}\} # %}}""", re.ASCII | re.VERBOSE) + +# Parses the parameters of a Hugo shortcode. +# +# For simplicity, this currently only supports the `key="value"` format. +shortcode_params_regex = re.compile(r"(?P\w+)=\"(?P[^\"]+)\"", re.ASCII) + def prefix_absolute_path_references(text, base_url): """Adds base_url to absolute-path references. @@ -44,17 +73,90 @@ def prefix_absolute_path_references(text, base_url): """ return text.replace("](/", "]({}/".format(base_url)) -def edit_links(node, base_url): - """Finds description nodes and makes any links in them absolute.""" +def replace_match(match, replacement): + """Replaces the regex match by the replacement in the text.""" + return match.string[:match.start()] + replacement + match.string[match.end():] + +def replace_shortcode(shortcode): + """Replaces the shortcode by a Markdown fallback in the text. + + The supported shortcodes are: + + * boxes/note, boxes/rationale, boxes/warning + * added-in, changed-in + + All closing tags (`{{ /shortcode }}`) are replaced with the empty string. + """ + + if shortcode['name'].startswith("/"): + # This is the end of the shortcode, just remove it. + return replace_match(shortcode, "") + + # Parse the parameters of the shortcode + params = {} + if shortcode['params']: + for param in shortcode_params_regex.finditer(shortcode['params']): + if param['key']: + params[param['key']] = param['value'] + + match shortcode['name']: + case "boxes/note": + return replace_match(shortcode, "**NOTE:** ") + case "boxes/rationale": + return replace_match(shortcode, "**RATIONALE:** ") + case "boxes/warning": + return replace_match(shortcode, "**WARNING:** ") + case "added-in": + version = params['v'] + if not version: + raise ValueError("Missing parameter `v` for `added-in` shortcode") + + return replace_match(shortcode, f"**[Added in `v{version}`]** ") + case "changed-in": + version = params['v'] + if not version: + raise ValueError("Missing parameter `v` for `changed-in` shortcode") + + return replace_match(shortcode, f"**[Changed in `v{version}`]** ") + case _: + raise ValueError("Unknown shortcode", shortcode['name']) + + +def find_and_replace_shortcodes(text): + """Finds Hugo shortcodes and replaces them by a Markdown fallback. + + The supported shortcodes are: + + * boxes/note, boxes/rationale, boxes/warning + * added-in, changed-in + """ + # We use a `while` loop with `search` instead of a `for` loop with + # `finditer`, because as soon as we start replacing text, the + # indices of the match are invalid. + while shortcode := shortcode_regex.search(text): + text = replace_shortcode(shortcode) + + return text + +def edit_descriptions(node, base_url): + """Finds description nodes and apply fixes to them. + + The fixes that are applied are: + + * Make links absolute + * Replace Hugo shortcodes + """ if isinstance(node, dict): for key in node: if isinstance(node[key], str): node[key] = prefix_absolute_path_references(node[key], base_url) + node[key] = find_and_replace_shortcodes(node[key]) else: - edit_links(node[key], base_url) + edit_descriptions(node[key], base_url) elif isinstance(node, list): for item in node: - edit_links(item, base_url) + edit_descriptions(item, base_url) + parser = argparse.ArgumentParser( "dump-openapi.py - assemble the OpenAPI specs into a single JSON file" @@ -164,7 +266,7 @@ for filename in os.listdir(selected_api_dir): if untagged != 0: print("{} untagged operations, you may want to look into fixing that.".format(untagged)) -edit_links(output, base_url) +edit_descriptions(output, base_url) print("Generating %s" % output_file) From ca9c376076b1e142c94277c741984f70283c24a1 Mon Sep 17 00:00:00 2001 From: Kim Brose <2803622+HarHarLinks@users.noreply.github.com> Date: Thu, 8 May 2025 11:55:51 +0000 Subject: [PATCH 28/67] Clarify Well-Known URIs (#2140) * Clarify Well-Known URIs Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com> * Fix section link --------- Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com> --- .../newsfragments/2140.clarification | 1 + .../newsfragments/2140.clarification | 1 + content/client-server-api/_index.md | 25 +++++++++++++++---- content/server-server-api.md | 3 ++- data/api/client-server/support.yaml | 7 ++++-- data/api/client-server/wellknown.yaml | 6 +++++ data/api/server-server/wellknown.yaml | 6 +++++ 7 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2140.clarification create mode 100644 changelogs/server_server/newsfragments/2140.clarification diff --git a/changelogs/client_server/newsfragments/2140.clarification b/changelogs/client_server/newsfragments/2140.clarification new file mode 100644 index 00000000..4a151fe8 --- /dev/null +++ b/changelogs/client_server/newsfragments/2140.clarification @@ -0,0 +1 @@ +Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. diff --git a/changelogs/server_server/newsfragments/2140.clarification b/changelogs/server_server/newsfragments/2140.clarification new file mode 100644 index 00000000..4a151fe8 --- /dev/null +++ b/changelogs/server_server/newsfragments/2140.clarification @@ -0,0 +1 @@ +Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 94dfe35f..f2de85de 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -371,15 +371,23 @@ valid data was obtained, but no server is available to serve the client. No further guess should be attempted and the user should make a conscientious decision what to do next. -### Well-known URI +### Well-known URIs + +Matrix facilitates automatic discovery for the Client-Server API base URL and more via the +[RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615) "Well-Known URI" method. +This method uses JSON files at a predetermined location on the root path `/.well-known/` to +specify parameter values. {{% boxes/note %}} +Diverging from the rest of the endpoints in the Client-Server spec, these files can not be provided +on the base URL that the Client-Server API is reachable on, as it is yet to be discovered. +Instead, they can be reached via HTTPS on the [server name](/appendices/#server-name)'s hostname as domain. + Servers hosting the `.well-known` JSON file SHOULD offer CORS headers, as per the [CORS](#web-browser-clients) section in this specification. {{% /boxes/note %}} -The `.well-known` method uses a JSON file at a predetermined location to -specify parameter values. The flow for this method is as follows: +The flow for auto-discovery is as follows: 1. Extract the [server name](/appendices/#server-name) from the user's Matrix ID by splitting the Matrix ID at the first colon. @@ -415,10 +423,17 @@ specify parameter values. The flow for this method is as follows: {{% http-api spec="client-server" api="wellknown" %}} -{{% http-api spec="client-server" api="versions" %}} - {{% http-api spec="client-server" api="support" %}} +### API Versions + +Upon connecting, the Matrix client and server need to negotiate which version of the specification +they commonly support, as the API evolves over time. The server advertises its supported versions +and optionally unstable features to the client, which can then go on to make requests to the +endpoints it supports. + +{{% http-api spec="client-server" api="versions" %}} + ## Client Authentication Most API endpoints require the user to identify themselves by presenting diff --git a/content/server-server-api.md b/content/server-server-api.md index c82e3bee..10d91468 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -119,7 +119,8 @@ to send. The process overall is as follows: server must present a valid certificate for the hostname. 3. If the hostname is not an IP literal, a regular HTTPS request is - made to `https:///.well-known/matrix/server`, expecting + made to `https:///.well-known/matrix/server` (according to + [RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615)), expecting the schema defined later in this section. 30x redirects should be followed, however redirection loops should be avoided. Responses (successful or otherwise) to the `/.well-known` endpoint should be diff --git a/data/api/client-server/support.yaml b/data/api/client-server/support.yaml index b9ca062e..154afbe7 100644 --- a/data/api/client-server/support.yaml +++ b/data/api/client-server/support.yaml @@ -22,9 +22,12 @@ paths: description: |- Gets server admin contact and support page of the domain. - Like the [well-known discovery URI](/client-server-api/#well-known-uri), - this should be accessed with the hostname of the homeserver by making a + {{% boxes/note %}} + Like the [well-known discovery URI](/client-server-api/#well-known-uris), + this endpoint should be accessed with the hostname of the homeserver's + [server name](/appendices/#server-name) by making a GET request to `https://hostname/.well-known/matrix/support`. + {{% /boxes/note %}} Note that this endpoint is not necessarily handled by the homeserver. It may be served by another webserver, used for discovering support diff --git a/data/api/client-server/wellknown.yaml b/data/api/client-server/wellknown.yaml index 72de3598..4e2383bf 100644 --- a/data/api/client-server/wellknown.yaml +++ b/data/api/client-server/wellknown.yaml @@ -26,6 +26,12 @@ paths: suitably namespaced for each application and reduces the risk of clashes. + {{% boxes/note %}} + This endpoint should be accessed with the hostname of the homeserver's + [server name](/appendices/#server-name) by making a + GET request to `https://hostname/.well-known/matrix/client`. + {{% /boxes/note %}} + Note that this endpoint is not necessarily handled by the homeserver, but by another webserver, to be used for discovering the homeserver URL. operationId: getWellknown diff --git a/data/api/server-server/wellknown.yaml b/data/api/server-server/wellknown.yaml index 717462f9..920bc356 100644 --- a/data/api/server-server/wellknown.yaml +++ b/data/api/server-server/wellknown.yaml @@ -24,6 +24,12 @@ paths: Gets information about the delegated server for server-server communication between Matrix homeservers. Servers should follow 30x redirects, carefully avoiding redirect loops, and use normal X.509 certificate validation. + + {{% boxes/note %}} + This endpoint should be accessed with the hostname of the homeserver's + [server name](/appendices/#server-name) by making a + GET request to `https://hostname/.well-known/matrix/server`. + {{% /boxes/note %}} operationId: getWellKnown responses: "200": From c74befd111aeb245c72cc98f854d04cd58aa1ab9 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 15:34:39 +0200 Subject: [PATCH 29/67] Clarify the meaning of "public rooms" for profile look-ups (#2101) --- .../client_server/newsfragments/2101.clarification | 1 + content/client-server-api/_index.md | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2101.clarification diff --git a/changelogs/client_server/newsfragments/2101.clarification b/changelogs/client_server/newsfragments/2101.clarification new file mode 100644 index 00000000..fa84c41c --- /dev/null +++ b/changelogs/client_server/newsfragments/2101.clarification @@ -0,0 +1 @@ +"Public" rooms in profile look-ups are defined through their join rule and history visibility. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index f2de85de..0b2a8346 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -2862,10 +2862,15 @@ re-invited. #### Server behaviour -Homeservers MUST at a minimum allow profile look-up for: +Homeservers MUST at a minimum allow profile look-up for users who are +visible to the requester based on their membership in rooms known to the +homeserver. This means: - users that share a room with the requesting user -- users that reside in public rooms known to the homeserver +- users who are joined to rooms known to the homeserver that have a + `public` [join rule](#mroomjoin_rules) +- users who are joined to rooms known to the homeserver that have a + `world_readable` [history visibility](#room-history-visibility) In all other cases, homeservers MAY deny profile look-up by responding with 403 and an error code of `M_FORBIDDEN`. From fc811710816e855ac3d996f42841de57008929b2 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 15:37:31 +0200 Subject: [PATCH 30/67] Clarify the meaning of "public rooms" for user directory queries (#2102) --- .../newsfragments/2102.clarification | 1 + data/api/client-server/users.yaml | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2102.clarification diff --git a/changelogs/client_server/newsfragments/2102.clarification b/changelogs/client_server/newsfragments/2102.clarification new file mode 100644 index 00000000..df9eab58 --- /dev/null +++ b/changelogs/client_server/newsfragments/2102.clarification @@ -0,0 +1 @@ +"Public" rooms in user directory queries are defined through their join rule and history visibility. diff --git a/data/api/client-server/users.yaml b/data/api/client-server/users.yaml index 3a7f2bfa..c1f3c6c8 100644 --- a/data/api/client-server/users.yaml +++ b/data/api/client-server/users.yaml @@ -20,10 +20,17 @@ paths: post: summary: Searches the user directory. description: |- - Performs a search for users. The homeserver may - determine which subset of users are searched, however the homeserver - MUST at a minimum consider the users the requesting user shares a - room with and those who reside in public rooms (known to the homeserver). + Performs a search for users. The homeserver may determine which + subset of users are searched. However, the homeserver MUST at a + minimum consider users who are visible to the requester based + on their membership in rooms known to the homeserver. This means: + + - users that share a room with the requesting user + - users who are joined to rooms known to the homeserver that have a + `public` [join rule](#mroomjoin_rules) + - users who are joined to rooms known to the homeserver that have a + `world_readable` [history visibility](#room-history-visibility) + The search MUST consider local users to the homeserver, and SHOULD query remote users as part of the search. From 2c6ddafb43cc92595cc24e307a95b1ed9d3ab8d8 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 16:09:12 +0200 Subject: [PATCH 31/67] Clarify the meaning of "public rooms" for call invites (#2106) --- .../client_server/newsfragments/2106.clarification | 1 + content/client-server-api/modules/voip_events.md | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2106.clarification diff --git a/changelogs/client_server/newsfragments/2106.clarification b/changelogs/client_server/newsfragments/2106.clarification new file mode 100644 index 00000000..8a0dd00a --- /dev/null +++ b/changelogs/client_server/newsfragments/2106.clarification @@ -0,0 +1 @@ +"Public" rooms with respect to call invites are defined through their join rule. diff --git a/content/client-server-api/modules/voip_events.md b/content/client-server-api/modules/voip_events.md index 14b7d796..1c0bfd28 100644 --- a/content/client-server-api/modules/voip_events.md +++ b/content/client-server-api/modules/voip_events.md @@ -202,11 +202,13 @@ specific user, and should be set to the Matrix user ID of that user. Invites without an `invitee` field are defined to be intended for any member of the room other than the sender of the event. -Clients should consider an incoming call if they see a non-expired invite event where the `invitee` field is either -absent or equal to their user's Matrix ID, however they should evaluate whether or not to ring based on their -user's trust relationship with the callers and/or where the call was placed. As a starting point, it is -suggested that clients ignore call invites from users in public rooms. It is strongly recommended that -when clients do not ring for an incoming call invite, they still display the call invite in the room and +Clients should consider an incoming call if they see a non-expired invite event +where the `invitee` field is either absent or equal to their user's Matrix ID. +They should, however, evaluate whether or not to ring based on their user's trust +relationship with the callers and/or where the call was placed. As a starting +point, it is RECOMMENDED that clients ignore call invites in rooms with a +[join rule](#mroomjoin_rules) of `public`. When clients suppress ringing for an +incoming call invite, they SHOULD still display the call invite in the room and annotate that it was ignored. ##### Glare From 0a1efd8c9ceebe700e7bc786bd2de3cb7a524613 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 16:10:08 +0200 Subject: [PATCH 32/67] Clarify the meaning of "public rooms" for policy lists (#2107) --- changelogs/client_server/newsfragments/2107.clarification | 1 + content/client-server-api/modules/moderation_policies.md | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2107.clarification diff --git a/changelogs/client_server/newsfragments/2107.clarification b/changelogs/client_server/newsfragments/2107.clarification new file mode 100644 index 00000000..0474010e --- /dev/null +++ b/changelogs/client_server/newsfragments/2107.clarification @@ -0,0 +1 @@ +"Public" rooms have no specific meaning with respect to moderation policy lists. diff --git a/content/client-server-api/modules/moderation_policies.md b/content/client-server-api/modules/moderation_policies.md index 2912d164..15a3a377 100644 --- a/content/client-server-api/modules/moderation_policies.md +++ b/content/client-server-api/modules/moderation_policies.md @@ -18,8 +18,9 @@ the entity making the decisions on filtering is best positioned to interpret the rules how it sees fit. Moderation policy lists are stored as room state events. There are no -restrictions on how the rooms can be configured (they could be public, -private, encrypted, etc). +restrictions on how the rooms can be configured in terms of +[join rules](#mroomjoin_rules), [history visibility](#room-history-visibility), +encryption, etc. There are currently 3 kinds of entities which can be affected by rules: `user`, `server`, and `room`. All 3 are described with From 73fcf366a0da5fb4e408a0e845e705277fdccea9 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 16:11:50 +0200 Subject: [PATCH 33/67] Clarify the meaning of "public rooms" for presence (#2108) --- changelogs/client_server/newsfragments/2108.clarification | 1 + content/client-server-api/modules/presence.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2108.clarification diff --git a/changelogs/client_server/newsfragments/2108.clarification b/changelogs/client_server/newsfragments/2108.clarification new file mode 100644 index 00000000..2e8c4e59 --- /dev/null +++ b/changelogs/client_server/newsfragments/2108.clarification @@ -0,0 +1 @@ +"Public" rooms with respect to presence are defined through their join rule. diff --git a/content/client-server-api/modules/presence.md b/content/client-server-api/modules/presence.md index ba46b327..4bbd43eb 100644 --- a/content/client-server-api/modules/presence.md +++ b/content/client-server-api/modules/presence.md @@ -68,5 +68,7 @@ will cause the server to automatically set their presence to `online`. #### Security considerations -Presence information is shared with all users who share a room with the -target user. In large public rooms this could be undesirable. +Presence information is published to all users who share a room with the +target user. If the target user is a member of a room with a `public` +[join rule](#mroomjoin_rules), any other user in the federation is +able to gain access to the target user's presence. This could be undesirable. From f4e6e6dea96c549bfe7b51d9eeab86e316fe321a Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 16:13:40 +0200 Subject: [PATCH 34/67] Clarify the meaning of "public rooms" for presence (#2108) From 04397076248040937783101d12c86010cbb08f93 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 13 May 2025 17:01:25 +0200 Subject: [PATCH 35/67] Spec PR - MSC3765: Rich text in room topics (#2095) Signed-off-by: Johannes Marbach --- .../client_server/newsfragments/2095.feature | 1 + .../server_server/newsfragments/2095.feature | 1 + content/client-server-api/modules/search.md | 7 ++-- data/api/client-server/create_room.yaml | 14 ++++---- .../definitions/public_rooms_chunk.yaml | 4 ++- data/event-schemas/examples/m.room.topic.yaml | 10 +++++- .../components/m_text_content_block.yaml | 28 +++++++++++++++ data/event-schemas/schema/m.room.topic.yaml | 35 +++++++++++++++---- 8 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2095.feature create mode 100644 changelogs/server_server/newsfragments/2095.feature create mode 100644 data/event-schemas/schema/components/m_text_content_block.yaml diff --git a/changelogs/client_server/newsfragments/2095.feature b/changelogs/client_server/newsfragments/2095.feature new file mode 100644 index 00000000..0a993bbb --- /dev/null +++ b/changelogs/client_server/newsfragments/2095.feature @@ -0,0 +1 @@ +Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). diff --git a/changelogs/server_server/newsfragments/2095.feature b/changelogs/server_server/newsfragments/2095.feature new file mode 100644 index 00000000..0a993bbb --- /dev/null +++ b/changelogs/server_server/newsfragments/2095.feature @@ -0,0 +1 @@ +Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). diff --git a/content/client-server-api/modules/search.md b/content/client-server-api/modules/search.md index 8115d5be..2705aa66 100644 --- a/content/client-server-api/modules/search.md +++ b/content/client-server-api/modules/search.md @@ -26,9 +26,10 @@ on certain keys of certain event types. The supported keys to search over are: -- `content.body` in `m.room.message` -- `content.name` in `m.room.name` -- `content.topic` in `m.room.topic` +- `content.body` in [`m.room.message`](/client-server-api/#mroommessage) +- `content.name` in [`m.room.name`](/client-server-api/#mroomname) +- In [`m.room.topic`](/client-server-api/#mroomtopic), `content.topic` + as well as the `body` of the `text/plain` representation in `content['m.topic']`. The search will *not* include rooms that are end to end encrypted. diff --git a/data/api/client-server/create_room.yaml b/data/api/client-server/create_room.yaml index 3992fdfe..03a85443 100644 --- a/data/api/client-server/create_room.yaml +++ b/data/api/client-server/create_room.yaml @@ -109,15 +109,17 @@ paths: name: type: string description: |- - If this is included, an `m.room.name` event will be sent - into the room to indicate the name of the room. See Room - Events for more information on `m.room.name`. + If this is included, an [`m.room.name`](/client-server-api/#mroomname) event + will be sent into the room to indicate the name for the room. + This overwrites any [`m.room.name`](/client-server-api/#mroomname) + event in `initial_state`. topic: type: string description: |- - If this is included, an `m.room.topic` event will be sent - into the room to indicate the topic for the room. See Room - Events for more information on `m.room.topic`. + If this is included, an [`m.room.topic`](/client-server-api/#mroomtopic) + event with a `text/plain` mimetype will be sent into the room + to indicate the topic for the room. This overwrites any + [`m.room.topic`](/client-server-api/#mroomtopic) event in `initial_state`. invite: type: array description: |- diff --git a/data/api/client-server/definitions/public_rooms_chunk.yaml b/data/api/client-server/definitions/public_rooms_chunk.yaml index 9c6ae6fc..64786432 100644 --- a/data/api/client-server/definitions/public_rooms_chunk.yaml +++ b/data/api/client-server/definitions/public_rooms_chunk.yaml @@ -33,7 +33,9 @@ properties: example: "!abcdefg:example.org" topic: type: string - description: The topic of the room, if any. + description: |- + The plain text topic of the room. Omitted if no `text/plain` mimetype + exists in [`m.room.topic`](/client-server-api/#mroomtopic). example: "All things general" world_readable: type: boolean diff --git a/data/event-schemas/examples/m.room.topic.yaml b/data/event-schemas/examples/m.room.topic.yaml index 69e5d4f1..993145a6 100644 --- a/data/event-schemas/examples/m.room.topic.yaml +++ b/data/event-schemas/examples/m.room.topic.yaml @@ -3,6 +3,14 @@ "type": "m.room.topic", "state_key": "", "content": { - "topic": "A room topic" + "m.topic": { + "m.text": [ { + "mimetype": "text/html", + "body": "An interesting room topic" + }, { + "body": "An interesting room topic" + }] + }, + "topic": "An interesting room topic" } } diff --git a/data/event-schemas/schema/components/m_text_content_block.yaml b/data/event-schemas/schema/components/m_text_content_block.yaml new file mode 100644 index 00000000..29c8d148 --- /dev/null +++ b/data/event-schemas/schema/components/m_text_content_block.yaml @@ -0,0 +1,28 @@ +type: array +description: |- + An ordered array of textual representations in different mimetypes. + + Senders SHOULD specify at least one representation and SHOULD always + include a plaintext representation. + + Receivers SHOULD use the first representation in the array that + they understand. +title: TextContentBlock +items: + type: object + title: TextualRepresentation + properties: + mimetype: + type: string + description: The mimetype. Defaults to `text/plain` if omitted. + example: "text/html" + body: + type: string + description: |- + The string content. + + Clients SHOULD validate and sanitize the content as they do + for rich content associated with [`msgtype`](/client-server-api/#mroommessage-msgtypes) + of [`m.room.message`](/client-server-api/#mroommessage). + required: + - body diff --git a/data/event-schemas/schema/m.room.topic.yaml b/data/event-schemas/schema/m.room.topic.yaml index 56f0caf9..580566d2 100644 --- a/data/event-schemas/schema/m.room.topic.yaml +++ b/data/event-schemas/schema/m.room.topic.yaml @@ -1,20 +1,41 @@ --- allOf: - $ref: core-event-schema/state_event.yaml -description: |- - A topic is a short message detailing what is currently being discussed in the room. - It can also be used as a way to display extra information about the room, which may not - be suitable for the room name. - The room topic can also be set when creating a room using `/createRoom` with the `topic` key.' - +description: |- + A topic is a short message detailing what is currently being discussed + in the room. It can also be used as a way to display extra information + about the room, which may not be suitable for the room name. The room + topic can also be set when creating a room using + [`/createRoom`](client-server-api/#post_matrixclientv3createroom), either + with the `topic` key or by specifying a full event in `initial_state`. + If the `topic` property is absent, null, or empty then the topic is unset. In other words, an empty `topic` property effectively resets the room to having no topic. + + In order to prevent formatting abuse in room topics, clients SHOULD + limit the length of topics during both entry and display, for instance, + by capping the number of displayed lines. Additionally, clients SHOULD + ignore things like headings and enumerations (or format them as regular + text). properties: content: properties: topic: - description: The topic text. + description: |- + The topic in plain text. + + This SHOULD duplicate the content of the `text/plain` + representation in `m.topic` if any exists. type: string + m.topic: + type: object + title: TopicContentBlock + x-addedInMatrixVersion: "1.15" + description: |- + Textual representation of the room topic in different mimetypes. + properties: + m.text: + $ref: components/m_text_content_block.yaml required: - topic type: object From 338047ec7bb628a1215a730611b9d87739012600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 13 May 2025 17:03:10 +0200 Subject: [PATCH 36/67] Clarify that `join_authorised_via_users_server` auth event is only necessary for `join`s (#2100) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille --- changelogs/server_server/newsfragments/2100.clarification | 1 + content/server-server-api.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelogs/server_server/newsfragments/2100.clarification diff --git a/changelogs/server_server/newsfragments/2100.clarification b/changelogs/server_server/newsfragments/2100.clarification new file mode 100644 index 00000000..a488b392 --- /dev/null +++ b/changelogs/server_server/newsfragments/2100.clarification @@ -0,0 +1 @@ +Clarify that auth event of `content.join_authorised_via_users_server` is only necessary for `m.room.member` with a `membership` of `join`. diff --git a/content/server-server-api.md b/content/server-server-api.md index 10d91468..2745bff6 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -544,8 +544,8 @@ the following subset of the room state: `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, - and the [room version supports restricted rooms](/rooms/#feature-matrix), + - If `membership` is `join`, `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`. From 67743d5715071afa4a2b8553321dccf5339a330d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 13 May 2025 17:09:18 +0200 Subject: [PATCH 37/67] Fix generation of historical spec (#2123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the move of the config file, the command in CI did not work as expected anymore. I am unsure why Hugo actually ignored the missing config file in the command… To avoid this problem in the future and simplify the job, we use the default config and add an environment variable for the status which will always take precedence over the config. Signed-off-by: Kévin Commaille --- .github/workflows/main.yml | 5 +++-- changelogs/internal/newsfragments/2123.clarification | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 changelogs/internal/newsfragments/2123.clarification diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index daa8fb67..446aca9c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -284,10 +284,11 @@ jobs: npm i npm run get-proposals - name: "⚙️ hugo" + env: + HUGO_PARAMS_VERSION_STATUS: "historical" # Create a baseURL like `/v1.2` out of the `v1.2` tag run: | - echo -e '[params.version]\nstatus="historical"' > historical.toml - hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" + hugo --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" - name: "📥 Spec definition download" uses: actions/download-artifact@v4 diff --git a/changelogs/internal/newsfragments/2123.clarification b/changelogs/internal/newsfragments/2123.clarification new file mode 100644 index 00000000..af26abaf --- /dev/null +++ b/changelogs/internal/newsfragments/2123.clarification @@ -0,0 +1 @@ +Fix the historical info box when generating the historical spec in CI. From 4ed55a60ecaaeb008191bd1715809114eef8cc39 Mon Sep 17 00:00:00 2001 From: V02460 Date: Tue, 20 May 2025 16:54:09 +0200 Subject: [PATCH 38/67] =?UTF-8?q?[schema]=20Correct=20null=20value=20handl?= =?UTF-8?q?ing=20for=20the=20AS=20Registration=E2=80=99s=20`url`=20propert?= =?UTF-8?q?y=20(#2130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> --- changelogs/application_service/newsfragments/2130.feature | 1 + data/api/application-service/definitions/registration.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/application_service/newsfragments/2130.feature diff --git a/changelogs/application_service/newsfragments/2130.feature b/changelogs/application_service/newsfragments/2130.feature new file mode 100644 index 00000000..7761505c --- /dev/null +++ b/changelogs/application_service/newsfragments/2130.feature @@ -0,0 +1 @@ +Correct null value handling for the AS Registration's `url` property. diff --git a/data/api/application-service/definitions/registration.yaml b/data/api/application-service/definitions/registration.yaml index ce702df0..f5db31e6 100644 --- a/data/api/application-service/definitions/registration.yaml +++ b/data/api/application-service/definitions/registration.yaml @@ -19,7 +19,7 @@ properties: type: string description: A unique, user-defined ID of the application service which will never change. url: - type: string + type: ["null", "string"] description: The URL for the application service. May include a path after the domain name. Optionally set to null if no traffic is required. as_token: type: string From 075d203ecd9d08660eadb10901d3ce0b22b1be0d Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Wed, 21 May 2025 16:34:29 +0100 Subject: [PATCH 39/67] Fix typo: as->has (#2144) Signed-off-by: Andy Balaam --- changelogs/client_server/newsfragments/2144.clarification | 1 + content/client-server-api/modules/end_to_end_encryption.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2144.clarification diff --git a/changelogs/client_server/newsfragments/2144.clarification b/changelogs/client_server/newsfragments/2144.clarification new file mode 100644 index 00000000..07917287 --- /dev/null +++ b/changelogs/client_server/newsfragments/2144.clarification @@ -0,0 +1 @@ +Fix typo: as->has. diff --git a/content/client-server-api/modules/end_to_end_encryption.md b/content/client-server-api/modules/end_to_end_encryption.md index 49b053f6..298f6726 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -528,7 +528,7 @@ messages, Alice only sends one request event (an event with type `m.room.message` with `msgtype: m.key.verification.request`, rather than an event with type `m.key.verification.request`), to the room. In addition, Alice does not send an `m.key.verification.cancel` event to tell Bob's other devices -that the request as already been accepted; instead, when Bob's other devices +that the request has already been accepted; instead, when Bob's other devices see his `m.key.verification.ready` event, they will know that the request has already been accepted, and that they should ignore the request. From 2c734c3c5b1aad5f949302e3ca9c86dc3a2c05e6 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 21 May 2025 17:43:02 +0200 Subject: [PATCH 40/67] Clarify the meaning of "public rooms" in the room directory (#2104) Signed-off-by: Johannes Marbach Co-authored-by: Kim Brose <2803622+HarHarLinks@users.noreply.github.com> Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- .../newsfragments/2104.clarification | 1 + .../newsfragments/2104.clarification | 1 + content/application-service-api.md | 6 +- content/client-server-api/_index.md | 30 ++++++- content/server-server-api.md | 7 +- .../appservice_room_directory.yaml | 15 ++-- data/api/client-server/create_room.yaml | 9 +- .../definitions/public_rooms_chunk.yaml | 2 +- .../definitions/public_rooms_response.yaml | 21 +---- data/api/client-server/list_public_rooms.yaml | 48 +++++------ data/api/server-server/public_rooms.yaml | 85 +++---------------- 11 files changed, 92 insertions(+), 133 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2104.clarification create mode 100644 changelogs/server_server/newsfragments/2104.clarification diff --git a/changelogs/client_server/newsfragments/2104.clarification b/changelogs/client_server/newsfragments/2104.clarification new file mode 100644 index 00000000..fc064c62 --- /dev/null +++ b/changelogs/client_server/newsfragments/2104.clarification @@ -0,0 +1 @@ +Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. diff --git a/changelogs/server_server/newsfragments/2104.clarification b/changelogs/server_server/newsfragments/2104.clarification new file mode 100644 index 00000000..fc064c62 --- /dev/null +++ b/changelogs/server_server/newsfragments/2104.clarification @@ -0,0 +1 @@ +Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. diff --git a/content/application-service-api.md b/content/application-service-api.md index 2882f3d9..4c1ada48 100644 --- a/content/application-service-api.md +++ b/content/application-service-api.md @@ -492,10 +492,10 @@ via the query string). It is expected that the application service use the transactions pushed to it to handle events rather than syncing with the user implied by `sender_localpart`. -#### Application service room directories +#### Published room directories -Application services can maintain their own room directories for their -defined third-party protocols. These room directories may be accessed by +Application services can maintain their own published room directories for +their defined third-party protocols. These directories may be accessed by clients through additional parameters on the `/publicRooms` client-server endpoint. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 0b2a8346..d4dfd561 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -2846,7 +2846,35 @@ re-invited. {{% http-api spec="client-server" api="banning" %}} -### Listing rooms +### Published room directory + +Homeservers MAY publish a room directory to allow users to discover rooms. A room +can have one of two visibility settings in the directory: + +- `public`: The room will be shown in the published room directory. +- `private`: The room will be hidden from the published room directory. + +Clients can define a room's initial visibility in the directory via the `visibility` +parameter in [`/createRoom`](#post_matrixclientv3createroom). Irrespective of room +creation, clients can query and change a room's visibility in the directory through +the endpoints listed below, provided that the server permits this. + +{{% boxes/warning %}} +The visibility setting merely defines whether a room is included in the published +room directory or not. It doesn't make any guarantees about the room's +[join rule](#mroomjoin_rules) or [history visibility](#room-history-visibility). + +In particular, a visibility setting of `public` should not be confused with a `public` +join rule. Rooms with a join rule of `knock`, for instance, could reasonably be published +in the directory, too. + +Similarly, a visibility setting of `public` does not necessarily imply a `world_readable` +history visibility. + +To increase performance or by preference, servers MAY apply additional filters when listing the +directory, for instance, by automatically excluding rooms with `invite` join rules +that are not `world_readable` regardless of their visibility. +{{% /boxes/warning %}} {{% http-api spec="client-server" api="list_public_rooms" %}} diff --git a/content/server-server-api.md b/content/server-server-api.md index 2745bff6..2c52c0e3 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -1048,11 +1048,10 @@ user's Matrix ID and the token delivered when the invite was stored, this verification will prove that the `m.room.member` invite event comes from the user owning the invited third-party identifier. -## Public Room Directory +## Published Room Directory -To complement the [Client-Server -API](/client-server-api)'s room directory, -homeservers need a way to query the public rooms for another server. +To complement the [room directory in the Client-Server API](/client-server-api#published-room-directory), +homeservers need a way to query the published rooms of another server. This can be done by making a request to the `/publicRooms` endpoint for the server the room directory should be retrieved for. diff --git a/data/api/client-server/appservice_room_directory.yaml b/data/api/client-server/appservice_room_directory.yaml index b4ec42f0..0443dad2 100644 --- a/data/api/client-server/appservice_room_directory.yaml +++ b/data/api/client-server/appservice_room_directory.yaml @@ -13,18 +13,21 @@ # limitations under the License. openapi: 3.1.0 info: - title: Matrix Client-Server Application Service Room Directory API + title: Matrix Client-Server Application Service Published Room Directory API version: 1.0.0 paths: "/directory/list/appservice/{networkId}/{roomId}": put: - summary: Updates a room's visibility in the application service's room directory. - description: |- - Updates the visibility of a given room on the application service's room + summary: |- + Updates a room's visibility in the application service's published room directory. + description: |- + Updates the visibility of a given room in the application service's + published room directory. - This API is similar to the room directory visibility API used by clients - to update the homeserver's more general room directory. + This API is similar to the + [visibility API](/client-server-api#put_matrixclientv3directorylistroomroomid) + used by clients to update the homeserver's more general published room directory. This API requires the use of an application service access token (`as_token`) instead of a typical client's access_token. This API cannot be invoked by diff --git a/data/api/client-server/create_room.yaml b/data/api/client-server/create_room.yaml index 03a85443..339217c5 100644 --- a/data/api/client-server/create_room.yaml +++ b/data/api/client-server/create_room.yaml @@ -87,12 +87,9 @@ paths: - public - private description: |- - A `public` visibility indicates that the room will be shown - in the published room list. A `private` visibility will hide - the room from the published room list. Rooms default to - `private` visibility if this key is not included. NB: This - should not be confused with `join_rules` which also uses the - word `public`. + The room's visibility in the server's + [published room directory](/client-server-api#published-room-directory). + Defaults to `private`. room_alias_name: type: string description: |- diff --git a/data/api/client-server/definitions/public_rooms_chunk.yaml b/data/api/client-server/definitions/public_rooms_chunk.yaml index 64786432..d2e9a09b 100644 --- a/data/api/client-server/definitions/public_rooms_chunk.yaml +++ b/data/api/client-server/definitions/public_rooms_chunk.yaml @@ -13,7 +13,7 @@ # limitations under the License. type: object -title: "PublicRoomsChunk" +title: "PublishedRoomsChunk" properties: canonical_alias: type: string diff --git a/data/api/client-server/definitions/public_rooms_response.yaml b/data/api/client-server/definitions/public_rooms_response.yaml index ba2b712c..4df62b08 100644 --- a/data/api/client-server/definitions/public_rooms_response.yaml +++ b/data/api/client-server/definitions/public_rooms_response.yaml @@ -13,28 +13,15 @@ # limitations under the License. type: object -description: A list of the rooms on the server. +description: A list of the published rooms on the server. required: ["chunk"] properties: chunk: type: array description: |- - A paginated chunk of public rooms. + A paginated chunk of published rooms. items: - allOf: - - $ref: "public_rooms_chunk.yaml" - - type: object - title: PublicRoomsChunk - properties: - # Override description of join_rule - join_rule: - type: string - description: |- - The room's join rule. When not present, the room is assumed to - be `public`. Note that rooms with `invite` join rules are not - expected here, but rooms with `knock` rules are given their - near-public nature. - example: "public" + $ref: "public_rooms_chunk.yaml" next_batch: type: string description: |- @@ -50,7 +37,7 @@ properties: total_room_count_estimate: type: integer description: |- - An estimate on the total number of public rooms, if the + An estimate on the total number of published rooms, if the server has an estimate. example: { "chunk": [ diff --git a/data/api/client-server/list_public_rooms.yaml b/data/api/client-server/list_public_rooms.yaml index ffd202a4..ef71ca63 100644 --- a/data/api/client-server/list_public_rooms.yaml +++ b/data/api/client-server/list_public_rooms.yaml @@ -13,14 +13,15 @@ # limitations under the License. openapi: 3.1.0 info: - title: Matrix Client-Server Room Directory API + title: Matrix Client-Server Published Room Directory API version: 1.0.0 paths: "/directory/list/room/{roomId}": get: summary: Gets the visibility of a room in the directory - description: Gets the visibility of a given room on the server's public room - directory. + description: |- + Gets the visibility of a given room in the server's + published room directory. operationId: getRoomVisibilityOnDirectory parameters: - in: path @@ -32,7 +33,7 @@ paths: type: string responses: "200": - description: The visibility of the room in the directory + description: The visibility of the room in the directory. content: application/json: schema: @@ -50,7 +51,7 @@ paths: "visibility": "public" } "404": - description: The room is not known to the server + description: The room is not known to the server. content: application/json: schema: @@ -64,14 +65,13 @@ paths: tags: - Room discovery put: - summary: Sets the visibility of a room in the room directory + summary: Sets the visibility of a room in the directory description: |- - Sets the visibility of a given room in the server's public room - directory. + Sets the visibility of a given room in the server's published room directory. - Servers may choose to implement additional access control checks - here, for instance that room visibility can only be changed by - the room creator or a server administrator. + Servers MAY implement additional access control checks, for instance, + to ensure that a room's visibility can only be changed by the room creator + or a server administrator. operationId: setRoomVisibilityOnDirectory security: - accessTokenQuery: [] @@ -97,11 +97,11 @@ paths: - public description: |- The new visibility setting for the room. - Defaults to 'public'. + Defaults to `public`. example: { "visibility": "public" } - description: The new visibility for the room on the room directory. + description: The new visibility for the room in the published room directory. required: true responses: "200": @@ -114,7 +114,7 @@ paths: response: value: {} "404": - description: The room is not known to the server + description: The room is not known to the server. content: application/json: schema: @@ -129,9 +129,9 @@ paths: - Room discovery /publicRooms: get: - summary: Lists the public rooms on the server. + summary: Lists a server's published room directory description: |- - Lists the public rooms on the server. + Lists a server's published room directory. This API returns paginated responses. The rooms are ordered by the number of joined members, with the largest rooms first. @@ -154,13 +154,13 @@ paths: - in: query name: server description: |- - The server to fetch the public room lists from. Defaults to the - local server. Case sensitive. + The server to fetch the published room directory from. Defaults + to the local server. Case sensitive. schema: type: string responses: "200": - description: A list of the rooms on the server. + description: A list of the published rooms on the server. content: application/json: schema: @@ -168,9 +168,9 @@ paths: tags: - Room discovery post: - summary: Lists the public rooms on the server with optional filter. + summary: Lists a server's published room directory with an optional filter description: |- - Lists the public rooms on the server, with optional filter. + Lists a server's published room directory with an optional filter. This API returns paginated responses. The rooms are ordered by the number of joined members, with the largest rooms first. @@ -182,8 +182,8 @@ paths: - in: query name: server description: |- - The server to fetch the public room lists from. Defaults to the - local server. Case sensitive. + The server to fetch the published room directory from. Defaults + to the local server. Case sensitive. schema: type: string requestBody: @@ -253,7 +253,7 @@ paths: required: true responses: "200": - description: A list of the rooms on the server. + description: A filtered list of the published rooms on the server. content: application/json: schema: diff --git a/data/api/server-server/public_rooms.yaml b/data/api/server-server/public_rooms.yaml index 565f1aa4..8beaecb2 100644 --- a/data/api/server-server/public_rooms.yaml +++ b/data/api/server-server/public_rooms.yaml @@ -13,16 +13,20 @@ # limitations under the License. openapi: 3.1.0 info: - title: Matrix Federation Public Rooms API + title: Matrix Federation Published Room Directory API version: 1.0.0 paths: /publicRooms: get: - summary: Get all the public rooms for a homeserver + summary: Lists the server's published room directory description: |- - Gets all the public rooms for the homeserver. This should not return - rooms that are listed on another homeserver's directory, just those - listed on the receiving homeserver's directory. + Lists the server's published room directory. + + This API returns paginated responses. The rooms are ordered by the number + of joined members, with the largest rooms first. + + This SHOULD not return rooms that are listed on another homeserver's directory, + just those listed on the receiving homeserver's directory. operationId: getPublicRooms security: - signedRequest: [] @@ -62,21 +66,18 @@ paths: type: string responses: "200": - description: The public room list for the homeserver. + description: A list of the published rooms on the server. content: application/json: schema: $ref: ../client-server/definitions/public_rooms_response.yaml post: - summary: Gets the public rooms on the server with optional filter. + summary: Lists the server's published room directory with an optional filter description: |- - Lists the public rooms on the server, with optional filter. + Lists the server's published room directory with an optional filter. This API returns paginated responses. The rooms are ordered by the number of joined members, with the largest rooms first. - - Note that this endpoint receives and returns the same format that is seen - in the Client-Server API's `POST /publicRooms` endpoint. operationId: queryPublicRooms security: - signedRequest: [] @@ -147,69 +148,11 @@ paths: required: true responses: "200": - description: A list of the rooms on the server. + description: A filtered list of the published rooms on the server. content: application/json: schema: - type: object - description: A list of the rooms on the server. - required: - - chunk - properties: - chunk: - title: PublicRoomsChunks - type: array - description: A paginated chunk of public rooms. - items: - allOf: - - $ref: ../client-server/definitions/public_rooms_chunk.yaml - - type: object - properties: - # Override description of join_rule - join_rule: - type: string - description: |- - The room's join rule. When not present, the room is assumed to - be `public`. Note that rooms with `invite` join rules are not - expected here, but rooms with `knock` rules are given their - near-public nature. - next_batch: - type: string - description: |- - A pagination token for the response. The absence of this token - means there are no more results to fetch and the client should - stop paginating. - prev_batch: - type: string - description: |- - A pagination token that allows fetching previous results. The - absence of this token means there are no results before this - batch, i.e. this is the first batch. - total_room_count_estimate: - type: integer - description: |- - An estimate on the total number of public rooms, if the - server has an estimate. - examples: - response: - value: { - "chunk": [ - { - "avatar_url": "mxc://bleecker.street/CHEDDARandBRIE", - "guest_can_join": false, - "name": "CHEESE", - "num_joined_members": 37, - "room_id": "!ol19s:bleecker.street", - "topic": "Tasty tasty cheese", - "world_readable": true, - "join_rule": "public", - "room_type": "m.space" - } - ], - "next_batch": "p190q", - "prev_batch": "p1902", - "total_room_count_estimate": 115 - } + $ref: ../client-server/definitions/public_rooms_response.yaml servers: - url: "{protocol}://{hostname}{basePath}" variables: From cbf1854b93ca43b7ad1538d6ecdb4600385da9a6 Mon Sep 17 00:00:00 2001 From: Kim Brose <2803622+HarHarLinks@users.noreply.github.com> Date: Tue, 27 May 2025 08:52:36 +0000 Subject: [PATCH 41/67] Update the header navigation menu with 2025 links to m.org (#2137) --- changelogs/internal/newsfragments/2137.clarification | 1 + config/_default/hugo.toml | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 changelogs/internal/newsfragments/2137.clarification diff --git a/changelogs/internal/newsfragments/2137.clarification b/changelogs/internal/newsfragments/2137.clarification new file mode 100644 index 00000000..6503f22b --- /dev/null +++ b/changelogs/internal/newsfragments/2137.clarification @@ -0,0 +1 @@ +Update the header navigation menu with links to modern matrix.org. Contributed by @HarHarLinks. diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index 3394c942..b31416c2 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -23,15 +23,15 @@ description = "Home of the Matrix specification for decentralised communication" [menus] [[menus.main]] name = 'Foundation' - url = 'https://matrix.org/foundation/' + url = 'https://matrix.org/foundation/about/' weight = 10 [[menus.main]] - name = 'FAQs' - url = 'https://matrix.org/faq' + name = 'User Docs' + url = 'https://matrix.org/docs/' weight = 20 [[menus.main]] name = 'Blog' - url = 'https://matrix.org/blog/posts' + url = 'https://matrix.org/blog/' weight = 30 [markup] From 643a6dca2d8860834c5c091999f3252e89e34222 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 28 May 2025 19:50:27 +0200 Subject: [PATCH 42/67] Spec PR - MSC4147: Including device keys with Olm-encrypted events (#2122) Signed-off-by: Johannes Marbach Co-authored-by: Richard van der Hoff --- .../client_server/newsfragments/2122.feature | 1 + .../modules/end_to_end_encryption.md | 93 +++++++++++++------ .../definitions/olm_payload.yaml | 88 ++++++++++++++++++ 3 files changed, 152 insertions(+), 30 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2122.feature create mode 100644 data/api/client-server/definitions/olm_payload.yaml diff --git a/changelogs/client_server/newsfragments/2122.feature b/changelogs/client_server/newsfragments/2122.feature new file mode 100644 index 00000000..0e299bad --- /dev/null +++ b/changelogs/client_server/newsfragments/2122.feature @@ -0,0 +1 @@ +Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147). diff --git a/content/client-server-api/modules/end_to_end_encryption.md b/content/client-server-api/modules/end_to_end_encryption.md index 298f6726..2c275089 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -1512,40 +1512,11 @@ message. The plaintext payload is of the form: -```json -{ - "type": "", - "content": "", - "sender": "", - "recipient": "", - "recipient_keys": { - "ed25519": "" - }, - "keys": { - "ed25519": "" - } -} -``` +{{% definition path="api/client-server/definitions/olm_payload" %}} The type and content of the plaintext message event are given in the payload. -Other properties are included in order to prevent an attacker from -publishing someone else's curve25519 keys as their own and subsequently -claiming to have sent messages which they didn't. `sender` must -correspond to the user who sent the event, `recipient` to the local -user, and `recipient_keys` to the local ed25519 key. - -Clients must confirm that the `sender_key` property in the cleartext -`m.room.encrypted` event body, and the `keys.ed25519` property in the -decrypted plaintext, match the keys returned by -[`/keys/query`](#post_matrixclientv3keysquery) for -the given user. Clients must also verify the signature of the keys from the -`/keys/query` response. Without this check, a client cannot be sure that -the sender device owns the private part of the ed25519 key it claims to -have in the Olm payload. This is crucial when the ed25519 key corresponds -to a verified device. - If a client has multiple sessions established with another device, it should use the session from which it last received and successfully decrypted a message. For these purposes, a session that has not received @@ -1555,6 +1526,68 @@ maximum number of olm sessions that it will maintain for each device, and expiring sessions on a Least Recently Used basis. The maximum number of olm sessions maintained per device should be at least 4. +###### Validation of incoming decrypted events + +{{% changed-in v="1.15" %}} Existing checks made more explicit, and checks for `sender_device_keys` added. + +After decrypting an incoming encrypted event, clients MUST apply the +following checks: + +1. The `sender` property in the decrypted content must match the + `sender` of the event. +2. The `keys.ed25519` property in the decrypted content must match + the `sender_key` property in the cleartext `m.room.encrypted` + event body. +3. The `recipient` property in the decrypted content must match + the user ID of the local user. +4. The `recipient_keys.ed25519` property in the decrypted content + must match the client device's [Ed25519 signing key](#device-keys). +5. Where `sender_device_keys` is present in the decrypted content: + 1. `sender_device_keys.user_id` must also match the `sender` + of the event. + 2. `sender_device_keys.keys.ed25519:` must also match + the `sender_key` property in the cleartext `m.room.encrypted` + event body. + 3. `sender_device_keys.keys.curve25519:` must match + the Curve25519 key used to establish the Olm session. + 4. The `sender_device_keys` structure must have a valid signature + from the key with ID `ed25519:` (i.e., the sending + device's Ed25519 key). + +Any event that does not comply with these checks MUST be discarded. + +###### Verification of the sending user for incoming events + +{{% added-in v="1.15" %}} + +In addition, for each Olm session, clients MUST verify that the +Curve25519 key used to establish the Olm session does indeed belong +to the claimed `sender`. This requires a signed "device keys" structure +for that Curve25519 key, which can be obtained in one of two ways: + +1. An Olm message may be received with a `sender_device_keys` property + in the decrypted content. +2. The keys are returned via a [`/keys/query`](#post_matrixclientv3keysquery) + request. Note that both the Curve25519 key **and** the Ed25519 key in + the returned device keys structure must match those used in an + Olm-encrypted event as above. (In particular, the Ed25519 key must + be present in the **encrypted** content of an Olm-encrypted event + to prevent an attacker from claiming another user's Curve25519 key + as their own.) + +Ownership of the Curve25519 key is then established in one of two ways: + +1. Via [cross-signing](#cross-signing). For this to be sufficient, the + device keys structure must be signed by the sender's self-signing key, + and that self-signing key must itself have been validated (either via + [explicit verification](#device-verification) or a "trust on first use" (TOFU) mechanism). +2. Via explicit verification of the device's Ed25519 signing key, as + contained in the device keys structure. This is no longer recommended. + +A failure to complete these verifications does not necessarily mean that +the session is bogus; however it is the case that there is no proof that +the claimed sender is accurate, and the user should be warned accordingly. + ###### Recovering from undecryptable messages Occasionally messages may be undecryptable by clients due to a variety diff --git a/data/api/client-server/definitions/olm_payload.yaml b/data/api/client-server/definitions/olm_payload.yaml new file mode 100644 index 00000000..8bac91e0 --- /dev/null +++ b/data/api/client-server/definitions/olm_payload.yaml @@ -0,0 +1,88 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +type: object +title: OlmPayload +description: |- + The plaintext payload of Olm message events. +properties: + type: + type: string + description: The type of the event. + content: + type: object + description: The event content. + sender: + type: string + description: The user ID of the event sender. + recipient: + type: string + description: The user ID of the intended event recipient. + recipient_keys: + description: The recipient's signing keys of the encrypted event. + $ref: "#/components/schemas/SigningKeys" + keys: + $ref: "#/components/schemas/SigningKeys" + description: The sender's signing keys of the encrypted event. + sender_device_keys: + $ref: device_keys.yaml + description: The sender's device keys. + x-addedInMatrixVersion: "1.15" +required: + - type + - content + - sender + - recipient + - recipient_keys + - keys +components: + schemas: + SigningKeys: + type: object + title: SigningKeys + description: Public keys used for an `m.olm.v1.curve25519-aes-sha2` event. + properties: + ed25519: + type: string + description: The Ed25519 public key encoded using unpadded base64. + required: + - ed25519 +example: { + "type": "", + "content": "", + "sender": "", + "recipient": "", + "recipient_keys": { + "ed25519": "" + }, + "keys": { + "ed25519": "" + }, + "sender_device_keys": { + "algorithms": ["", ""], + "user_id": "", + "device_id": "", + "keys": { + "ed25519:": "", + "curve25519:": "" + }, + "signatures": { + "": { + "ed25519:": "", + "ed25519:": "", + } + } + } +} From 7470c72d94304ec3b7d1c91c655dcd94ac96121b Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Thu, 29 May 2025 22:19:46 +0200 Subject: [PATCH 43/67] Clarify the meaning of "public spaces" (#2109) Relates to: #633 Signed-off-by: Johannes Marbach --- .../newsfragments/2109.clarification | 1 + content/client-server-api/modules/spaces.md | 21 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2109.clarification diff --git a/changelogs/client_server/newsfragments/2109.clarification b/changelogs/client_server/newsfragments/2109.clarification new file mode 100644 index 00000000..5aa7de17 --- /dev/null +++ b/changelogs/client_server/newsfragments/2109.clarification @@ -0,0 +1 @@ +Spaces are subject to the same access mechanisms as rooms. diff --git a/content/client-server-api/modules/spaces.md b/content/client-server-api/modules/spaces.md index 11734ac3..7de41459 100644 --- a/content/client-server-api/modules/spaces.md +++ b/content/client-server-api/modules/spaces.md @@ -2,8 +2,8 @@ {{% added-in v="1.2" %}} -Often used to group rooms of similar subject matter (such as a public "Official -matrix.org rooms" space or personal "Work stuff" space), spaces are a way to +Often used to group rooms of similar subject matter (such as an "Official +matrix.org rooms" space or a "Work stuff" space), spaces are a way to organise rooms while being represented as rooms themselves. A space is defined by the [`m.space` room type](#types), making it known as a @@ -18,11 +18,11 @@ In the default power level structure, this would be `100`. Clients might wish to go a step further and explicitly ignore notification counts on space-rooms. Membership of a space is defined and controlled by the existing mechanisms which -govern a room: [`m.room.member`](#mroommember), [`m.room.history_visibility`](#mroomhistory_visibility), -and [`m.room.join_rules`](#mroomjoin_rules). Public spaces are encouraged to have -a similar setup to public rooms: `world_readable` history visibility, published -canonical alias, and suitably public `join_rule`. Invites, including third-party -invites, still work just as they do in normal rooms as well. +govern a room: [`m.room.member`](/client-server-api#mroommember), [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility), +and [`m.room.join_rules`](/client-server-api#mroomjoin_rules). Canonical aliases and invites, including +third-party invites, still work just as they do in normal rooms as well. Furthermore, +spaces can also be published in the [room directory](/client-server-api#published-room-directory) to make them +discoverable. All other aspects of regular rooms are additionally carried over, such as the ability to set arbitrary state events, hold room account data, etc. Spaces are @@ -87,10 +87,9 @@ the state of `#space:example.org` would consist of: } ``` -No state events in the child rooms themselves would be required (though they -can also be present). This allows for users -to define personal/private spaces to organise their own rooms without needing explicit -permission from the room moderators/admins. +No state events in the child rooms themselves would be required (though they can also +be present). This allows for users to define spaces without needing explicit permission +from the room moderators/admins. Child rooms can be removed from a space by omitting the `via` key of `content` on the relevant state event, such as through redaction or otherwise clearing the `content`. From 866c05f487ef997710f8be4a2b8c9cc32251bfcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 3 Jun 2025 20:05:24 +0200 Subject: [PATCH 44/67] Reorganize client authentication section to separate the legacy API and the new OAuth 2.0 API (#2141) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since account locking and suspension are authentication API agnostic, this is a pre-requisite to adding the new OAuth 2.0-based API. This also splits the endpoints that where all included in the registration OpenAPI data, to separate them cleanly in the spec, and avoid having deactivation show before registration. Signed-off-by: Kévin Commaille --- .../client_server/newsfragments/2141.feature | 1 + content/client-server-api/_index.md | 66 ++-- .../client-server/account_deactivation.yaml | 141 ++++++++ .../client-server/password_management.yaml | 242 ++++++++++++++ data/api/client-server/registration.yaml | 309 ------------------ 5 files changed, 424 insertions(+), 335 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2141.feature create mode 100644 data/api/client-server/account_deactivation.yaml create mode 100644 data/api/client-server/password_management.yaml diff --git a/changelogs/client_server/newsfragments/2141.feature b/changelogs/client_server/newsfragments/2141.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2141.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index d4dfd561..855e8df9 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -439,7 +439,7 @@ endpoints it supports. Most API endpoints require the user to identify themselves by presenting previously obtained credentials in the form of an access token. An access token is typically obtained via the [Login](#login) or -[Registration](#account-registration-and-management) processes. Access tokens +[Registration](#account-registration) processes. Access tokens can expire; a new access token can be generated by using a refresh token. {{% boxes/note %}} @@ -494,7 +494,7 @@ used to generate a new access token and refresh token, the new access and refresh tokens are now bound to the device associated with the initial refresh token. -By default, the [Login](#login) and [Registration](#account-registration-and-management) +By default, the [Login](#login) and [Registration](#account-registration) processes auto-generate a new `device_id`. A client is also free to generate its own `device_id` or, provided the user remains the same, reuse a device: in either case the client should pass the `device_id` in @@ -560,9 +560,11 @@ specifying the device ID it is already using to the login API. with an `M_USER_LOCKED` error code, cannot obtain a new access token until the account has been [unlocked](#account-locking). -### User-Interactive Authentication API +### Legacy API -#### Overview +#### User-Interactive Authentication API + +##### Overview Some API endpoints require authentication that interacts with the user. The homeserver may provide many different ways of authenticating, such @@ -586,7 +588,7 @@ the flows in order must result in an HTTP 401 response, as defined below. When all stages in a flow are complete, authentication is complete and the API call succeeds. -#### User-interactive API in the REST API +##### User-interactive API in the REST API In the REST API described in this specification, authentication works by the client and server exchanging JSON dictionaries. The server indicates @@ -764,7 +766,7 @@ auth by offering a stage with only the `m.login.dummy` auth type, but they must still give a 401 response to requests with no auth data. {{% /boxes/note %}} -#### Example +**Example** At a high level, the requests made for an API call completing an auth flow with three stages will resemble the following diagram: @@ -806,7 +808,7 @@ flow with three stages will resemble the following diagram: |_______________________| ``` -#### Authentication types +##### Authentication types This specification defines the following auth types: - `m.login.password` @@ -817,7 +819,7 @@ This specification defines the following auth types: - `m.login.dummy` - `m.login.registration_token` -##### Password-based +###### Password-based | Type | Description | @@ -876,7 +878,7 @@ explicitly as follows: In the case that the homeserver does not know about the supplied 3PID, the homeserver must respond with 403 Forbidden. -##### Google ReCaptcha +###### Google ReCaptcha | Type | Description | |---------------------|------------------------------------------------------| @@ -893,7 +895,7 @@ follows: } ``` -##### Single Sign-On +###### Single Sign-On | Type | Description | |---------------|--------------------------------------------------------------------------------------| @@ -903,7 +905,7 @@ A client wanting to complete authentication using SSO should use the [Fallback](#fallback) mechanism. See [SSO during User-Interactive Authentication](#sso-during-user-interactive-authentication) for more information. -##### Email-based (identity / homeserver) +###### Email-based (identity / homeserver) | Type | Description | |--------------------------|------------------------------------------------------------------------------------------------------------------| @@ -932,7 +934,7 @@ follows: Note that `id_server` (and therefore `id_access_token`) is optional if the [`/requestToken`](#post_matrixclientv3registeremailrequesttoken) request did not include them. -##### Phone number/MSISDN-based (identity / homeserver) +###### Phone number/MSISDN-based (identity / homeserver) | Type | Description | |------------------|----------------------------------------------------------------------------------------------------------------| @@ -961,7 +963,7 @@ follows: Note that `id_server` (and therefore `id_access_token`) is optional if the [`/requestToken`](#post_matrixclientv3registermsisdnrequesttoken) request did not include them. -##### Dummy Auth +###### Dummy Auth | Type | Description | |------------------|------------------------------------------------------------------------| @@ -987,7 +989,7 @@ just the type and session, if provided: } ``` -##### Token-authenticated registration +###### Token-authenticated registration {{% added-in v="1.2" %}} @@ -1031,7 +1033,7 @@ in the registration process that their token has expired. {{% http-api spec="client-server" api="registration_tokens" %}} -##### Terms of service at registration +###### Terms of service at registration {{% added-in v="1.11" %}} @@ -1154,7 +1156,7 @@ user during registration, if applicable. {{% definition path="api/client-server/definitions/m.login.terms_params" %}} -#### Fallback +##### Fallback Clients cannot be expected to be able to know how to process every single login type. If a client does not know how to handle a given login @@ -1195,7 +1197,7 @@ with just the session ID: } ``` -##### Example +**Example** A client webapp might use the following JavaScript to open a popup window which will handle unknown login types: @@ -1251,7 +1253,7 @@ function unknownLoginType(homeserverUrl, apiEndpoint, loginType, sessionID, onCo } ``` -#### Identifier types +##### Identifier types Some authentication mechanisms use a user identifier object to identify a user. The user identifier object has a `type` field to indicate the @@ -1264,7 +1266,7 @@ This specification defines the following identifier types: - `m.id.thirdparty` - `m.id.phone` -##### Matrix User ID +###### Matrix User ID | Type | Description | |-------------|--------------------------------------------| @@ -1281,7 +1283,7 @@ ID. } ``` -##### Third-party ID +###### Third-party ID | Type | Description | |-------------------|---------------------------------------------------------------------------| @@ -1301,7 +1303,7 @@ ID media. } ``` -##### Phone number +###### Phone number | Type | Description | |--------------|-------------------------------------------| @@ -1327,7 +1329,7 @@ The `country` is the two-letter uppercase ISO-3166-1 alpha-2 country code that the number in `phone` should be parsed as if it were dialled from. -### Login +#### Login A client can obtain access tokens using the [`/login`](#post_matrixclientv3login) API. @@ -1399,7 +1401,7 @@ a token for their user ID if supported by the homeserver using {{% http-api spec="client-server" api="logout" %}} -#### Appservice Login +##### Appservice Login {{% added-in v="1.2" %}} @@ -1436,7 +1438,7 @@ If the access token does correspond to an appservice, but the user id does not lie within its namespace then the homeserver will respond with an errcode of `M_EXCLUSIVE`. -#### Login Fallback +##### Login Fallback If a client does not recognize any or all login flows it can use the fallback login API: @@ -1456,11 +1458,13 @@ forwarded to the login endpoint during the login process. For example: GET /_matrix/static/client/login/?device_id=GHTYAJCE -### Account registration and management +#### Account registration {{% http-api spec="client-server" api="registration" %}} -#### Notes on password management +#### Account management + +##### Password management {{% boxes/warning %}} Clients SHOULD enforce that the password provided is suitably complex. @@ -1469,6 +1473,16 @@ number and a symbol and be at a minimum 8 characters in length. Servers MAY reject weak passwords with an error code `M_WEAK_PASSWORD`. {{% /boxes/warning %}} +{{% http-api spec="client-server" api="password_management" %}} + +##### Account deactivation + +{{% http-api spec="client-server" api="account_deactivation" %}} + +### OAuth 2.0 API + +### Account moderation + #### Account locking {{% added-in v="1.12" %}} diff --git a/data/api/client-server/account_deactivation.yaml b/data/api/client-server/account_deactivation.yaml new file mode 100644 index 00000000..467af659 --- /dev/null +++ b/data/api/client-server/account_deactivation.yaml @@ -0,0 +1,141 @@ +# Copyright 2016 OpenMarket Ltd +# Copyright 2022 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +openapi: 3.1.0 +info: + title: Matrix Client-Server Account Deactivation API + version: 1.0.0 +paths: + /account/deactivate: + post: + summary: Deactivate a user's account. + description: |- + Deactivate the user's account, removing all ability for the user to + login again. + + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). + + An access token should be submitted to this endpoint if the client has + an active session. + + The homeserver may change the flows available depending on whether a + valid access token is provided. + + Unlike other endpoints, this endpoint does not take an `id_access_token` + parameter because the homeserver is expected to sign the request to the + identity server instead. + security: + - {} + - accessTokenQuery: [] + - accessTokenBearer: [] + operationId: deactivateAccount + requestBody: + content: + application/json: + schema: + type: object + properties: + auth: + description: Additional authentication information for the user-interactive + authentication API. + allOf: + - $ref: definitions/auth_data.yaml + id_server: + type: string + description: |- + The identity server to unbind all of the user's 3PIDs from. + If not provided, the homeserver MUST use the `id_server` + that was originally use to bind each identifier. If the + homeserver does not know which `id_server` that was, + it must return an `id_server_unbind_result` of + `no-support`. + example: example.org + erase: + x-addedInMatrixVersion: "1.10" + type: boolean + description: |- + Whether the user would like their content to be erased as + much as possible from the server. + + Erasure means that any users (or servers) which join the + room after the erasure request are served redacted copies of + the events sent by this account. Users which had visibility + on those events prior to the erasure are still able to see + unredacted copies. No redactions are sent and the erasure + request is not shared over federation, so other servers + might still serve unredacted copies. + + The server should additionally erase any non-event data + associated with the user, such as [account data](/client-server-api/#client-config) + and [contact 3PIDs](/client-server-api/#adding-account-administrative-contact-information). + + Defaults to `false` if not present. + required: true + responses: + "200": + description: The account has been deactivated. + content: + application/json: + schema: + type: object + properties: + id_server_unbind_result: + type: string + enum: + - success + - no-support + description: |- + An indicator as to whether or not the homeserver was able to unbind + the user's 3PIDs from the identity server(s). `success` indicates + that all identifiers have been unbound from the identity server while + `no-support` indicates that one or more identifiers failed to unbind + due to the identity server refusing the request or the homeserver + being unable to determine an identity server to unbind from. This + must be `success` if the homeserver has no identifiers to unbind + for the user. + example: success + required: + - id_server_unbind_result + "401": + description: The homeserver requires additional authentication information. + content: + application/json: + schema: + $ref: definitions/auth_response.yaml + "429": + description: This request was rate-limited. + content: + application/json: + schema: + $ref: definitions/errors/rate_limited.yaml + tags: + - Account management +servers: + - url: "{protocol}://{hostname}{basePath}" + variables: + protocol: + enum: + - http + - https + default: https + hostname: + default: localhost:8008 + basePath: + default: /_matrix/client/v3 +components: + securitySchemes: + accessTokenQuery: + $ref: definitions/security.yaml#/accessTokenQuery + accessTokenBearer: + $ref: definitions/security.yaml#/accessTokenBearer diff --git a/data/api/client-server/password_management.yaml b/data/api/client-server/password_management.yaml new file mode 100644 index 00000000..bf310ff9 --- /dev/null +++ b/data/api/client-server/password_management.yaml @@ -0,0 +1,242 @@ +# Copyright 2016 OpenMarket Ltd +# Copyright 2022 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +openapi: 3.1.0 +info: + title: Matrix Client-Server Password Management API + version: 1.0.0 +paths: + /account/password: + post: + summary: Changes a user's password. + description: |- + Changes the password for an account on this homeserver. + + This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api) to + ensure the user changing the password is actually the owner of the + account. + + An access token should be submitted to this endpoint if the client has + an active session. + + The homeserver may change the flows available depending on whether a + valid access token is provided. The homeserver SHOULD NOT revoke the + access token provided in the request. Whether other access tokens for + the user are revoked depends on the request parameters. + security: + - {} + - accessTokenQuery: [] + - accessTokenBearer: [] + operationId: changePassword + requestBody: + content: + application/json: + schema: + type: object + properties: + new_password: + type: string + description: The new password for the account. + example: ihatebananas + logout_devices: + type: boolean + description: |- + Whether the user's other access tokens, and their associated devices, should be + revoked if the request succeeds. Defaults to true. + + When `false`, the server can still take advantage of the [soft logout method](/client-server-api/#soft-logout) + for the user's remaining devices. + example: true + auth: + description: Additional authentication information for the user-interactive + authentication API. + allOf: + - $ref: definitions/auth_data.yaml + required: + - new_password + required: true + responses: + "200": + description: The password has been changed. + content: + application/json: + schema: + type: object + examples: + response: + value: {} + "401": + description: The homeserver requires additional authentication information. + content: + application/json: + schema: + $ref: definitions/auth_response.yaml + "429": + description: This request was rate-limited. + content: + application/json: + schema: + $ref: definitions/errors/rate_limited.yaml + tags: + - Account management + /account/password/email/requestToken: + post: + summary: Requests a validation token be sent to the given email address for the + purpose of resetting a user's password + description: |- + The homeserver must check that the given email address **is + associated** with an account on this homeserver. This API should be + used to request validation tokens when authenticating for the + `/account/password` endpoint. + + This API's parameters and response are identical to that of the + [`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken) + endpoint, except that + `M_THREEPID_NOT_FOUND` may be returned if no account matching the + given email address could be found. The server may instead send an + email to the given address prompting the user to create an account. + `M_THREEPID_IN_USE` may not be returned. + + The homeserver should validate the email itself, either by sending a + validation email itself or by using a service it has control over. + operationId: requestTokenToResetPasswordEmail + requestBody: + content: + application/json: + schema: + $ref: definitions/request_email_validation.yaml + required: true + responses: + "200": + description: An email was sent to the given address. + content: + application/json: + schema: + $ref: definitions/request_token_response.yaml + "400": + description: |- + The referenced third-party identifier is not recognised by the + homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED` + can be returned if the server does not trust/support the identity server + provided in the request. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_THREEPID_NOT_FOUND", + "error": "Email not found" + } + "403": + description: |- + The homeserver does not allow the third-party identifier as a + contact option. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_THREEPID_DENIED", + "error": "Third-party identifier is not allowed" + } + tags: + - Account management + /account/password/msisdn/requestToken: + post: + summary: Requests a validation token be sent to the given phone number for the + purpose of resetting a user's password. + description: |- + The homeserver must check that the given phone number **is + associated** with an account on this homeserver. This API should be + used to request validation tokens when authenticating for the + `/account/password` endpoint. + + This API's parameters and response are identical to that of the + [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) + endpoint, except that + `M_THREEPID_NOT_FOUND` may be returned if no account matching the + given phone number could be found. The server may instead send the SMS + to the given phone number prompting the user to create an account. + `M_THREEPID_IN_USE` may not be returned. + + The homeserver should validate the phone number itself, either by sending a + validation message itself or by using a service it has control over. + operationId: requestTokenToResetPasswordMSISDN + requestBody: + content: + application/json: + schema: + $ref: definitions/request_msisdn_validation.yaml + required: true + responses: + "200": + description: An SMS message was sent to the given phone number. + content: + application/json: + schema: + $ref: definitions/request_token_response.yaml + "400": + description: |- + The referenced third-party identifier is not recognised by the + homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED` + can be returned if the server does not trust/support the identity server + provided in the request. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_THREEPID_NOT_FOUND", + "error": "Phone number not found" + } + "403": + description: |- + The homeserver does not allow the third-party identifier as a + contact option. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_THREEPID_DENIED", + "error": "Third-party identifier is not allowed" + } + tags: + - Account management +servers: + - url: "{protocol}://{hostname}{basePath}" + variables: + protocol: + enum: + - http + - https + default: https + hostname: + default: localhost:8008 + basePath: + default: /_matrix/client/v3 +components: + securitySchemes: + accessTokenQuery: + $ref: definitions/security.yaml#/accessTokenQuery + accessTokenBearer: + $ref: definitions/security.yaml#/accessTokenBearer diff --git a/data/api/client-server/registration.yaml b/data/api/client-server/registration.yaml index a418d2d2..e7ede561 100644 --- a/data/api/client-server/registration.yaml +++ b/data/api/client-server/registration.yaml @@ -373,315 +373,6 @@ paths: } tags: - Account management - /account/password: - post: - summary: Changes a user's password. - description: |- - Changes the password for an account on this homeserver. - - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api) to - ensure the user changing the password is actually the owner of the - account. - - An access token should be submitted to this endpoint if the client has - an active session. - - The homeserver may change the flows available depending on whether a - valid access token is provided. The homeserver SHOULD NOT revoke the - access token provided in the request. Whether other access tokens for - the user are revoked depends on the request parameters. - security: - - {} - - accessTokenQuery: [] - - accessTokenBearer: [] - operationId: changePassword - requestBody: - content: - application/json: - schema: - type: object - properties: - new_password: - type: string - description: The new password for the account. - example: ihatebananas - logout_devices: - type: boolean - description: |- - Whether the user's other access tokens, and their associated devices, should be - revoked if the request succeeds. Defaults to true. - - When `false`, the server can still take advantage of the [soft logout method](/client-server-api/#soft-logout) - for the user's remaining devices. - example: true - auth: - description: Additional authentication information for the user-interactive - authentication API. - allOf: - - $ref: definitions/auth_data.yaml - required: - - new_password - required: true - responses: - "200": - description: The password has been changed. - content: - application/json: - schema: - type: object - examples: - response: - value: {} - "401": - description: The homeserver requires additional authentication information. - content: - application/json: - schema: - $ref: definitions/auth_response.yaml - "429": - description: This request was rate-limited. - content: - application/json: - schema: - $ref: definitions/errors/rate_limited.yaml - tags: - - Account management - /account/password/email/requestToken: - post: - summary: Requests a validation token be sent to the given email address for the - purpose of resetting a user's password - description: |- - The homeserver must check that the given email address **is - associated** with an account on this homeserver. This API should be - used to request validation tokens when authenticating for the - `/account/password` endpoint. - - This API's parameters and response are identical to that of the - [`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken) - endpoint, except that - `M_THREEPID_NOT_FOUND` may be returned if no account matching the - given email address could be found. The server may instead send an - email to the given address prompting the user to create an account. - `M_THREEPID_IN_USE` may not be returned. - - The homeserver should validate the email itself, either by sending a - validation email itself or by using a service it has control over. - operationId: requestTokenToResetPasswordEmail - requestBody: - content: - application/json: - schema: - $ref: definitions/request_email_validation.yaml - required: true - responses: - "200": - description: An email was sent to the given address. - content: - application/json: - schema: - $ref: definitions/request_token_response.yaml - "400": - description: |- - The referenced third-party identifier is not recognised by the - homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED` - can be returned if the server does not trust/support the identity server - provided in the request. - content: - application/json: - schema: - $ref: definitions/errors/error.yaml - examples: - response: - value: { - "errcode": "M_THREEPID_NOT_FOUND", - "error": "Email not found" - } - "403": - description: |- - The homeserver does not allow the third-party identifier as a - contact option. - content: - application/json: - schema: - $ref: definitions/errors/error.yaml - examples: - response: - value: { - "errcode": "M_THREEPID_DENIED", - "error": "Third-party identifier is not allowed" - } - tags: - - Account management - /account/password/msisdn/requestToken: - post: - summary: Requests a validation token be sent to the given phone number for the - purpose of resetting a user's password. - description: |- - The homeserver must check that the given phone number **is - associated** with an account on this homeserver. This API should be - used to request validation tokens when authenticating for the - `/account/password` endpoint. - - This API's parameters and response are identical to that of the - [`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) - endpoint, except that - `M_THREEPID_NOT_FOUND` may be returned if no account matching the - given phone number could be found. The server may instead send the SMS - to the given phone number prompting the user to create an account. - `M_THREEPID_IN_USE` may not be returned. - - The homeserver should validate the phone number itself, either by sending a - validation message itself or by using a service it has control over. - operationId: requestTokenToResetPasswordMSISDN - requestBody: - content: - application/json: - schema: - $ref: definitions/request_msisdn_validation.yaml - required: true - responses: - "200": - description: An SMS message was sent to the given phone number. - content: - application/json: - schema: - $ref: definitions/request_token_response.yaml - "400": - description: |- - The referenced third-party identifier is not recognised by the - homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED` - can be returned if the server does not trust/support the identity server - provided in the request. - content: - application/json: - schema: - $ref: definitions/errors/error.yaml - examples: - response: - value: { - "errcode": "M_THREEPID_NOT_FOUND", - "error": "Phone number not found" - } - "403": - description: |- - The homeserver does not allow the third-party identifier as a - contact option. - content: - application/json: - schema: - $ref: definitions/errors/error.yaml - examples: - response: - value: { - "errcode": "M_THREEPID_DENIED", - "error": "Third-party identifier is not allowed" - } - tags: - - Account management - /account/deactivate: - post: - summary: Deactivate a user's account. - description: |- - Deactivate the user's account, removing all ability for the user to - login again. - - This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). - - An access token should be submitted to this endpoint if the client has - an active session. - - The homeserver may change the flows available depending on whether a - valid access token is provided. - - Unlike other endpoints, this endpoint does not take an `id_access_token` - parameter because the homeserver is expected to sign the request to the - identity server instead. - security: - - {} - - accessTokenQuery: [] - - accessTokenBearer: [] - operationId: deactivateAccount - requestBody: - content: - application/json: - schema: - type: object - properties: - auth: - description: Additional authentication information for the user-interactive - authentication API. - allOf: - - $ref: definitions/auth_data.yaml - id_server: - type: string - description: |- - The identity server to unbind all of the user's 3PIDs from. - If not provided, the homeserver MUST use the `id_server` - that was originally use to bind each identifier. If the - homeserver does not know which `id_server` that was, - it must return an `id_server_unbind_result` of - `no-support`. - example: example.org - erase: - x-addedInMatrixVersion: "1.10" - type: boolean - description: |- - Whether the user would like their content to be erased as - much as possible from the server. - - Erasure means that any users (or servers) which join the - room after the erasure request are served redacted copies of - the events sent by this account. Users which had visibility - on those events prior to the erasure are still able to see - unredacted copies. No redactions are sent and the erasure - request is not shared over federation, so other servers - might still serve unredacted copies. - - The server should additionally erase any non-event data - associated with the user, such as [account data](/client-server-api/#client-config) - and [contact 3PIDs](/client-server-api/#adding-account-administrative-contact-information). - - Defaults to `false` if not present. - required: true - responses: - "200": - description: The account has been deactivated. - content: - application/json: - schema: - type: object - properties: - id_server_unbind_result: - type: string - enum: - - success - - no-support - description: |- - An indicator as to whether or not the homeserver was able to unbind - the user's 3PIDs from the identity server(s). `success` indicates - that all identifiers have been unbound from the identity server while - `no-support` indicates that one or more identifiers failed to unbind - due to the identity server refusing the request or the homeserver - being unable to determine an identity server to unbind from. This - must be `success` if the homeserver has no identifiers to unbind - for the user. - example: success - required: - - id_server_unbind_result - "401": - description: The homeserver requires additional authentication information. - content: - application/json: - schema: - $ref: definitions/auth_response.yaml - "429": - description: This request was rate-limited. - content: - application/json: - schema: - $ref: definitions/errors/rate_limited.yaml - tags: - - Account management /register/available: get: summary: Checks to see if a username is available on the server. From 7bcc3ecb817f19b62d300a278ad238947a96b966 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 4 Jun 2025 13:43:06 +0200 Subject: [PATCH 45/67] Spec PR - MSC3266: Room Summary API (#2125) Signed-off-by: Johannes Marbach --- .../client_server/newsfragments/2125.feature | 1 + .../server_server/newsfragments/2125.feature | 1 + content/client-server-api/_index.md | 4 + .../definitions/public_rooms_chunk.yaml | 1 - .../definitions/room_summary.yaml | 48 +++++++ data/api/client-server/room_summary.yaml | 136 ++++++++++++++++++ data/api/client-server/space_hierarchy.yaml | 15 +- data/api/server-server/space_hierarchy.yaml | 38 ++--- 8 files changed, 212 insertions(+), 32 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2125.feature create mode 100644 changelogs/server_server/newsfragments/2125.feature create mode 100644 data/api/client-server/definitions/room_summary.yaml create mode 100644 data/api/client-server/room_summary.yaml diff --git a/changelogs/client_server/newsfragments/2125.feature b/changelogs/client_server/newsfragments/2125.feature new file mode 100644 index 00000000..f9275b0d --- /dev/null +++ b/changelogs/client_server/newsfragments/2125.feature @@ -0,0 +1 @@ +Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). diff --git a/changelogs/server_server/newsfragments/2125.feature b/changelogs/server_server/newsfragments/2125.feature new file mode 100644 index 00000000..0a369ea0 --- /dev/null +++ b/changelogs/server_server/newsfragments/2125.feature @@ -0,0 +1 @@ +Extend `/_matrix/federation/v1/hierarchy/{roomId}` with the new optional properties `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 855e8df9..b478a0c9 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -2892,6 +2892,10 @@ that are not `world_readable` regardless of their visibility. {{% http-api spec="client-server" api="list_public_rooms" %}} +### Room Summaries + +{{% http-api spec="client-server" api="room_summary" %}} + ## User Data ### User Directory diff --git a/data/api/client-server/definitions/public_rooms_chunk.yaml b/data/api/client-server/definitions/public_rooms_chunk.yaml index d2e9a09b..89e76059 100644 --- a/data/api/client-server/definitions/public_rooms_chunk.yaml +++ b/data/api/client-server/definitions/public_rooms_chunk.yaml @@ -61,7 +61,6 @@ properties: example: "public" room_type: type: string - x-addedInMatrixVersion: "1.4" description: |- The `type` of room (from [`m.room.create`](/client-server-api/#mroomcreate)), if any. required: diff --git a/data/api/client-server/definitions/room_summary.yaml b/data/api/client-server/definitions/room_summary.yaml new file mode 100644 index 00000000..a8682e51 --- /dev/null +++ b/data/api/client-server/definitions/room_summary.yaml @@ -0,0 +1,48 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: object +title: RoomSummary +allOf: + - $ref: public_rooms_chunk.yaml + - type: object + properties: + room_type: + type: string + description: The `type` of room (from + [`m.room.create`](/client-server-api/#mroomcreate)), + if any. + allowed_room_ids: + type: array + items: + type: string + description: |- + If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which + are specified by the join rules. Empty or omitted otherwise. + encryption: + type: string + enum: + - "m.megolm.v1.aes-sha2" + description: |- + The encryption algorithm to be used to encrypt messages sent in the + room. + room_version: + description: The version of the room. + type: string + +required: + - room_id + - num_joined_members + - world_readable + - guest_can_join diff --git a/data/api/client-server/room_summary.yaml b/data/api/client-server/room_summary.yaml new file mode 100644 index 00000000..9d23c829 --- /dev/null +++ b/data/api/client-server/room_summary.yaml @@ -0,0 +1,136 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +openapi: 3.1.0 +info: + title: Matrix Client-Server Room Summary API + version: 1.0.0 +paths: + "/room_summary/{roomIdOrAlias}": + get: + x-addedInMatrixVersion: "1.15" + summary: Retrieves a summary for a room. + description: |- + Retrieves a summary for a room. + + Clients should note that requests for rooms where the user's membership + is `invite` or `knock` might yield outdated, partial or even no data + since the server may not have access to the current state of the room. + + Servers MAY allow unauthenticated access to this API if at least one of + the following conditions holds true: + + - The room has a [join rule](#mroomjoin_rules) of `public`, `knock` or + `knock_restricted`. + - The room has a `world_readable` [history visibility](#room-history-visibility). + + Servers should consider rate limiting requests that require a federation + request more heavily if the client is unauthenticated. + operationId: getRoomSummary + security: + - signedRequest: [] + parameters: + - in: path + name: roomIdOrAlias + description: The room identifier or alias to summarise. + required: true + example: "#monkeys:matrix.org" + schema: + type: string + - in: query + name: via + description: |- + The servers to attempt to request the summary from when + the local server cannot generate it (for instance, because + it has no local user in the room). + example: + - matrix.org + - elsewhere.ca + schema: + type: array + items: + type: string + responses: + "200": + description: A summary of the room. + content: + application/json: + schema: + description: A summary of the room. + allOf: + - $ref: ../client-server/definitions/room_summary.yaml + - type: object + properties: + membership: + description: |- + The membership state of the user if the user is joined to the room. Absent + if the API was called unauthenticated. + enum: + - invite + - join + - knock + - leave + - ban + type: string + required: + - guest_can_join + - num_joined_members + - room_id + - world_readable + examples: + response: + value: { + room_id: "!ol19s:bleecker.street", + avatar_url: "mxc://bleecker.street/CHEDDARandBRIE", + guest_can_join: false, + name: "CHEESE", + num_joined_members: 37, + topic: "Tasty tasty cheese", + world_readable: true, + join_rule: "public", + room_type: "m.space", + membership: "invite", + encryption: "m.megolm.v1.aes-sha2", + room_version: "9001", + } + "404": + description: |- + The room could not be found. + content: + application/json: + schema: + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_NOT_FOUND", + "error": "Room not found." + } +servers: + - url: "{protocol}://{hostname}{basePath}" + variables: + protocol: + enum: + - http + - https + default: https + hostname: + default: localhost:8008 + basePath: + default: /_matrix/client/v1 +components: + securitySchemes: + accessTokenQuery: + $ref: definitions/security.yaml#/accessTokenQuery + accessTokenBearer: + $ref: definitions/security.yaml#/accessTokenBearer diff --git a/data/api/client-server/space_hierarchy.yaml b/data/api/client-server/space_hierarchy.yaml index 3a4a14a5..5f6657a2 100644 --- a/data/api/client-server/space_hierarchy.yaml +++ b/data/api/client-server/space_hierarchy.yaml @@ -102,15 +102,10 @@ paths: * The room's [`m.room.history_visibility`](#room-history-visibility) is set to `world_readable`. items: allOf: - - $ref: definitions/public_rooms_chunk.yaml + - $ref: definitions/room_summary.yaml - type: object title: SpaceHierarchyRoomsChunk properties: - room_type: - type: string - description: The `type` of room (from - [`m.room.create`](/client-server-api/#mroomcreate)), - if any. children_state: type: array description: |- @@ -130,6 +125,14 @@ paths: description: The `origin_server_ts` for the event. required: - origin_server_ts + room_type: + x-addedInMatrixVersion: "1.4" # Extends room_summary.yaml + allowed_room_ids: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml + encryption: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml + room_version: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml required: - children_state next_batch: diff --git a/data/api/server-server/space_hierarchy.yaml b/data/api/server-server/space_hierarchy.yaml index 8394588b..adc2c3e5 100644 --- a/data/api/server-server/space_hierarchy.yaml +++ b/data/api/server-server/space_hierarchy.yaml @@ -61,22 +61,10 @@ paths: room: description: A summary of the room requested. allOf: - - $ref: ../client-server/definitions/public_rooms_chunk.yaml + - $ref: ../client-server/definitions/room_summary.yaml - type: object title: SpaceHierarchyParentRoom properties: - room_type: - type: string - description: The `type` of room (from - [`m.room.create`](/client-server-api/#mroomcreate)), - if any. - allowed_room_ids: - type: array - items: - type: string - description: |- - If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which - are specified by the join rules. Empty or omitted otherwise. children_state: type: array description: |- @@ -96,6 +84,12 @@ paths: description: The `origin_server_ts` for the event. required: - origin_server_ts + room_type: + x-addedInMatrixVersion: "1.4" # Extends room_summary.yaml + encryption: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml + room_version: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml required: - children_state children: @@ -105,22 +99,16 @@ paths: be excluded. items: allOf: - - $ref: ../client-server/definitions/public_rooms_chunk.yaml + - $ref: ../client-server/definitions/room_summary.yaml - type: object title: SpaceHierarchyChildRoomsChunk properties: room_type: - type: string - description: The `type` of room (from - [`m.room.create`](/client-server-api/#mroomcreate)), - if any. - allowed_room_ids: - type: array - items: - type: string - description: |- - If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which - are specified by the join rules. Empty or omitted otherwise. + x-addedInMatrixVersion: "1.4" # Extends room_summary.yaml + encryption: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml + room_version: + x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml inaccessible_children: type: array items: From 32b1f0514d4be78b3020119b530d108b0010de3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Sat, 7 Jun 2025 15:26:56 +0200 Subject: [PATCH 46/67] Clarify some string formats of room summary endpoint (#2158) --- changelogs/client_server/newsfragments/2158.feature | 1 + .../client-server/definitions/public_rooms_chunk.yaml | 4 ++++ data/api/client-server/definitions/room_summary.yaml | 2 ++ data/api/client-server/room_summary.yaml | 9 ++++++++- 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2158.feature diff --git a/changelogs/client_server/newsfragments/2158.feature b/changelogs/client_server/newsfragments/2158.feature new file mode 100644 index 00000000..f9275b0d --- /dev/null +++ b/changelogs/client_server/newsfragments/2158.feature @@ -0,0 +1 @@ +Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). diff --git a/data/api/client-server/definitions/public_rooms_chunk.yaml b/data/api/client-server/definitions/public_rooms_chunk.yaml index 89e76059..33276662 100644 --- a/data/api/client-server/definitions/public_rooms_chunk.yaml +++ b/data/api/client-server/definitions/public_rooms_chunk.yaml @@ -17,6 +17,8 @@ title: "PublishedRoomsChunk" properties: canonical_alias: type: string + format: mx-room-alias + pattern: "^#" description: The canonical alias of the room, if any. example: "#general:example.org" name: @@ -29,6 +31,8 @@ properties: example: 42 room_id: type: string + format: mx-room-id + pattern: "^!" description: The ID of the room. example: "!abcdefg:example.org" topic: diff --git a/data/api/client-server/definitions/room_summary.yaml b/data/api/client-server/definitions/room_summary.yaml index a8682e51..8499bac1 100644 --- a/data/api/client-server/definitions/room_summary.yaml +++ b/data/api/client-server/definitions/room_summary.yaml @@ -27,6 +27,8 @@ allOf: type: array items: type: string + format: mx-room-id + pattern: "^!" description: |- If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which are specified by the join rules. Empty or omitted otherwise. diff --git a/data/api/client-server/room_summary.yaml b/data/api/client-server/room_summary.yaml index 9d23c829..e5e241ed 100644 --- a/data/api/client-server/room_summary.yaml +++ b/data/api/client-server/room_summary.yaml @@ -46,7 +46,13 @@ paths: required: true example: "#monkeys:matrix.org" schema: - type: string + oneOf: + - type: string + format: mx-room-id + pattern: "^!" + - type: string + format: mx-room-alias + pattern: "^#" - in: query name: via description: |- @@ -60,6 +66,7 @@ paths: type: array items: type: string + format: mx-server-name responses: "200": description: A summary of the room. From a2a9a02efa4cc841c2031c6ba789828619bbfae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:40:17 +0200 Subject: [PATCH 47/67] Add OAuth 2.0 scopes (#2149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per MSC2967 Signed-off-by: Kévin Commaille --- .../client_server/newsfragments/2149.feature | 1 + content/client-server-api/_index.md | 90 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 changelogs/client_server/newsfragments/2149.feature diff --git a/changelogs/client_server/newsfragments/2149.feature b/changelogs/client_server/newsfragments/2149.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2149.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index b478a0c9..1dcdd82f 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -1481,6 +1481,96 @@ MAY reject weak passwords with an error code `M_WEAK_PASSWORD`. ### OAuth 2.0 API +#### Scope + +The client requests a scope in the OAuth 2.0 authorization flow, which is then +associated to the generated access and refresh tokens. This provides a framework +for obtaining user consent. + +A scope is defined in [RFC 6749 section 3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) +as a string containing a list of space-separated scope tokens. + +{{% boxes/note %}} +The framework encourages the practice of obtaining additional user consent when +a client asks for a new scope that was not granted previously. This could be +used by future MSCs to replace the legacy [User-Interactive Authentication API](#user-interactive-authentication-api). +{{% /boxes/note %}} + +##### Scope token format + +All scope tokens related to Matrix should start with `urn:matrix:` and use the +`:` delimiter for further sub-division. + +Scope tokens related to mapping of Client-Server API access levels should start +with `urn:matrix:client:`. + +{{% boxes/note %}} +For MSCs that build on this namespace, unstable subdivisions should be used +whilst in development. For example, if MSCXXXX wants to introduce the +`urn:matrix:client:foo` scope, it could use +`urn:matrix:client:com.example.mscXXXX.foo` during development. +If it needs to introduce multiple scopes, like `urn:matrix:client:foo` and +`urn:matrix:client:bar`, it could use +`urn:matrix:client:com.example.mscXXXX:foo` and +`urn:matrix:client:com.example.mscXXXX:bar`. +{{% /boxes/note %}} + +##### Allocated scope tokens + +This specification defines the following scope tokens: +- [`urn:matrix:client:api:*`](#full-client-server-api-readwrite-access) +- [`urn:matrix:client:device:`](#device-id-allocation) + +###### Full client-server API read/write access + +| Scope | Purpose | +|---------------------------|---------------------------------------------| +| `urn:matrix:client:api:*` | Grants full access to the Client-Server API. | + +{{% boxes/note %}} +This token matches the behavior of the legacy authentication API. Future MSCs +could introduce more fine-grained scope tokens like +`urn:matrix:client:api:read:*` for read-only access. +{{% /boxes/note %}} + +###### Device ID allocation + +| Scope | Purpose | +|----------------------------------------|----------------------------------------------------------------------------------------------| +| `urn:matrix:client:device:` | Allocates the given `device_id` and associates it to the generated access and refresh tokens. | + +Contrary to the legacy login and registration APIs where the homeserver is +typically the one generating a `device_id` and providing it to the client, with +the OAuth 2.0 API, the client is responsible for allocating the `device_id`. + +There MUST be exactly one `urn:matrix:client:device:` token in the +requested scope in the login flow. + +When generating a new `device_id`, the client SHOULD generate a random string +with enough entropy. It SHOULD only use characters from the unreserved character +list defined by [RFC 3986 section 2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3): + +``` +unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~" +``` + +Using this alphabet, a 10 character string is enough to stand a sufficient +chance of being unique per user. The homeserver MAY reject a request for a +`device_id` that is not long enough or contains characters outside the +unreserved list. + +In any case it MUST only use characters allowed by the OAuth 2.0 scope +definition in [RFC 6749 section 3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3), +which is defined as the following ASCII ranges: + +``` +%x21 / %x23-5B / %x5D-7E +``` + +This definition matches: +- alphanumeric characters: `A-Z`, `a-z`, `0-9` +- the following characters: ``! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~`` + ### Account moderation #### Account locking From 51ccbbd240d3749eddb7390cc554e8e1b2b631a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:47:30 +0200 Subject: [PATCH 48/67] Add the OAuth 2.0 server metadata discovery endpoint (#2147) As per MSC2965. --- .../client_server/newsfragments/2147.new | 1 + content/client-server-api/_index.md | 4 + .../client-server/oauth_server_metadata.yaml | 176 ++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 changelogs/client_server/newsfragments/2147.new create mode 100644 data/api/client-server/oauth_server_metadata.yaml diff --git a/changelogs/client_server/newsfragments/2147.new b/changelogs/client_server/newsfragments/2147.new new file mode 100644 index 00000000..c72bf35e --- /dev/null +++ b/changelogs/client_server/newsfragments/2147.new @@ -0,0 +1 @@ +Add `GET /_matrix/client/v1/auth_metadata`, as per [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965). diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 1dcdd82f..72b425e2 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -1481,6 +1481,10 @@ MAY reject weak passwords with an error code `M_WEAK_PASSWORD`. ### OAuth 2.0 API +#### Server metadata discovery + +{{% http-api spec="client-server" api="oauth_server_metadata" %}} + #### Scope The client requests a scope in the OAuth 2.0 authorization flow, which is then diff --git a/data/api/client-server/oauth_server_metadata.yaml b/data/api/client-server/oauth_server_metadata.yaml new file mode 100644 index 00000000..4cdb3aa6 --- /dev/null +++ b/data/api/client-server/oauth_server_metadata.yaml @@ -0,0 +1,176 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +openapi: 3.1.0 +info: + title: Matrix Client-Server OAuth 2.0 Server Metadata Discovery API + version: 1.0.0 +paths: + "/auth_metadata": + get: + summary: Get the OAuth 2.0 authorization server metadata. + description: |- + Gets the OAuth 2.0 authorization server metadata, as defined in + [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414), including the + endpoint URLs and the supported parameters that can be used by the + clients. + + This endpoint definition includes only the fields that are meaningful in + the context of the Matrix specification. The full list of possible + fields is available in the [OAuth Authorization Server Metadata + registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata), + and normative definitions of them are available in their respective + RFCs. + + {{% boxes/note %}} + The authorization server metadata is relatively large and may change + over time. Clients should: + + - Cache the metadata appropriately based on HTTP caching headers + - Refetch the metadata if it is stale + {{% /boxes/note %}} + operationId: getAuthMetadata + responses: + "200": + description: The OAuth 2.0 authorization server metadata. + content: + application/json: + schema: + type: object + properties: + issuer: + type: string + format: uri + description: |- + The authorization server's issuer identifier, which is a URL that uses the + `https` scheme and has no query or fragment components. + + This is not used in the context of the Matrix specification, but is required + by [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414). + authorization_endpoint: + type: string + format: uri + description: |- + URL of the authorization endpoint, necessary to use the authorization code + grant. + token_endpoint: + type: string + format: uri + description: |- + URL of the token endpoint, necessary to use the authorization code grant and + the refresh token grant. + revocation_endpoint: + type: string + format: uri + description: |- + URL of the revocation endpoint, necessary to log out a client by invalidating + its access and refresh tokens. + registration_endpoint: + type: string + format: uri + description: |- + URL of the client registration endpoint, necessary to perform dynamic + registration of a client. + response_types_supported: + type: array + description: |- + List of OAuth 2.0 response type strings that the server supports at the + authorization endpoint. + + This array MUST contain at least the `code` value, for clients to be able to + use the authorization code grant. + items: + type: string + description: A response type that the server supports. + grant_types_supported: + type: array + description: |- + List of OAuth 2.0 grant type strings that the server supports at the token + endpoint. + + This array MUST contain at least the `authorization_code` and `refresh_token` + values, for clients to be able to use the authorization code grant and refresh + token grant, respectively. + items: + type: string + description: A grant type that the server supports. + response_modes_supported: + type: array + description: |- + List of OAuth 2.0 response mode strings that the server supports at the + authorization endpoint. + + This array MUST contain at least the `query` and `fragment` values, for + improved security in the authorization code grant. + items: + type: string + description: A response mode that the server supports. + code_challenge_methods_supported: + type: array + description: |- + List of OAuth 2.0 Proof Key for Code Exchange (PKCE) code challenge methods + that the server supports at the authorization endpoint. + + This array MUST contain at least the `S256` value, for improved security in + the authorization code grant. + items: + type: string + description: A PKCE code challenge method that the server supports. + prompt_values_supported: + type: array + description: |- + List of OpenID Connect prompt values that the server supports at the + authorization endpoint. + + Only the `create` value defined in [Initiating User Registration via OpenID + Connect](https://openid.net/specs/openid-connect-prompt-create-1_0.html) is + supported, for a client to signal to the server that the user desires to + register a new account. + items: + type: string + description: A prompt value that the server supports. + required: + - issuer + - authorization_endpoint + - token_endpoint + - revocation_endpoint + - registration_endpoint + - response_types_supported + - grant_types_supported + - response_modes_supported + - code_challenge_methods_supported + example: { + "issuer": "https://account.example.com/", + "authorization_endpoint": "https://account.example.com/oauth2/auth", + "token_endpoint": "https://account.example.com/oauth2/token", + "registration_endpoint": "https://account.example.com/oauth2/clients/register", + "revocation_endpoint": "https://account.example.com/oauth2/revoke", + "response_types_supported": ["code"], + "grant_types_supported": ["authorization_code", "refresh_token"], + "response_modes_supported": ["query", "fragment"], + "code_challenge_methods_supported": ["S256"], + } + tags: + - Session management +servers: + - url: "{protocol}://{hostname}{basePath}" + variables: + protocol: + enum: + - http + - https + default: https + hostname: + default: localhost:8008 + basePath: + default: /_matrix/client/v1 From 979264e923609b9dacfdc846f18bb221b094297b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:43:40 +0100 Subject: [PATCH 49/67] Fix example for `ExportedSessionData` (#2154) Currently, the example for `ExportedSessionData` is missing values for `room_id` and `session_id`. Move the example field values for `KeyBackupSessionData` into the field definitions, so that an example for the object as a whole is built automatically, and when we extend it to form `ExportedSessionData` the explicit example does not override the more complete autogenerated one. --- .../newsfragments/2154.clarification | 1 + .../definitions/key_backup_session_data.yaml | 16 +++++----------- 2 files changed, 6 insertions(+), 11 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2154.clarification diff --git a/changelogs/client_server/newsfragments/2154.clarification b/changelogs/client_server/newsfragments/2154.clarification new file mode 100644 index 00000000..660e41b5 --- /dev/null +++ b/changelogs/client_server/newsfragments/2154.clarification @@ -0,0 +1 @@ +Add missing fields in example for `ExportedSessionData`. diff --git a/data/api/client-server/definitions/key_backup_session_data.yaml b/data/api/client-server/definitions/key_backup_session_data.yaml index e2579142..b5878471 100644 --- a/data/api/client-server/definitions/key_backup_session_data.yaml +++ b/data/api/client-server/definitions/key_backup_session_data.yaml @@ -23,6 +23,7 @@ properties: type: string description: |- The end-to-end message encryption algorithm that the key is for. Must be `m.megolm.v1.aes-sha2`. + example: "m.megolm.v1.aes-sha2" forwarding_curve25519_key_chain: type: array items: @@ -30,31 +31,24 @@ properties: description: |- Chain of Curve25519 keys through which this session was forwarded, via [m.forwarded_room_key](/client-server-api/#mforwarded_room_key) events. + example: [ "hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw" ] sender_key: type: string description: |- Unpadded base64-encoded device Curve25519 key. + example: "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU" sender_claimed_keys: type: object additionalProperties: type: string description: |- A map from algorithm name (`ed25519`) to the Ed25519 signing key of the sending device. + example: { "ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y" } session_key: type: string description: |- Unpadded base64-encoded session key in [session-export format](https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md#session-export-format). -example: { - "algorithm": "m.megolm.v1.aes-sha2", - "forwarding_curve25519_key_chain": [ - "hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw" - ], - "sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU", - "sender_claimed_keys": { - "ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y", - }, - "session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf..." -} + example: "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf..." required: - algorithm - forwarding_curve25519_key_chain From 9244c84a322081aced03035d87a94c122a55966e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Wed, 18 Jun 2025 11:12:48 +0200 Subject: [PATCH 50/67] Add OAuth 2.0 dynamic client registration (#2148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per MSC2966 Signed-off-by: Kévin Commaille --- .../client_server/newsfragments/2148.feature | 1 + content/client-server-api/_index.md | 203 ++++++++++++++++++ data/schemas/oauth2-client-metadata.yaml | 140 ++++++++++++ 3 files changed, 344 insertions(+) create mode 100644 changelogs/client_server/newsfragments/2148.feature create mode 100644 data/schemas/oauth2-client-metadata.yaml diff --git a/changelogs/client_server/newsfragments/2148.feature b/changelogs/client_server/newsfragments/2148.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2148.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 72b425e2..b9c4a7d5 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -1485,6 +1485,209 @@ MAY reject weak passwords with an error code `M_WEAK_PASSWORD`. {{% http-api spec="client-server" api="oauth_server_metadata" %}} +#### Client registration + +Before being able to use the authorization flow to obtain an access token, a +client needs to obtain a `client_id` by registering itself with the server. + +This should be done via OAuth 2.0 Dynamic Client Registration as defined in +[RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591). + +##### Client metadata + +In OAuth 2.0, clients register a set of metadata values with the authorization +server, which associates it with a newly generated `client_id`. These values are +used to describe the client to the user and define how the client interacts with +the server. + +{{% definition path="schemas/oauth2-client-metadata" %}} + +###### Metadata localization + +As per [RFC 7591 section 2.2](https://tools.ietf.org/html/rfc7591#section-2.2), +all the human-readable metadata values MAY be localized. + +The human-readable values include: +- `client_name` +- `logo_uri` +- `tos_uri` +- `policy-uri` + +For example: + +```json +{ + "client_name": "Digital mailbox", + "client_name#en-US": "Digital mailbox", + "client_name#en-GB": "Digital postbox", + "client_name#fr": "Boîte aux lettres numérique", + "tos_uri": "https://example.com/tos.html", + "tos_uri#fr": "https://example.com/fr/tos.html", + "policy_uri": "https://example.com/policy.html", + "policy_uri#fr": "https://example.com/fr/policy.html" +} +``` + +###### Redirect URI validation + +The redirect URI plays a critical role in validating the authenticity of the +client. The client "proves" its identity by demonstrating that it controls the +redirect URI. This is why it is critical to have strict validation of the +redirect URI. + +The `application_type` metadata is used to determine the type of client. + +In all cases, the redirect URI MUST NOT have a fragment component. + +**Web clients** + +`web` clients can use redirect URIs that: + +- MUST use the `https` scheme. +- MUST NOT use a user or password in the authority component of the URI. +- MUST use the client URI as a common base for the authority component, as + defined previously. +- MAY include an `application/x-www-form-urlencoded` formatted query component. + +For example, with `https://example.com/` as the client URI, the following are +valid redirect URIs: +- `https://example.com/callback` +- `https://app.example.com/callback` +- `https://example.com:5173/?query=value` + +With the same client URI, the following are invalid redirect URIs: +- `https://example.com/callback#fragment` +- `http://example.com/callback` +- `http://localhost/` + +**Native clients** + +`native` clients can use three types of redirect URIs: + +1. **Private-Use URI Scheme** + - The scheme MUST be prefixed with the client URI hostname in reverse-DNS + notation. For example, if the client URI is `https://example.com/`, then a + valid custom URI scheme would be `com.example.app:/`. + - There MUST NOT be an authority component. This means that the URI MUST have + either a single slash or none immediately following the scheme, with no + hostname, username, or port. +2. **`http` URI on the loopback interface** + - The scheme MUST be `http`. + - The host part MUST be `localhost`, `127.0.0.1`, or `[::1]`. + - There MUST NOT be a port. The homeserver MUST then accept any port number + during the authorization flow. +3. **Claimed `https` Scheme URI** + + Some operating systems allow apps to claim `https` scheme URIs in the + domains they control. When the browser encounters a claimed URI, instead of + the page being loaded in the browser, the native app is launched with the + URI supplied as a launch parameter. The same rules as for `web` clients + apply. + +These restrictions are the same as defined by [RFC 8252 section 7](https://tools.ietf.org/html/rfc8252#section-7). + +For example, with `https://example.com/` as the client URI, + +These are valid redirect URIs: +- `com.example.app:/callback` +- `com.example:/` +- `com.example:callback` +- `http://localhost/callback` +- `http://127.0.0.1/callback` +- `http://[::1]/callback` + +These are invalid redirect URIs: +- `example:/callback` +- `com.example.app://callback` +- `https://localhost/callback` +- `http://localhost:1234/callback` + +##### Dynamic client registration flow + +To register, the client sends an HTTP `POST` request to the +`registration_endpoint`, which can be found in the [server metadata](#server-metadata-discovery). +The body of the request is the JSON-encoded [`OAuthClientMetadata`](#client-metadata). + +For example, the client could send the following registration request: + +```http +POST /register HTTP/1.1 +Content-Type: application/json +Accept: application/json +Server: auth.example.com +``` + +```json +{ + "client_name": "My App", + "client_name#fr": "Mon application", + "client_uri": "https://example.com/", + "logo_uri": "https://example.com/logo.png", + "tos_uri": "https://example.com/tos.html", + "tos_uri#fr": "https://example.com/fr/tos.html", + "policy_uri": "https://example.com/policy.html", + "policy_uri#fr": "https://example.com/fr/policy.html", + "redirect_uris": ["https://app.example.com/callback"], + "token_endpoint_auth_method": "none", + "response_types": ["code"], + "grant_types": [ + "authorization_code", + "refresh_token", + "urn:ietf:params:oauth:grant-type:token-exchange" + ], + "application_type": "web" +} +``` + +Upon successful registration, the server replies with an `HTTP 201 Created` +response, with a JSON object containing the allocated `client_id` and all the +registered metadata values. + +With the registration request above, the server might reply with: + +```json +{ + "client_id": "s6BhdRkqt3", + "client_name": "My App", + "client_uri": "https://example.com/", + "logo_uri": "https://example.com/logo.png", + "tos_uri": "https://example.com/tos.html", + "policy_uri": "https://example.com/policy.html", + "redirect_uris": ["https://app.example.com/callback"], + "token_endpoint_auth_method": "none", + "response_types": ["code"], + "grant_types": ["authorization_code", "refresh_token"], + "application_type": "web" +} +``` + +In this example, the server has not registered the locale-specific values for +`client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in +the response. The server also does not support the +`urn:ietf:params:oauth:grant-type:token-exchange` grant type, which is why it is +not present in the response. + +The client MUST store the `client_id` for future use. + +To avoid the number of client registrations growing over time, the server MAY +choose to delete client registrations that don't have an active session. The +server MUST NOT delete client registrations that have an active session. + +Clients MUST perform a new client registration at the start of each +authorization flow. + +{{% boxes/note %}} +Because each client on each user device will do its own registration, they may +all have different `client_id`s. This means that the server may store the same +client registration multiple times, which could lead to a large number of client +registrations. + +This can be mitigated by de-duplicating client registrations that have identical +metadata. By doing so, different users on different devices using the same +client can share a single `client_id`, reducing the overall number of +registrations. +{{% /boxes/note %}} + #### Scope The client requests a scope in the OAuth 2.0 authorization flow, which is then diff --git a/data/schemas/oauth2-client-metadata.yaml b/data/schemas/oauth2-client-metadata.yaml new file mode 100644 index 00000000..ba12f3f9 --- /dev/null +++ b/data/schemas/oauth2-client-metadata.yaml @@ -0,0 +1,140 @@ +# Copyright 2025 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +title: OAuthClientMetadata +type: object +description: |- + This definition of the metadata specifies only the fields that are meaningful + in the context of the Matrix specification. All the possible values are + registered in the [OAuth Dynamic Client Registration Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata), + and normative definitions of them are available in their respective RFCs. +properties: + client_uri: + type: string + format: uri + description: |- + A URL to a valid web page that SHOULD give the user more information about + the client. + + This URL MUST use the `https` scheme and SHOULD NOT require authentication + to access. It MUST NOT use a user or password in the authority component + of the URI. + + The server MAY reject client registrations if this field is invalid or + missing. + + This URI is a common base for all the other URIs in the metadata: those + MUST be either on the same host or on a subdomain of the host of the + `client_uri`. The port number, path and query components MAY be different. + + For example, if the `client_uri` is `https://example.com/`, then one of + the `redirect_uris` can be `https://example.com/callback` or + `https://app.example.com/callback`, but not `https://app.com/callback`. + client_name: + type: string + description: |- + Human-readable name of the client to be presented to the user. + + This field can be [localized](/client-server-api/#metadata-localization). + logo_uri: + type: string + format: uri + description: |- + URL that references a logo for the client. + + This URL MUST use the `https` scheme. + + This field can be [localized](/client-server-api/#metadata-localization). + tos_uri: + type: string + format: uri + description: |- + URL that points to a human-readable terms of service document for the + client. + + This URL MUST use the `https` scheme and SHOULD NOT require authentication + to access. It MUST NOT use a user or password in the authority component + of the URI. + + If this field is set, the server SHOULD show or link to this URL. + + This field can be [localized](/client-server-api/#metadata-localization). + policy_uri: + type: string + format: uri + description: |- + URL that points to a human-readable policy document for the client. + + This URL MUST use the `https` scheme and SHOULD NOT require authentication + to access. It MUST NOT use a user or password in the authority component + of the URI. + + If this field is set, the server SHOULD show or link to this URL. + + This field can be [localized](/client-server-api/#metadata-localization). + redirect_uris: + type: array + description: |- + Array of redirection URIs for use in redirect-based flows. + + At least one URI is required to use the authorization code grant. + + The server MUST perform [validation on redirect URIs](/client-server-api/#redirect-uri-validation). + items: + type: string + format: uri + description: A redirection URI. + response_types: + type: array + description: |- + Array of the OAuth 2.0 response types that the client may use. + + This MUST include the `code` value to use the authorization code grant. + + The server MUST ignore values that it does not understand. + items: + type: string + description: A response type that the client may use. + grant_types: + type: array + description: |- + Array of the OAuth 2.0 grant types that the client may use. + + This MUST include: + - the `authorization_code` value to use the authorization code grant, + - the `refresh_token` value to use the refresh token grant. + + The server MUST ignore values that it does not understand. + items: + type: string + description: A grant type that the client may use. + token_endpoint_auth_method: + type: string + description: |- + String indicator of the requested authentication method for the token + endpoint. + + The homeserver MUST support the `none` value, as most Matrix clients are + client-side only, do not have a server component, and therefore are public + clients. + application_type: + type: string + description: |- + Kind of the application. + + The homeserver MUST support the `web` and `native` values to be able to + perform [redirect URI validation](/client-server-api/#redirect-uri-validation). + + Defaults to `web` if omitted. +required: + - client_uri From e4740e36e8c0598309d388ea89a832ee36bf9424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:45:17 +0200 Subject: [PATCH 51/67] Add OAuth 2.0 authorization code and refresh token grant types (#2150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per MSC2964 Signed-off-by: Kévin Commaille --- .../client_server/newsfragments/2150.feature | 1 + content/client-server-api/_index.md | 246 ++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 changelogs/client_server/newsfragments/2150.feature diff --git a/changelogs/client_server/newsfragments/2150.feature b/changelogs/client_server/newsfragments/2150.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2150.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index b9c4a7d5..d1f9654d 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -1481,6 +1481,174 @@ MAY reject weak passwords with an error code `M_WEAK_PASSWORD`. ### OAuth 2.0 API +#### Login flow + +Logging in with the OAuth 2.0 API should be done with the [authorization code +grant](#authorization-code-grant). In the context of the Matrix specification, +this means requesting a [scope](#scope) including full client-server API +read/write access and allocating a device ID. + +Once the client has retrieved the [server metadata](#server-metadata-discovery), +it needs to generate the following values: + +- `device_id`: a unique identifier for this device; see the + [`urn:matrix:client:device:`](#device-id-allocation) scope token. +- `state`: a unique opaque identifier, like a [transaction ID](#transaction-identifiers), + that will allow the client to maintain state between the authorization request + and the callback. +- `code_verifier`: a cryptographically random value that will allow to make sure + that the client that makes the token request for a given `code` is the same + one that made the authorization request. + + It is defined in [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) as + a high-entropy cryptographic random string using the characters `[A-Z]`, + `[a-z]`, `[0-9]`, `-`, `.`, `_` and `~` with a minimum length of 43 characters + and a maximum length of 128 characters. + +**Authorization request** + +The client then constructs the authorization request URL using the +`authorization_endpoint` value, with the following query parameters: + +| Parameter | Value | +|-------------------------|----------------------------------------------------| +| `response_type` | `code` | +| `client_id` | The client ID returned from client registration. | +| `redirect_uri` | The redirect URI that MUST match one of the values registered in the client metadata | +| `scope` | `urn:matrix:client:api:* urn:matrix:client:device:` with the `device_id` generated previously. | +| `state` | The `state` value generated previously. | +| `response_mode` | `fragment` or `query` (see "[Callback](#callback)" below). | +| `code_challenge` | Computed from the `code_verifier` value generated previously using the SHA-256 algorithm, as described in [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636). | +| `code_challenge_method` | `S256` | + +This authorization request URL must be opened in the user's browser: + +- For web-based clients, this can be done through a redirection or by opening + the URL in a new tab. +- For native clients, this can be done by opening the URL using the system + browser, or, when available, through platform-specific APIs such as + [`ASWebAuthenticationSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) + on iOS or [Android Custom Tabs](https://developer.chrome.com/docs/android/custom-tabs). + +Sample authorization request, with extra whitespaces for readability: + +``` +https://account.example.com/oauth2/auth? + client_id = s6BhdRkqt3 & + response_type = code & + response_mode = fragment & + redirect_uri = https://app.example.com/oauth2-callback & + scope = urn:matrix:client:api:* urn:matrix:client:device:AAABBBCCCDDD & + state = ewubooN9weezeewah9fol4oothohroh3 & + code_challenge = 72xySjpngTcCxgbPfFmkPHjMvVDl2jW1aWP7-J6rmwU & + code_challenge_method = S256 +``` + + **Callback** + +Once completed, the user is redirected to the `redirect_uri`, with either a +successful or failed authorization in the URL fragment or query parameters. +Whether the parameters are in the URL fragment or query parameters is determined +by the `response_mode` value: + +- If set to `fragment`, the parameters will be placed in the URL fragment, like + `https://example.com/callback#param1=value1¶m2=value2`. +- If set to `query`, the parameters will be in placed the query string, like + `com.example.app:/callback?param1=value1¶m2=value2`. + +To avoid disclosing the parameters to the web server hosting the `redirect_uri`, +clients SHOULD use the `fragment` response mode if the `redirect_uri` is an +HTTPS URI with a remote host. + +In both success and failure cases, the parameters will include the `state` value +used in the authorization request. + +A successful authorization will have a `code` value, for example: + +``` +https://app.example.com/oauth2-callback#state=ewubooN9weezeewah9fol4oothohroh3&code=iuB7Eiz9heengah1joh2ioy9ahChuP6R +``` + +A failed authorization will have the following values: + +- `error`: the error code +- `error_description`: the error description (optional) +- `error_uri`: the URI where the user can find more information about the error (optional) + +For example: + +``` +https://app.example.com/oauth2-callback#state=ewubooN9weezeewah9fol4oothohroh3&error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.&error_uri=https%3A%2F%2Ferrors.example.com%2F +``` + +**Token request** + +The client then exchanges the authorization code to obtain an access token using +the token endpoint. + +This is done by making a POST request to the `token_endpoint` with the following +parameters, encoded as `application/x-www-form-urlencoded` in the body: + +| Parameter | Value | +|-----------------|------------------------------------------------------------| +| `grant_type` | `authorization_code` | +| `code` | The value of `code` obtained from the callback. | +| `redirect_uri` | The same `redirect_uri` used in the authorization request. | +| `client_id` | The client ID returned from client registration. | +| `code_verifier` | The value generated at the start of the authorization flow. | + +The server replies with a JSON object containing the access token, the token +type, the expiration time, and the refresh token. + +Sample token request: + +``` +POST /oauth2/token HTTP/1.1 +Host: account.example.com +Content-Type: application/x-www-form-urlencoded +Accept: application/json + +grant_type=authorization_code + &code=iuB7Eiz9heengah1joh2ioy9ahChuP6R + &redirect_uri=https://app.example.com/oauth2-callback + &client_id=s6BhdRkqt3 + &code_verifier=ogie4iVaeteeKeeLaid0aizuimairaCh +``` + +Sample response: + +```json +{ + "access_token": "2YotnFZFEjr1zCsicMWpAA", + "token_type": "Bearer", + "expires_in": 299, + "refresh_token": "tGz3JOkF0XG5Qx2TlKWIA", + "scope": "urn:matrix:client:api:* urn:matrix:client:device:AAABBBCCCDDD" +} +``` + +Finally, the client can call the [`/whoami`](#get_matrixclientv3accountwhoami) +endpoint to get the user ID that owns the access token. + +#### Token refresh flow + +Refreshing a token with the OAuth 2.0 API should be done with the [refresh token +grant](#refresh-token-grant). + +When the access token expires, the client must refresh it by making a `POST` +request to the `token_endpoint` with the following parameters, encoded as +`application/x-www-form-urlencoded` in the body: + +| Parameter | Value | +|-----------------|------------------------------------------------------------| +| `grant_type` | `refresh_token` | +| `refresh_token` | The `refresh_token` obtained from the token response during the last token request. | +| `client_id` | The client ID returned from client registration. | + +The server replies with a JSON object containing the new access token, the token +type, the expiration time, and a new refresh token, like in the authorization +flow. + #### Server metadata discovery {{% http-api spec="client-server" api="oauth_server_metadata" %}} @@ -1778,6 +1946,84 @@ This definition matches: - alphanumeric characters: `A-Z`, `a-z`, `0-9` - the following characters: ``! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~`` +#### Grant types + +[RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) and other RFCs define +several "grant types": ways to obtain an ["access token"](#using-access-tokens). + +All these grants types require the client to know the following [authorization +server metadata](#server-metadata-discovery): +- `token_endpoint` +- `grant_types_supported` + +The client must also have obtained a `client_id` by [registering with the server](#client-registration). + +This specification supports the following grant types: +- [Authorization code grant](#authorization-code-grant) +- [Refresh token grant](#refresh-token-grant) + +##### Authorization code grant + +As per [RFC 6749 section 4.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1), +the authorization code grant lets the client obtain an access token through a +browser redirect. + +This grant requires the client to know the following [authorization server +metadata](#server-metadata-discovery): +- `authorization_endpoint` +- `response_types_supported` +- `response_mode_supported` + +To use this grant, homeservers and clients MUST: + +- Support the authorization code grant as per [RFC 6749 section 4.1](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1). +- Support the [refresh token grant](#refresh-token-grant). +- Support PKCE using the `S256` code challenge method as per [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636). +- Use [pre-registered](#client-registration), strict redirect URIs. +- Use the `fragment` response mode as per [OAuth 2.0 Multiple Response Type + Encoding Practices](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html) + for clients with an HTTPS redirect URI. + +###### User registration + +Clients can signal to the server that the user desires to register a new account +by initiating the authorization code grant with the `prompt=create` parameter +set in the authorization request as defined in [Initiating User Registration via +OpenID Connect 1.0](https://openid.net/specs/openid-connect-prompt-create-1_0.html). + +Whether the homeserver supports this parameter is advertised by the +`prompt_values_supported` authorization server metadata. + +Servers that support this parameter SHOULD show the account registration UI in +the browser. + +##### Refresh token grant + +As per [RFC 6749 section 6](https://datatracker.ietf.org/doc/html/rfc6749#section-6), +the refresh token grant lets the client exchange a refresh token for an access +token. + +When authorization is granted to a client, the homeserver MUST issue a refresh +token to the client in addition to the access token. + +The access token MUST be short-lived and SHOULD be refreshed using the +`refresh_token` when expired. + +The homeserver SHOULD issue a new refresh token each time an old one is used, +and invalidate the old one. However, it MUST ensure that the client is able to +retry the refresh request in the case that the response to the request is lost. + +The homeserver SHOULD consider that the session is compromised if an old, +invalidated refresh token is used, and SHOULD revoke the session. + +The client MUST handle access token refresh failures as follows: + + - If the refresh fails due to network issues or a `5xx` HTTP status code from + the server, the client should retry the request with the old refresh token + later. + - If the refresh fails due to a `4xx` HTTP status code from the server, the + client should consider the session logged out. + ### Account moderation #### Account locking From ccd9e50eb18f81b3c98998106354dab824dd09c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:51:17 +0200 Subject: [PATCH 52/67] Add OAuth 2.0 token revocation (#2151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per MSC4254 Signed-off-by: Kévin Commaille --- .../client_server/newsfragments/2151.feature | 1 + content/client-server-api/_index.md | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 changelogs/client_server/newsfragments/2151.feature diff --git a/changelogs/client_server/newsfragments/2151.feature b/changelogs/client_server/newsfragments/2151.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2151.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index d1f9654d..922f4012 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -2024,6 +2024,84 @@ The client MUST handle access token refresh failures as follows: - If the refresh fails due to a `4xx` HTTP status code from the server, the client should consider the session logged out. +#### Token revocation + +When a user wants to log out from a client, the client SHOULD use OAuth 2.0 +token revocation as defined in [RFC 7009](https://datatracker.ietf.org/doc/html/rfc7009). + +The client makes a `POST` request to the `revocation_endpoint` that can be found +in the [authorization server metadata](#server-metadata-discovery). + +The body of the request includes the following parameters, encoded as +`application/x-www-form-urlencoded`: + +
Git commit{{ $commitLink }}
Release date{{ .Date | time.Format ":date_long" }}
+ + + + + + + + + + + + + + + + + + + + +
ParameterValue
token + Required. MUST contain either the access token or the + refresh token to be revoked. +
token_type_hint + Optional. If present, MUST have a value of either + access_token or refresh_token. The server MAY + use this value to optimize the token lookup process. +
client_id +

+ Optional. The client identifier obtained during + client registration. +

+

+ If the client_id is not provided, or does not match the + client associated with the token, the server SHOULD still revoke the + token. This behavior is meant to help good actors like secret scanning + tools to proactively revoke leaked tokens. The server MAY also warn + the user that one of their sessions may be compromised in this + scenario. +

+
+ +For example, revoking using the access token: + +``` +POST /oauth2/revoke HTTP/1.1 +Host: auth.example.com +Content-Type: application/x-www-form-urlencoded + +token=mat_ooreiPhei2wequu9fohkai3AeBaec9oo& +token_type_hint=access_token& +client_id=s6BhdRkqt3 +``` + +The server MUST revoke both the access token and refresh token associated with +the token provided in the request. + +The server SHOULD return one of the following responses: + +- If the token is already revoked or invalid, the server returns a `200 OK` + response +- If the client is not authorized to revoke the token, the server returns a + `401 Unauthorized` response +- For other errors, the server returns a `400 Bad Request` response with error + details + ### Account moderation #### Account locking From b278a4e0ecb4b25b01db5a78f4761581427e00e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Fri, 20 Jun 2025 16:50:14 +0200 Subject: [PATCH 53/67] Clarify the differences between the two authentication APIs (#2159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I tried to summarize MSC3861, and add sections to be able to find quickly how to do something with either API. Signed-off-by: Kévin Commaille --- .../client_server/newsfragments/2159.feature | 1 + content/client-server-api/_index.md | 149 +++++++++++++++--- 2 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2159.feature diff --git a/changelogs/client_server/newsfragments/2159.feature b/changelogs/client_server/newsfragments/2159.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2159.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 922f4012..fbf678a6 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -292,9 +292,8 @@ and the two requests would be considered distinct because the two are considered separate endpoints. Similarly, if a client logs out and back in between two requests using the same transaction ID, the requests are distinct because the act of logging in and out creates a new device (unless an existing -`device_id` is passed to [`POST -/_matrix/client/v3/login`](#post_matrixclientv3login)). On the other hand, if a -client re-uses a transaction ID for the same endpoint after +`device_id` is given during the [login](#login) process). On the other hand, if +a client re-uses a transaction ID for the same endpoint after [refreshing](#refreshing-access-tokens) an access token, it will be assumed to be a duplicate request and ignored. See also [Relationship between access tokens and devices](#relationship-between-access-tokens-and-devices). @@ -436,6 +435,8 @@ endpoints it supports. ## Client Authentication +{{% changed-in v="1.15" %}} OAuth 2.0 API added to the specification. + Most API endpoints require the user to identify themselves by presenting previously obtained credentials in the form of an access token. An access token is typically obtained via the [Login](#login) or @@ -449,6 +450,60 @@ free to choose an appropriate format. Server implementors may like to investigate [macaroons](http://research.google.com/pubs/pub41892.html). {{% /boxes/note %}} +Since Matrix 1.15, the Client-Server specification supports two authentication +APIs: + +* The [legacy API](#legacy-api) +* The [OAuth 2.0 API](#oauth-20-api) + +The legacy API has existed since the first version of the Matrix specification, +while the OAuth 2.0 API has been introduced to rely on a industry standard and +its experience rather than implementing a custom protocol that might not follow +the best practices. + +A homeserver may support one of those two APIs, or both. The two APIs are +mutually incompatible, which means that after logging in, clients MUST only use +the API that was used to obtain their current access token. + +{{% boxes/note %}} +Currently the OAuth 2.0 API doesn't cover all the use cases of the legacy API, +such as automated applications that cannot use a web browser, or +user management by [application services](application-service-api/#server-admin-style-permissions). +{{% /boxes/note %}} + +### Authentication API discovery + +To discover if a homeserver supports the legacy API, the [`GET /login`](#get_matrixclientv3login) +endpoint can be used. + +To discover if a homeserver supports the OAuth 2.0 API, the +[`GET /auth_metadata`](#get_matrixclientv1auth_metadata) endpoint can be used. + +In both cases, the server SHOULD respond with 404 and an `M_UNRECOGNIZED` error +code if the corresponding API is not supported. + +### Account registration + +With the legacy API, a client can register a new account with the +[`/register`](#post_matrixclientv3register) endpoint. + +With the OAuth 2.0 API, a client can't register a new account directly. The end +user must do that directly in the homeserver's web UI. However, the client can +signal to the homeserver that the user wishes to create a new account with the +[`prompt=create`](#user-registration) parameter during authorization. + +### Login + +With the legacy API, a client can obtain an access token by using one of the +[login](#legacy-login) methods supported by the homeserver at the [`POST /login`](#post_matrixclientv3login) +endpoint. To invalidate the access token the client must call the [`/logout`](#post_matrixclientv3logout) +endpoint. + +With the OAuth 2.0 API, a client can obtain an access token by using one of the +[grant types](#grant-types) supported by the homeserver and authorizing the +proper [scope](#scope), as demonstrated in the [login flow](#login-flow). To +invalidate the access token the client must use [token revocation](#token-revocation). + ### Using access tokens Access tokens may be provided via a request header, using the Authentication @@ -494,12 +549,14 @@ used to generate a new access token and refresh token, the new access and refresh tokens are now bound to the device associated with the initial refresh token. -By default, the [Login](#login) and [Registration](#account-registration) -processes auto-generate a new `device_id`. A client is also free to -generate its own `device_id` or, provided the user remains the same, -reuse a device: in either case the client should pass the `device_id` in -the request body. If the client sets the `device_id`, the server will -invalidate any access and refresh tokens previously assigned to that device. +During login or registration, the generated access token should be associated +with a `device_id`. The legacy [Login](#legacy-login) and [Registration](#legacy-account-registration) +processes auto-generate a new `device_id`, but a client is also free to provide +its own `device_id`. With the OAuth 2.0 API, the `device_id` is always provided +by the client. The client can generate a new `device_id` or, provided the user +remains the same, reuse an existing device. If the client sets the `device_id`, +the server will invalidate any access and refresh tokens previously assigned to +that device. ### Refreshing access tokens @@ -508,14 +565,13 @@ invalidate any access and refresh tokens previously assigned to that device. Access tokens can expire after a certain amount of time. Any HTTP calls that use an expired access token will return with an error code `M_UNKNOWN_TOKEN`, preferably with `soft_logout: true`. When a client receives this error and it -has a refresh token, it should attempt to refresh the access token by calling -[`/refresh`](#post_matrixclientv3refresh). Clients can also refresh their -access token at any time, even if it has not yet expired. If the token refresh -succeeds, the client should use the new token for future requests, and can -re-try previously-failed requests with the new token. When an access token is -refreshed, a new refresh token may be returned; if a new refresh token is -given, the old refresh token will be invalidated, and the new refresh token -should be used when the access token needs to be refreshed. +has a refresh token, it should attempt to refresh the access token. Clients can +also refresh their access token at any time, even if it has not yet expired. If +the token refresh succeeds, the client should use the new token for future +requests, and can re-try previously-failed requests with the new token. When an +access token is refreshed, a new refresh token may be returned; if a new refresh +token is given, the old refresh token will be invalidated, and the new refresh +token should be used when the access token needs to be refreshed. The old refresh token remains valid until the new access token or refresh token is used, at which point the old refresh token is revoked. This ensures that if @@ -528,6 +584,7 @@ and attempt to obtain a new access token by re-logging in. If the error response does not include a `soft_logout: true` property, the client should consider the user as being logged out. +With the legacy API, refreshing access tokens is done by calling [`/refresh`](#post_matrixclientv3refresh). Handling of clients that do not support refresh tokens is up to the homeserver; clients indicate their support for refresh tokens by including a `refresh_token: true` property in the request body of the @@ -537,6 +594,11 @@ may allow the use of non-expiring access tokens, or may expire access tokens anyways and rely on soft logout behaviour on clients that don't support refreshing. +With the OAuth 2.0 API, refreshing access tokens is done with the [refresh token +grant type](#refresh-token-grant), as demonstrated in the [token refresh +flow](#token-refresh-flow). Support for refreshing access tokens is mandatory +with this API. + ### Soft logout A client can be in a "soft logout" state if the server requires @@ -560,8 +622,24 @@ specifying the device ID it is already using to the login API. with an `M_USER_LOCKED` error code, cannot obtain a new access token until the account has been [unlocked](#account-locking). +### Account management + +With the legacy API, a client can use several endpoints to allow the user to +manage their account like [changing their password](#password-management), +[managing their devices](#device-management) or +[deactivating their account](#account-deactivation). + +With the OAuth 2.0 API, all account management is done via the homeserver's web +UI. + ### Legacy API +This is the original authentication API that was introduced in the first version +of the Client-Server specification and uses custom APIs. Contrary to the OAuth +2.0 API, account management is primarily done in the client's interface and as +such it does not usually require the end user to be redirected to a web UI in +their browser. + #### User-Interactive Authentication API ##### Overview @@ -1329,7 +1407,7 @@ The `country` is the two-letter uppercase ISO-3166-1 alpha-2 country code that the number in `phone` should be parsed as if it were dialled from. -#### Login +#### Login {id="legacy-login"} A client can obtain access tokens using the [`/login`](#post_matrixclientv3login) API. @@ -1458,11 +1536,11 @@ forwarded to the login endpoint during the login process. For example: GET /_matrix/static/client/login/?device_id=GHTYAJCE -#### Account registration +#### Account registration {id="legacy-account-registration"} {{% http-api spec="client-server" api="registration" %}} -#### Account management +#### Account management {id="legacy-account-management"} ##### Password management @@ -1481,6 +1559,37 @@ MAY reject weak passwords with an error code `M_WEAK_PASSWORD`. ### OAuth 2.0 API +{{% added-in v="1.15" %}} + +Contrary to the legacy API that uses custom endpoints and UIA, this +authentication API is based on the [OAuth 2.0](https://oauth.net/2/) industry +standard introduced in [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) +and extended by other RFCs, with a few features from [OpenID Connect](https://openid.net/connect/). +This allows us to benefit from its experience and from any further enhancements +or best practice recommendations. + +The main change for end users with this API is that all the account management +occurs in their browser on the homeserver's web UI. This is where they will +register a new account or log into an existing account and authorize a client to +access their Matrix account. This means that the homeserver has complete control +over the requirements to create a new account and is not limited by the steps +defined in this specification. It also means that less trust is given to clients +because they don't have access to the user's credentials anymore. + +{{% boxes/warning %}} +The [User-Interactive Authentication API](#user-interactive-authentication-api) +is not compatible with the OAuth 2.0 API, so the endpoints that depend on it for +authentication can't be used when an access token is obtained with this API. +{{% /boxes/warning %}} + +**Sample flow** + +1. [Discover the OAuth 2.0 server metadata](#server-metadata-discovery). +2. [Register the client with the homeserver](#client-registration). +3. [Obtain an access token](#login-flow) by authorizing a [scope](#scope) for the client with the [authorization code grant](#authorization-code-grant). +4. [Refresh the access token](#token-refresh-flow) with the [refresh token grant](#refresh-token-grant) when it expires. +5. [Revoke the tokens](#token-revocation) when the users wants to log out of the client. + #### Login flow Logging in with the OAuth 2.0 API should be done with the [authorization code From 0e05e45d846735289c74f595922e59568f80e429 Mon Sep 17 00:00:00 2001 From: Peter Gervai Date: Tue, 24 Jun 2025 18:46:02 +0200 Subject: [PATCH 54/67] Update proposals.md: add reference to the guide about how to handle not-yet-known MSC number (#2153) Suggest how to number the draft before user have the PR/MSC ID, referring to the other guide. --- content/proposals.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/content/proposals.md b/content/proposals.md index b58a98be..d0d99bae 100644 --- a/content/proposals.md +++ b/content/proposals.md @@ -185,6 +185,10 @@ is as follows: - Take care in creating your proposal. Specify your intended changes, and give reasoning to back them up. Changes without justification will likely be poorly received by the community. + - At the time of creating your draft you will not yet know the PR number, so you + should use a placeholder number to name your file and edit that + after PR submission. The suggested steps are described in + detail [in the proposals guide](https://github.com/matrix-org/matrix-spec-proposals#1-writing-the-proposal). - Fork and make a PR to the [matrix-spec-proposals](https://github.com/matrix-org/matrix-spec-proposals) repository. The ID of your PR will become the MSC ID for the lifetime of your From 6353b46addde7cf2bbd50ecb707ace4ef170da6d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 26 Jun 2025 10:30:39 -0600 Subject: [PATCH 55/67] Normalize changelog --- .../application_service/newsfragments/2130.clarification | 1 + changelogs/application_service/newsfragments/2130.feature | 1 - changelogs/client_server/newsfragments/2083.clarification | 3 +-- changelogs/client_server/newsfragments/2125.new | 1 + changelogs/client_server/newsfragments/2144.clarification | 2 +- changelogs/server_server/newsfragments/2083.clarification | 3 +-- 6 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 changelogs/application_service/newsfragments/2130.clarification delete mode 100644 changelogs/application_service/newsfragments/2130.feature create mode 100644 changelogs/client_server/newsfragments/2125.new diff --git a/changelogs/application_service/newsfragments/2130.clarification b/changelogs/application_service/newsfragments/2130.clarification new file mode 100644 index 00000000..9cd12b4e --- /dev/null +++ b/changelogs/application_service/newsfragments/2130.clarification @@ -0,0 +1 @@ +Clarify in the application service registration schema the `url: null` behaviour. diff --git a/changelogs/application_service/newsfragments/2130.feature b/changelogs/application_service/newsfragments/2130.feature deleted file mode 100644 index 7761505c..00000000 --- a/changelogs/application_service/newsfragments/2130.feature +++ /dev/null @@ -1 +0,0 @@ -Correct null value handling for the AS Registration's `url` property. diff --git a/changelogs/client_server/newsfragments/2083.clarification b/changelogs/client_server/newsfragments/2083.clarification index cc3dc3c7..eb334aab 100644 --- a/changelogs/client_server/newsfragments/2083.clarification +++ b/changelogs/client_server/newsfragments/2083.clarification @@ -1,2 +1 @@ -Clarify the format of third-party invites, including the fact that identity -server public keys can be encoded using standard or URL-safe base64. +Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. diff --git a/changelogs/client_server/newsfragments/2125.new b/changelogs/client_server/newsfragments/2125.new new file mode 100644 index 00000000..bc329452 --- /dev/null +++ b/changelogs/client_server/newsfragments/2125.new @@ -0,0 +1 @@ +Add `GET /_matrix/client/v1/room_summary/{roomIdOrAlias}`, as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2144.clarification b/changelogs/client_server/newsfragments/2144.clarification index 07917287..3ccb2333 100644 --- a/changelogs/client_server/newsfragments/2144.clarification +++ b/changelogs/client_server/newsfragments/2144.clarification @@ -1 +1 @@ -Fix typo: as->has. +Fix various typos throughout the specification. diff --git a/changelogs/server_server/newsfragments/2083.clarification b/changelogs/server_server/newsfragments/2083.clarification index cc3dc3c7..eb334aab 100644 --- a/changelogs/server_server/newsfragments/2083.clarification +++ b/changelogs/server_server/newsfragments/2083.clarification @@ -1,2 +1 @@ -Clarify the format of third-party invites, including the fact that identity -server public keys can be encoded using standard or URL-safe base64. +Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. From 1c06ed9cf77c56094ab7ee43f86a7e7fb6e61654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Thu, 26 Jun 2025 18:40:43 +0200 Subject: [PATCH 56/67] Final tweaks for the OAuth 2.0 API (#2164) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Clarify that SSO login applies to the legacy authentication API Signed-off-by: Kévin Commaille * Do not point to specific authentication API for obtaining access token Signed-off-by: Kévin Commaille * Add warnings about incompatibility with OAuth 2.0 to endpoints that use UIA Signed-off-by: Kévin Commaille * Add changelog Signed-off-by: Kévin Commaille * Add note about API standards not applying to OAuth 2.0 Signed-off-by: Kévin Commaille * Apply suggestions from code review --------- Signed-off-by: Kévin Commaille Co-authored-by: Travis Ralston --- changelogs/client_server/newsfragments/2164.feature | 1 + content/client-server-api/_index.md | 6 ++++++ content/client-server-api/modules/sso_login.md | 9 +++++---- data/api/client-server/administrative_contact.yaml | 5 +++++ data/api/client-server/cross_signing.yaml | 11 ++++++++--- data/api/client-server/definitions/security.yaml | 12 ++++++------ data/api/client-server/device_management.yaml | 10 ++++++++++ 7 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2164.feature diff --git a/changelogs/client_server/newsfragments/2164.feature b/changelogs/client_server/newsfragments/2164.feature new file mode 100644 index 00000000..6eff5607 --- /dev/null +++ b/changelogs/client_server/newsfragments/2164.feature @@ -0,0 +1 @@ +Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index fbf678a6..e7de10eb 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -12,6 +12,12 @@ clients which maintain a full local persistent copy of server state. ## API Standards +{{% boxes/note %}} +These standards only apply to the APIs defined in the Matrix specification. APIs +used by this specification but defined in other specifications, like the [OAuth +2.0 API](#oauth-20-api), use their own rules. +{{% /boxes/note %}} + The mandatory baseline for client-server communication in Matrix is exchanging JSON objects over HTTP APIs. More efficient transports may be specified in future as optional extensions. diff --git a/content/client-server-api/modules/sso_login.md b/content/client-server-api/modules/sso_login.md index f50a2eb1..8b228356 100644 --- a/content/client-server-api/modules/sso_login.md +++ b/content/client-server-api/modules/sso_login.md @@ -6,9 +6,10 @@ allow users to log into applications via a single web-based authentication portal. Examples include OpenID Connect, "Central Authentication Service" (CAS) and SAML. -This module allows a Matrix homeserver to delegate user authentication -to an external authentication server supporting one of these protocols. -In this process, there are three systems involved: +This module allows a Matrix homeserver that supports the [legacy authentication +API](#legacy-api) to delegate user authentication to an external authentication +server supporting one of these protocols. In this process, there are three +systems involved: - A Matrix client, using the APIs defined in this specification, which is seeking to authenticate a user to a Matrix homeserver. @@ -24,7 +25,7 @@ used to communicate with the authentication server. Different Matrix homeserver implementations might support different SSO protocols. Clients and homeservers implementing the SSO flow will need to consider -both [login](#login) and [user-interactive authentication](#user-interactive-authentication-api). The flow is +both [login](#legacy-login) and [user-interactive authentication](#user-interactive-authentication-api). The flow is similar in both cases, but there are slight differences. Typically, SSO systems require a single "callback" URI to be configured diff --git a/data/api/client-server/administrative_contact.yaml b/data/api/client-server/administrative_contact.yaml index eddb2b01..54b91d42 100644 --- a/data/api/client-server/administrative_contact.yaml +++ b/data/api/client-server/administrative_contact.yaml @@ -201,6 +201,11 @@ paths: Homeservers should prevent the caller from adding a 3PID to their account if it has already been added to another user's account on the homeserver. + + {{% boxes/warning %}} + Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). + {{% /boxes/warning %}} operationId: add3PID security: - accessTokenQuery: [] diff --git a/data/api/client-server/cross_signing.yaml b/data/api/client-server/cross_signing.yaml index 8f499d23..60fa9e5b 100644 --- a/data/api/client-server/cross_signing.yaml +++ b/data/api/client-server/cross_signing.yaml @@ -26,7 +26,7 @@ paths: Publishes cross-signing keys for the user. This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). - + User-Interactive Authentication MUST be performed, except in these cases: - there is no existing cross-signing master key uploaded to the homeserver, OR - there is an existing cross-signing master key and it exactly matches the @@ -34,11 +34,16 @@ paths: keys provided in the request (self-signing key, user-signing key) they MUST also match the existing keys stored on the server. In other words, the request contains no new keys. - + This allows clients to freely upload one set of keys, but not modify/overwrite keys if - they already exist. Allowing clients to upload the same set of keys more than once + they already exist. Allowing clients to upload the same set of keys more than once makes this endpoint idempotent in the case where the response is lost over the network, which would otherwise cause a UIA challenge upon retry. + + {{% boxes/warning %}} + When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained + via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). + {{% /boxes/warning %}} operationId: uploadCrossSigningKeys security: - accessTokenQuery: [] diff --git a/data/api/client-server/definitions/security.yaml b/data/api/client-server/definitions/security.yaml index 0c9bd1c7..bb84a08c 100644 --- a/data/api/client-server/definitions/security.yaml +++ b/data/api/client-server/definitions/security.yaml @@ -14,8 +14,8 @@ accessTokenQuery: type: apiKey description: |- - **Deprecated.** The `access_token` returned by a call to `/login` or `/register`, as a query - parameter. + **Deprecated.** The `access_token` obtained during [account registration](/client-server-api/#account-registration) + or [login](/client-server-api/#login), as a query parameter. It can also be the `as_token` of an application service. name: access_token @@ -23,11 +23,11 @@ accessTokenQuery: accessTokenBearer: type: http description: |- - The `access_token` returned by a call to `/login` or `/register`, using the - `Authorization: Bearer` header. + The `access_token` obtained during [account registration](/client-server-api/#account-registration) + or [login](/client-server-api/#login), using the `Authorization: Bearer` header. It can also be the `as_token` of an application service. - + This is the preferred method. scheme: bearer appserviceAccessTokenQuery: @@ -42,6 +42,6 @@ appserviceAccessTokenBearer: description: |- The `as_token` of an application service, using the `Authorization: Bearer` header. - + This is the preferred method. scheme: bearer diff --git a/data/api/client-server/device_management.yaml b/data/api/client-server/device_management.yaml index b2bcb8ce..1b245e78 100644 --- a/data/api/client-server/device_management.yaml +++ b/data/api/client-server/device_management.yaml @@ -137,6 +137,11 @@ paths: This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). Deletes the given device, and invalidates any access token associated with it. + + {{% boxes/warning %}} + Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). + {{% /boxes/warning %}} operationId: deleteDevice security: - accessTokenQuery: [] @@ -189,6 +194,11 @@ paths: This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api). Deletes the given devices, and invalidates any access token associated with them. + + {{% boxes/warning %}} + Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained + via the [OAuth 2.0 API](/client-server-api/#oauth-20-api). + {{% /boxes/warning %}} operationId: deleteDevices security: - accessTokenQuery: [] From 40065811a143cd3175f5ccfeff87e926c6f0e452 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 26 Jun 2025 10:43:51 -0600 Subject: [PATCH 57/67] Matrix 1.15 --- .../newsfragments/2130.clarification | 1 - .../newsfragments/2068.clarification | 1 - .../newsfragments/2077.clarification | 1 - .../newsfragments/2083.clarification | 1 - .../client_server/newsfragments/2095.feature | 1 - .../newsfragments/2101.clarification | 1 - .../newsfragments/2102.clarification | 1 - .../newsfragments/2104.clarification | 1 - .../newsfragments/2106.clarification | 1 - .../newsfragments/2107.clarification | 1 - .../newsfragments/2108.clarification | 1 - .../newsfragments/2109.clarification | 1 - .../newsfragments/2121.clarification | 1 - .../client_server/newsfragments/2122.feature | 1 - .../client_server/newsfragments/2125.feature | 1 - .../client_server/newsfragments/2125.new | 1 - .../newsfragments/2140.clarification | 1 - .../client_server/newsfragments/2141.feature | 1 - .../newsfragments/2144.clarification | 1 - .../client_server/newsfragments/2147.new | 1 - .../client_server/newsfragments/2148.feature | 1 - .../client_server/newsfragments/2149.feature | 1 - .../client_server/newsfragments/2150.feature | 1 - .../client_server/newsfragments/2151.feature | 1 - .../newsfragments/2154.clarification | 1 - .../client_server/newsfragments/2158.feature | 1 - .../client_server/newsfragments/2159.feature | 1 - .../client_server/newsfragments/2164.feature | 1 - .../newsfragments/2083.clarification | 1 - .../internal/newsfragments/2081.clarification | 1 - .../internal/newsfragments/2088.clarification | 1 - .../internal/newsfragments/2115.clarification | 1 - .../internal/newsfragments/2123.clarification | 1 - .../internal/newsfragments/2137.clarification | 1 - .../newsfragments/2067.clarification | 1 - .../newsfragments/2083.clarification | 1 - .../server_server/newsfragments/2095.feature | 1 - .../newsfragments/2100.clarification | 1 - .../newsfragments/2104.clarification | 1 - .../server_server/newsfragments/2125.feature | 1 - .../newsfragments/2128.clarification | 1 - .../newsfragments/2140.clarification | 1 - config/_default/hugo.toml | 6 +- content/changelog/v1.15.md | 97 +++++++++++++++++++ 44 files changed, 100 insertions(+), 45 deletions(-) delete mode 100644 changelogs/application_service/newsfragments/2130.clarification delete mode 100644 changelogs/client_server/newsfragments/2068.clarification delete mode 100644 changelogs/client_server/newsfragments/2077.clarification delete mode 100644 changelogs/client_server/newsfragments/2083.clarification delete mode 100644 changelogs/client_server/newsfragments/2095.feature delete mode 100644 changelogs/client_server/newsfragments/2101.clarification delete mode 100644 changelogs/client_server/newsfragments/2102.clarification delete mode 100644 changelogs/client_server/newsfragments/2104.clarification delete mode 100644 changelogs/client_server/newsfragments/2106.clarification delete mode 100644 changelogs/client_server/newsfragments/2107.clarification delete mode 100644 changelogs/client_server/newsfragments/2108.clarification delete mode 100644 changelogs/client_server/newsfragments/2109.clarification delete mode 100644 changelogs/client_server/newsfragments/2121.clarification delete mode 100644 changelogs/client_server/newsfragments/2122.feature delete mode 100644 changelogs/client_server/newsfragments/2125.feature delete mode 100644 changelogs/client_server/newsfragments/2125.new delete mode 100644 changelogs/client_server/newsfragments/2140.clarification delete mode 100644 changelogs/client_server/newsfragments/2141.feature delete mode 100644 changelogs/client_server/newsfragments/2144.clarification delete mode 100644 changelogs/client_server/newsfragments/2147.new delete mode 100644 changelogs/client_server/newsfragments/2148.feature delete mode 100644 changelogs/client_server/newsfragments/2149.feature delete mode 100644 changelogs/client_server/newsfragments/2150.feature delete mode 100644 changelogs/client_server/newsfragments/2151.feature delete mode 100644 changelogs/client_server/newsfragments/2154.clarification delete mode 100644 changelogs/client_server/newsfragments/2158.feature delete mode 100644 changelogs/client_server/newsfragments/2159.feature delete mode 100644 changelogs/client_server/newsfragments/2164.feature delete mode 100644 changelogs/identity_service/newsfragments/2083.clarification delete mode 100644 changelogs/internal/newsfragments/2081.clarification delete mode 100644 changelogs/internal/newsfragments/2088.clarification delete mode 100644 changelogs/internal/newsfragments/2115.clarification delete mode 100644 changelogs/internal/newsfragments/2123.clarification delete mode 100644 changelogs/internal/newsfragments/2137.clarification delete mode 100644 changelogs/server_server/newsfragments/2067.clarification delete mode 100644 changelogs/server_server/newsfragments/2083.clarification delete mode 100644 changelogs/server_server/newsfragments/2095.feature delete mode 100644 changelogs/server_server/newsfragments/2100.clarification delete mode 100644 changelogs/server_server/newsfragments/2104.clarification delete mode 100644 changelogs/server_server/newsfragments/2125.feature delete mode 100644 changelogs/server_server/newsfragments/2128.clarification delete mode 100644 changelogs/server_server/newsfragments/2140.clarification create mode 100644 content/changelog/v1.15.md diff --git a/changelogs/application_service/newsfragments/2130.clarification b/changelogs/application_service/newsfragments/2130.clarification deleted file mode 100644 index 9cd12b4e..00000000 --- a/changelogs/application_service/newsfragments/2130.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify in the application service registration schema the `url: null` behaviour. diff --git a/changelogs/client_server/newsfragments/2068.clarification b/changelogs/client_server/newsfragments/2068.clarification deleted file mode 100644 index 1b3c13e8..00000000 --- a/changelogs/client_server/newsfragments/2068.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify behaviour when the `topic` key of a `m.room.topic` event is absent, null, or empty. diff --git a/changelogs/client_server/newsfragments/2077.clarification b/changelogs/client_server/newsfragments/2077.clarification deleted file mode 100644 index 2077d47f..00000000 --- a/changelogs/client_server/newsfragments/2077.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix the example of the `GET /sync` endpoint and the `m.room.member` example used in several places. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2083.clarification b/changelogs/client_server/newsfragments/2083.clarification deleted file mode 100644 index eb334aab..00000000 --- a/changelogs/client_server/newsfragments/2083.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. diff --git a/changelogs/client_server/newsfragments/2095.feature b/changelogs/client_server/newsfragments/2095.feature deleted file mode 100644 index 0a993bbb..00000000 --- a/changelogs/client_server/newsfragments/2095.feature +++ /dev/null @@ -1 +0,0 @@ -Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). diff --git a/changelogs/client_server/newsfragments/2101.clarification b/changelogs/client_server/newsfragments/2101.clarification deleted file mode 100644 index fa84c41c..00000000 --- a/changelogs/client_server/newsfragments/2101.clarification +++ /dev/null @@ -1 +0,0 @@ -"Public" rooms in profile look-ups are defined through their join rule and history visibility. diff --git a/changelogs/client_server/newsfragments/2102.clarification b/changelogs/client_server/newsfragments/2102.clarification deleted file mode 100644 index df9eab58..00000000 --- a/changelogs/client_server/newsfragments/2102.clarification +++ /dev/null @@ -1 +0,0 @@ -"Public" rooms in user directory queries are defined through their join rule and history visibility. diff --git a/changelogs/client_server/newsfragments/2104.clarification b/changelogs/client_server/newsfragments/2104.clarification deleted file mode 100644 index fc064c62..00000000 --- a/changelogs/client_server/newsfragments/2104.clarification +++ /dev/null @@ -1 +0,0 @@ -Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. diff --git a/changelogs/client_server/newsfragments/2106.clarification b/changelogs/client_server/newsfragments/2106.clarification deleted file mode 100644 index 8a0dd00a..00000000 --- a/changelogs/client_server/newsfragments/2106.clarification +++ /dev/null @@ -1 +0,0 @@ -"Public" rooms with respect to call invites are defined through their join rule. diff --git a/changelogs/client_server/newsfragments/2107.clarification b/changelogs/client_server/newsfragments/2107.clarification deleted file mode 100644 index 0474010e..00000000 --- a/changelogs/client_server/newsfragments/2107.clarification +++ /dev/null @@ -1 +0,0 @@ -"Public" rooms have no specific meaning with respect to moderation policy lists. diff --git a/changelogs/client_server/newsfragments/2108.clarification b/changelogs/client_server/newsfragments/2108.clarification deleted file mode 100644 index 2e8c4e59..00000000 --- a/changelogs/client_server/newsfragments/2108.clarification +++ /dev/null @@ -1 +0,0 @@ -"Public" rooms with respect to presence are defined through their join rule. diff --git a/changelogs/client_server/newsfragments/2109.clarification b/changelogs/client_server/newsfragments/2109.clarification deleted file mode 100644 index 5aa7de17..00000000 --- a/changelogs/client_server/newsfragments/2109.clarification +++ /dev/null @@ -1 +0,0 @@ -Spaces are subject to the same access mechanisms as rooms. diff --git a/changelogs/client_server/newsfragments/2121.clarification b/changelogs/client_server/newsfragments/2121.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2121.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2122.feature b/changelogs/client_server/newsfragments/2122.feature deleted file mode 100644 index 0e299bad..00000000 --- a/changelogs/client_server/newsfragments/2122.feature +++ /dev/null @@ -1 +0,0 @@ -Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147). diff --git a/changelogs/client_server/newsfragments/2125.feature b/changelogs/client_server/newsfragments/2125.feature deleted file mode 100644 index f9275b0d..00000000 --- a/changelogs/client_server/newsfragments/2125.feature +++ /dev/null @@ -1 +0,0 @@ -Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). diff --git a/changelogs/client_server/newsfragments/2125.new b/changelogs/client_server/newsfragments/2125.new deleted file mode 100644 index bc329452..00000000 --- a/changelogs/client_server/newsfragments/2125.new +++ /dev/null @@ -1 +0,0 @@ -Add `GET /_matrix/client/v1/room_summary/{roomIdOrAlias}`, as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/2140.clarification b/changelogs/client_server/newsfragments/2140.clarification deleted file mode 100644 index 4a151fe8..00000000 --- a/changelogs/client_server/newsfragments/2140.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. diff --git a/changelogs/client_server/newsfragments/2141.feature b/changelogs/client_server/newsfragments/2141.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2141.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/client_server/newsfragments/2144.clarification b/changelogs/client_server/newsfragments/2144.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/client_server/newsfragments/2144.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/2147.new b/changelogs/client_server/newsfragments/2147.new deleted file mode 100644 index c72bf35e..00000000 --- a/changelogs/client_server/newsfragments/2147.new +++ /dev/null @@ -1 +0,0 @@ -Add `GET /_matrix/client/v1/auth_metadata`, as per [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965). diff --git a/changelogs/client_server/newsfragments/2148.feature b/changelogs/client_server/newsfragments/2148.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2148.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/client_server/newsfragments/2149.feature b/changelogs/client_server/newsfragments/2149.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2149.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/client_server/newsfragments/2150.feature b/changelogs/client_server/newsfragments/2150.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2150.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/client_server/newsfragments/2151.feature b/changelogs/client_server/newsfragments/2151.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2151.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/client_server/newsfragments/2154.clarification b/changelogs/client_server/newsfragments/2154.clarification deleted file mode 100644 index 660e41b5..00000000 --- a/changelogs/client_server/newsfragments/2154.clarification +++ /dev/null @@ -1 +0,0 @@ -Add missing fields in example for `ExportedSessionData`. diff --git a/changelogs/client_server/newsfragments/2158.feature b/changelogs/client_server/newsfragments/2158.feature deleted file mode 100644 index f9275b0d..00000000 --- a/changelogs/client_server/newsfragments/2158.feature +++ /dev/null @@ -1 +0,0 @@ -Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). diff --git a/changelogs/client_server/newsfragments/2159.feature b/changelogs/client_server/newsfragments/2159.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2159.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/client_server/newsfragments/2164.feature b/changelogs/client_server/newsfragments/2164.feature deleted file mode 100644 index 6eff5607..00000000 --- a/changelogs/client_server/newsfragments/2164.feature +++ /dev/null @@ -1 +0,0 @@ -Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. diff --git a/changelogs/identity_service/newsfragments/2083.clarification b/changelogs/identity_service/newsfragments/2083.clarification deleted file mode 100644 index 7e5575c9..00000000 --- a/changelogs/identity_service/newsfragments/2083.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that public keys can be encoded using standard or URL-safe base64. diff --git a/changelogs/internal/newsfragments/2081.clarification b/changelogs/internal/newsfragments/2081.clarification deleted file mode 100644 index a4923694..00000000 --- a/changelogs/internal/newsfragments/2081.clarification +++ /dev/null @@ -1 +0,0 @@ -Adjust margins in rendered endpoints. diff --git a/changelogs/internal/newsfragments/2088.clarification b/changelogs/internal/newsfragments/2088.clarification deleted file mode 100644 index a0e53726..00000000 --- a/changelogs/internal/newsfragments/2088.clarification +++ /dev/null @@ -1 +0,0 @@ -Replace Hugo shortcodes in OpenAPI output. diff --git a/changelogs/internal/newsfragments/2115.clarification b/changelogs/internal/newsfragments/2115.clarification deleted file mode 100644 index 3deaf8c8..00000000 --- a/changelogs/internal/newsfragments/2115.clarification +++ /dev/null @@ -1 +0,0 @@ -Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks. diff --git a/changelogs/internal/newsfragments/2123.clarification b/changelogs/internal/newsfragments/2123.clarification deleted file mode 100644 index af26abaf..00000000 --- a/changelogs/internal/newsfragments/2123.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix the historical info box when generating the historical spec in CI. diff --git a/changelogs/internal/newsfragments/2137.clarification b/changelogs/internal/newsfragments/2137.clarification deleted file mode 100644 index 6503f22b..00000000 --- a/changelogs/internal/newsfragments/2137.clarification +++ /dev/null @@ -1 +0,0 @@ -Update the header navigation menu with links to modern matrix.org. Contributed by @HarHarLinks. diff --git a/changelogs/server_server/newsfragments/2067.clarification b/changelogs/server_server/newsfragments/2067.clarification deleted file mode 100644 index 4bd8176b..00000000 --- a/changelogs/server_server/newsfragments/2067.clarification +++ /dev/null @@ -1 +0,0 @@ -Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/2083.clarification b/changelogs/server_server/newsfragments/2083.clarification deleted file mode 100644 index eb334aab..00000000 --- a/changelogs/server_server/newsfragments/2083.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. diff --git a/changelogs/server_server/newsfragments/2095.feature b/changelogs/server_server/newsfragments/2095.feature deleted file mode 100644 index 0a993bbb..00000000 --- a/changelogs/server_server/newsfragments/2095.feature +++ /dev/null @@ -1 +0,0 @@ -Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). diff --git a/changelogs/server_server/newsfragments/2100.clarification b/changelogs/server_server/newsfragments/2100.clarification deleted file mode 100644 index a488b392..00000000 --- a/changelogs/server_server/newsfragments/2100.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that auth event of `content.join_authorised_via_users_server` is only necessary for `m.room.member` with a `membership` of `join`. diff --git a/changelogs/server_server/newsfragments/2104.clarification b/changelogs/server_server/newsfragments/2104.clarification deleted file mode 100644 index fc064c62..00000000 --- a/changelogs/server_server/newsfragments/2104.clarification +++ /dev/null @@ -1 +0,0 @@ -Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. diff --git a/changelogs/server_server/newsfragments/2125.feature b/changelogs/server_server/newsfragments/2125.feature deleted file mode 100644 index 0a369ea0..00000000 --- a/changelogs/server_server/newsfragments/2125.feature +++ /dev/null @@ -1 +0,0 @@ -Extend `/_matrix/federation/v1/hierarchy/{roomId}` with the new optional properties `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). diff --git a/changelogs/server_server/newsfragments/2128.clarification b/changelogs/server_server/newsfragments/2128.clarification deleted file mode 100644 index 3ccb2333..00000000 --- a/changelogs/server_server/newsfragments/2128.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various typos throughout the specification. diff --git a/changelogs/server_server/newsfragments/2140.clarification b/changelogs/server_server/newsfragments/2140.clarification deleted file mode 100644 index 4a151fe8..00000000 --- a/changelogs/server_server/newsfragments/2140.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index b31416c2..f4441833 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -61,13 +61,13 @@ copyright = "The Matrix.org Foundation CIC" [params.version] # must be one of "unstable", "current", "historical" # this is used to decide whether to show a banner pointing to the current release -status = "unstable" +status = "stable" # A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner. current_version_url = "https://spec.matrix.org/latest" # The following is used when status = "stable", and is displayed in various UI elements on a released version # of the spec. -# major = "1" -# minor = "14" +major = "1" +minor = "15" # User interface configuration [params.ui] diff --git a/content/changelog/v1.15.md b/content/changelog/v1.15.md new file mode 100644 index 00000000..e6f8f243 --- /dev/null +++ b/content/changelog/v1.15.md @@ -0,0 +1,97 @@ +--- +title: v1.15 Changelog +linkTitle: v1.15 +type: docs +layout: changelog +outputs: + - html + - checklist +date: 2025-06-26 +--- + +## Client-Server API + +**New Endpoints** + +- Add `GET /_matrix/client/v1/room_summary/{roomIdOrAlias}`, as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125)) +- Add `GET /_matrix/client/v1/auth_metadata`, as per [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965). ([#2147](https://github.com/matrix-org/matrix-spec/issues/2147)) + +**Backwards Compatible Changes** + +- Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). ([#2095](https://github.com/matrix-org/matrix-spec/issues/2095)) +- Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147). ([#2122](https://github.com/matrix-org/matrix-spec/issues/2122)) +- Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125), [#2158](https://github.com/matrix-org/matrix-spec/issues/2158)) +- Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. ([#2141](https://github.com/matrix-org/matrix-spec/issues/2141), [#2148](https://github.com/matrix-org/matrix-spec/issues/2148), [#2149](https://github.com/matrix-org/matrix-spec/issues/2149), [#2150](https://github.com/matrix-org/matrix-spec/issues/2150), [#2151](https://github.com/matrix-org/matrix-spec/issues/2151), [#2159](https://github.com/matrix-org/matrix-spec/issues/2159), [#2164](https://github.com/matrix-org/matrix-spec/issues/2164)) + +**Spec Clarifications** + +- Clarify behaviour when the `topic` key of a `m.room.topic` event is absent, null, or empty. ([#2068](https://github.com/matrix-org/matrix-spec/issues/2068)) +- Fix the example of the `GET /sync` endpoint and the `m.room.member` example used in several places. ([#2077](https://github.com/matrix-org/matrix-spec/issues/2077)) +- Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083)) +- "Public" rooms in profile look-ups are defined through their join rule and history visibility. ([#2101](https://github.com/matrix-org/matrix-spec/issues/2101)) +- "Public" rooms in user directory queries are defined through their join rule and history visibility. ([#2102](https://github.com/matrix-org/matrix-spec/issues/2102)) +- Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. ([#2104](https://github.com/matrix-org/matrix-spec/issues/2104)) +- "Public" rooms with respect to call invites are defined through their join rule. ([#2106](https://github.com/matrix-org/matrix-spec/issues/2106)) +- "Public" rooms have no specific meaning with respect to moderation policy lists. ([#2107](https://github.com/matrix-org/matrix-spec/issues/2107)) +- "Public" rooms with respect to presence are defined through their join rule. ([#2108](https://github.com/matrix-org/matrix-spec/issues/2108)) +- Spaces are subject to the same access mechanisms as rooms. ([#2109](https://github.com/matrix-org/matrix-spec/issues/2109)) +- Fix various typos throughout the specification. ([#2121](https://github.com/matrix-org/matrix-spec/issues/2121), [#2144](https://github.com/matrix-org/matrix-spec/issues/2144)) +- Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. ([#2140](https://github.com/matrix-org/matrix-spec/issues/2140)) +- Add missing fields in example for `ExportedSessionData`. ([#2154](https://github.com/matrix-org/matrix-spec/issues/2154)) + + +## Server-Server API + +**Backwards Compatible Changes** + +- Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). ([#2095](https://github.com/matrix-org/matrix-spec/issues/2095)) +- Extend `/_matrix/federation/v1/hierarchy/{roomId}` with the new optional properties `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125)) + +**Spec Clarifications** + +- Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room. ([#2067](https://github.com/matrix-org/matrix-spec/issues/2067)) +- Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083)) +- Clarify that auth event of `content.join_authorised_via_users_server` is only necessary for `m.room.member` with a `membership` of `join`. ([#2100](https://github.com/matrix-org/matrix-spec/issues/2100)) +- Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. ([#2104](https://github.com/matrix-org/matrix-spec/issues/2104)) +- Fix various typos throughout the specification. ([#2128](https://github.com/matrix-org/matrix-spec/issues/2128)) +- Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. ([#2140](https://github.com/matrix-org/matrix-spec/issues/2140)) + + +## Application Service API + +**Spec Clarifications** + +- Clarify in the application service registration schema the `url: null` behaviour. ([#2130](https://github.com/matrix-org/matrix-spec/issues/2130)) + + +## Identity Service API + +**Spec Clarifications** + +- Clarify that public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083)) + + +## Push Gateway API + +No significant changes. + + +## Room Versions + +No significant changes. + + +## Appendices + +No significant changes. + + +## Internal Changes/Tooling + +**Spec Clarifications** + +- Adjust margins in rendered endpoints. ([#2081](https://github.com/matrix-org/matrix-spec/issues/2081)) +- Replace Hugo shortcodes in OpenAPI output. ([#2088](https://github.com/matrix-org/matrix-spec/issues/2088)) +- Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks. ([#2115](https://github.com/matrix-org/matrix-spec/issues/2115)) +- Fix the historical info box when generating the historical spec in CI. ([#2123](https://github.com/matrix-org/matrix-spec/issues/2123)) +- Update the header navigation menu with links to modern matrix.org. Contributed by @HarHarLinks. ([#2137](https://github.com/matrix-org/matrix-spec/issues/2137)) From 6edb6ba1cdbcc807ac0f9c94929fc79984c02b3d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 26 Jun 2025 10:48:27 -0600 Subject: [PATCH 58/67] become unstable --- config/_default/hugo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/_default/hugo.toml b/config/_default/hugo.toml index f4441833..abec3958 100644 --- a/config/_default/hugo.toml +++ b/config/_default/hugo.toml @@ -61,13 +61,13 @@ copyright = "The Matrix.org Foundation CIC" [params.version] # must be one of "unstable", "current", "historical" # this is used to decide whether to show a banner pointing to the current release -status = "stable" +status = "unstable" # A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner. current_version_url = "https://spec.matrix.org/latest" # The following is used when status = "stable", and is displayed in various UI elements on a released version # of the spec. -major = "1" -minor = "15" +# major = "1" +# minor = "15" # User interface configuration [params.ui] From 484a77757204c220ad1a46c94f3b6a434818d62c Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 2 Jul 2025 12:20:48 +0200 Subject: [PATCH 59/67] Fix typo (#2171) Signed-off-by: Johannes Marbach --- changelogs/client_server/newsfragments/2171.clarification | 1 + content/client-server-api/modules/event_replacements.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2171.clarification diff --git a/changelogs/client_server/newsfragments/2171.clarification b/changelogs/client_server/newsfragments/2171.clarification new file mode 100644 index 00000000..3ccb2333 --- /dev/null +++ b/changelogs/client_server/newsfragments/2171.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/content/client-server-api/modules/event_replacements.md b/content/client-server-api/modules/event_replacements.md index 90c67ecf..c4563a88 100644 --- a/content/client-server-api/modules/event_replacements.md +++ b/content/client-server-api/modules/event_replacements.md @@ -364,7 +364,7 @@ property under `m.new_content`. A particular constraint applies to events which replace a [reply](#rich-replies): in contrast to the original reply, there should be no `m.in_reply_to` property -in the the `m.relates_to` object, since it would be redundant (see +in the `m.relates_to` object, since it would be redundant (see [Applying `m.new_content`](#applying-mnew_content) above, which notes that the original event's `m.relates_to` is preserved), as well as being contrary to the spirit of the event relationships mechanism which expects only one "parent" per From 625ed5c599a9e190aad42c110d14bb7507ec388b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 10 Jul 2025 10:30:56 -0600 Subject: [PATCH 60/67] Define some process for placeholder MSCs (#2157) * Define some process for placeholder MSCs * changelog * Clarity + adjust to use dedicated labels * add contact details * Clarify that closure may be later --- .../internal/newsfragments/2157.feature | 1 + content/proposals.md | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 changelogs/internal/newsfragments/2157.feature diff --git a/changelogs/internal/newsfragments/2157.feature b/changelogs/internal/newsfragments/2157.feature new file mode 100644 index 00000000..58571d8c --- /dev/null +++ b/changelogs/internal/newsfragments/2157.feature @@ -0,0 +1 @@ +Add "placeholder MSC" process definition. \ No newline at end of file diff --git a/content/proposals.md b/content/proposals.md index d0d99bae..0b2c4a16 100644 --- a/content/proposals.md +++ b/content/proposals.md @@ -497,6 +497,42 @@ In summary: a small table at the bottom mapping the various values from stable to unstable. +### Placeholder MSCs + +Some proposals may contain security-sensitive or private context which can't be +publicly disclosed until a later stage in the idea or solution process. Typically, +the initial idea is validated using some amount of implementation or experimentation +and may require an MSC number to make that implementation easier. + +Placeholder MSCs are used to represent proposals in a state where implementation +is ongoing, but the MSC details can't yet be disclosed. Authors which feel as +though their MSC could be highly sensitive MUST get in contact with the Spec Core +Team or [Security Team](https://matrix.org/security-disclosure-policy/) prior to +opening their MSC. If either team determines that a placeholder MSC is required, +it may be opened as such. + +There are a few expectations attached to placeholder MSCs: + +* They have a title which marks them WIP, and are in the "draft" state. +* They have the following labels: `[proposal-placeholder, action-required, needs-implementation]`. + * Notably, *not* `proposal`. +* They are relatively short-lived (ideally less than 6-12 months in placeholder). +* They propose solutions which are reasonably likely to be accepted. If a placeholder + needs to be closed because the idea won't work, isn't needed, etc, then the MSC's + content MUST be published ahead of that closure. + * Note: the MSC's publication (and therefore closure) may be delayed until an + appropriate point in the security disclosure cycle. For example, an alternative + MSC being published, or a stream of work being completed. +* When they are updated to receive real content, the following happens: + 1. The Spec Core Team or the author leaves a comment to cause a notification + that the MSC has been replaced with real content. + 2. The `proposal` label (or its equivalent) is added to trigger chat notifications + in the public Matrix rooms. The `proposal-placeholder` and `action-required` + labels should be removed at this stage as well. Other labels are removed/applied + per normal process. +* The Spec Core Team is aware of the intended MSC's title and purpose. This is + especially important if the Security Team approved the use of a placeholder MSC. + ## Proposal Tracking This is a living document generated from the list of proposals on the From 0e280ed014adcd61507e645a80c2849d5a9ebaa5 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 14 Jul 2025 13:09:08 +0200 Subject: [PATCH 61/67] Fix typo (#2177) Signed-off-by: Johannes Marbach --- changelogs/client_server/newsfragments/2177.clarification | 1 + data/api/client-server/logout.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2177.clarification diff --git a/changelogs/client_server/newsfragments/2177.clarification b/changelogs/client_server/newsfragments/2177.clarification new file mode 100644 index 00000000..3ccb2333 --- /dev/null +++ b/changelogs/client_server/newsfragments/2177.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/data/api/client-server/logout.yaml b/data/api/client-server/logout.yaml index 60464932..0a555efc 100644 --- a/data/api/client-server/logout.yaml +++ b/data/api/client-server/logout.yaml @@ -47,7 +47,7 @@ paths: deleted alongside the device. This endpoint does not use the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api) because - User-Interactive Authentication is designed to protect against attacks where the + User-Interactive Authentication is designed to protect against attacks where someone gets hold of a single access token then takes over the account. This endpoint invalidates all access tokens for the user, including the token used in the request, and therefore the attacker is unable to take over the account in From 3877598b1e7b9d2c93b447b6a2bdfc423e4c089a Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 15 Jul 2025 10:47:50 +0200 Subject: [PATCH 62/67] Clarify that format is required if formatted_body is specified (#2167) Signed-off-by: Johannes Marbach --- changelogs/client_server/newsfragments/2167.clarification | 1 + data/event-schemas/schema/m.room.message$m.audio.yaml | 4 ++-- data/event-schemas/schema/m.room.message$m.emote.yaml | 4 ++-- data/event-schemas/schema/m.room.message$m.file.yaml | 4 ++-- data/event-schemas/schema/m.room.message$m.image.yaml | 4 ++-- .../schema/m.room.message$m.key.verification.request.yaml | 4 ++-- data/event-schemas/schema/m.room.message$m.notice.yaml | 4 ++-- data/event-schemas/schema/m.room.message$m.text.yaml | 4 ++-- data/event-schemas/schema/m.room.message$m.video.yaml | 4 ++-- 9 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2167.clarification diff --git a/changelogs/client_server/newsfragments/2167.clarification b/changelogs/client_server/newsfragments/2167.clarification new file mode 100644 index 00000000..99805f73 --- /dev/null +++ b/changelogs/client_server/newsfragments/2167.clarification @@ -0,0 +1 @@ +Clarify that `format` is required if `formatted_body` is specified. diff --git a/data/event-schemas/schema/m.room.message$m.audio.yaml b/data/event-schemas/schema/m.room.message$m.audio.yaml index 825419bd..6bb23c31 100644 --- a/data/event-schemas/schema/m.room.message$m.audio.yaml +++ b/data/event-schemas/schema/m.room.message$m.audio.yaml @@ -15,8 +15,8 @@ properties: "1.10": This property can act as a caption for the audio. format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string x-addedInMatrixVersion: "1.10" formatted_body: diff --git a/data/event-schemas/schema/m.room.message$m.emote.yaml b/data/event-schemas/schema/m.room.message$m.emote.yaml index 43e2639d..b611b888 100644 --- a/data/event-schemas/schema/m.room.message$m.emote.yaml +++ b/data/event-schemas/schema/m.room.message$m.emote.yaml @@ -14,8 +14,8 @@ properties: type: string format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string formatted_body: description: |- diff --git a/data/event-schemas/schema/m.room.message$m.file.yaml b/data/event-schemas/schema/m.room.message$m.file.yaml index 8e269366..65a7b3d6 100644 --- a/data/event-schemas/schema/m.room.message$m.file.yaml +++ b/data/event-schemas/schema/m.room.message$m.file.yaml @@ -15,8 +15,8 @@ properties: "1.10": This property can act as a caption for the file. format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string x-addedInMatrixVersion: "1.10" formatted_body: diff --git a/data/event-schemas/schema/m.room.message$m.image.yaml b/data/event-schemas/schema/m.room.message$m.image.yaml index 15bdeda4..9017b945 100644 --- a/data/event-schemas/schema/m.room.message$m.image.yaml +++ b/data/event-schemas/schema/m.room.message$m.image.yaml @@ -15,8 +15,8 @@ properties: "1.10": This property can act as a caption for the image. format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string x-addedInMatrixVersion: "1.10" formatted_body: diff --git a/data/event-schemas/schema/m.room.message$m.key.verification.request.yaml b/data/event-schemas/schema/m.room.message$m.key.verification.request.yaml index 43882ab9..a773ebda 100644 --- a/data/event-schemas/schema/m.room.message$m.key.verification.request.yaml +++ b/data/event-schemas/schema/m.room.message$m.key.verification.request.yaml @@ -22,8 +22,8 @@ properties: verification. format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string formatted_body: description: |- diff --git a/data/event-schemas/schema/m.room.message$m.notice.yaml b/data/event-schemas/schema/m.room.message$m.notice.yaml index 7b735d60..8c59149c 100644 --- a/data/event-schemas/schema/m.room.message$m.notice.yaml +++ b/data/event-schemas/schema/m.room.message$m.notice.yaml @@ -14,8 +14,8 @@ properties: type: string format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string formatted_body: description: |- diff --git a/data/event-schemas/schema/m.room.message$m.text.yaml b/data/event-schemas/schema/m.room.message$m.text.yaml index 4cba2bd6..7171b82a 100644 --- a/data/event-schemas/schema/m.room.message$m.text.yaml +++ b/data/event-schemas/schema/m.room.message$m.text.yaml @@ -14,8 +14,8 @@ properties: type: string format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string formatted_body: description: |- diff --git a/data/event-schemas/schema/m.room.message$m.video.yaml b/data/event-schemas/schema/m.room.message$m.video.yaml index 75752534..325c231a 100644 --- a/data/event-schemas/schema/m.room.message$m.video.yaml +++ b/data/event-schemas/schema/m.room.message$m.video.yaml @@ -15,8 +15,8 @@ properties: "1.10": This property can act as a caption for the video. format: description: |- - The format used in the `formatted_body`. Currently only - `org.matrix.custom.html` is supported. + The format used in the `formatted_body`. This is required if `formatted_body` + is specified. Currently only `org.matrix.custom.html` is supported. type: string x-addedInMatrixVersion: "1.10" formatted_body: From c8380d95529ce2a16967968d2ccdb9a2066e4111 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 19 Jul 2025 22:52:41 +0300 Subject: [PATCH 63/67] Add `format` query parameter to `GET /state/{eventType}/{stateKey}` (#2175) --- .../client_server/newsfragments/2175.feature | 1 + data/api/client-server/rooms.yaml | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 changelogs/client_server/newsfragments/2175.feature diff --git a/changelogs/client_server/newsfragments/2175.feature b/changelogs/client_server/newsfragments/2175.feature new file mode 100644 index 00000000..ddd71d27 --- /dev/null +++ b/changelogs/client_server/newsfragments/2175.feature @@ -0,0 +1 @@ +Add `format` query parameter to `GET /state/{eventType}/{stateKey}` to allow fetching metadata of a specific state event. diff --git a/data/api/client-server/rooms.yaml b/data/api/client-server/rooms.yaml index a2197f34..a5c9977e 100644 --- a/data/api/client-server/rooms.yaml +++ b/data/api/client-server/rooms.yaml @@ -105,13 +105,31 @@ paths: example: "" schema: type: string + - in: query + name: format + x-addedInMatrixVersion: "1.16" + description: |- + The format to use for the returned data. `content` (the default) will + return only the content of the state event. `event` will return the entire + event in the usual format suitable for clients, including fields like event + ID, sender and timestamp. + example: event + schema: + type: string + enum: + - content + - event responses: "200": - description: The content of the state event. + description: |- + The content of the state event, or the entire client-formatted event + if `?format=event` was used. content: application/json: schema: - type: object + oneOf: + - type: object + - $ref: "../../event-schemas/schema/core-event-schema/state_event.yaml" examples: response: value: { From 3e1e9fa8df8780e08d24ccd6213b9d0cc0591d67 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 21 Jul 2025 13:35:59 +0200 Subject: [PATCH 64/67] Fix typo (#2179) Signed-off-by: Johannes Marbach --- changelogs/client_server/newsfragments/2179.clarification | 1 + content/client-server-api/modules/end_to_end_encryption.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2179.clarification diff --git a/changelogs/client_server/newsfragments/2179.clarification b/changelogs/client_server/newsfragments/2179.clarification new file mode 100644 index 00000000..3ccb2333 --- /dev/null +++ b/changelogs/client_server/newsfragments/2179.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/content/client-server-api/modules/end_to_end_encryption.md b/content/client-server-api/modules/end_to_end_encryption.md index 2c275089..c06178d7 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -1124,7 +1124,7 @@ The process between Alice and Bob verifying each other would be: framework as described above. 3. Alice's client displays a QR code that Bob is able to scan if Bob's client indicated the ability to scan, an option to scan Bob's QR code if her client - is able to scan. Bob's client prompts displays a QR code that Alice can + is able to scan. Bob's client displays a QR code that Alice can scan if Alice's client indicated the ability to scan, and an option to scan Alice's QR code if his client is able to scan. The format for the QR code is described below. Other options, like starting SAS Emoji verification, From 4c87e0e745d1943e2d97035c53447f301c37ee99 Mon Sep 17 00:00:00 2001 From: Pierre 'McFly' Marty Date: Tue, 22 Jul 2025 08:13:51 -0600 Subject: [PATCH 65/67] ci(build-openapi): indentity routes were missing (#2172) --- .github/workflows/main.yml | 5 +++++ changelogs/internal/newsfragments/2172.clarification | 1 + 2 files changed, 6 insertions(+) create mode 100644 changelogs/internal/newsfragments/2172.clarification diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 446aca9c..cdaf0431 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -155,6 +155,11 @@ jobs: --api server-server \ -r "$RELEASE" \ -o spec/server-server-api/api.json + scripts/dump-openapi.py \ + --base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \ + --api identity \ + -r "$RELEASE" \ + -o spec/identity-service-api/api.json tar -czf openapi.tar.gz spec - name: "📤 Artifact upload" uses: actions/upload-artifact@v4 diff --git a/changelogs/internal/newsfragments/2172.clarification b/changelogs/internal/newsfragments/2172.clarification new file mode 100644 index 00000000..53f01c68 --- /dev/null +++ b/changelogs/internal/newsfragments/2172.clarification @@ -0,0 +1 @@ +GitHub actions are now building the OpenAPI `spec/identity-service-api/api.json` file. From fb4a0d8f66fb6263786ab7c4de3ef21517fcc64c Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 22 Jul 2025 16:23:28 +0200 Subject: [PATCH 66/67] Clarify that the `latest_event` field is serialized in the same form as the event itself (#2169) --- changelogs/client_server/newsfragments/2169.clarification | 1 + content/client-server-api/modules/threading.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelogs/client_server/newsfragments/2169.clarification diff --git a/changelogs/client_server/newsfragments/2169.clarification b/changelogs/client_server/newsfragments/2169.clarification new file mode 100644 index 00000000..49648401 --- /dev/null +++ b/changelogs/client_server/newsfragments/2169.clarification @@ -0,0 +1 @@ +The `latest_event` in an aggregated set of thread events uses the same format as the event itself. diff --git a/content/client-server-api/modules/threading.md b/content/client-server-api/modules/threading.md index 5fedbcf8..9f87920a 100644 --- a/content/client-server-api/modules/threading.md +++ b/content/client-server-api/modules/threading.md @@ -185,7 +185,7 @@ included under the `m.relations` property in `unsigned` for the thread root. For ``` `latest_event` is the most recent event (topologically to the server) in the thread sent by an -un-[ignored user](#ignoring-users). +un-[ignored user](#ignoring-users). It should be serialized in the same form as the event itself. Note that, as in the example above, child events of the `latest_event` should themselves be aggregated and included under `m.relations` for that event. The From 7d2de48cb4774db60c63bc339daf089dd09387cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= <76261501+zecakeh@users.noreply.github.com> Date: Tue, 29 Jul 2025 19:22:26 +0200 Subject: [PATCH 67/67] Fix new redocly lints (#2182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kévin Commaille Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- .../newsfragments/2182.clarification | 1 + .../newsfragments/2182.clarification | 1 + .../definitions/protocol.yaml | 1 + .../definitions/protocol_base.yaml | 2 +- .../client-server/definitions/protocol.yaml | 3 +- .../definitions/room_summary.yaml | 6 --- data/api/client-server/room_summary.yaml | 5 --- .../schema/core-event-schema/room_event.yaml | 22 +++++----- .../core-event-schema/sync_room_event.yaml | 44 +++++++++---------- .../core-event-schema/sync_state_event.yaml | 30 ++++++------- 10 files changed, 54 insertions(+), 61 deletions(-) create mode 100644 changelogs/application_service/newsfragments/2182.clarification create mode 100644 changelogs/client_server/newsfragments/2182.clarification diff --git a/changelogs/application_service/newsfragments/2182.clarification b/changelogs/application_service/newsfragments/2182.clarification new file mode 100644 index 00000000..82426693 --- /dev/null +++ b/changelogs/application_service/newsfragments/2182.clarification @@ -0,0 +1 @@ +Minor fixes to JSON schemas. diff --git a/changelogs/client_server/newsfragments/2182.clarification b/changelogs/client_server/newsfragments/2182.clarification new file mode 100644 index 00000000..82426693 --- /dev/null +++ b/changelogs/client_server/newsfragments/2182.clarification @@ -0,0 +1 @@ +Minor fixes to JSON schemas. diff --git a/data/api/application-service/definitions/protocol.yaml b/data/api/application-service/definitions/protocol.yaml index eb56ab26..a91045b9 100644 --- a/data/api/application-service/definitions/protocol.yaml +++ b/data/api/application-service/definitions/protocol.yaml @@ -23,3 +23,4 @@ allOf: type: array items: $ref: protocol_instance.yaml + required: ['instances'] diff --git a/data/api/application-service/definitions/protocol_base.yaml b/data/api/application-service/definitions/protocol_base.yaml index 0238104f..d90f9848 100644 --- a/data/api/application-service/definitions/protocol_base.yaml +++ b/data/api/application-service/definitions/protocol_base.yaml @@ -77,4 +77,4 @@ properties: "placeholder": "#foobar" } } -required: ['user_fields', 'location_fields', 'icon', 'field_types', 'instances'] +required: ['user_fields', 'location_fields', 'icon', 'field_types'] diff --git a/data/api/client-server/definitions/protocol.yaml b/data/api/client-server/definitions/protocol.yaml index 96db7736..8ffdb6b6 100644 --- a/data/api/client-server/definitions/protocol.yaml +++ b/data/api/client-server/definitions/protocol.yaml @@ -37,7 +37,8 @@ allOf: A unique identifier for this instance on the homeserver. This field is added to the response of [`GET /_matrix/app/v1/thirdparty/protocol/{protocol}`](/application-service-api/#get_matrixappv1thirdpartyprotocolprotocol) by the homeserver. - + This is the identifier to use as the `third_party_instance_id` in a request to [`POST /_matrix/client/v3/publicRooms`](/client-server-api/#post_matrixclientv3publicrooms). example: "irc-freenode" + required: ['instances'] diff --git a/data/api/client-server/definitions/room_summary.yaml b/data/api/client-server/definitions/room_summary.yaml index 8499bac1..cdcfb7cd 100644 --- a/data/api/client-server/definitions/room_summary.yaml +++ b/data/api/client-server/definitions/room_summary.yaml @@ -42,9 +42,3 @@ allOf: room_version: description: The version of the room. type: string - -required: - - room_id - - num_joined_members - - world_readable - - guest_can_join diff --git a/data/api/client-server/room_summary.yaml b/data/api/client-server/room_summary.yaml index e5e241ed..e8ee3c8e 100644 --- a/data/api/client-server/room_summary.yaml +++ b/data/api/client-server/room_summary.yaml @@ -89,11 +89,6 @@ paths: - leave - ban type: string - required: - - guest_can_join - - num_joined_members - - room_id - - world_readable examples: response: value: { diff --git a/data/event-schemas/schema/core-event-schema/room_event.yaml b/data/event-schemas/schema/core-event-schema/room_event.yaml index 7eaae223..917031f9 100644 --- a/data/event-schemas/schema/core-event-schema/room_event.yaml +++ b/data/event-schemas/schema/core-event-schema/room_event.yaml @@ -1,13 +1,13 @@ +title: RoomEvent +description: Room Events have the following fields. allOf: - $ref: sync_room_event.yaml -description: Room Events have the following fields. -properties: - room_id: - description: |- - The ID of the room associated with this event. Will not be present on events - that arrive through `/sync`, despite being required everywhere else. - type: string -required: -- room_id -title: RoomEvent -type: object +- type: object + properties: + room_id: + description: |- + The ID of the room associated with this event. Will not be present on events + that arrive through `/sync`, despite being required everywhere else. + type: string + required: + - room_id diff --git a/data/event-schemas/schema/core-event-schema/sync_room_event.yaml b/data/event-schemas/schema/core-event-schema/sync_room_event.yaml index 7ad7191b..c1ac84d9 100644 --- a/data/event-schemas/schema/core-event-schema/sync_room_event.yaml +++ b/data/event-schemas/schema/core-event-schema/sync_room_event.yaml @@ -17,27 +17,27 @@ # be on events, so we give it a whole event structure as a base for room_event. # This base doesn't declare a room_id, which instead appears in the room_event. -allOf: -- $ref: event.yaml +title: SyncRoomEvent description: In addition to the Event fields, Room Events have the following additional fields. -properties: - event_id: - description: The globally unique event identifier. - type: string - sender: - description: Contains the fully-qualified ID of the user who sent this event. - type: string - origin_server_ts: - description: Timestamp in milliseconds on originating homeserver - when this event was sent. - type: integer - format: int64 - unsigned: - $ref: unsigned_prop.yaml -required: -- event_id -- sender -- origin_server_ts -title: SyncRoomEvent -type: object +allOf: +- $ref: event.yaml +- type: object + properties: + event_id: + description: The globally unique event identifier. + type: string + sender: + description: Contains the fully-qualified ID of the user who sent this event. + type: string + origin_server_ts: + description: Timestamp in milliseconds on originating homeserver + when this event was sent. + type: integer + format: int64 + unsigned: + $ref: unsigned_prop.yaml + required: + - event_id + - sender + - origin_server_ts diff --git a/data/event-schemas/schema/core-event-schema/sync_state_event.yaml b/data/event-schemas/schema/core-event-schema/sync_state_event.yaml index 7033a5e6..6d43c322 100644 --- a/data/event-schemas/schema/core-event-schema/sync_state_event.yaml +++ b/data/event-schemas/schema/core-event-schema/sync_state_event.yaml @@ -14,21 +14,21 @@ # See sync_room_event.yaml for why this file is here. -allOf: -- $ref: sync_room_event.yaml +title: SyncStateEvent description: In addition to the Room Event fields, State Events have the following additional fields. -properties: - state_key: - description: A unique key which defines the overwriting semantics for this piece - of room state. This value is often a zero-length string. The presence of this - key makes this event a State Event. +allOf: +- $ref: sync_room_event.yaml +- type: object + properties: + state_key: + description: A unique key which defines the overwriting semantics for this piece + of room state. This value is often a zero-length string. The presence of this + key makes this event a State Event. - State keys starting with an `@` are reserved for referencing user IDs, such - as room members. With the exception of a few events, state events set with a - given user's ID as the state key MUST only be set by that user. - type: string -required: -- state_key -title: SyncStateEvent -type: object + State keys starting with an `@` are reserved for referencing user IDs, such + as room members. With the exception of a few events, state events set with a + given user's ID as the state key MUST only be set by that user. + type: string + required: + - state_key