From 09a768763d89365308152168095be862b246efcc Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Sat, 14 Jan 2017 19:09:23 +0200 Subject: [PATCH 001/219] Add missing enum fields for the set_presence parameter Signed-off-by: Konstantinos Sideris --- api/client-server/sync.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/client-server/sync.yaml b/api/client-server/sync.yaml index 66f7d935b..b7965da93 100644 --- a/api/client-server/sync.yaml +++ b/api/client-server/sync.yaml @@ -76,7 +76,7 @@ paths: - in: query name: set_presence type: string - enum: ["offline"] + enum: ["offline", "online", "unavailable"] description: |- Controls whether the client is automatically marked as online by polling this API. If this parameter is omitted then the client is From 1e656d836ead371bb395a768e35173a6cf41f5ea Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 15 Apr 2018 22:35:44 +0100 Subject: [PATCH 002/219] spec notifications key on power level event and provide @room in example --- event-schemas/examples/m.room.power_levels | 5 ++++- event-schemas/schema/m.room.power_levels | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/event-schemas/examples/m.room.power_levels b/event-schemas/examples/m.room.power_levels index 0c8f8bc53..2b0aaca55 100644 --- a/event-schemas/examples/m.room.power_levels +++ b/event-schemas/examples/m.room.power_levels @@ -14,7 +14,10 @@ "users": { "@example:localhost": 100 }, - "users_default": 0 + "users_default": 0, + "notifications": { + "room": 20 + } }, "state_key": "", "origin_server_ts": 1431961217939, diff --git a/event-schemas/schema/m.room.power_levels b/event-schemas/schema/m.room.power_levels index 13a44c709..f348b52d0 100644 --- a/event-schemas/schema/m.room.power_levels +++ b/event-schemas/schema/m.room.power_levels @@ -85,6 +85,14 @@ properties: ``user_id`` is mentioned in the ``users`` key. Defaults to 0 if unspecified. type: number + notifications: + additionalProperties: + type: number + description: |- + The power level requirements for specific notification types. + This is a mapping from ``key`` to power level for that notifications key. + title: Notification power level requirements + type: object type: object state_key: description: A zero-length string. From 60ae73b179c53213ce952251c7e9f4d14c323fef Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 15 Apr 2018 22:37:23 +0100 Subject: [PATCH 003/219] specify default --- event-schemas/schema/m.room.power_levels | 1 + 1 file changed, 1 insertion(+) diff --git a/event-schemas/schema/m.room.power_levels b/event-schemas/schema/m.room.power_levels index f348b52d0..a00746f00 100644 --- a/event-schemas/schema/m.room.power_levels +++ b/event-schemas/schema/m.room.power_levels @@ -91,6 +91,7 @@ properties: description: |- The power level requirements for specific notification types. This is a mapping from ``key`` to power level for that notifications key. + Defaults to 50 for unspecified keys. title: Notification power level requirements type: object type: object From c305317fa57b918d68731f69a0ab21367debde0b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sun, 15 Apr 2018 22:41:24 +0100 Subject: [PATCH 004/219] explicitly specify @room --- event-schemas/schema/m.room.power_levels | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/event-schemas/schema/m.room.power_levels b/event-schemas/schema/m.room.power_levels index a00746f00..25d33f085 100644 --- a/event-schemas/schema/m.room.power_levels +++ b/event-schemas/schema/m.room.power_levels @@ -86,13 +86,16 @@ properties: unspecified. type: number notifications: + properties: + room: + type: number + description: The level required to trigger an ``@room`` notification. Defaults to 50 if unspecified. additionalProperties: type: number description: |- The power level requirements for specific notification types. This is a mapping from ``key`` to power level for that notifications key. - Defaults to 50 for unspecified keys. - title: Notification power level requirements + title: Notifications type: object type: object state_key: From 9ca62edda0a664f65ac7ff31b659a77efce7edb1 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 25 May 2018 19:39:54 +0100 Subject: [PATCH 005/219] Document new application service registration file options. --- .../application_service.yaml | 2 +- specification/application_service_api.rst | 89 +++++++++++++++---- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/api/application-service/application_service.yaml b/api/application-service/application_service.yaml index c39ce198f..a63774a24 100644 --- a/api/application-service/application_service.yaml +++ b/api/application-service/application_service.yaml @@ -43,7 +43,7 @@ paths: x-example: "35" - in: body name: body - description: A list of events + description: A list of events. schema: type: object example: { diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index b4950eac0..6eb8e87e2 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -83,34 +83,93 @@ regular expressions and look like: users: - exclusive: true - regex: @irc.freenode.net_.* + regex: "@irc.freenode.net_.*" + group_id: "+irc:matrix.org" + +Application Services may define the following namespaces (with none being explicitly required): + ++------------------+-----------------------------------------------------------+ +| Name | Description | ++==================+===========================================================+ +| users | Events which are sent from certain users. | ++------------------+-----------------------------------------------------------+ +| aliases | Events which are sent in rooms with certain room aliases. | ++------------------+-----------------------------------------------------------+ +| rooms | Events which are sent in rooms with certain room IDs. | ++------------------+-----------------------------------------------------------+ + +Each individual namespace MUST declare the following fields: + ++------------------+-----------------------------------------------------------------------------------------------------------------------------------+ +| Name | Description | ++==================+===================================================================================================================================+ +| exclusive | **Required** A true or false value stating whether this Application Service has exclusive access to events within this namespace. | ++------------------+-----------------------------------------------------------------------------------------------------------------------------------+ +| regex | **Required** A regular expression defining which values this namespace includes. | ++------------------+-----------------------------------------------------------------------------------------------------------------------------------+ + +An optional ``group_id`` field may be added to the users namespace: + ++------------------+-----------------------------------------------------------+ +| Name | Description | ++==================+===========================================================+ +| group_id | All matching users will be considered part of this group. | ++------------------+-----------------------------------------------------------+ + +.. WARNING:: + + Users that are matched by ``group_id`` should not be publically listed by + Homeservers. The intention is to differentiate users, perhaps with a flair, + rather than having a list of people to spam. The registration is represented by a series of key-value pairs, which this -specification will present as YAML. An example HS configuration required to pass -traffic to the AS is: +specification will present as YAML. See below for the possible options along +with their explanation: + ++------------------+----------------------------------------------------------------------------------------------------------+ +| Name | Description | ++==================+==========================================================================================================+ +| id | **Required.** A unique, user-defined ID of the Application Service which will never change. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| url | **Required.** The base URL for the Application Service. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| as_token | **Required.** A unique token for Application Services to use to authenticate requests to Homeservers. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| hs_token | **Required.** A unique token for Homeservers to use to authenticate requests to Application Services. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| sender_localpart | **Required.** The localpart of the user associated with the Application Service. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| namespaces | **Required.** A list of "users", "aliases" and "rooms" namespaces that the Application Service controls. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| rate_limited | Whether requests from masqueraded users are rate-limited. The sender is excluded. | ++------------------+----------------------------------------------------------------------------------------------------------+ +| protocols | The external protocols which the Application Service provides (e.g. IRC). | ++------------------+----------------------------------------------------------------------------------------------------------+ + +An example registration file for an IRC-bridging Application Service is below: .. code-block:: yaml - id: - url: - as_token: - hs_token: - sender_localpart: + id: "IRC Bridge" + url: "http://127.0.0.1:1234" + as_token: "30c05ae90a248a4188e620216fa72e349803310ec83e2a77b34fe90be6081f46" + hs_token: "312df522183efd404ec1cd22d2ffa4bbc76a8c1ccf541dd692eef281356bb74e" + sender_localpart: "_irc_bot" # Will result in @_irc_bot:domain.com namespaces: - users: # Namespaces of users which should be delegated to the AS - - exclusive: - regex: - - ... - aliases: [] # Namespaces of room aliases which should be delegated to the AS - rooms: [] # Namespaces of room ids which should be delegated to the AS + users: + - exclusive: true + regex: "@irc_bridge_.*" + aliases: + - exclusive: false + regex: "#irc_bridge_.*" + rooms: [] .. WARNING:: If the homeserver in question has multiple application services, each ``as_token`` and ``id`` MUST be unique per application service as these are used to identify the application service. The homeserver MUST enforce this. - Homeserver -> Application Service API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From d6fb5afd16ad1682d90c9dd3bd505e9baf60e513 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 28 May 2018 23:30:40 +0100 Subject: [PATCH 006/219] Clarified group_id group visibility, url possibilities, regex starters Changed Application Service capatalization to be consistent with the rest of the document. --- specification/application_service_api.rst | 68 ++++++++++++----------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 6eb8e87e2..31983a0cc 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -83,10 +83,10 @@ regular expressions and look like: users: - exclusive: true - regex: "@irc.freenode.net_.*" + regex: "@_irc.freenode.net_.*" group_id: "+irc:matrix.org" -Application Services may define the following namespaces (with none being explicitly required): +Application services may define the following namespaces (with none being explicitly required): +------------------+-----------------------------------------------------------+ | Name | Description | @@ -103,22 +103,24 @@ Each individual namespace MUST declare the following fields: +------------------+-----------------------------------------------------------------------------------------------------------------------------------+ | Name | Description | +==================+===================================================================================================================================+ -| exclusive | **Required** A true or false value stating whether this Application Service has exclusive access to events within this namespace. | +| exclusive | **Required** A true or false value stating whether this application service has exclusive access to events within this namespace. | +------------------+-----------------------------------------------------------------------------------------------------------------------------------+ | regex | **Required** A regular expression defining which values this namespace includes. | +------------------+-----------------------------------------------------------------------------------------------------------------------------------+ -An optional ``group_id`` field may be added to the users namespace: +An application service's users and regex field MUST begin with an underscore (``_``), in +order to provide a visually clear distinction between AS users and regular +users. An optional ``group_id`` field may be added to the ``users`` namespace: -+------------------+-----------------------------------------------------------+ -| Name | Description | -+==================+===========================================================+ -| group_id | All matching users will be considered part of this group. | -+------------------+-----------------------------------------------------------+ ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Name | Description | ++==================+============================================================================================================================================================================================================================================================================+ +| group_id | An existing group that all matching user IDs will be considered a part of. Users who are joined to this group through an application service are not to be listed when querying for the group's members, however the group should be listed when querying a user's groups. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ .. WARNING:: - Users that are matched by ``group_id`` should not be publically listed by + Users that are matched by ``group_id`` should not be publicly listed by Homeservers. The intention is to differentiate users, perhaps with a flair, rather than having a list of people to spam. @@ -127,27 +129,27 @@ The registration is represented by a series of key-value pairs, which this specification will present as YAML. See below for the possible options along with their explanation: -+------------------+----------------------------------------------------------------------------------------------------------+ -| Name | Description | -+==================+==========================================================================================================+ -| id | **Required.** A unique, user-defined ID of the Application Service which will never change. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| url | **Required.** The base URL for the Application Service. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| as_token | **Required.** A unique token for Application Services to use to authenticate requests to Homeservers. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| hs_token | **Required.** A unique token for Homeservers to use to authenticate requests to Application Services. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| sender_localpart | **Required.** The localpart of the user associated with the Application Service. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| namespaces | **Required.** A list of "users", "aliases" and "rooms" namespaces that the Application Service controls. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| rate_limited | Whether requests from masqueraded users are rate-limited. The sender is excluded. | -+------------------+----------------------------------------------------------------------------------------------------------+ -| protocols | The external protocols which the Application Service provides (e.g. IRC). | -+------------------+----------------------------------------------------------------------------------------------------------+ - -An example registration file for an IRC-bridging Application Service is below: ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| Name | Description | ++==================+====================================================================================================================================================+ +| id | **Required.** A unique, user-defined ID of the application service which will never change. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| url | **Required.** 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 | **Required.** A unique token for application services to use to authenticate requests to Homeservers. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| hs_token | **Required.** A unique token for Homeservers to use to authenticate requests to application services. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| sender_localpart | **Required.** The localpart of the user associated with the application service. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| namespaces | **Required.** A list of ``users``, ``aliases`` and ``rooms`` namespaces that the application service controls. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| rate_limited | Whether requests from masqueraded users are rate-limited. The sender is excluded. | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| protocols | The external protocols which the application service provides (e.g. IRC). | ++------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ + +An example registration file for an IRC-bridging application service is below: .. code-block:: yaml @@ -159,10 +161,10 @@ An example registration file for an IRC-bridging Application Service is below: namespaces: users: - exclusive: true - regex: "@irc_bridge_.*" + regex: "@_irc_bridge_.*" aliases: - exclusive: false - regex: "#irc_bridge_.*" + regex: "#_irc_bridge_.*" rooms: [] .. WARNING:: From 0dd330962d7bf54e65737d5ca0e5f9a074c237e3 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 3 Jul 2018 14:14:26 -0400 Subject: [PATCH 007/219] initial draft of .well-known discovery --- .../definitions/wellknown/homeserver.yaml | 23 ++++++ .../definitions/wellknown/homeserver.yaml~ | 23 ++++++ .../wellknown/identity_server.yaml | 23 ++++++ api/client-server/wellknown.yaml | 63 ++++++++++++++++ specification/client_server_api.rst | 72 +++++++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 api/client-server/definitions/wellknown/homeserver.yaml create mode 100644 api/client-server/definitions/wellknown/homeserver.yaml~ create mode 100644 api/client-server/definitions/wellknown/identity_server.yaml create mode 100644 api/client-server/wellknown.yaml diff --git a/api/client-server/definitions/wellknown/homeserver.yaml b/api/client-server/definitions/wellknown/homeserver.yaml new file mode 100644 index 000000000..7efba8169 --- /dev/null +++ b/api/client-server/definitions/wellknown/homeserver.yaml @@ -0,0 +1,23 @@ +# 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. +title: Homeserver Information +description: |- + Used by clients to discover homeserver information. +type: object +properties: + base_url: + type: string + description: The base URL for the homeserver for client-server connections. +required: + - base_url diff --git a/api/client-server/definitions/wellknown/homeserver.yaml~ b/api/client-server/definitions/wellknown/homeserver.yaml~ new file mode 100644 index 000000000..e42dfbf3b --- /dev/null +++ b/api/client-server/definitions/wellknown/homeserver.yaml~ @@ -0,0 +1,23 @@ +# 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. +title: Authentication Data +description: |- + Used by clients to submit authentication information to the interactive-authentication API +type: object +properties: + base_url: + type: string + description: The base URL for the homeserver for client-server connections. +required: + - base_url diff --git a/api/client-server/definitions/wellknown/identity_server.yaml b/api/client-server/definitions/wellknown/identity_server.yaml new file mode 100644 index 000000000..eb0e0bafc --- /dev/null +++ b/api/client-server/definitions/wellknown/identity_server.yaml @@ -0,0 +1,23 @@ +# 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. +title: Identity Server Information +description: |- + Used by clients to discover identity server information. +type: object +properties: + base_url: + type: string + description: The base URL for the identity server for client-server connections. +required: + - base_url diff --git a/api/client-server/wellknown.yaml b/api/client-server/wellknown.yaml new file mode 100644 index 000000000..44d9ef731 --- /dev/null +++ b/api/client-server/wellknown.yaml @@ -0,0 +1,63 @@ +# 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. +swagger: '2.0' +info: + title: "Matrix Client-Server server discovery API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https +basePath: /.well-known +produces: + - application/json +paths: + "/matrix/client": + get: + summary: Gets Matrix server discovery information about the domain. + description: |- + Gets discovery information about the domain. The file may include + additional keys, which SHOULD follow the Java package naming convention, + e.g. ``com.example.myapp.property``. This ensures property names are + suitably namespaced for each application and reduces the risk of + clashes. + + **FIXME:** do we need to add a note that this endpoint is not + necessarily handled by the homeserver, but by another webserver? Or + does the context make this clear enough? + operationId: getWellknown + responses: + 200: + description: Server discovery information + examples: + application/json: { + "m.homeserver": { + "base_url": "https://matrix.example.com" + }, + "m.identity_server": { + "base_url": "https://identity.example.com" + } + } + schema: + type: object + properties: + m.homeserver: + description: Information about the homeserver to connect to. + "$ref": "definitions/wellknown/homeserver.yaml" + m.identity_server: + description: Information about the identity server to connect to. + "$ref": "definitions/wellknown/identity_server.yaml" + 404: + description: No server discovery information available + tags: + - Server administration diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index dec3a4f44..e0befddf4 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -164,6 +164,78 @@ recommended. {{versions_cs_http_api}} +Server Discovery +~~~~~~~~~~~~~~~~ + +In order to allow users to connect to a Matrix server without needing to +explicitly specify the homeserver's URL or other parameters, clients may use an +auto-discovery mechanism to determine the server's URL based on a user's +Matrix ID. Auto-discovery should only be done at login time, with the +discovered values retained for the duration of the user's session. + +In this section, the following terms are used with specific meanings: + +``PROMPT`` + Retrieve the specific piece of information from the user in a way which + fits within the existing client UX, if the client is inclined to do so. + Failure can take place instead if no good UX is possible at this point. + +``IGNORE`` + Stop the current auto-discovery mechanism. If no more auto-discovery + mechanisms are available, then the client may use other methods of + determining the required parameters, such as prompting the user, or using + default values. + +``FAIL_PROMPT`` + Inform the user that auto-discovery failed due to invalid/empty data and + ``PROMPT`` for the parameter. + +``FAIL_ERROR`` + Inform the user that auto-discovery did not return any usable URLs. Do not + continue further with the current login process. At this point, valid data + was obtained, but no homeserver 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 +++++++++++++++ + +The ``.well-known`` method uses a JSON file at a predetermined location to +specify parameter values. The flow for this method is as follows: + +1. Extract the server name from the user's Matrix ID by splitting the Matrix ID + at the first colon. +2. Extract the DNS name from the server name. +3. Make a GET request to ``https://dns_name/.well-known/matrix/client``. + + a. If the returned status code is 404, then ``IGNORE``. + b. If the returned status code is not 200, or the response body is empty, + then ``FAIL_PROMPT``. + c. Parse the response body as a JSON object + + i. If the content cannot be parsed, then ``FAIL_PROMPT``. + + d. Extract the ``base_url`` value from the ``m.homeserver`` property. This + value is to be used as the base URL of the homeserver. + + i. If this value is not provided, then ``FAIL_PROMPT``. + + e. Validate the homeserver base URL: + + i. Parse it as a URL. If it is not a URL, then ``FAIL_ERROR``. + ii. Clients should validate that the URL points to a valid homeserver + before accepting it. Currently, the suggested way of validating is + to connect to the ``/_matrix/client/versions`` endpoint, and to parse + and validate the data. If any step in the validation fails, then + ``FAIL_ERROR``. + + f. If the ``m.identity_server`` property is present, extract the + ``base_url`` value for use as the base URL of the identity server. This + value can be validated as in the step above, but using + ``/_matrix/identity/api/v1``. + +{{wellknown_cs_http_api}} + Client Authentication --------------------- From 5bc29eb11c5c07c47e6fb4afe0c7c1caba12cbf2 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 4 Jul 2018 17:01:35 -0400 Subject: [PATCH 008/219] remove accidentally-committed backup file --- .../definitions/wellknown/homeserver.yaml~ | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 api/client-server/definitions/wellknown/homeserver.yaml~ diff --git a/api/client-server/definitions/wellknown/homeserver.yaml~ b/api/client-server/definitions/wellknown/homeserver.yaml~ deleted file mode 100644 index e42dfbf3b..000000000 --- a/api/client-server/definitions/wellknown/homeserver.yaml~ +++ /dev/null @@ -1,23 +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. -title: Authentication Data -description: |- - Used by clients to submit authentication information to the interactive-authentication API -type: object -properties: - base_url: - type: string - description: The base URL for the homeserver for client-server connections. -required: - - base_url From ce1e2c0904a793b25527e88e060e0d0f6809cc1f Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 4 Jul 2018 17:58:37 -0400 Subject: [PATCH 009/219] incorporate feedback from reviewers --- api/client-server/wellknown.yaml | 13 +++++++----- changelogs/client_server.rst | 4 ++++ specification/client_server_api.rst | 31 ++++++++++++++++------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/api/client-server/wellknown.yaml b/api/client-server/wellknown.yaml index 44d9ef731..8d19f38a8 100644 --- a/api/client-server/wellknown.yaml +++ b/api/client-server/wellknown.yaml @@ -27,14 +27,13 @@ paths: summary: Gets Matrix server discovery information about the domain. description: |- Gets discovery information about the domain. The file may include - additional keys, which SHOULD follow the Java package naming convention, + additional keys, which MUST follow the Java package naming convention, e.g. ``com.example.myapp.property``. This ensures property names are suitably namespaced for each application and reduces the risk of clashes. - **FIXME:** do we need to add a note that this endpoint is not - necessarily handled by the homeserver, but by another webserver? Or - does the context make this clear enough? + 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 responses: 200: @@ -55,8 +54,12 @@ paths: description: Information about the homeserver to connect to. "$ref": "definitions/wellknown/homeserver.yaml" m.identity_server: - description: Information about the identity server to connect to. + description: Optional. Information about the identity server to connect to. "$ref": "definitions/wellknown/identity_server.yaml" + additionalProperties: + description: Application-dependent keys using Java package naming convention. + required: + - m.homeserver 404: description: No server discovery information available tags: diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index feabecab5..c6eb740ad 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -16,6 +16,10 @@ Unreleased changes - Add sticker message event definition. (`#1158 `_). + - Server discovery: + - Add ``.well-known`` discovery method + (`#1359 `_). + - Spec clarifications: - Update ``ImageInfo`` and ``ThumbnailInfo`` dimension schema descriptions diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index e0befddf4..fbeb87cbc 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -168,17 +168,17 @@ Server Discovery ~~~~~~~~~~~~~~~~ In order to allow users to connect to a Matrix server without needing to -explicitly specify the homeserver's URL or other parameters, clients may use an -auto-discovery mechanism to determine the server's URL based on a user's -Matrix ID. Auto-discovery should only be done at login time, with the -discovered values retained for the duration of the user's session. +explicitly specify the homeserver's URL or other parameters, clients SHOULD use +an auto-discovery mechanism to determine the server's URL based on a user's +Matrix ID. Auto-discovery should only be done at login time. In this section, the following terms are used with specific meanings: ``PROMPT`` Retrieve the specific piece of information from the user in a way which - fits within the existing client UX, if the client is inclined to do so. - Failure can take place instead if no good UX is possible at this point. + fits within the existing client user experience, if the client is inclined to + do so. Failure can take place instead if no good user experience for this is + possible at this point. ``IGNORE`` Stop the current auto-discovery mechanism. If no more auto-discovery @@ -223,16 +223,19 @@ specify parameter values. The flow for this method is as follows: e. Validate the homeserver base URL: i. Parse it as a URL. If it is not a URL, then ``FAIL_ERROR``. - ii. Clients should validate that the URL points to a valid homeserver - before accepting it. Currently, the suggested way of validating is - to connect to the ``/_matrix/client/versions`` endpoint, and to parse - and validate the data. If any step in the validation fails, then - ``FAIL_ERROR``. + ii. Clients SHOULD validate that the URL points to a valid homeserver + before accepting it by connecting to the ``/_matrix/client/versions`` + endpoint, and parsing and validating the data. If any step in the + validation fails, then ``FAIL_ERROR``. Validation is done as a simple + check against configuration errors, before sending sensitive + information such as a user's password to the server. f. If the ``m.identity_server`` property is present, extract the - ``base_url`` value for use as the base URL of the identity server. This - value can be validated as in the step above, but using - ``/_matrix/identity/api/v1``. + ``base_url`` value for use as the base URL of the identity server. + Validation for this URL is done as in the step above, but using + ``/_matrix/identity/api/v1`` as the endpoint to connect to. If the + ``m.identity_server`` property is present, but does not have a + ``base_url`` value, then ``FAIL_ERROR``. {{wellknown_cs_http_api}} From bbd909d09f6f0d1b91f66655ed815a5726f3e2ab Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 20 Jul 2018 17:19:32 +0100 Subject: [PATCH 010/219] State Resolution: Reloaded MSC --- proposals/0000-state-resolution.md | 447 +++++++++++++++++++++++++++++ proposals/images/state-res.png | Bin 0 -> 61233 bytes 2 files changed, 447 insertions(+) create mode 100644 proposals/0000-state-resolution.md create mode 100644 proposals/images/state-res.png diff --git a/proposals/0000-state-resolution.md b/proposals/0000-state-resolution.md new file mode 100644 index 000000000..66d1eb38c --- /dev/null +++ b/proposals/0000-state-resolution.md @@ -0,0 +1,447 @@ +# State Resolution: Reloaded + + +Thoughts on the next iteration of the state resolution algorithm that aims to mitigate currently known attacks + + +# Background + +The state of a room at an event is a mapping from key to event, which is built +up and updated by sending state events into the room. All the information about +the room is encoded in the state, from metadata like the name and topic to +membership of the room to security policies like bans and join rules. + +It is therefore important that─wherever possible─the view of the state of the +room is consistent across all servers. If different servers have different +views of the state then it can lead to the room bifurcating, due to differing +ideas on who is in the room, who is allowed to talk, etc. + +The difficulty comes when the room DAG forks and then merges again (which can +happen naturally if two servers send events at the same time or when a network +partition is resolved). The state after the merge has to be resolved from the +state of the two branches: the algorithm to resolve this is called the _state +resolution algorithm_. + +Since the result of state resolution must be consistent across servers, the +information that the algorithm can use is strictly limited to the information +that will always be available to all servers (including future servers that may +not even be in the room at that point) at any point in time where the +resolution needs to be calculated. In particular, this has the consequence that +the algorithm cannot use information from the room DAG, since servers are not +required to store events for any length of time. + +**As such, the state resolution algorithm is effectively a pure function from +sets of state to a single resolved set of state.** + +The final important property for state resolution is that it should not allow +malicious servers to avoid moderation action by forking and merging the room +DAG. For example, if a server gets banned and then forks the room before the +ban, any merge back should always ensure that the ban is still in the state. + + +# Current Algorithm + +The current state resolution is known to have some undesirable properties, +which can be summarized into two separate cases: + +1. Moderation evasion ─ where an attacker can avoid e.g. bans by forking and joining the room DAG in particular ways. +1. State resets ─ where a server (often innocently) sends an event that points to disparate parts of the graph, causing state resolution to pick old state rather than later versions. + +These have the following causes: + +1. Conflicting state must pass auth checks to be eligible to be picked, but the algorithm does not consider previous (superseded) state changes in a fork. For example, where Alice gives Bob power and then Bob gives Charlie power on one branch of a conflict, when the latter power level event is authed against the original power level (where Bob didn't have power), it fails. +1. The algorithm relies on the deprecated and untrustable depth parameter to try and ensure that the "most recent" state is picked. Without having a copy of the complete room DAG the algorithm doesn't know that e.g. one topic event came strictly after another in the DAG. For efficiency and storage reasons servers are not required (or expected) to store the whole room DAG. +1. The algorithm always accepts events where there are no conflicting alternatives in other forks. This means that if an admin changed the join rules to `private`, then new joins on forks based on parts of the DAG which predate that change would always be accepted without being authed against the join_rules event. + + +# Desirable Properties + +As well as the important properties listed in the "Background" section, there are also some other properties that would significantly improve the experience of end users, though not strictly essential. These include: + +* Banning and changing power levels should "do the right thing", i.e. end users shouldn't have to take extra steps to make the state resolution produce the "right" results. +* Minimise occurences of "state resets". Servers will sometimes point to disparate parts of the room DAG (due to a variety of reasons), which ideally should not result in changes in the state. +* Be efficient; state resolution can happen a lot on some large rooms. Ideally it would also support efficiently working on "state deltas" - i.e. the ability to calculate state resolution incrementally from snapshots rather than having to consider the full state of each fork each time a conflict is resolved + + +# Ideas for New Algorithm + + +## Auth Chain + +The _auth events_ of a given event is the set of events which justify why a +given event is allowed to be sent into a room (e.g. an m.room.create, an +m.room.power_levels and the sender's m.room.membership). The _auth chain_ of an +event is its auth events and their auth events, recursively. The auth chains of +a set of events in a given room form a DAG. + +"Auth events" are events that can appear as auth events of an event. These +include power levels, membership etc.[^1] + +Servers in a room are required to have the full auth chain for all events that +they have seen, and so the auth chain is available to be used by state +resolution algorithms. + + +## Unconflicted State + +The current algorithm defines the notion of "unconflicted state" to be all +entries that for each set of state either has the same event or no entry. All +unconflicted state entries are included in the resolved state. This is +problematic due to the fact that any new entries introduced on forks always +appear in the resolved state, regardless of if they would pass the checks +applied to conflicted state. + +The new algorithm could redefine "unconflicted state" to be all entries which +both exist and are the same in every state set (as opposed to previously where +the entry didn't need to exist in every state set). + + +## Replacing Depth + +Since depth of an event cannot be reliably calculated without possessing the +full DAG, and cannot be trusted when provided by other servers, it can not be +used in future versions of state resolution. A potential alternative, however, +is to use "origin_server_ts". While it cannot be relied on to be accurate─an +attacker can set it to arbitrary values─it has the advantage over depth that +end users can clearly see when a server is using incorrect values. (Note that +server clocks don't need to be particularly accurate for the ordering to still +be more useful than other arbitrary orderings). + +It can also be assumed that in most cases the origin_server_ts for a given +benign server will be mostly consistent. For example, if a server sends a join +and then a leave in the vast majority of cases the leave would have a greater +origin_server_ts. + +This makes "origin_server_ts" a good candidate to be used as a last resort to +order events if necessary, where otherwise a different arbitrary ordering would +be used. However, it's important that there is some other mechanism to ensure +that malicious servers can't abuse origin_server_ts to ensure their state +always gets picked during resolution (In the proposal below we use the auth DAG +ordering to override users who set state with malicious origin_server_ts.) + + +## Ordering and Authing + +Roughly, the current algorithm tries to ensure that moderation evasion doesn't +happen by ordering conflicted events by depth and (re)authing them +sequentially. The exact implementation has several issues, but the idea of +ensuring that state events from forks still need to pass auth subject to e.g. +bans and power level changes is a powerful one, as it reduces the utility of +maliciously forking. + +For that to work we need to ensure that there is a suitable ordering that puts +e.g. bans before events sent in other forks. (However events can point to old +parts of the DAG, for a variety of reasons, and ideally in that case the +resolved state would closely match the recent state). + + +## Power Level Ordering + +Actions that malicious servers would try and evade are actions that require +greater power levels to perform, for example banning, reducing power level, +etc. We define "power events" as events that have the potential to remove the +ability of another user to do something.[^2] (Note that they are a subset of +auth events.) + +In all these cases it is desirable for those privileged actions to take +precedence over events in other forks. This can be achieved by first +considering "power events", and requiring the remaining events to pass auth +based on them. + + +## Mainline + +An issue caused by servers not storing the full room DAG is that one can't tell +how two arbitrary events are ordered. The auth chain gives a partial ordering +to certain events, though far from complete; however, all events do contain a +reference to the current power levels in their auth events. As such if two +state events reference two different power levels events, and one power levels' +auth chain references the other, then there is a strong likelihood that the +event referencing the latter power level came after the other event. + +A "mainline" is a list of power levels events created if you pick a particular +power levels event (usually the current resolved power level) and recursively +follow each power level referenced in auth_events back to the first power level +event. + +The mainline can then be used to induce an ordering on events by looking at +where the power level referenced in their auth_events is in the mainline (or +recursively following the chain of power level events back until one is found +that appears in the mainline). This effectively partitions the room into +epochs, where a new epoch is started whenever a new power level is sent. + +If this mainline ordering is combined with ordering by origin_server_ts, then +it gives an ordering that is correct for servers that don't lie about the time, +while giving a mechanism that can be used to deal if a server lied (by room +admins starting a new epoch). + +The natural course of action for a room admin to take when noticing a +user/server is misbehaving is to ban them from the room, rather than changing +the power levels. It would therefore be useful if banning a user or server +started a new epoch as well. This would require being able to create a mainline +that includes power level events and bans[^3], which would suggest that power +level and ban events would need to point to the latest ban event as well. (This +would be significantly easier if we maintained a list of bans in a single +event, however there is concern that would limit the number of possible bans in +a room.) + + +# Proposed Algorithm + +First we define: + +* **"State sets"** are the sets of state that the resolution algorithm tries to resolve, i.e. the inputs to the algorithm. +* **"Power events"** are events that have the potential to remove the ability of another user to do something. These are power levels, join rules, bans and kicks. +* The **"unconflicted state map"** is the state where the value of each key exists and is the same in every state set. The** "conflicted state map"** is everything else. (Note that this is subtly different to the definition used in the existing algorithm, which considered the merge of a present event with an absent event to be unconflicted rather than conflicted) +* The "**auth difference"** is calculated by first calculating the full auth chain for each state set and taking every event that doesn't appear in every auth chain. +* The **"full conflicted set"** is the union of the conflicted state map and auth difference. +* The **"reverse topological power ordering"**[^4] of a set of events is an ordering of the given events, plus any events in their auth chains that appear in the auth difference, ordered such that x < y if: + + 1. x is in the auth chain of y, or if + 1. x's sender has a greater power level than y (calculated by looking at their respective auth events, or if + 1. x's origin_server_ts is less than y's, or if + 1. x's event_id is lexicographically less than y's + + This is also known as a lexicographical topological sort. + +* The **"mainline ordering"** based on a power level event P of a set of events is calculated as follows: + 1. Generate the list of power levels starting at P and recursively take the power level from its auth events. This list is called the mainline, ordered such that P is last. + 1. We say the "closest mainline event" of an event is the first power level event encountered in mainline when iteratively descending through the power level events in the auth events. + 1. Order the set of events such that x < y if: + 1. The closest mainline event of x appears strictly before the closest of y in the mainline list, or if + 1. x's origin_server_ts is less than y's, or if + 1. x's event_id lexicographically sorts before y's +* The **"iterative auth checks"** algorithm is where given a sorted list of events, the auth check algorithm is applied to each event in turn. The state events used to auth are built up from previous events that passed the auth checks, starting from a base set of state. If a required auth key doesn't exist in the state, then the one in the event's auth_events is used. (See _Variations_ and _Attack Vectors_ below). + +The algorithm proceeds as follows: + + +1. Take all power events and any events in their auth chains that appear in the _full_ _conflicted set_ and order them by the _reverse topological power ordering._ +1. Apply the _iterative auth checks_ algorithm based on the unconflicted state map to get a partial set of resolved state. +1. Take all remaining events that weren't picked in step 1 and order them by the _mainline ordering_ based on the power level in the partially resolved state. +1. Apply the _iterative auth checks algorithm_ based on the partial resolved state. +1. Update the result with the _unconflicted state_ to get the final resolved state[^5]. +(_Note_: this is different from the current algorithm, which considered different event types at distinct stages) + +An example python implementation can be found on github +[here](https://github.com/matrix-org/matrix-test-state-resolution-ideas). + +Note that this works best if we also change which events to include as an +event's auth_events. See the "Auth Events" section below. + + +## Discussion + +Essentially, the algorithm works by producing a sorted list of all conflicted +events (and differences in auth chains), and applies the auth checks one by +one, building up the state as it goes. The list is produced in two parts: first +the power events and auth dependencies are ordered by power level of the +senders and resolved, then the remaining events are ordered using the +"mainline" of the resolved power levels and then resolved to produce the final +resolved state. + +(This is equivalent to linearizing the full conflicted set of events and +reapplying the usual state updates and auth rules.) + + +### Variations + +There are multiple options for what to use as the base state for _iterative +auth checks_ algorithm; while it needs to be some variation of auth events and +unconflicted events, it is unclear exactly which combination is best (and least +manipulatable by malicious servers). + +Care has to be taken if we want to ensure that old auth events that appear in +the _auth chain difference_ can't supercede unconflicted state entries. + +Due to auth chain differences being added to the resolved states during +_iterative auth checks_, we therefore need to re-apply the unconflicted state +at the end to ensure that they appear in the final resolved state. This feels +like an odd fudge that shouldn't be necessary, and may point to a flaw in the +proposed algorithm. + + +### State Resets + +The proposed algorithm still has some potentially unexpected behaviour. + +One example of this is when Alice sets a topic and then gets banned. If an +event gets created (potentially much later) that points to both before and +after the topic and ban then the proposed algorithm will resolve and apply the +ban before resolving the topic, causing the topic to be denied and dropped from +the resolved state. This will result in no topic being set in the resolved +state. + + +### Auth Events + +The algorithm relies heavily on the ordering induced by the auth chain DAG. + +There are two types of auth events (not necessarily distinct): + +* Those that give authorization to do something +* Those that revoke authorization to do something. + +For example, invites/joins are in the former category, leaves/kicks/bans are in +the latter and power levels are both. + +Assuming[^6] revocations always point to (i.e., have in their auth chain) the +authorization event that they are revoking, and authorization events point to +revocations that they are superseding, then the algorithm will ensure that the +authorization events are applied in order (so generally the "latest" +authorization state would win). + +This helps ensure that e.g. an invite cannot be reused after a leave/kick, +since the leave (revocation) would have the invite in their auth chain. + +This idea also relies on revocations replacing the state that granted +authorization to do an action (and vice versa). For example, in the current +model bans (basically) revoke the ability for a particular user from being able +to join. If the user later gets unbanned and then rejoins, the join would point +to the join rules as the authorization that lets them join, but would not +(necessarily) point to the unban. This has the effect that if a state +resolution happened between the new join and the ban, the unban would not be +included in the resolution and so the join would be rejected. + +The changes to the current model that would be required to make the above +assumptions true would be, for example: + + + +1. By default permissions are closed. +1. Bans would need to be a list in either the join rules event or a separate event type which all membership events pointed to. +1. Bans would only revoke the ability to join, not automatically remove users from the room. +1. Change the defaults of join_rules to be closed by default + + +### Efficiency and Delta State Resolution + +The current (unoptimised) implementation of the algorithm is 10x slower than +the current algorithm, based on a single, large test case. While hopefully some +optimisations can be made, the ability to [incrementally calculate state +resolution via deltas](https://github.com/matrix-org/synapse/pull/3122) will +also mitigate some of the slow down. + +Another aspect that should be considered is the amount of data that is required +to perform the resolution. The current algorithm only requires the events for +the conflicted set, plus the events from the unconflicted set needed to auth +them. The proposed algorithm also requires the events in the auth chain +difference (calculating the auth chain difference may also require more data to +calculate). + +Delta state resolution is where if you have, say, two state sets and their +resolution, then you can use that result to work out the new resolution where +there has been a small change to the state sets. For the proposed algorithm, if +the following properties hold true then the result can be found by simply +applying steps 3 and 4 to the state deltas. The properties are: + + + +1. The delta contains no power events +1. The origin_server_ts of all events in state delta are strictly greater than those in the previous state sets +1. Any event that has been removed must not have been used to auth subsequent events (e.g. if we replaced a member event and that user had also set a topic) + +These properties will likely hold true for most state updates that happen in a +room, allowing servers to use this more efficient algorithm the majority of the +time. + + +### Full DAG + +It's worth noting that if the algorithm had access to the full room DAG that it +would really only help by ensuring that the ordering in "reverse topological +ordering" and "mainline ordering" respected the ordering induced by the DAG. + +This would help, e.g., ensure the latest topic was always picked rather than +rely on origin_server_ts and mainline. As well as obviate the need to maintain +a separate auth chain, and the difficulties that entails (like having to +reapply the unconflicted state at the end). + + +### Attack Vectors + +The main potential attack vector that needs to be considered is in the +_iterative auth checks_ algorithm, and whether an attacker could make use of +the fact that it's based on the unconflicted state and/or auth events of the +event. + + +# Appendix + +The following is an example room DAG, where time flows down the page. We shall +work through resolving the state at both _Message 2_ and _Message 3_. + + +![alt_text](images/state-res.png) + + +(Note that green circles are events sent by Alice, blue circles sent by Bob and +black arrows point to previous events. The red arrows are the mainline computed +during resolution.) + +First we resolve the state at _Message 2_. The conflicted event types are the +power levels and topics, and since the auth chains are the same for both state +sets the auth difference is the empty set. + +Step 1: The _full conflicted set_ are the events _P2, P3, Topic 2 _and _Topic +3_, of which _P2_ and _P3_ are the only power events. Since Alice (the room +creator) has a greater power level than Bob (and neither _P2 _and _P3_ appear +in each other's auth chain), the reverse topological ordering is: [_P2, P3_]. + +Step 2: Now we apply the auth rules iteratively, _P2_ trivially passes based on +the unconflicted state, but _P3_ does not pass since after _P2_ Bob no longer +has sufficient power to set state. This results in the power levels resolving +to _P2_. + +Step 3: Now we work out the mainline based on P2, which is coloured in red on +the diagram. We use the mainline to order _Topic 2_ and _Topic 3_. _Topic 2_ +points to_ P1_, while the closest mainline to _Topic 3_ is also _P1_. We then +order based on the _origin_server_ts_ of the two events, let's assume that +gives us: [_Topic 2_, _Topic 3_]. + +Step 4: Iteratively applying the auth rules results in _Topic 2_ being allowed, +but _Topic 3 _being denied (since Bob doesn't have power to set state anymore), +so the topic is resolved to _Topic 2_. + +This gives the resolved state at _Message 2_ to be _P2 _and _Topic 2_. (This is +actually the same result as the existing algorithm gives) + +Now let's look at the state at _Message 3_. + +Step 1: The full conflicted set are simple: _Topic 2_ and _Topic 4_. There are +no conflicted power events. + +Step 2: N/A + +Step 3: _Topic 2_ points to _P1_ in the mainline, and _Topic 4_ points to _P2_ +in its auth events. Since _P2_ comes after _P1_ in the mainline, this gives an +ordering of [_Topic 2, Topic 4_]. + +Step 4: Iteratively applying the auth rules results in both topics passing the +auth checks, and so the last topic, _Topic 4_, is chosen. + +This gives the resolved state at _Message 3_ to be _Topic 4_. + + +## Notes + +[^1]: + In the current room protocol these are: the create event, power levels, membership, join rules and third party invites. See the [spec](https://matrix.org/docs/spec/server_server/unstable.html#pdu-fields). + +[^2]: + In the current protocol these are: power levels, kicks, bans and join rules. + +[^3]: + Future room versions may have a concept of server ban event that works like existing bans, which would also be included + +[^4]: + The topology being considered here is the auth chain DAG, rather than the room DAG, so this ordering is only applicable to events which appear in the auth chain DAG. + +[^5]: + We do this so that, if we receive events with misleading auth_events, this ensures that the unconflicted state at least is correct. + +[^6]: + This isn't true in the current protocol + + + diff --git a/proposals/images/state-res.png b/proposals/images/state-res.png new file mode 100644 index 0000000000000000000000000000000000000000..573d1927afa216cd3a59e0d8e015aa300a30c295 GIT binary patch literal 61233 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�~ zUf1xg!~f(I%dRCp5+@i*v~a>pL2@6r6Q_f?xq#O?y2LmQQ!8R&fUk(sTJN!UP6&E^mJ8-Z?%^(Lj7P=Wy5B5wde37-JX8UqV$po9Oom%lHl2a_Iedhqpxy?@V zye&B@A$*0-y9Ywhz;pa`CGz6&GJku`)2oo6ko4x0**_bSv_W!jvCt+i-de)%s{Ttx7S{o{R@hq^+5a0a6_pMe zf4@B>p~N#*=79F#_28V$6*Pl!(?zA=rM2w`w7;_b+9kICO7hFRlCeSE z>t5>SZi8)bJj}{^I+`)MJ2j0M2p#*vklYd)Dn*^SwDdFarhbAf4WBEjLmelY;`RbH znpiMi=ga+wkYIG9fz6^IKR-eyH+jz&1c;4DDJq?dj@)yK+GhsJ7i!evsI2t(D0I9Q z*?3}8J8wyUM1-!2wMwu!d9n44^|@H=Ef9(@h)f~*3*Q2Fp|tNxOGz{1^8BsL6B+5I zyU%^DY3IX;a9Sz5-8!cvqx$p)-rXKJbk-BCy%%)q8F}1{akh*dnU+Fjf>KVVt=DSX zYG8eM;4bz@wFq0RU83?wBodtU^thXKMh+IWP_B$Ow6?%P$gO{^y5slex%(RKhfX7e zWDZlpRwf&vk?X~u=)Xov26ZZjg>-j^ViLHiXa!Q{9@adzjDea3yO009FwXiB@gyb* z4~?i=`5EW1jDbyzPxnsyOZGCE6C-AG^D1LLNw0p_V@+Zzq^4n6%^8x(rluy-;_JE? zJmX9zLS6ma-Q5uO@nTt{d8ztBsP5jQVfIWI;d{<{&qoXn6?PTuRXtxiEL+Bq#cj3H zsd*?@_mP{R*A_4bY*Ww*Dy7mywMv58f)`$Rs%@v4`$@77U#1+ZAyrEVyXmZACpa2qWj}_`Vsy^C_>R5 zefHq5m^}hVcOqLW=1*fzWZ}9RyvIJk&0O|NsjcmxGkD3v#Yn48PlLw7#mFna zK~6$&I=~S9w@#QR=;Q_Et(OsR$_%J6rIiIqRxPZJjOKdzSc8ekC=>L!ZnqvO(=&^u0@Or7E@E;$%dF3qEw^?l7n);Ox@skbRANN`hE zbvL2u@OxN5dvjdf_q%4pYE~(~*F|ZEwQjFj_mp@a&h2kjnudPqo8#vC?k}FpbL!79 zN?(Ve~H&eYGVqR3+Zx}G9O;);!n$dEB{ zUmf?=1Rj#&l9NR&qeCv;hV;>+XV0F^Z>Wjae&l|!{3qZZ$=ai&yjw4l$Pf$jGS}hr zEZ%UVKdE@tL2JZ*6MN1%?#*d?IG&Q=EIo|k;W|kFv#`;dwKq1uyTo}BaNgS>a$s_l z>f||QhtCRLeoJK$KqzHp`*J>Z@I~>NOtaCm2eS*`{+-R0m^VfxMJ@FH5d3_)|F5js zCb6=$=NE!rf>XPyIxfFsi5zRxb=HbmNQv?rW)a#f!B@SaCQ zFhY{|ADlH*g>EPB2-P#epnWftbC~-!Uo8(z(X1in;aZtg{@MC&jbujwr}+`ahab$WtcCgcW^$Aj=e>+4m3m6wGkqAZmg~nj zfMr~fTQ8X6Ghvf85B%xk4%NJQzDvys8+_b55;!pE{e+|>R>F_K7*UNgl&ijaa+o*N zFD;09;y8Qi#6N!cQ97Jg)4AH=jTBY%McgHc<)iK0RGaC9>Fma2=f%r=wLwMOdf9^u zNFGSg*wz-3mH^s(DM2ryExfKf=_hyd!JlFJQ+|*nsOKHy6VvG5_(NU1SSgPn=h|UE z%}AfMGl9L;v`gZHfJLvA%6~|KY?^>}vFhGrg~U1yusbiE_DlK4kLgFdY8vN03+i2g z3)3c!vhX#2EXI1t=8SExABt~)DY|w);kso08#^ne#6581nlJt}U$5HNt@o$dWc{^V z;ovLzJ@G$o?eW87Qd+tR4(;H^Vw0P6&`COzcL%~g2{ zfG|s*e+5Y>Xg4bV{2@fy{-gez{+mQ%MDT~>ZxRq-C0Hcxd_xJW^{?E&tH6{kG-+G1 zlcL((H!o0nOU_698oTC`;=h4(9iiGk4}=)lsKZHlSOLlcNNiV$cGp)UtM5yP43n$^ zleD0kGc-7wNStcgzQ2pBP)C|O7;v{k@2x3j#c`;&ZqC=`}qC$I}d-{k8_;++~DCjOIJb)n>8)Vx!{qp^gzEmx4(RG^e@aSH@@6794OQt)DMdl`%vE) zY^zwv^Vg-=O9-nFbIj78V9gg-Fb1)Sa4!4#%c$EBJj@{|=K_G#;B*L@wO`mT5{=52 z8-!wLTPp)BBOWN1+my$+XB-)bQnoHd@Mh|sKV?Ow*t1b*7s_+e=iFsW%i7Dw5YtK+ zH5^qF^5pQuU%~ID`ue?_4bFr!q~SMrcTgA>O)ImjZ6MyX`E}}LCaKXbYtPQI-5}2n zzcx6Uto8h&IyCdWlD7&-h5I_1KKFnA+`sGgwn=8^flBVHUD99y14EHfCC{~ zk1-`Z2)~5r$iU$80bB%ic2_SUI5sv;sGvg*pSbuH8uGK#$R2Vpwu_F8WMyGlObe&D zTP7hKLlzpkt7~gP;9Sp%9vdB{qM^ywZAsMcPCd^w!$l6$jXga*#huqpk63IAkbR*m zb#nmjK_LT{%7aH6X9O!}6lAFhD(MIY$g5|W2Hcc@MDj;|N<=qrXsq%=WDQdE@0J!# zLAJMFWis@ySX*C5uXaf4u`w|x%Se=e_I4M1;ES%Q{{DW_t1lfLKOkrb3ki{>u%^bw zMCBkKL*RAXPBKtP(7+Ro##?>1$B19cl1(PV35A8H0v5lkF;kA)*Og+{8i$TlQ?l(_oR` zIu3}VnK?}H-Lns|5AlvXd>9l?kL)+e$!1M)Al8rT9_AlEPgcX;Tjhs_hLUMH$5Wd> zTBNDY9R>Ii`tKX7F_=R`zY*!r>LeJx++6N9Wj|^lllhIVjC=$-Xp&4JDJZ zb8=?z_Vf8RCQbuv=~7`har-T2WEwATvtt~LnV|(aX=xU?QZ`7lat9BRrQqi07gAB$4E03a zO%^e>s4yz!G9v$93HIE%a}brGD78Dh!P`{T)H?aA6c1u7l;Y*mwNa|JqrKhzuNlZ* z7EVsmZsTeNfQ|1Ju;Qq|S3PH>f2@*@cB-%_s^xpg6GX0|zJWnZQqrqzN(j2w-Q0fQ zf=_lJ3v|E!8LF)G^Q*@AxoaEB$yGa5{@TUL+QA)omK(;;6D#;orR`|<@>A!9t~Wqr z8$J9IuR2v#S8FDoy<}=SRPPGD8ppDPb7Rh9k5?ym3+ZHcy_7!d33v`1H>(->*gwjo zwt>QLuSZkKwj9GkTgdigOHsRq`TfLPf)9>h6T5hM$PDfrT+q#IP|?uKEC6@@kfm2sMU!52$`IWPfYa2<=fL^P{2#J{NAHS zbY^jJvE^i=ub&@K@MO8b)(7{8eScUc_~YZ6<4$E~WZY9sEx+m+7aJQC^qM>(<%fvG zCo1W%Sm7dV=p<|T2Lvonc7S0H4j>EgQC zLFF>p&gbUlMo%A-k@VrinXNt`GYi6Km^gJMLjj7Rixt6ssG>Y2MK=44dV8u@c3$2h zNH`c}yeu!2UqhJ(JSNYxgO;kLvmMyi-cbH04Mq07DSC=P3cVWo`fj5SH;VH`l4E~Z zXdtlu`uEYe)gPDSE3I7o@PVH}^@g+$i)L?Vh8{Ei5hW`H1Tx<`1{uEmync(9<)E8=4ph^?&KVq$^v+<8FTHm_ehfRVsH#*#vI&u7C;@0XW8V|=4MB%65-Y3 z09VVT*gu?EnC-YZ z$;aa>?5{>WTMT!>k(c4o$jSIP=K4bSaA5U0JG?ln4z(Q;5zJY@8}G`?0sr|nj4|#J zp_0=`+xm5IQB*Fq4IH|Kl@&D=75T=qXBI5^kDtP7)Y6wzag2C}J?LJ1(G`5p~{dVgXYQ>Z9kSH?e zL;eT%AlYQp;gypp*ay}d`d;GMnDwl$M$o-}v!BxPMAD;CSEqW4za78!rw{G+4X5B9SxC!y(UwFsJ{G0GlA!)2{z#YQ z8VcFshEU@|=FXyF{{T(b80$l#=V9BHot5P*hy;bVJf7NzfjI;+>`Cc3DoL8*3SRx% zl#@g0;s23!KUdS3iUG&(#fXRr-{J>sxiY#6;Wo_`+&hLV+*$5wS7{E$b3Z2dNlHEC zj=Dj$t`lELt8G^Qh{5N1mWkz+$(j*)`PX~W0{MREgjvwlr>g{)pKo2gFJoPQWZG-o z#BEplbUvP5&#!_JV&$Kin#T%nlN?DJSp1Ql6@@TP#S*sM^&gT-Ga@&<4IKe-^ z^G%EoVZ@4PW#1R2x;_54SYIMDzrdVCT;uoqj44|>=}7#XN3SRDUM?XT*J}=vTBdXf zcR9^M#%bD3b%`%}Ddd$DWI3N40Sd-BpFDjWS%t2yu3(igf>W<-u<$Bvp-{a-MO_l9 zSCr4$5~u8zUoUy4qI06U`GNTF`^-$Yw*^&Q4$Mz@b}xyK_x_?Qoz|rLwjg=yd-BdP zyaXE(k6@IH)r}j+fY}Xn55+QEV>v`1T=<*#yvSnf`iTMsnq>m(6PJ+6*aJ#;T*{jU z!yZ2=_W1GsX++$uAg+soUDt?b&YY%%+1%=Gj@jgG(m7SzJ#`U znBJV?S?<%8hLHvOQ5o&S6a*zU7P`k&$(>=8hodO77G00OmNd~OuAcsJ)|Yeluk^|^ zqq>H=x`w`@Q2B?9*FO*comW&ua~D@{!39&?FcOk*i`UcDMF#t;?F{pcbgsh(gg%V~ z_v|2f=GMis4mKK6r-TvkRa1Lf%Gsr^#aPVuRz39#5Zfb3`9X8Lb(?adl`!R9-I$1{ zJkQNnX#xVnBN%s`wfCV3{1y@OUVVp1m88-Y6GyS|SkC5GSu0zMM{fT^3d(P5@|HJ9Cqm6!Idx6ft&Zr~t<$@#h zc6FTgLlX@bgSAP!Zm1{vwX3foZ0T@K2Ogx{iY2nW+Y72T%n9% zBd{Ft??~lZCN*`=is}>|NM36S&hXP}RR5y7_rS=s8XqlzRUqR8U449s(oP*2;Su^Y zH73h*j*cbd?{JijnNzpobyk}9Y<*|Oc&q{G`+);ui3(mW<(db_ekJ^^cgtD!%%_+=IR-xZH|Q)x!~_IBHaF*XO>`e#>#Nw9 zUVRz&A?`0RYmKN5zxCq}LLK&Zjfu1{zdcAN^E7X++qiefAUMcDDPGF}@%IojfqZ2g-@9_GWYAl4td~i8!M@l(WohVrD&A0OI zneKp{O?dw3tqOxI5(CGKjpm~<`ueG)o`>02b6zrkiupY>`0MA%M_UOTcZ9-c3k?2Y z;z>84rP?ZV&%c&Ar}ToxJ()a}_K@TJx5vh7rDcdFLP_r;nG##fLGxi=?P9K9|Cb^o9b zaXZl>+hR5LV7c38$SagD!B1LBD)%bVAedQCELb)Q{VtW^dYzXiA|jI45M8gd`J?;W zJEv#U9s3=73rDAE?r4bq9$tz5xKNslAEoKanr9&6{wvZoPh84prm1OY1{_x$Z?9ka zxzHp3*6W95fr?IHens1~gK#`OlVa*ZRRFy|LqX2T9R2K}`5{Z8hKj#5vW6=KGOFf3 z=iTI%_ZH$zymi)eb~(CQJTfjrh)AU8HaN}r)I8ec3`Zi`X>f85f@fb_m1g4fA2+Sk z>6EP{o@)L;8r&QztvA!SeOUPQsZj!9%bc?OIo+tzn?J17)titk+B+@NphDamI#_y5 zH6jfmn#=U~%D&OIwl*w%kcJcOt|D!-=d^NW2LN2K+s@A6nV+Io3q<3$Q~T-Y=ztVC zb8AU(3#B2+YqFG+fg1JdN0)DDCP_6_bExt$(}Fat9GZ76*}c6r&jAviD*~+H;o7U0 zlrY@Q;An4;5FC#l`_msr8<21>0P4od3Npz0#zw3oouR()=k9K~T8O*8y&UZxEsrKyy;xU^b08fj3=6zsqueB0-z9{XNbH&zA7@i|WB3xm zhwd$_w76cve{Jo);> z-RN0r3=2z8U0y%d_zO4unK5AbeX~fzmtJ3p%gV|-N)!_Ml;^qneRy!tgu4b=U05`) z&GXvy3TIBQBbg7Fvi1vI1%-eC$Lr!i1rsc#o_xhXezMSx;EnvGE6DcYX0^s zJL!O9(Z_FMH@;u?@{*hTX5e{a77037!m}v^ef$<6n_Rq%A_FBx%@79? zG|C3%oX;Sd_88@FcNhOP)pbPS0=RyjM_OzO-OE_`=H})G2ZIuIM#>-(zeO396d6lNX{Mrp5g-3Z>0+AAWljaK=+_Bg>u2Q&7e7@*X}OPAIr z!)?F0Mey!)3W&56LuAGhbmMFy1}Roe_(_@jWCZgSoMF;zA9y^gd@(6-ok&3(bD$Ke zE<(7hnXU~$rFQP!jRo0`lX`mCKYwJ~$ytP|K>GkeT+B7Sj}|84x)%m1_AzG2g@%Vuf6#j0Kr@K9FJkk6I9?E4?-XqGwv literal 0 HcmV?d00001 From 4f97b80dccf9413b362f53d75cf85836b44bce19 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 20 Jul 2018 23:35:54 +0100 Subject: [PATCH 011/219] fix MD --- proposals/0000-state-resolution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-state-resolution.md b/proposals/0000-state-resolution.md index 66d1eb38c..78d4059b2 100644 --- a/proposals/0000-state-resolution.md +++ b/proposals/0000-state-resolution.md @@ -192,7 +192,7 @@ First we define: * **"State sets"** are the sets of state that the resolution algorithm tries to resolve, i.e. the inputs to the algorithm. * **"Power events"** are events that have the potential to remove the ability of another user to do something. These are power levels, join rules, bans and kicks. -* The **"unconflicted state map"** is the state where the value of each key exists and is the same in every state set. The** "conflicted state map"** is everything else. (Note that this is subtly different to the definition used in the existing algorithm, which considered the merge of a present event with an absent event to be unconflicted rather than conflicted) +* The **"unconflicted state map"** is the state where the value of each key exists and is the same in every state set. The **"conflicted state map"** is everything else. (Note that this is subtly different to the definition used in the existing algorithm, which considered the merge of a present event with an absent event to be unconflicted rather than conflicted) * The "**auth difference"** is calculated by first calculating the full auth chain for each state set and taking every event that doesn't appear in every auth chain. * The **"full conflicted set"** is the union of the conflicted state map and auth difference. * The **"reverse topological power ordering"**[^4] of a set of events is an ordering of the given events, plus any events in their auth chains that appear in the auth difference, ordered such that x < y if: From 3f891681ece09119781fa7222578eb1095ba9118 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 1 Aug 2018 14:12:46 +0100 Subject: [PATCH 012/219] Move proposal to have MSC number prefix --- proposals/{0000-state-resolution.md => 1442-state-resolution.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename proposals/{0000-state-resolution.md => 1442-state-resolution.md} (100%) diff --git a/proposals/0000-state-resolution.md b/proposals/1442-state-resolution.md similarity index 100% rename from proposals/0000-state-resolution.md rename to proposals/1442-state-resolution.md From 67757a30274da1aec27dadb60759de729337c77a Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 2 Aug 2018 13:48:44 +0100 Subject: [PATCH 013/219] Wrap lines --- proposals/1442-state-resolution.md | 174 +++++++++++++++++++---------- 1 file changed, 118 insertions(+), 56 deletions(-) diff --git a/proposals/1442-state-resolution.md b/proposals/1442-state-resolution.md index 78d4059b2..4dd0fe7c0 100644 --- a/proposals/1442-state-resolution.md +++ b/proposals/1442-state-resolution.md @@ -1,7 +1,8 @@ # State Resolution: Reloaded -Thoughts on the next iteration of the state resolution algorithm that aims to mitigate currently known attacks +Thoughts on the next iteration of the state resolution algorithm that aims to +mitigate currently known attacks # Background @@ -44,23 +45,48 @@ ban, any merge back should always ensure that the ban is still in the state. The current state resolution is known to have some undesirable properties, which can be summarized into two separate cases: -1. Moderation evasion ─ where an attacker can avoid e.g. bans by forking and joining the room DAG in particular ways. -1. State resets ─ where a server (often innocently) sends an event that points to disparate parts of the graph, causing state resolution to pick old state rather than later versions. +1. Moderation evasion ─ where an attacker can avoid e.g. bans by forking and + joining the room DAG in particular ways. +1. State resets ─ where a server (often innocently) sends an event that points + to disparate parts of the graph, causing state resolution to pick old state + rather than later versions. These have the following causes: -1. Conflicting state must pass auth checks to be eligible to be picked, but the algorithm does not consider previous (superseded) state changes in a fork. For example, where Alice gives Bob power and then Bob gives Charlie power on one branch of a conflict, when the latter power level event is authed against the original power level (where Bob didn't have power), it fails. -1. The algorithm relies on the deprecated and untrustable depth parameter to try and ensure that the "most recent" state is picked. Without having a copy of the complete room DAG the algorithm doesn't know that e.g. one topic event came strictly after another in the DAG. For efficiency and storage reasons servers are not required (or expected) to store the whole room DAG. -1. The algorithm always accepts events where there are no conflicting alternatives in other forks. This means that if an admin changed the join rules to `private`, then new joins on forks based on parts of the DAG which predate that change would always be accepted without being authed against the join_rules event. +1. Conflicting state must pass auth checks to be eligible to be picked, but the + algorithm does not consider previous (superseded) state changes in a fork. + For example, where Alice gives Bob power and then Bob gives Charlie power on + one branch of a conflict, when the latter power level event is authed + against the original power level (where Bob didn't have power), it fails. +1. The algorithm relies on the deprecated and untrustable depth parameter to + try and ensure that the "most recent" state is picked. Without having a copy + of the complete room DAG the algorithm doesn't know that e.g. one topic + event came strictly after another in the DAG. For efficiency and storage + reasons servers are not required (or expected) to store the whole room DAG. +1. The algorithm always accepts events where there are no conflicting + alternatives in other forks. This means that if an admin changed the join + rules to `private`, then new joins on forks based on parts of the DAG which + predate that change would always be accepted without being authed against + the join_rules event. # Desirable Properties -As well as the important properties listed in the "Background" section, there are also some other properties that would significantly improve the experience of end users, though not strictly essential. These include: +As well as the important properties listed in the "Background" section, there +are also some other properties that would significantly improve the experience +of end users, though not strictly essential. These include: -* Banning and changing power levels should "do the right thing", i.e. end users shouldn't have to take extra steps to make the state resolution produce the "right" results. -* Minimise occurences of "state resets". Servers will sometimes point to disparate parts of the room DAG (due to a variety of reasons), which ideally should not result in changes in the state. -* Be efficient; state resolution can happen a lot on some large rooms. Ideally it would also support efficiently working on "state deltas" - i.e. the ability to calculate state resolution incrementally from snapshots rather than having to consider the full state of each fork each time a conflict is resolved +* Banning and changing power levels should "do the right thing", i.e. end + users shouldn't have to take extra steps to make the state resolution + produce the "right" results. +* Minimise occurences of "state resets". Servers will sometimes point to + disparate parts of the room DAG (due to a variety of reasons), which ideally + should not result in changes in the state. +* Be efficient; state resolution can happen a lot on some large rooms. Ideally + it would also support efficiently working on "state deltas" - i.e. the + ability to calculate state resolution incrementally from snapshots rather + than having to consider the full state of each fork each time a conflict is + resolved # Ideas for New Algorithm @@ -132,7 +158,7 @@ maliciously forking. For that to work we need to ensure that there is a suitable ordering that puts e.g. bans before events sent in other forks. (However events can point to old parts of the DAG, for a variety of reasons, and ideally in that case the -resolved state would closely match the recent state). +resolved state would closely match the recent state). ## Power Level Ordering @@ -190,38 +216,69 @@ a room.) First we define: -* **"State sets"** are the sets of state that the resolution algorithm tries to resolve, i.e. the inputs to the algorithm. -* **"Power events"** are events that have the potential to remove the ability of another user to do something. These are power levels, join rules, bans and kicks. -* The **"unconflicted state map"** is the state where the value of each key exists and is the same in every state set. The **"conflicted state map"** is everything else. (Note that this is subtly different to the definition used in the existing algorithm, which considered the merge of a present event with an absent event to be unconflicted rather than conflicted) -* The "**auth difference"** is calculated by first calculating the full auth chain for each state set and taking every event that doesn't appear in every auth chain. -* The **"full conflicted set"** is the union of the conflicted state map and auth difference. -* The **"reverse topological power ordering"**[^4] of a set of events is an ordering of the given events, plus any events in their auth chains that appear in the auth difference, ordered such that x < y if: +* **"State sets"** are the sets of state that the resolution algorithm tries + to resolve, i.e. the inputs to the algorithm. +* **"Power events"** are events that have the potential to remove the ability + of another user to do something. These are power levels, join rules, bans + and kicks. +* The **"unconflicted state map"** is the state where the value of each key + exists and is the same in every state set. The **"conflicted state map"** is + everything else. (Note that this is subtly different to the definition used + in the existing algorithm, which considered the merge of a present event + with an absent event to be unconflicted rather than conflicted) +* The "**auth difference"** is calculated by first calculating the full auth + chain for each state set and taking every event that doesn't appear in every + auth chain. +* The **"full conflicted set"** is the union of the conflicted state map and + auth difference. +* The **"reverse topological power ordering"**[^4] of a set of events is an + ordering of the given events, plus any events in their auth chains that + appear in the auth difference, ordered such that x < y if: 1. x is in the auth chain of y, or if - 1. x's sender has a greater power level than y (calculated by looking at their respective auth events, or if - 1. x's origin_server_ts is less than y's, or if - 1. x's event_id is lexicographically less than y's + 2. x's sender has a greater power level than y (calculated by looking at + their respective auth events, or if + 3. x's origin_server_ts is less than y's, or if + 4. x's event_id is lexicographically less than y's This is also known as a lexicographical topological sort. -* The **"mainline ordering"** based on a power level event P of a set of events is calculated as follows: - 1. Generate the list of power levels starting at P and recursively take the power level from its auth events. This list is called the mainline, ordered such that P is last. - 1. We say the "closest mainline event" of an event is the first power level event encountered in mainline when iteratively descending through the power level events in the auth events. +* The **"mainline ordering"** based on a power level event P of a set of + events is calculated as follows: + 1. Generate the list of power levels starting at P and recursively take the + power level from its auth events. This list is called the mainline, + ordered such that P is last. + 1. We say the "closest mainline event" of an event is the first power level + event encountered in mainline when iteratively descending through the + power level events in the auth events. 1. Order the set of events such that x < y if: - 1. The closest mainline event of x appears strictly before the closest of y in the mainline list, or if + 1. The closest mainline event of x appears strictly before the closest + of y in the mainline list, or if 1. x's origin_server_ts is less than y's, or if 1. x's event_id lexicographically sorts before y's -* The **"iterative auth checks"** algorithm is where given a sorted list of events, the auth check algorithm is applied to each event in turn. The state events used to auth are built up from previous events that passed the auth checks, starting from a base set of state. If a required auth key doesn't exist in the state, then the one in the event's auth_events is used. (See _Variations_ and _Attack Vectors_ below). +* The **"iterative auth checks"** algorithm is where given a sorted list of + events, the auth check algorithm is applied to each event in turn. The state + events used to auth are built up from previous events that passed the auth + checks, starting from a base set of state. If a required auth key doesn't + exist in the state, then the one in the event's auth_events is used. (See + _Variations_ and _Attack Vectors_ below). The algorithm proceeds as follows: -1. Take all power events and any events in their auth chains that appear in the _full_ _conflicted set_ and order them by the _reverse topological power ordering._ -1. Apply the _iterative auth checks_ algorithm based on the unconflicted state map to get a partial set of resolved state. -1. Take all remaining events that weren't picked in step 1 and order them by the _mainline ordering_ based on the power level in the partially resolved state. -1. Apply the _iterative auth checks algorithm_ based on the partial resolved state. -1. Update the result with the _unconflicted state_ to get the final resolved state[^5]. -(_Note_: this is different from the current algorithm, which considered different event types at distinct stages) +1. Take all power events and any events in their auth chains that appear in the + _full_ _conflicted set_ and order them by the _reverse topological power + ordering._ +1. Apply the _iterative auth checks_ algorithm based on the unconflicted state + map to get a partial set of resolved state. +1. Take all remaining events that weren't picked in step 1 and order them by + the _mainline ordering_ based on the power level in the partially resolved + state. +1. Apply the _iterative auth checks algorithm_ based on the partial resolved + state. +1. Update the result with the _unconflicted state_ to get the final resolved + state[^5]. (_Note_: this is different from the current algorithm, which + considered different event types at distinct stages) An example python implementation can be found on github [here](https://github.com/matrix-org/matrix-test-state-resolution-ideas). @@ -265,12 +322,11 @@ proposed algorithm. The proposed algorithm still has some potentially unexpected behaviour. -One example of this is when Alice sets a topic and then gets banned. If an -event gets created (potentially much later) that points to both before and -after the topic and ban then the proposed algorithm will resolve and apply the -ban before resolving the topic, causing the topic to be denied and dropped from -the resolved state. This will result in no topic being set in the resolved -state. +One example of this is when Alice sets a topic and then gets banned. If an event +gets created (potentially much later) that points to both before and after the +topic and ban then the proposed algorithm will resolve and apply the ban before +resolving the topic, causing the topic to be denied and dropped from the +resolved state. This will result in no topic being set in the resolved state. ### Auth Events @@ -299,9 +355,9 @@ authorization to do an action (and vice versa). For example, in the current model bans (basically) revoke the ability for a particular user from being able to join. If the user later gets unbanned and then rejoins, the join would point to the join rules as the authorization that lets them join, but would not -(necessarily) point to the unban. This has the effect that if a state -resolution happened between the new join and the ban, the unban would not be -included in the resolution and so the join would be rejected. +(necessarily) point to the unban. This has the effect that if a state resolution +happened between the new join and the ban, the unban would not be included in +the resolution and so the join would be rejected. The changes to the current model that would be required to make the above assumptions true would be, for example: @@ -309,8 +365,10 @@ assumptions true would be, for example: 1. By default permissions are closed. -1. Bans would need to be a list in either the join rules event or a separate event type which all membership events pointed to. -1. Bans would only revoke the ability to join, not automatically remove users from the room. +1. Bans would need to be a list in either the join rules event or a separate + event type which all membership events pointed to. +1. Bans would only revoke the ability to join, not automatically remove users + from the room. 1. Change the defaults of join_rules to be closed by default @@ -338,8 +396,11 @@ applying steps 3 and 4 to the state deltas. The properties are: 1. The delta contains no power events -1. The origin_server_ts of all events in state delta are strictly greater than those in the previous state sets -1. Any event that has been removed must not have been used to auth subsequent events (e.g. if we replaced a member event and that user had also set a topic) +1. The origin_server_ts of all events in state delta are strictly greater than + those in the previous state sets +1. Any event that has been removed must not have been used to auth subsequent + events (e.g. if we replaced a member event and that user had also set a + topic) These properties will likely hold true for most state updates that happen in a room, allowing servers to use this more efficient algorithm the majority of the @@ -425,23 +486,24 @@ This gives the resolved state at _Message 3_ to be _Topic 4_. ## Notes -[^1]: - In the current room protocol these are: the create event, power levels, membership, join rules and third party invites. See the [spec](https://matrix.org/docs/spec/server_server/unstable.html#pdu-fields). +[^1]: In the current room protocol these are: the create event, power levels, + membership, join rules and third party invites. See the + [spec](https://matrix.org/docs/spec/server_server/unstable.html#pdu-fields). -[^2]: - In the current protocol these are: power levels, kicks, bans and join rules. +[^2]: In the current protocol these are: power levels, kicks, bans and join + rules. -[^3]: - Future room versions may have a concept of server ban event that works like existing bans, which would also be included +[^3]: Future room versions may have a concept of server ban event that works + like existing bans, which would also be included -[^4]: - The topology being considered here is the auth chain DAG, rather than the room DAG, so this ordering is only applicable to events which appear in the auth chain DAG. +[^4]: The topology being considered here is the auth chain DAG, rather than the + room DAG, so this ordering is only applicable to events which appear in the + auth chain DAG. -[^5]: - We do this so that, if we receive events with misleading auth_events, this ensures that the unconflicted state at least is correct. +[^5]: We do this so that, if we receive events with misleading auth_events, this + ensures that the unconflicted state at least is correct. -[^6]: - This isn't true in the current protocol +[^6]: This isn't true in the current protocol From 9af5ecd080b5ebef7a952c4639774524ec83c7be Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 2 Aug 2018 14:24:25 +0100 Subject: [PATCH 014/219] Fixup definition of reverse topological power ordering --- proposals/1442-state-resolution.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proposals/1442-state-resolution.md b/proposals/1442-state-resolution.md index 4dd0fe7c0..61ee4611b 100644 --- a/proposals/1442-state-resolution.md +++ b/proposals/1442-state-resolution.md @@ -233,13 +233,13 @@ First we define: auth difference. * The **"reverse topological power ordering"**[^4] of a set of events is an ordering of the given events, plus any events in their auth chains that - appear in the auth difference, ordered such that x < y if: + appear in the auth difference, topologically ordered by their auth chains + with ties broken such that x < y if: - 1. x is in the auth chain of y, or if - 2. x's sender has a greater power level than y (calculated by looking at + 1. x's sender has a greater power level than y (calculated by looking at their respective auth events, or if - 3. x's origin_server_ts is less than y's, or if - 4. x's event_id is lexicographically less than y's + 2. x's origin_server_ts is less than y's, or if + 3. x's event_id is lexicographically less than y's This is also known as a lexicographical topological sort. From fa70e3e486952c942573ac2ce066f1b2e92a3713 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 2 Aug 2018 14:42:36 +0100 Subject: [PATCH 015/219] Mention why auth difference are useful --- proposals/1442-state-resolution.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/proposals/1442-state-resolution.md b/proposals/1442-state-resolution.md index 61ee4611b..ce36efa51 100644 --- a/proposals/1442-state-resolution.md +++ b/proposals/1442-state-resolution.md @@ -160,6 +160,14 @@ e.g. bans before events sent in other forks. (However events can point to old parts of the DAG, for a variety of reasons, and ideally in that case the resolved state would closely match the recent state). +Similarly care should be taken when multiple changes to e.g. power levels happen +in a fork. If Alice gives Bob power (A), then Bob gives Charlie power (B) and +then Charlie, say, changes the ban level (C). If you try and resolve two state +sets one of which has A and the other has C, C will not pass auth unless B is +also taken into account. This case can be handled if we also consider the +difference in auth chains between the two sets, which in the previous example +would include B. + ## Power Level Ordering @@ -362,8 +370,6 @@ the resolution and so the join would be rejected. The changes to the current model that would be required to make the above assumptions true would be, for example: - - 1. By default permissions are closed. 1. Bans would need to be a list in either the join rules event or a separate event type which all membership events pointed to. From 472f75d9a596b331f49fd0ab3c2a02ae80dfca9f Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 3 Aug 2018 12:18:41 +0100 Subject: [PATCH 016/219] Mention hotel california --- proposals/1442-state-resolution.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/proposals/1442-state-resolution.md b/proposals/1442-state-resolution.md index ce36efa51..9fd7da8a8 100644 --- a/proposals/1442-state-resolution.md +++ b/proposals/1442-state-resolution.md @@ -168,6 +168,14 @@ also taken into account. This case can be handled if we also consider the difference in auth chains between the two sets, which in the previous example would include B. +(This is also the root cause of the "Hotel California" issue, where left users +get spontaneously rejoined to rooms. This happens when a user has a sequence of +memberships changes of the form: leave (A), join (B) and then another leave (C). +In the current algorithm a resoluton of A and C would pick A, and a resolution +of A and B would then pick B, i.e. the join. This means that a suitably forked +graph can reset the state to B. This is fixed if when resolving A and C we also +consider B, since its in the auth chain of C.) + ## Power Level Ordering From dc499bc440ae38422f2041e4b2534579940c7756 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 3 Aug 2018 14:00:47 +0100 Subject: [PATCH 017/219] Expand on reverse topological power ordering --- proposals/1442-state-resolution.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/proposals/1442-state-resolution.md b/proposals/1442-state-resolution.md index 9fd7da8a8..1a2e82a35 100644 --- a/proposals/1442-state-resolution.md +++ b/proposals/1442-state-resolution.md @@ -257,7 +257,10 @@ First we define: 2. x's origin_server_ts is less than y's, or if 3. x's event_id is lexicographically less than y's - This is also known as a lexicographical topological sort. + This is also known as a lexicographical topological sort (i.e. this is the + unique topological ordering such that for an entry x all entries after it + must either have x in their auth chain or be greater than x as defined + above). This can be implemented using Kahn's algorithm. * The **"mainline ordering"** based on a power level event P of a set of events is calculated as follows: From 88b35d1be5e016958878af6890286023b31aa272 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 9 Aug 2018 08:30:50 -0600 Subject: [PATCH 018/219] Clarify how third party invites work This adds several diagrams to the Client-Server API about how invites are handled, including what the server is expected to do. This helps implementors know what they are supposed to do in the common cases, and infer where needed to get the more complex cases correct. Although lacking in some areas, this is how third party invites work today. A link to the now-improved client-server documentation for third party invites has been added to the server-server specification. The existing server-server specification needed no further changes on the subject. Fixes https://github.com/matrix-org/matrix-doc/issues/1366 --- api/identity/pubkey.yaml | 2 +- specification/modules/third_party_invites.rst | 205 +++++++++++++----- specification/server_server_api.rst | 4 + 3 files changed, 158 insertions(+), 53 deletions(-) diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 00796975d..5ea6341fc 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -56,7 +56,7 @@ paths: get: summary: Check whether a long-term public key is valid. description: |- - Check whether a long-term public key is valid. + Check whether a long-term public key is valid. The request must be idempotent. operationId: isPubKeyValid parameters: - in: query diff --git a/specification/modules/third_party_invites.rst b/specification/modules/third_party_invites.rst index 9ea0eb0b2..a9b06258b 100644 --- a/specification/modules/third_party_invites.rst +++ b/specification/modules/third_party_invites.rst @@ -40,6 +40,7 @@ with ``content.membership`` = ``invite``, as well as a ``content.third_party_invite`` property which contains proof that the invitee does indeed own that third party identifier. + Events ------ @@ -55,41 +56,79 @@ A client asks a server to invite a user by their third party identifier. Server behaviour ---------------- -All homeservers MUST verify the signature in the event's -``content.third_party_invite.signed`` object. - -When a homeserver inserts an ``m.room.member`` ``invite`` event into the graph -because of an ``m.room.third_party_invite`` event, -that homesever MUST validate that the public -key used for signing is still valid, by checking ``key_validity_url`` from the ``m.room.third_party_invite``. It does -this by making an HTTP GET request to ``key_validity_url``: - -.. TODO: Link to identity server spec when it exists +Upon receipt of an ``/invite``, 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: + +:: + + +---------+ +-------------+ +-----------------+ + | Client | | Homeserver | | IdentityServer | + +---------+ +-------------+ +-----------------+ + | | | + | POST /invite | | + |------------------------------------>| | + | | | + | | GET /lookup | + | |--------------------------------------------------->| + | | | + | | User ID result | + | |<---------------------------------------------------| + | | | + | | Invite process for the discovered User ID | + | |------------------------------------------ | + | | | | + | |<----------------------------------------- | + | | | + | Complete the /invite request | | + |<------------------------------------| | + | | | + + +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: + +:: + + +---------+ +-------------+ +-----------------+ + | Client | | Homeserver | | IdentityServer | + +---------+ +-------------+ +-----------------+ + | | | + | POST /invite | | + |------------------------------------>| | + | | | + | | GET /lookup | + | |-------------------------------------------------------------->| + | | | + | | "no users" result | + | |<--------------------------------------------------------------| + | | | + | | POST /store-invite | + | |-------------------------------------------------------------->| + | | | + | | Information needed for the m.room.third_party_invite | + | |<--------------------------------------------------------------| + | | | + | | Emit m.room.third_party_invite to the room | + | |------------------------------------------- | + | | | | + | |<------------------------------------------ | + | | | + | Complete the /invite request | | + |<------------------------------------| | + | | | -Schema:: - => GET $key_validity_url?public_key=$public_key - <= HTTP/1.1 200 OK - { - "valid": true|false - } - - -Example:: - - key_validity_url = https://identity.server/is_valid - public_key = ALJWLAFQfqffQHFqFfeqFUOEHf4AIHfefh4 - => GET https://identity.server/is_valid?public_key=ALJWLAFQfqffQHFqFfeqFUOEHf4AIHfefh4 - <= HTTP/1.1 200 OK - { - "valid": true - } +All homeservers MUST verify the signature in the event's +``content.third_party_invite.signed`` object. -with the querystring -?public_key=``public_key``. A JSON object will be returned. -The invitation is valid if the object contains a key named ``valid`` which is -``true``. Otherwise, the invitation MUST be rejected. This request is -idempotent and may be retried by the homeserver. +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. 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 in the @@ -102,26 +141,85 @@ No other homeservers may reject the joining of the room on the basis of the room. They may, however, indicate to their clients that a member's' membership is questionable. -For example: - -#. Room R has two participating homeservers, H1, H2 - -#. User A on H1 invites a third party identifier to room R - -#. H1 asks the identity server for a binding to a Matrix user ID, and has none, - so issues an ``m.room.third_party_invite`` event to the room. - -#. When the third party user validates their identity, their homeserver H3 - is notified and attempts to issue an ``m.room.member`` event to participate - in the room. - -#. H3 validates the signature given to it by the identity server. - -#. H3 then asks H1 to join it to the room. H1 *must* validate the ``signed`` - property *and* check ``key_validity_url``. - -#. Having validated these things, H1 writes the invite event to the room, and H3 - begins participating in the room. H2 *must* accept this event. +For example, given H1, H2, and H3 as homeservers, UserA as a user of H1, and an +identity server IS, the full sequence for a third party invite would look like +the following. This diagram assumes H1 and H2 are residents of the room while +H3 is attempting to join. + +:: + + +-------+ +-----------------+ +-----+ +-----+ +-----+ +-----+ + | UserA | | ThirdPartyUser | | H1 | | H2 | | H3 | | IS | + +-------+ +-----------------+ +-----+ +-----+ +-----+ +-----+ + | | | | | | + | POST /invite for ThirdPartyUser | | | | + |----------------------------------->| | | | + | | | | | | + | | | GET /lookup | | | + | | |---------------------------------------------------------------------------------------------->| + | | | | | | + | | | | Lookup results (empty object) | + | | |<----------------------------------------------------------------------------------------------| + | | | | | | + | | | POST /store-invite | | | + | | |---------------------------------------------------------------------------------------------->| + | | | | | | + | | | | Token, keys, etc for third party invite | + | | |<----------------------------------------------------------------------------------------------| + | | | | | | + | | | (Federation) Emit m.room.third_party_invite | | | + | | |----------------------------------------------->| | | + | | | | | | + | Complete /invite request | | | | + |<-----------------------------------| | | | + | | | | | | + | | Verify identity | | | | + | |-------------------------------------------------------------------------------------------------------------------->| + | | | | | | + | | | | | POST /3pid/onbind | + | | | | |<---------------------------| + | | | | | | + | | | PUT /exchange_third_party_invite/:roomId | | + | | |<-----------------------------------------------------------------| | + | | | | | | + | | | Verify the request | | | + | | |------------------- | | | + | | | | | | | + | | |<------------------ | | | + | | | | | | + | | | (Federation) Emit m.room.member for invite | | | + | | |----------------------------------------------->| | | + | | | | | | + | | | | Accept event | | + | | | |------------- | | + | | | | | | | + | | | |<------------ | | + | | | | | | + | | | (Federation) Emit the m.room.member event sent to H2 | | + | | |----------------------------------------------------------------->| | + | | | | | | + | | | Complete /exchange_third_party_invite/:roomId request | | + | | |----------------------------------------------------------------->| | + | | | | | | + | | | | | Participate in the room | + | | | | |------------------------ | + | | | | | | | + | | | | |<----------------------- | + | | | | | | + + +Note that when H1 sends the ``m.room.member`` event to H2 and H3 it does not +have to block on either server's receipt of the event. Likewise, H1 may complete +the ``/exchange_third_party_invite/:roomId`` request at the same time as sending +the ``m.room.member`` event to H2 and H3. Additionally, H3 may complete the +``/3pid/onbind`` request it got from IS 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`_ endpoint, using the provided URL +rather than constructing a new one. The query string and response for the provided +URL must match the Identity Server specification. The reason that no other homeserver may reject the event based on checking ``key_validity_url`` is that we must ensure event acceptance is deterministic. @@ -158,3 +256,6 @@ There is some risk of denial of service attacks by flooding homeservers or identity servers with many requests, or much state to store. Defending against these is left to the implementer's discretion. + + +.. _`Identity Server /isvalid`: ../identity_service/unstable.html#get-matrix-identity-api-v1-pubkey-isvalid diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 472aca125..b8df0b476 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -734,6 +734,10 @@ event to other servers in the room. Third-party invites ------------------- +.. NOTE:: + More information about third party invites is available in the `Client-Server API`_ + under the Third Party Invites module. + When an user wants to invite another user in a room but doesn't know the Matrix ID to invite, they can do so using a third-party identifier (e.g. an e-mail or a phone number). From a556e33eb9d606efeea321466678ba1ed2c3c379 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 13 Aug 2018 16:59:36 -0600 Subject: [PATCH 019/219] Spec /3pid/onbind Fixes https://github.com/matrix-org/matrix-doc/issues/1422 --- api/server-server/third_party_invite.yaml | 123 ++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/api/server-server/third_party_invite.yaml b/api/server-server/third_party_invite.yaml index 754a3282e..2225bf1a4 100644 --- a/api/server-server/third_party_invite.yaml +++ b/api/server-server/third_party_invite.yaml @@ -190,3 +190,126 @@ paths: type: object description: An empty object example: {} + "/3pid/onbind": + put: + summary: |- + Notifies the server that a third party identifier has been bound to one + of its users. + description: |- + Used by Identity Servers to notify the homeserver that one of its users + has bound a third party identifier successfully, including any pending + room invites the Identity Server has been made aware of. + operationId: onBindThirdPartyIdentifier + parameters: + - in: body + name: body + type: object + required: true + schema: + type: object + properties: + medium: + type: string + description: |- + The type of third party identifier. Currently only "email" is + a possible value. + example: "email" + address: + type: string + description: |- + The third party identifier itself. For example, an email address. + example: "alice@domain.com" + mxid: + type: string + description: The user that is now bound to the third party identifier. + example: "@alice:matrix.org" + invites: + type: array + description: |- + A list of pending invites that the third party identifier has received. + items: + type: object + title: Third Party Invite + properties: + medium: + type: string + description: |- + The type of third party invite issues. Currently only + "email" is used. + example: "email" + address: + type: string + description: |- + The third party identifier that received the invite. + example: "alice@domain.com" + mxid: + type: string + description: The now-bound user ID that received the invite. + example: "@alice:matrix.org" + room_id: + type: string + description: The room ID the invite is valid for. + example: "!somewhere:example.org" + sender: + type: string + description: The user ID that sent the invite. + 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'] + required: + - medium + - address + - mxid + - room_id + - sender + - signed + required: ['medium', 'address', 'mxid', 'invites'] + responses: + 200: + description: The homeserver has processed the notification. + examples: + application/json: {} + schema: + type: object + description: An empty object + example: {} From fcca80dad8329332733a23038a9840db397af4c8 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 14 Aug 2018 17:58:57 -0400 Subject: [PATCH 020/219] various minor fixes - formatting fixes - add examples to homeserver/identity server discovery schema - replace DNS name with hostname --- .../definitions/wellknown/homeserver.yaml | 7 ++++--- .../definitions/wellknown/identity_server.yaml | 7 ++++--- api/client-server/wellknown.yaml | 8 ++++---- specification/client_server_api.rst | 14 +++++++------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/api/client-server/definitions/wellknown/homeserver.yaml b/api/client-server/definitions/wellknown/homeserver.yaml index 7efba8169..92ff34ed3 100644 --- a/api/client-server/definitions/wellknown/homeserver.yaml +++ b/api/client-server/definitions/wellknown/homeserver.yaml @@ -16,8 +16,9 @@ description: |- Used by clients to discover homeserver information. type: object properties: - base_url: - type: string - description: The base URL for the homeserver for client-server connections. + base_url: + type: string + description: The base URL for the homeserver for client-server connections. + example: https://matrix.example.com required: - base_url diff --git a/api/client-server/definitions/wellknown/identity_server.yaml b/api/client-server/definitions/wellknown/identity_server.yaml index eb0e0bafc..a8f7c31cf 100644 --- a/api/client-server/definitions/wellknown/identity_server.yaml +++ b/api/client-server/definitions/wellknown/identity_server.yaml @@ -16,8 +16,9 @@ description: |- Used by clients to discover identity server information. type: object properties: - base_url: - type: string - description: The base URL for the identity server for client-server connections. + base_url: + type: string + description: The base URL for the identity server for client-server connections. + example: https://identity.example.com required: - base_url diff --git a/api/client-server/wellknown.yaml b/api/client-server/wellknown.yaml index 8d19f38a8..24e190f96 100644 --- a/api/client-server/wellknown.yaml +++ b/api/client-server/wellknown.yaml @@ -13,7 +13,7 @@ # limitations under the License. swagger: '2.0' info: - title: "Matrix Client-Server server discovery API" + title: "Matrix Client-Server Server Discovery API" version: "1.0.0" host: localhost:8008 schemes: @@ -26,7 +26,7 @@ paths: get: summary: Gets Matrix server discovery information about the domain. description: |- - Gets discovery information about the domain. The file may include + Gets discovery information about the domain. The file may include additional keys, which MUST follow the Java package naming convention, e.g. ``com.example.myapp.property``. This ensures property names are suitably namespaced for each application and reduces the risk of @@ -37,7 +37,7 @@ paths: operationId: getWellknown responses: 200: - description: Server discovery information + description: Server discovery information. examples: application/json: { "m.homeserver": { @@ -61,6 +61,6 @@ paths: required: - m.homeserver 404: - description: No server discovery information available + description: No server discovery information available. tags: - Server administration diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index 6d5645241..d2b7aa61f 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -219,12 +219,12 @@ Well-known URI ++++++++++++++ The ``.well-known`` method uses a JSON file at a predetermined location to -specify parameter values. The flow for this method is as follows: +specify parameter values. The flow for this method is as follows: 1. Extract the server name from the user's Matrix ID by splitting the Matrix ID at the first colon. -2. Extract the DNS name from the server name. -3. Make a GET request to ``https://dns_name/.well-known/matrix/client``. +2. Extract the hostname from the server name. +3. Make a GET request to ``https://hostname/.well-known/matrix/client``. a. If the returned status code is 404, then ``IGNORE``. b. If the returned status code is not 200, or the response body is empty, @@ -233,17 +233,17 @@ specify parameter values. The flow for this method is as follows: i. If the content cannot be parsed, then ``FAIL_PROMPT``. - d. Extract the ``base_url`` value from the ``m.homeserver`` property. This + d. Extract the ``base_url`` value from the ``m.homeserver`` property. This value is to be used as the base URL of the homeserver. i. If this value is not provided, then ``FAIL_PROMPT``. e. Validate the homeserver base URL: - i. Parse it as a URL. If it is not a URL, then ``FAIL_ERROR``. + i. Parse it as a URL. If it is not a URL, then ``FAIL_ERROR``. ii. Clients SHOULD validate that the URL points to a valid homeserver before accepting it by connecting to the ``/_matrix/client/versions`` - endpoint, and parsing and validating the data. If any step in the + endpoint, and parsing and validating the data. If any step in the validation fails, then ``FAIL_ERROR``. Validation is done as a simple check against configuration errors, before sending sensitive information such as a user's password to the server. @@ -251,7 +251,7 @@ specify parameter values. The flow for this method is as follows: f. If the ``m.identity_server`` property is present, extract the ``base_url`` value for use as the base URL of the identity server. Validation for this URL is done as in the step above, but using - ``/_matrix/identity/api/v1`` as the endpoint to connect to. If the + ``/_matrix/identity/api/v1`` as the endpoint to connect to. If the ``m.identity_server`` property is present, but does not have a ``base_url`` value, then ``FAIL_ERROR``. From a264120b387a52d8506057148b681d1faf938c1c Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 14 Aug 2018 18:06:03 -0400 Subject: [PATCH 021/219] put server discovery as its own section --- specification/client_server_api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index d2b7aa61f..d775f2c04 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -183,7 +183,7 @@ headers to be returned by servers on all requests are: Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization Server Discovery -~~~~~~~~~~~~~~~~ +---------------- In order to allow users to connect to a Matrix server without needing to explicitly specify the homeserver's URL or other parameters, clients SHOULD use @@ -216,7 +216,7 @@ In this section, the following terms are used with specific meanings: what to do next. Well-known URI -++++++++++++++ +~~~~~~~~~~~~~~ The ``.well-known`` method uses a JSON file at a predetermined location to specify parameter values. The flow for this method is as follows: From ba51d5960ecbc7b820235ad75765c06ccd4da379 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 16 Aug 2018 11:44:48 -0600 Subject: [PATCH 022/219] r0.1.0 release of the Push Gateway specification Because this is the first release, it has several moving parts to it: * The version variables have been defined. * The towncrier changelog has been prepared for future modifications. * The templating has been updated to better support future versions of the specification. * A release process document has been created. --- api/push-gateway/push_notifier.yaml | 2 +- changelogs/push_gateway.rst | 6 +++ .../push_gateway/newsfragments/.gitignore | 1 + changelogs/push_gateway/pyproject.toml | 30 ++++++++++++ meta/releasing_a_spec.md | 47 +++++++++++++++++++ scripts/gendoc.py | 6 +++ .../templating/matrix_templates/sections.py | 5 ++ scripts/templating/matrix_templates/units.py | 5 +- specification/push_gateway.rst | 19 +++++++- specification/targets.yaml | 2 +- 10 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 changelogs/push_gateway.rst create mode 100644 changelogs/push_gateway/newsfragments/.gitignore create mode 100644 changelogs/push_gateway/pyproject.toml create mode 100644 meta/releasing_a_spec.md diff --git a/api/push-gateway/push_notifier.yaml b/api/push-gateway/push_notifier.yaml index 4a6cb8f75..21c1ea29b 100644 --- a/api/push-gateway/push_notifier.yaml +++ b/api/push-gateway/push_notifier.yaml @@ -20,7 +20,7 @@ host: localhost:8008 schemes: - https - http -basePath: /_matrix/push/v1 +basePath: /_matrix/push/%PUSH_GATEWAY_MAJOR_VERSION% consumes: - application/json produces: diff --git a/changelogs/push_gateway.rst b/changelogs/push_gateway.rst new file mode 100644 index 000000000..33a7683c1 --- /dev/null +++ b/changelogs/push_gateway.rst @@ -0,0 +1,6 @@ +r0.1.0 +====== + +The first release of the Push Gateway specification. This release contains +a single endpoint, ``/notify``, that pushers may use to send push notifications +to clients. diff --git a/changelogs/push_gateway/newsfragments/.gitignore b/changelogs/push_gateway/newsfragments/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/changelogs/push_gateway/newsfragments/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/changelogs/push_gateway/pyproject.toml b/changelogs/push_gateway/pyproject.toml new file mode 100644 index 000000000..dad1bc04b --- /dev/null +++ b/changelogs/push_gateway/pyproject.toml @@ -0,0 +1,30 @@ +[tool.towncrier] + filename = "../push_gateway.rst" + directory = "newsfragments" + issue_format = "`#{issue} `_" + title_format = "{version}" + + [[tool.towncrier.type]] + directory = "breaking" + name = "Breaking Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "new" + name = "New Endpoints" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Backwards Compatible Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "clarification" + name = "Spec Clarifications" + showcontent = true diff --git a/meta/releasing_a_spec.md b/meta/releasing_a_spec.md new file mode 100644 index 000000000..cd7033fcb --- /dev/null +++ b/meta/releasing_a_spec.md @@ -0,0 +1,47 @@ +# How to release a specification + +There are several specifications that belong to matrix, such as the client-server +specification, server-server specification, and identity server specification. Each +of these gets released independently of each other with their own version numbers. + +Once a specification is ready for release, a branch should be created to track the +changes in. This should be the name of the specification (as it appears in the directory +structure of this project) followed by a forward slash and the version being released, +followed by `_updates`. For example, if the Client-Server Specification was getting +an r0.4.0 release, the branch name would be `client_server/r0.4.0_updates`. + +*Note*: Historical releases prior to this process may or may not have an appropriate +release branch. Releases after this document came into place will have an appropriate +branch. + +The remainder of the process is as follows: +1. Activate your Python 3 virtual environment. +1. Having checked out the new release branch, navigate your way over to `./changelogs`. +1. Follow the release instructions provided in the README.md located there. +1. Update the changelog section of the specification you're releasing to make a reference + to the new version. +1. Update any version/link references across all specifications. +1. Update the index to list the version correctly. +1. Add the changes to the matrix-org/matrix.org repository (for historic tracking). + * This is done by making a PR to the `unstyled_docs/spec` folder for the version and + specification you're releasing. +1. Commit the changes and PR them to master. +1. Tag the release with the format `client_server/r0.4.0`. +1. Perform a release on GitHub to tag the release. +1. Yell from the mountaintop to the world about the new release. + +### Creating a release for a brand-new specification + +Some specifications may not have ever had a release, and therefore need a bit more work +to become ready. + +1. Activate your Python 3 virtual environment. +1. Having checked out the new release branch, navigate your way over to `./changelogs`. +1. Follow the "new changelog" instructions provided in the README.md located there. +1. Open the specification RST file and make some changes: + * Using a released specification as a template, update the changelog section. + * Use the appropriate changelog variable in the RST. +1. Create/define the appropriate variables in `gendoc.py`. +1. Update `targets.yml`. +1. Update any version/link references across all specifications. +1. Follow the regular release process. diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 16c40af5d..042e3d9dd 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -518,6 +518,10 @@ if __name__ == '__main__': "--server_release", "-s", action="store", default="unstable", help="The server-server release tag to generate, e.g. r1.2" ) + parser.add_argument( + "--push_gateway_release", "-p", action="store", default="unstable", + help="The push gateway release tag to generate, e.g. r1.2" + ) parser.add_argument( "--list_targets", action="store_true", help="Do not update the specification. Instead print a list of targets.", @@ -542,6 +546,8 @@ if __name__ == '__main__': "%CLIENT_MAJOR_VERSION%": "r0", "%SERVER_RELEASE_LABEL%": args.server_release, "%SERVER_MAJOR_VERSION%": extract_major(args.server_release), + "%PUSH_GATEWAY_MAJOR_VERSION%": "v1", + "%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release, } exit (main(args.target or ["all"], args.dest, args.nodelete, substitutions)) diff --git a/scripts/templating/matrix_templates/sections.py b/scripts/templating/matrix_templates/sections.py index 1a93c7237..65ed7f6d0 100644 --- a/scripts/templating/matrix_templates/sections.py +++ b/scripts/templating/matrix_templates/sections.py @@ -31,6 +31,11 @@ class MatrixSections(Sections): def render_client_server_changelog(self): changelogs = self.units.get("changelogs") return changelogs["client_server"] + + # TODO: We should make this a generic variable instead of having to add functions all the time. + def render_push_gateway_changelog(self): + changelogs = self.units.get("changelogs") + return changelogs["push_gateway"] def _render_events(self, filterFn, sortFn): template = self.env.get_template("events.tmpl") diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 90a87cd47..c400b691e 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -754,6 +754,7 @@ class MatrixUnits(Units): def load_apis(self, substitutions): cs_ver = substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable") fed_ver = substitutions.get("%SERVER_RELEASE_LABEL%", "unstable") + push_gw_ver = substitutions.get("%PUSH_GATEWAY_RELEASE_LABEL%", "unstable") # we abuse the typetable to return this info to the templates return TypeTable(rows=[ @@ -774,8 +775,8 @@ class MatrixUnits(Units): "unstable", "Mapping of third party IDs to Matrix IDs", ), TypeTableRow( - "`Push Gateway API `_", - "unstable", + "`Push Gateway API `_", + push_gw_ver, "Push notifications for Matrix events", ), ]) diff --git a/specification/push_gateway.rst b/specification/push_gateway.rst index e4a9d6ea8..e46238875 100644 --- a/specification/push_gateway.rst +++ b/specification/push_gateway.rst @@ -1,4 +1,5 @@ .. Copyright 2016 OpenMarket Ltd +.. 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. @@ -21,13 +22,27 @@ the homeserver. This is managed by a distinct entity called the Push Gateway. .. contents:: Table of Contents .. sectnum:: -Specification version ---------------------- +Changelog +--------- + +.. topic:: Version: %PUSH_GATEWAY_RELEASE_LABEL% +{{push_gateway_changelog}} This version of the specification is generated from `matrix-doc `_ as of Git commit `{{git_version}} `_. +For the full historical changelog, see +https://github.com/matrix-org/matrix-doc/blob/master/changelogs/push_gateway.rst + +Other versions of this specification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following other versions are also available, in reverse chronological order: + +- `HEAD `_: Includes all changes since the latest versioned release. +- `r0.1.0 `_ + Overview -------- diff --git a/specification/targets.yaml b/specification/targets.yaml index 53957e0af..db8693307 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -25,7 +25,7 @@ targets: push_gateway: files: - push_gateway.rst - version_label: unstable + version_label: "%PUSH_GATEWAY_RELEASE_LABEL%" appendices: files: - appendices.rst From 17a0dcc7d396a1ce9ca55141a5491e47b62c1f62 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 16 Aug 2018 23:11:07 +0100 Subject: [PATCH 023/219] add newsfragment for #1176 --- changelogs/client_server/newsfragments/1176.new | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1176.new diff --git a/changelogs/client_server/newsfragments/1176.new b/changelogs/client_server/newsfragments/1176.new new file mode 100644 index 000000000..41e30799b --- /dev/null +++ b/changelogs/client_server/newsfragments/1176.new @@ -0,0 +1 @@ +Specify how to control the power level required for ``@room`` \ No newline at end of file From 3de50cbc7f9b9187b426108f810eab9516586560 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 17 Aug 2018 09:49:09 -0600 Subject: [PATCH 024/219] Clarify how /isvalid is meant to always be truthful --- api/identity/pubkey.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 5ea6341fc..1cd7b94cd 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -56,7 +56,8 @@ paths: get: summary: Check whether a long-term public key is valid. description: |- - Check whether a long-term public key is valid. The request must be idempotent. + Check whether a long-term public key is valid. The response should always + be the same, provided the key exists. operationId: isPubKeyValid parameters: - in: query From 6612dbecf182399af05403bc60097819382476ab Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Fri, 17 Aug 2018 11:54:14 -0400 Subject: [PATCH 025/219] tweak wording for validation --- specification/client_server_api.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index d775f2c04..1a566aa03 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -242,11 +242,13 @@ specify parameter values. The flow for this method is as follows: i. Parse it as a URL. If it is not a URL, then ``FAIL_ERROR``. ii. Clients SHOULD validate that the URL points to a valid homeserver - before accepting it by connecting to the ``/_matrix/client/versions`` - endpoint, and parsing and validating the data. If any step in the - validation fails, then ``FAIL_ERROR``. Validation is done as a simple - check against configuration errors, before sending sensitive - information such as a user's password to the server. + before accepting it by connecting to the |/_matrix/client/versions|_ + endpoint, ensuring that it does not return an error, and parsing and + validating that the data conforms with the expected response + format. If any step in the validation fails, then + ``FAIL_ERROR``. Validation is done as a simple check against + configuration errors, in order to ensure that the discovered address + points to a valid homeserver. f. If the ``m.identity_server`` property is present, extract the ``base_url`` value for use as the base URL of the identity server. @@ -1649,5 +1651,8 @@ have to wait in milliseconds before they can try again. .. |/user//account_data/| replace:: ``/user//account_data/`` .. _/user//account_data/: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type +.. |/_matrix/client/versions| replace:: ``/_matrix/client/versions`` +.. _/_matrix/client/versions: #get-matrix-client-versions + .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 .. _`3PID Types`: ../appendices.html#pid-types From 5b73a0174dec6889d00aba7488ffd79df9c319dc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 20 Aug 2018 14:05:23 -0600 Subject: [PATCH 026/219] Clarify what the release branch is used for, and how it should be named --- meta/releasing_a_spec.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/meta/releasing_a_spec.md b/meta/releasing_a_spec.md index cd7033fcb..078d71789 100644 --- a/meta/releasing_a_spec.md +++ b/meta/releasing_a_spec.md @@ -5,10 +5,10 @@ specification, server-server specification, and identity server specification. E of these gets released independently of each other with their own version numbers. Once a specification is ready for release, a branch should be created to track the -changes in. This should be the name of the specification (as it appears in the directory -structure of this project) followed by a forward slash and the version being released, -followed by `_updates`. For example, if the Client-Server Specification was getting -an r0.4.0 release, the branch name would be `client_server/r0.4.0_updates`. +changes in and to hold potential future hotfixes. This should be the name of the +specification (as it appears in the directory structure of this project) followed +by "release-" and the release version. For example, if the Client-Server Specification +was getting an r0.4.0 release, the branch name would be `client_server/release-r0.4.0`. *Note*: Historical releases prior to this process may or may not have an appropriate release branch. Releases after this document came into place will have an appropriate From e141f61df3a1d8305b3644ba516a1260f41744ec Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 20 Aug 2018 14:05:48 -0600 Subject: [PATCH 027/219] Update release instructions to reference symlinks, what files to update, etc --- meta/releasing_a_spec.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/meta/releasing_a_spec.md b/meta/releasing_a_spec.md index 078d71789..3a9da8938 100644 --- a/meta/releasing_a_spec.md +++ b/meta/releasing_a_spec.md @@ -21,12 +21,13 @@ The remainder of the process is as follows: 1. Update the changelog section of the specification you're releasing to make a reference to the new version. 1. Update any version/link references across all specifications. -1. Update the index to list the version correctly. +1. Ensure the `targets.yml` file lists the version correctly. +1. Commit the changes and PR them to master. +1. Tag the release with the format `client_server/r0.4.0`. 1. Add the changes to the matrix-org/matrix.org repository (for historic tracking). * This is done by making a PR to the `unstyled_docs/spec` folder for the version and specification you're releasing. -1. Commit the changes and PR them to master. -1. Tag the release with the format `client_server/r0.4.0`. + * Don't forget to symlink the new release as `latest`. 1. Perform a release on GitHub to tag the release. 1. Yell from the mountaintop to the world about the new release. From 339a2748e806a8a42925afd0384521cafbd57d2d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 21 Aug 2018 09:49:41 -0600 Subject: [PATCH 028/219] Take out groups for now; Move namespace mention Groups aren't landing in the spec yet, so we shouldn't include them yet. --- specification/application_service_api.rst | 31 +++++------------------ 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 9e84339f6..258f80c0d 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -75,8 +75,7 @@ said to be interested in a given event if one of the application service's names users is the target of the event, or is a joined member of the room where the event occurred. -An application -service can also state whether they should be the only ones who +An application service can also state whether they should be the only ones who can manage a specified namespace. This is referred to as an "exclusive" namespace. An exclusive namespace prevents humans and other application services from creating/deleting entities in that namespace. Typically, @@ -91,7 +90,6 @@ regular expressions and look like: users: - exclusive: true regex: "@_irc.freenode.net_.*" - group_id: "+irc:matrix.org" Application services may define the following namespaces (with none being explicitly required): @@ -115,22 +113,11 @@ Each individual namespace MUST declare the following fields: | regex | **Required** A regular expression defining which values this namespace includes. | +------------------+-----------------------------------------------------------------------------------------------------------------------------------+ -An application service's users and regex field MUST begin with an underscore (``_``), in -order to provide a visually clear distinction between AS users and regular -users. An optional ``group_id`` field may be added to the ``users`` namespace: - -+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Name | Description | -+==================+============================================================================================================================================================================================================================================================================+ -| group_id | An existing group that all matching user IDs will be considered a part of. Users who are joined to this group through an application service are not to be listed when querying for the group's members, however the group should be listed when querying a user's groups. | -+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -.. WARNING:: - - Users that are matched by ``group_id`` should not be publicly listed by - Homeservers. The intention is to differentiate users, perhaps with a flair, - rather than having a list of people to spam. - +Exclusive user and alias namespaces should begin with an underscore after the +sigil to avoid collisions with other users on the homeserver. Application +services should additionally attempt to identify the service they represent +in the reserved namespace. For example, ``@_irc_.*`` would be a good namespace +to register for an application service which deals with IRC. The registration is represented by a series of key-value pairs, which this specification will present as YAML. See below for the possible options along @@ -174,12 +161,6 @@ An example registration file for an IRC-bridging application service is below: regex: "#_irc_bridge_.*" rooms: [] -Exclusive user and alias namespaces should begin with an underscore after the -sigil to avoid collisions with other users on the homeserver. Application -services should additionally attempt to identify the service they represent -in the reserved namespace. For example, ``@_irc_.*`` would be a good namespace -to register for an application service which deals with IRC. - .. WARNING:: If the homeserver in question has multiple application services, each ``as_token`` and ``id`` MUST be unique per application service as these are From 2d8a321b4629859d15b938b9bf9463dfa2569604 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 31 Jul 2018 17:27:50 +0200 Subject: [PATCH 029/219] document key sharing and m.room_key_request --- .../m.room_key_request#cancel_request | 8 +++ .../examples/m.room_key_request#request | 14 +++++ event-schemas/schema/m.room_key_request | 59 +++++++++++++++++++ .../modules/end_to_end_encryption.rst | 18 ++++++ 4 files changed, 99 insertions(+) create mode 100644 event-schemas/examples/m.room_key_request#cancel_request create mode 100644 event-schemas/examples/m.room_key_request#request create mode 100644 event-schemas/schema/m.room_key_request diff --git a/event-schemas/examples/m.room_key_request#cancel_request b/event-schemas/examples/m.room_key_request#cancel_request new file mode 100644 index 000000000..c6eb25de8 --- /dev/null +++ b/event-schemas/examples/m.room_key_request#cancel_request @@ -0,0 +1,8 @@ +{ + "content": { + "action": "cancel_request", + "requesting_device_id": "RJYKSTBOIE", + "request_id": "1495474790150.19" + }, + "type": "m.room_key_request" +} diff --git a/event-schemas/examples/m.room_key_request#request b/event-schemas/examples/m.room_key_request#request new file mode 100644 index 000000000..8557f08e8 --- /dev/null +++ b/event-schemas/examples/m.room_key_request#request @@ -0,0 +1,14 @@ +{ + "content": { + "body": { + "algorithm": "m.megolm.v1.aes-sha2", + "room_id": "!Cuyf34gef24t:localhost", + "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ", + "sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU" + }, + "action": "request", + "requesting_device_id": "RJYKSTBOIE", + "request_id": "1495474790150.19" + }, + "type": "m.room_key_request" +} diff --git a/event-schemas/schema/m.room_key_request b/event-schemas/schema/m.room_key_request new file mode 100644 index 000000000..6893dd783 --- /dev/null +++ b/event-schemas/schema/m.room_key_request @@ -0,0 +1,59 @@ +--- +allOf: + - $ref: core-event-schema/event.yaml + +description: |- + This event type is used to request keys for end-to-end encryption. It is sent as an + unencrypted `to-device`_ event. +properties: + content: + properties: + body: + description: Information about the requested key. + properties: + algorithm: + type: string + description: |- + The encryption algorithm the requested key in this event is to be used + with. + room_id: + type: string + description: The room where the key is used. + sender_key: + type: string + description: |- + The Curve25519 key of the device which initiated the session originally. + session_id: + type: string + description: The ID of the session holding the key. + required: + - algorithm + - room_id + - session_id + - sender_key + type: object + title: RequestedKeyInfo + action: + enum: + - request + - cancel_request + type: string + requesting_device_id: + description: ID of the device requesting the key. + type: string + request_id: + description: |- + A random string uniquely identifying the request for a key. If the key is + requested multiple times, it should be reused. It should also reused in order + to cancel a request. + type: string + required: + - action + - requesting_device_id + - request_id + type: object + type: + enum: + - m.room_key_request + type: string +type: object diff --git a/specification/modules/end_to_end_encryption.rst b/specification/modules/end_to_end_encryption.rst index fa461cc28..e235e2e9e 100644 --- a/specification/modules/end_to_end_encryption.rst +++ b/specification/modules/end_to_end_encryption.rst @@ -283,6 +283,20 @@ Device verification may reach one of several conclusions. For example: decrypted by such a device. For the Olm protocol, this is documented at https://matrix.org/git/olm/about/docs/signing.rst. +Key sharing +----------- + +If Bob has an encrypted conversation with Alice on his computer, and then logs in +through his phone for the first time, he may want to have access to the previously +exchanged messages. To address this issue, events exist for requesting and sending +keys from device to device. + +.. NOTE:: + + Key sharing can be a big attack vector, thus it must be done very carefully. + A reasonable stategy is for a user's client to only send keys requested by the + verified devices of the same user. + Messaging Algorithms -------------------- @@ -464,6 +478,10 @@ Events {{m_room_key_event}} +{{m_room_key_request_event}} + +{{m_forwarded_room_key_event}} + Key management API ~~~~~~~~~~~~~~~~~~ From 019c290fa2e4aef1e0b98aad358d5a35fef45c50 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 1 Aug 2018 00:25:31 +0200 Subject: [PATCH 030/219] document m.forwarded_room_key --- event-schemas/examples/m.forwarded_room_key | 14 +++++ event-schemas/schema/m.forwarded_room_key | 58 +++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 event-schemas/examples/m.forwarded_room_key create mode 100644 event-schemas/schema/m.forwarded_room_key diff --git a/event-schemas/examples/m.forwarded_room_key b/event-schemas/examples/m.forwarded_room_key new file mode 100644 index 000000000..8ab85c48d --- /dev/null +++ b/event-schemas/examples/m.forwarded_room_key @@ -0,0 +1,14 @@ +{ + "content": { + "algorithm": "m.megolm.v1.aes-sha2", + "room_id": "!Cuyf34gef24t:localhost", + "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ", + "session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf...", + "sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU", + "sender_claimed_ed25519_key": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y", + "forwarding_curve25519_key_chain": [ + "hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw" + ] + }, + "type": "m.room_key" +} diff --git a/event-schemas/schema/m.forwarded_room_key b/event-schemas/schema/m.forwarded_room_key new file mode 100644 index 000000000..02d91f4ef --- /dev/null +++ b/event-schemas/schema/m.forwarded_room_key @@ -0,0 +1,58 @@ +--- +allOf: + - $ref: core-event-schema/event.yaml + +description: |- + This event type is used to forward keys for end-to-end encryption. Typically + it is encrypted as an ``m.room.encrypted`` event. +properties: + content: + properties: + algorithm: + type: string + description: |- + The encryption algorithm the key in this event is to be used with. + room_id: + type: string + description: The room where the key is used. + sender_key: + type: string + description: |- + The Curve25519 key of the device which initiated the session originally. + session_id: + type: string + description: The ID of the session holding the key. + session_key: + type: string + description: The key to be exchanged. + sender_claimed_ed25519_key: + type: string + description: |- + The Ed25519 key of the device which initiated the session originally. + It is 'claimed' because the receiving device has no way to tell that the + original room_key actually came from a device which owns the private part of + this key unless they have done device verification. + forwarding_curve25519_key_chain: + type: array + items: + type: string + description: |- + Chain of Curve25519 keys. It starts out empty, but each time the + key is forwarded to another device, the previous sender in the chain is added + to the end of the list. For example, if the key is forwarded from A to B to + C, this field is empty between A and B, and contains A's Curve25519 key between + B and C. + required: + - algorithm + - room_id + - session_id + - session_key + - sender_claimed_ed25519_key + - forwarding_curve25519_key_chain + - sender_key + type: object + type: + enum: + - m.forwarded_room_key + type: string +type: object From 7355d23ea50820f120e73ea5d56b8ed17f7fcdd2 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 21 Aug 2018 21:53:02 +0200 Subject: [PATCH 031/219] add key sharing changelog --- changelogs/client_server/newsfragments/1465.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1465.feature diff --git a/changelogs/client_server/newsfragments/1465.feature b/changelogs/client_server/newsfragments/1465.feature new file mode 100644 index 000000000..61a7ed396 --- /dev/null +++ b/changelogs/client_server/newsfragments/1465.feature @@ -0,0 +1 @@ +Share room encryption keys between devices From 9835c98544249c65612072f1030908001e266687 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 21 Aug 2018 19:27:48 -0600 Subject: [PATCH 032/219] Document how mentions (pills) work Implements the proposal over at https://github.com/matrix-org/matrix-doc/issues/1067 Includes some specification for how matrix.to is structured, and how it is intended to be replaced. --- .../appendices/identifier_grammar.rst | 32 +++++++- specification/modules/mentions.rst | 73 +++++++++++++++++++ specification/targets.yaml | 1 + 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 specification/modules/mentions.rst diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index 7156c7d57..013afa799 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -1,5 +1,5 @@ .. Copyright 2016 Openmarket Ltd. -.. Copyright 2017 New Vector Ltd. +.. Copyright 2017, 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. @@ -252,3 +252,33 @@ domain). .. TODO-spec - Need to specify precise grammar for Room Aliases. https://matrix.org/jira/browse/SPEC-391 + +matrix.to navigation +++++++++++++++++++++ + +.. NOTE: + This namespacing is in place pending a ``matrix://`` (or similar) URI scheme. + +Rooms, users, aliases, and groups may be represented as a "matrix.to" URI. +This URI can be used to reference particular objects in a given context, such +as mentioning a user in a message or linking someone to a particular point +in the room's history (a permalink). + +A matrix.to URI has the following format, based upon the specification defined +in RFC 3986: + + https://matrix.to/#// + +The identifier may be a room ID, room alias, user ID, or group ID. The extra +parameter is only used in the case of permalinks where an event ID is referenced. +The matrix.to URI, when referenced, must always start with ``https://matrix.to/#/`` +followed by the identifier. + +Examples of matrix.to URIs are: + +* Room: ``https://matrix.to/#/!somewhere:domain.com`` +* Room alias: ``https://matrix.to/#/#somewhere:domain.com`` +* Permalink by room: ``https://matrix.to/#/!somewhere:domain.com/$event:example.org`` +* Permalink by room alias: ``https://matrix.to/#/#somewhere:domain.com/$event:example.org`` +* User: ``https://matrix.to/#/@alice:example.org`` +* Group: ``https://matrix.to/#/+example:domain.com`` diff --git a/specification/modules/mentions.rst b/specification/modules/mentions.rst new file mode 100644 index 000000000..e7483ae4f --- /dev/null +++ b/specification/modules/mentions.rst @@ -0,0 +1,73 @@ +.. 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. + +User, room, and group mentions +============================== + +.. _module:mentions: + +This module allows users to mention other users, rooms, and groups within +a room message. This is achieved by including a `matrix.to URI`_ in the HTML +body of an `m.room.message`_ event. This module does not have any server-specific +behaviour to it. + +Mentions apply only to `m.room.message`_ events where the ``msgtype`` is ``m.text``, +``m.emote``, or ``m.notice``. The ``format`` for the event must be ``org.matrix.custom.html`` +and therefore requires a ``formatted_body``. + +To make a mention, reference the entity being mentioned in the ``formatted_body`` +using an anchor, like so:: + + { + "body": "Hello Alice!", + "msgtype": "m.text", + "format": "org.matrix.custom.html", + "formatted_body": "Hello Alice!" + } + + +Client behaviour +---------------- + +In addition to using the appropriate ``matrix.to URI`` for the mention, +clients should use the following guidelines when making mentions: + +* When mentioning users, use the user's potentially ambigious display name for + the anchor's text. If the user does not have a display name, use the user's + ID. + +* When mentioning rooms, use the canonical alias for the room. If the room + does not have a canonical alias, prefer one of the aliases listed on the + room. If no alias can be found, fall back to the room ID. In all cases, + use the alias/room ID being linked to as the anchor's text. + +* When referencing groups, use the group ID as the anchor's text. + +The text component of the anchor should be used in the event's ``body`` where +the mention would normally be represented, as shown in the example above. + +Clients should display mentions differently from other elements. For example, +this may be done by changing the background color of the mention to indicate +that it is different from a normal link. + +If the current user is mentioned in a message (either by a mention as defined +in this module or by a push rule), the client should show that mention differently +from other mentions, such as by using a red background color to signify to the +user that they were mentioned. + +When clicked, the mention should navigate the user to the appropriate room, group, +or user information. + + +.. _`matrix.to URI`: ../appendices.html#matrix-to-navigation \ No newline at end of file diff --git a/specification/targets.yaml b/specification/targets.yaml index 5480bbc5a..ced204366 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -67,6 +67,7 @@ groups: # reusable blobs of files when prefixed with 'group:' - modules/report_content.rst - modules/third_party_networks.rst - modules/openid.rst + - modules/mentions.rst title_styles: ["=", "-", "~", "+", "^", "`", "@", ":"] From ef41b5c2bf5acf349493279ce19851de7542d04e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Aug 2018 12:48:37 -0600 Subject: [PATCH 033/219] Server ACLs Implements the proposal for https://github.com/matrix-org/matrix-doc/issues/1383 --- event-schemas/examples/m.room.server_acl | 14 +++++ event-schemas/schema/m.room.server_acl | 69 ++++++++++++++++++++++++ specification/modules/server_acls.rst | 66 +++++++++++++++++++++++ specification/server_server_api.rst | 26 +++++++++ specification/targets.yaml | 1 + 5 files changed, 176 insertions(+) create mode 100644 event-schemas/examples/m.room.server_acl create mode 100644 event-schemas/schema/m.room.server_acl create mode 100644 specification/modules/server_acls.rst diff --git a/event-schemas/examples/m.room.server_acl b/event-schemas/examples/m.room.server_acl new file mode 100644 index 000000000..86da20931 --- /dev/null +++ b/event-schemas/examples/m.room.server_acl @@ -0,0 +1,14 @@ +{ + "age": 242352, + "content": { + "allow_ip_literals": false, + "allow": ["*"], + "deny": ["*.evil.com", "evil.com"] + }, + "state_key": "", + "origin_server_ts": 1431961217939, + "event_id": "$WLGTSEFSEF:localhost", + "type": "m.room.server_acl", + "room_id": "!Cuyf34gef24t:localhost", + "sender": "@example:localhost" +} diff --git a/event-schemas/schema/m.room.server_acl b/event-schemas/schema/m.room.server_acl new file mode 100644 index 000000000..ed64038ca --- /dev/null +++ b/event-schemas/schema/m.room.server_acl @@ -0,0 +1,69 @@ +--- +title: Server ACL +description: |- + An event to indicate which servers are permitted to participate in the + room. Server ACLs may allow or deny groups of hosts. All servers participating + in the room, including those that are denied, are expected to uphold the + server ACL. Servers that do not uphold the ACLs are recommended to be + added to the denied hosts list. + + The ``allow`` and ``deny`` lists are lists of globs supporting ``?`` and ``*`` + as wildcards. When comparing against the server ACLs, the suspect server's port + number must not be considered. Therefore ``evil.com``, ``evil.com:8448``, and + ``evil.com:1234`` would all match rules that apply to ``evil.com``, for example. + + The ACLs are applied to servers when they make requests, and are applied in + the following order: + + 1. If there is no ``m.room.server_acl`` event in the room state, allow. + #. If the server name is an IP address (v4 or v6) literal, and ``allow_ip_literals`` + is present and ``false``, deny. + #. If the server name matches an entry in the ``deny`` list, deny. + #. If the server name matches an entry in the ``allow`` list, allow. + #. Otherwise, deny. + + .. WARNING:: + Failing to provide an ``allow`` rule of some kind will prevent **all** + servers from participating in the room, including the sender. This renders + the room unusable. A common allow rule is ``[ "*" ]`` which would still + permit the use of the ``deny`` list without losing the room. +allOf: + - $ref: core-event-schema/state_event.yaml +type: object +properties: + content: + properties: + allow_ip_literals: + type: boolean + description: |- + True to allow server names that are IP address literals. False to + deny. Defaults to true if missing or otherwise not a boolean. + allow: + type: array + description: |- + The server names to allow in the room, excluding any port information. + Wildcards may be used to cover a wider range of hosts, where ``*`` + matches zero or more characters and ``?`` matches one or more characters. + + **This defaults to an empty list when not provided, effectively disallowing + every server.** + items: + type: string + deny: + type: array + description: |- + The server names to disallow in the room, excluding any port information. + Wildcards may be used to cover a wider range of hosts, where ``*`` + matches zero or more characters and ``?`` matches one or more characters. + + This defaults to an empty list when not provided. + items: + type: string + type: object + state_key: + description: A zero-length string. + pattern: '^$' + type: string + type: + enum: ['m.room.server_acl'] + type: enum diff --git a/specification/modules/server_acls.rst b/specification/modules/server_acls.rst new file mode 100644 index 000000000..72892fce5 --- /dev/null +++ b/specification/modules/server_acls.rst @@ -0,0 +1,66 @@ +.. 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. + +Server Access Control Lists (ACLs) for rooms +============================================ + +.. _module:server-acls: + +In some scenarios room operators may wish to prevent a malicous or untrusted +server from participating in their room. Sending an `m.room.server_acl`_ state +event into a room is an effective way to prevent the server from participating +in the room at the federation level. + +Server ACLs can also be used to make rooms only federate with a limited set of +servers, or retroactively make the room no longer federate with any other server, +similar to setting the ``m.federate`` value on the `m.room.create`_ event. + +{{m_room_server_acl_event}} + +.. Note:: + Port numbers are not supported because it is unclear to parsers whether a + port number should be matched or an IP address literal. + +.. Note:: + CIDR notation is not supported for IP addresses because Matrix does not + encourage the use of IPs for identifying servers. Instead, a blanket + ``allow_ip_literals`` is provided to cover banning them. + +Client behaviour +---------------- +Clients are not expected to perform any additional duties beyond sending the +event. Clients should describe changes to the server ACLs to the user in the +user interface, such as in the timeline. + +Clients may wish to kick affected users from the room prior to denying a server +access to the room to help prevent those servers from participating. + +Server behaviour +---------------- +Servers MUST prevent blacklisted servers from sending events or participating +in the room when an `m.room.server_acl`_ event is present in the room state. +Which APIs are specifically affected are described in the Server-Server API +specification. + +Servers should still send events to denied servers if they are still residents +of the room. + + +Security considerations +----------------------- +Server ACLs are only effective if every server in the room honours them. Servers +that do not honour the ACLs may still permit events sent by denied servers into +the room, leaking them to other servers in the room. To effectively enforce an +ACL in a room, the servers that do not honour the ACLs should be denied in the +room as well. \ No newline at end of file diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index dbde8b104..439b35f90 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -929,6 +929,32 @@ described in the `Client-Server API`_, being sure to use the ``allow_remote`` parameter (set to ``false``). +Server Access Control Lists (ACLs) +---------------------------------- + +Server ACLs and their purpose are described in the `Server ACLs`_ section of the +Client-Server API. + +When a remote server makes a request, it MUST be verified to be allowed by the +server ACLs. If the server is denied access to a room, the receiving server +MUST reply with a 403 HTTP status code and an ``errcode`` of ``M_FORBIDDEN``. + +The following endpoint prefixes MUST be protected: + +* ``/_matrix/federation/v1/send`` (on a per-PDU basis) +* ``/_matrix/federation/v1/make_join`` +* ``/_matrix/federation/v1/make_leave`` +* ``/_matrix/federation/v1/send_join`` +* ``/_matrix/federation/v1/send_leave`` +* ``/_matrix/federation/v1/invite`` +* ``/_matrix/federation/v1/state`` +* ``/_matrix/federation/v1/state_ids`` +* ``/_matrix/federation/v1/backfill`` +* ``/_matrix/federation/v1/event_auth`` +* ``/_matrix/federation/v1/query_auth`` +* ``/_matrix/federation/v1/get_missing_events`` + + Signing Events -------------- diff --git a/specification/targets.yaml b/specification/targets.yaml index 5480bbc5a..acf4b6ac9 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -67,6 +67,7 @@ groups: # reusable blobs of files when prefixed with 'group:' - modules/report_content.rst - modules/third_party_networks.rst - modules/openid.rst + - modules/server_acls.rst title_styles: ["=", "-", "~", "+", "^", "`", "@", ":"] From 7ec3cc4343a30c41176c50bb208d57fc698663a5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Aug 2018 15:21:21 -0600 Subject: [PATCH 034/219] General improvements to the push rules module This commit does a few things: * Add 3 undocumented push rules to the spec for encrypted events and at-room notifications. * Require unrecognized conditions to not match, ensuring that future conditions do not cause clients to accidentally notify users. * Clarify that push rules should be enabled when created. * Document a new condition required for at-room notifications. Fixes https://github.com/matrix-org/matrix-doc/issues/1163 Fixes https://github.com/matrix-org/matrix-doc/issues/1034 Fixes https://github.com/matrix-org/matrix-doc/issues/676 Fixes https://github.com/matrix-org/matrix-doc/issues/1033 Relates to https://github.com/matrix-org/matrix-doc/issues/1101 --- api/client-server/pushrules.yaml | 4 +- specification/modules/push.rst | 118 ++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 3 deletions(-) diff --git a/api/client-server/pushrules.yaml b/api/client-server/pushrules.yaml index ceb9954b1..e23c9189e 100644 --- a/api/client-server/pushrules.yaml +++ b/api/client-server/pushrules.yaml @@ -343,6 +343,8 @@ paths: This endpoint allows the creation, modification and deletion of pushers for this user ID. The behaviour of this endpoint varies depending on the values in the JSON body. + + When creating push rules, they MUST be enabled by default. operationId: setPushRule security: - accessToken: [] @@ -424,7 +426,7 @@ paths: required: ["actions"] responses: 200: - description: The pusher was set. + description: The push rule was created/updated. examples: application/json: { } diff --git a/specification/modules/push.rst b/specification/modules/push.rst index e9ee8c90d..946834362 100644 --- a/specification/modules/push.rst +++ b/specification/modules/push.rst @@ -124,7 +124,7 @@ There are different "kinds" of push rules and each rule has an associated priority. Every push rule MUST have a ``kind`` and ``rule_id``. The ``rule_id`` is a unique string within the kind of rule and its' scope: ``rule_ids`` do not need to be unique between rules of the same kind on different devices. Rules may -have extra keys depending on the value of ``kind``.The different kinds of rule +have extra keys depending on the value of ``kind``. The different kinds of rule in descending order of priority are: Override Rules ``override`` @@ -369,6 +369,41 @@ Definition: } +``.m.rule.roomnotif`` +````````````````````````````````` +Matches any message whose content is unencrypted and contains the +text ``@room``, signifying the whole room should be notified of +the event. + +Definition: + +.. code:: json + + { + "rule_id": ".m.rule.roomnotif", + "default": true, + "enabled": true, + "conditions": [ + { + "kind": "event_match", + "key": "content.body", + "pattern": "@room" + }, + { + "kind": "sender_notification_permission", + "key": "room" + } + ], + "actions": [ + "notify", + { + "set_tweak": "highlight", + "value": true + } + ] + } + + Default Content Rules ^^^^^^^^^^^^^^^^^^^^^ @@ -428,7 +463,38 @@ Definition: "value": false } ] - }, + } + +``.m.rule.encrypted_room_one_to_one`` +``````````````````````````` +Matches any encrypted event sent in a room with exactly two members. + +Definition: + +.. code:: json + + { + "rule_id": ".m.rule.encrypted_room_one_to_one", + "default": true, + "enabled": true, + "conditions": [ + { + "kind": "room_member_count", + "is": "2" + } + ], + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight", + "value": false + } + ] + } ``.m.rule.room_one_to_one`` ``````````````````````````` @@ -446,6 +512,11 @@ Definition: { "kind": "room_member_count", "is": "2" + }, + { + "kind": "event_match", + "key": "type", + "pattern": "m.room.encrypted" } ], "actions": [ @@ -489,6 +560,34 @@ Definition: ] } +``.m.rule.encrypted`` +``````````````````` +Matches all encrypted events. + +Definition: + +.. code:: json + + { + "rule_id": ".m.rule.encrypted", + "default": true, + "enabled": true, + "conditions": [ + { + "kind": "event_match", + "key": "type", + "pattern": "m.room.encrypted" + } + ], + "actions": [ + "notify", + { + "set_tweak": "highlight", + "value": false + } + ] + } + Conditions ++++++++++ @@ -523,6 +622,21 @@ rule determines its behaviour. The following conditions are defined: count is strictly less than the given number and so forth. If no prefix is present, this parameter defaults to ``==``. +``sender_notification_permission`` + This takes into account the current power levels in the room, ensuring the + sender of the event has high enough power to trigger the notification. + + Parameters: + + * ``key``: The notification power level to require the sender to have. Refer to + the `m.room.power_levels`_ event schema for information about what the defaults + are and how to interpret the event. The ``key`` is used to look up a specific + notification type from the ``notifications`` object in the power level event + content. + +Unrecognised conditions MUST NOT match any events, effectively making the push +rule disabled. + Push Rules: API ~~~~~~~~~~~~~~~ From ab0be0457199e65d115ed3eb6fd46ba94f591d1a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Aug 2018 15:24:53 -0600 Subject: [PATCH 035/219] Fix titles --- specification/modules/push.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/modules/push.rst b/specification/modules/push.rst index 946834362..408eabe62 100644 --- a/specification/modules/push.rst +++ b/specification/modules/push.rst @@ -370,7 +370,7 @@ Definition: ``.m.rule.roomnotif`` -````````````````````````````````` +````````````````````` Matches any message whose content is unencrypted and contains the text ``@room``, signifying the whole room should be notified of the event. @@ -466,7 +466,7 @@ Definition: } ``.m.rule.encrypted_room_one_to_one`` -``````````````````````````` +````````````````````````````````````` Matches any encrypted event sent in a room with exactly two members. Definition: @@ -561,7 +561,7 @@ Definition: } ``.m.rule.encrypted`` -``````````````````` +````````````````````` Matches all encrypted events. Definition: From bce324818b8e1a41e1ee313f6944ca3e03d27d40 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Aug 2018 15:26:27 -0600 Subject: [PATCH 036/219] Changelog --- changelogs/client_server/newsfragments/1551.clarification | 1 + changelogs/client_server/newsfragments/1551.feature | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelogs/client_server/newsfragments/1551.clarification create mode 100644 changelogs/client_server/newsfragments/1551.feature diff --git a/changelogs/client_server/newsfragments/1551.clarification b/changelogs/client_server/newsfragments/1551.clarification new file mode 100644 index 000000000..06eac4daa --- /dev/null +++ b/changelogs/client_server/newsfragments/1551.clarification @@ -0,0 +1 @@ +Clarify that new push rules should be enabled by default, and that unrecognised conditions should not match. diff --git a/changelogs/client_server/newsfragments/1551.feature b/changelogs/client_server/newsfragments/1551.feature new file mode 100644 index 000000000..dfce0f0a4 --- /dev/null +++ b/changelogs/client_server/newsfragments/1551.feature @@ -0,0 +1 @@ +Add new push rules for encrypted events and ``@room`` notifications. From a95d7092eb3bf4e02cbd1aabc31548462d6376c2 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Aug 2018 15:27:48 -0600 Subject: [PATCH 037/219] Changelog --- changelogs/client_server/newsfragments/1550.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1550.feature diff --git a/changelogs/client_server/newsfragments/1550.feature b/changelogs/client_server/newsfragments/1550.feature new file mode 100644 index 000000000..f04fa9ae0 --- /dev/null +++ b/changelogs/client_server/newsfragments/1550.feature @@ -0,0 +1 @@ +Add server ACLs as an option for controlling federation in a room. From dc94820450bcbd907e99bbae99e7c5b1df5380d5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 22 Aug 2018 15:28:55 -0600 Subject: [PATCH 038/219] Changelog --- changelogs/client_server/newsfragments/1547.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1547.feature diff --git a/changelogs/client_server/newsfragments/1547.feature b/changelogs/client_server/newsfragments/1547.feature new file mode 100644 index 000000000..76346f230 --- /dev/null +++ b/changelogs/client_server/newsfragments/1547.feature @@ -0,0 +1 @@ +Add a common standard for user, room, and group mentions in messages. From bbd33c146131939790e6939e881bfd46b971bd62 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 23 Aug 2018 13:29:04 -0600 Subject: [PATCH 039/219] Move appservice transaction API to the right section Part of https://github.com/matrix-org/matrix-doc/issues/1532 --- .../application_service.yaml | 70 ------------- api/application-service/transactions.yaml | 98 +++++++++++++++++++ specification/application_service_api.rst | 2 + 3 files changed, 100 insertions(+), 70 deletions(-) create mode 100644 api/application-service/transactions.yaml diff --git a/api/application-service/application_service.yaml b/api/application-service/application_service.yaml index bc6e45d5d..8fcfa0066 100644 --- a/api/application-service/application_service.yaml +++ b/api/application-service/application_service.yaml @@ -26,76 +26,6 @@ consumes: produces: - application/json paths: - "/transactions/{txnId}": - put: - summary: Send some events to the application service. - description: |- - This API is called by the homeserver when it wants to push an event - (or batch of events) to the application service. - - Note that the application service should distinguish state events - from message events via the presence of a ``state_key``, rather than - via the event type. - operationId: sendTransaction - parameters: - - in: path - name: txnId - type: string - description: |- - The transaction ID for this set of events. Homeservers generate - these IDs and they are used to ensure idempotency of requests. - required: true - x-example: "35" - - in: body - name: body - description: A list of events. - schema: - type: object - example: { - "events": [ - { - "age": 32, - "content": { - "body": "incoming message", - "msgtype": "m.text" - }, - "event_id": "$14328055551tzaee:localhost", - "origin_server_ts": 1432804485886, - "room_id": "!TmaZBKYIFrIPVGoUYp:localhost", - "type": "m.room.message", - "user_id": "@bob:localhost" - }, - { - "age": 1984, - "content": { - "body": "another incoming message", - "msgtype": "m.text" - }, - "event_id": "$1228055551ffsef:localhost", - "origin_server_ts": 1432804485886, - "room_id": "!TmaZBKYIFrIPVGoUYp:localhost", - "type": "m.room.message", - "user_id": "@bob:localhost" - } - ] - } - description: "Transaction informations" - properties: - events: - type: array - description: A list of events - items: - type: object - title: Event - required: ["events"] - responses: - 200: - description: The transaction was processed successfully. - examples: - application/json: { - } - schema: - type: object "/_matrix/app/unstable/thirdparty/protocol/{protocol}": get: summary: Retrieve metadata about a specific protocol that the application service supports. diff --git a/api/application-service/transactions.yaml b/api/application-service/transactions.yaml new file mode 100644 index 000000000..9388d3c5b --- /dev/null +++ b/api/application-service/transactions.yaml @@ -0,0 +1,98 @@ +# Copyright 2016 OpenMarket Ltd +# 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. +swagger: '2.0' +info: + title: "Matrix Application Service API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: "/" +consumes: + - application/json +produces: + - application/json +paths: + "/transactions/{txnId}": + put: + summary: Send some events to the application service. + description: |- + This API is called by the homeserver when it wants to push an event + (or batch of events) to the application service. + + Note that the application service should distinguish state events + from message events via the presence of a ``state_key``, rather than + via the event type. + operationId: sendTransaction + parameters: + - in: path + name: txnId + type: string + description: |- + The transaction ID for this set of events. Homeservers generate + these IDs and they are used to ensure idempotency of requests. + required: true + x-example: "35" + - in: body + name: body + description: A list of events. + schema: + type: object + example: { + "events": [ + { + "age": 32, + "content": { + "body": "incoming message", + "msgtype": "m.text" + }, + "event_id": "$14328055551tzaee:localhost", + "origin_server_ts": 1432804485886, + "room_id": "!TmaZBKYIFrIPVGoUYp:localhost", + "type": "m.room.message", + "user_id": "@bob:localhost" + }, + { + "age": 1984, + "content": { + "body": "another incoming message", + "msgtype": "m.text" + }, + "event_id": "$1228055551ffsef:localhost", + "origin_server_ts": 1432804485886, + "room_id": "!TmaZBKYIFrIPVGoUYp:localhost", + "type": "m.room.message", + "user_id": "@bob:localhost" + } + ] + } + description: "Transaction informations" + properties: + events: + type: array + description: A list of events + items: + type: object + title: Event + required: ["events"] + responses: + 200: + description: The transaction was processed successfully. + examples: + application/json: { + } + schema: + type: object \ No newline at end of file diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 08e3b0626..09e38e914 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -155,6 +155,8 @@ be made without blocking other aspects of the homeserver. Homeservers MUST NOT alter (e.g. add more) events they were going to send within that transaction ID on retries, as the AS may have already processed the events. +{{transactions_as_http_api}} + Querying ++++++++ From 6a91ea9c85a597f0ac89fce9e99f57be4be388da Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 23 Aug 2018 13:31:33 -0600 Subject: [PATCH 040/219] Specify that application services receive events in the CSAPI format Fixes https://github.com/matrix-org/matrix-doc/issues/1269 This is also supposed to fix the 'age' problem, however that is a larger problem with the event schemas that is reserved for a future PR/commit. Reference: https://github.com/matrix-org/matrix-doc/issues/1294 Reference: https://github.com/matrix-org/matrix-doc/issues/1524 --- api/application-service/transactions.yaml | 38 +++++------------------ 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/api/application-service/transactions.yaml b/api/application-service/transactions.yaml index 9388d3c5b..8735cc8f7 100644 --- a/api/application-service/transactions.yaml +++ b/api/application-service/transactions.yaml @@ -21,8 +21,6 @@ schemes: - https - http basePath: "/" -consumes: - - application/json produces: - application/json paths: @@ -53,37 +51,16 @@ paths: type: object example: { "events": [ - { - "age": 32, - "content": { - "body": "incoming message", - "msgtype": "m.text" - }, - "event_id": "$14328055551tzaee:localhost", - "origin_server_ts": 1432804485886, - "room_id": "!TmaZBKYIFrIPVGoUYp:localhost", - "type": "m.room.message", - "user_id": "@bob:localhost" - }, - { - "age": 1984, - "content": { - "body": "another incoming message", - "msgtype": "m.text" - }, - "event_id": "$1228055551ffsef:localhost", - "origin_server_ts": 1432804485886, - "room_id": "!TmaZBKYIFrIPVGoUYp:localhost", - "type": "m.room.message", - "user_id": "@bob:localhost" - } + {"$ref": "../../event-schemas/examples/m.room.member"}, + {"$ref": "../../event-schemas/examples/m.room.message#m.text"} ] } - description: "Transaction informations" + description: Transaction information properties: events: type: array - description: A list of events + description: |- + A list of events, formatted as per the Client-Server API. items: type: object title: Event @@ -92,7 +69,6 @@ paths: 200: description: The transaction was processed successfully. examples: - application/json: { - } + application/json: {} schema: - type: object \ No newline at end of file + type: object From 9eda1a697143249a03da6bbf02674263f74e5929 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 23 Aug 2018 15:07:55 -0600 Subject: [PATCH 041/219] Move the third party network API to it's own section --- .../application_service.yaml | 240 ---------------- api/application-service/protocols.yaml | 267 ++++++++++++++++++ specification/application_service_api.rst | 20 ++ 3 files changed, 287 insertions(+), 240 deletions(-) create mode 100644 api/application-service/protocols.yaml diff --git a/api/application-service/application_service.yaml b/api/application-service/application_service.yaml index bc6e45d5d..8a32c95b3 100644 --- a/api/application-service/application_service.yaml +++ b/api/application-service/application_service.yaml @@ -96,243 +96,3 @@ paths: } schema: type: object - "/_matrix/app/unstable/thirdparty/protocol/{protocol}": - get: - summary: Retrieve metadata about a specific protocol that the application service supports. - description: |- - This API is called by the homeserver when it wants to present clients - with specific information about the various third party networks that - an application service supports. - operationId: getProtocolMetadata - parameters: - - in: path - name: protocol - type: string - description: The protocol ID. - required: true - x-example: "irc" - responses: - 200: - description: The protocol was found and metadata returned. - schema: - $ref: definitions/protocol_metadata.yaml - 401: - description: |- - The homeserver has not supplied credentials to the application service. - Optional error information can be included in the body of this response. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 403: - description: |- - The credentials supplied by the homeserver were rejected. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 404: - description: No protocol was found with the given path. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/user/{protocol}": - get: - summary: Retrieve the Matrix User ID of a corresponding third party user. - description: |- - This API is called by the homeserver in order to retrieve a Matrix - User ID linked to a user on the third party network, given a set of - user parameters. - operationId: queryUserByProtocol - parameters: - - in: path - name: protocol - type: string - description: The protocol ID. - required: true - x-example: irc - - in: query - name: fields... - type: string - description: |- - One or more custom fields that are passed to the application - service to help identify the user. - responses: - 200: - description: The Matrix User IDs found with the given parameters. - schema: - $ref: definitions/user_batch.yaml - 401: - description: |- - The homeserver has not supplied credentials to the application service. - Optional error information can be included in the body of this response. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 403: - description: |- - The credentials supplied by the homeserver were rejected. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 404: - description: No users were found with the given parameters. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/location/{protocol}": - get: - summary: Retreive Matrix-side portal rooms leading to a third party location. - description: |- - Retrieve a list of Matrix portal rooms that lead to the matched third party location. - operationId: queryLocationByProtocol - parameters: - - in: path - name: protocol - type: string - description: The protocol ID. - required: true - x-example: irc - - in: query - name: fields... - type: string - description: |- - One or more custom fields that are passed to the application - service to help identify the third party location. - responses: - 200: - description: At least one portal room was found. - schema: - $ref: definitions/location_batch.yaml - 401: - description: |- - The homeserver has not supplied credentials to the application service. - Optional error information can be included in the body of this response. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 403: - description: |- - The credentials supplied by the homeserver were rejected. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 404: - description: No mappings were found with the given parameters. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/location": - get: - summary: Reverse-lookup third party locations given a Matrix room alias. - description: |- - Retreive an array of third party network locations from a Matrix room - alias. - operationId: queryLocationByAlias - parameters: - - in: query - name: alias - type: string - description: The Matrix room alias to look up. - responses: - 200: - description: |- - All found third party locations. - schema: - $ref: definitions/location_batch.yaml - 401: - description: |- - The homeserver has not supplied credentials to the application service. - Optional error information can be included in the body of this response. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 403: - description: |- - The credentials supplied by the homeserver were rejected. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 404: - description: No mappings were found with the given parameters. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/user": - get: - summary: Reverse-lookup third party users given a Matrix User ID. - description: |- - Retreive an array of third party users from a Matrix User ID. - operationId: queryUserByID - parameters: - - in: query - name: userid - type: string - description: The Matrix User ID to look up. - responses: - 200: - description: |- - An array of third party users. - schema: - $ref: definitions/user_batch.yaml - 401: - description: |- - The homeserver has not supplied credentials to the application service. - Optional error information can be included in the body of this response. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 403: - description: |- - The credentials supplied by the homeserver were rejected. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml - 404: - description: No mappings were found with the given parameters. - examples: - application/json: { - "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" - } - schema: - $ref: ../client-server/definitions/errors/error.yaml diff --git a/api/application-service/protocols.yaml b/api/application-service/protocols.yaml new file mode 100644 index 000000000..376e66c0b --- /dev/null +++ b/api/application-service/protocols.yaml @@ -0,0 +1,267 @@ +# 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. +swagger: '2.0' +info: + title: "Matrix Application Service API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: "/" +consumes: + - application/json +produces: + - application/json +paths: + "/_matrix/app/unstable/thirdparty/protocol/{protocol}": + get: + summary: Retrieve metadata about a specific protocol that the application service supports. + description: |- + This API is called by the homeserver when it wants to present clients + with specific information about the various third party networks that + an application service supports. + operationId: getProtocolMetadata + parameters: + - in: path + name: protocol + type: string + description: The protocol ID. + required: true + x-example: "irc" + responses: + 200: + description: The protocol was found and metadata returned. + schema: + $ref: definitions/protocol_metadata.yaml + 401: + description: |- + The homeserver has not supplied credentials to the application service. + Optional error information can be included in the body of this response. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 403: + description: |- + The credentials supplied by the homeserver were rejected. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 404: + description: No protocol was found with the given path. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + "/_matrix/app/unstable/thirdparty/user/{protocol}": + get: + summary: Retrieve the Matrix User ID of a corresponding third party user. + description: |- + This API is called by the homeserver in order to retrieve a Matrix + User ID linked to a user on the third party network, given a set of + user parameters. + operationId: queryUserByProtocol + parameters: + - in: path + name: protocol + type: string + description: The protocol ID. + required: true + x-example: irc + - in: query + name: fields... + type: string + description: |- + One or more custom fields that are passed to the application + service to help identify the user. + responses: + 200: + description: The Matrix User IDs found with the given parameters. + schema: + $ref: definitions/user_batch.yaml + 401: + description: |- + The homeserver has not supplied credentials to the application service. + Optional error information can be included in the body of this response. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 403: + description: |- + The credentials supplied by the homeserver were rejected. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 404: + description: No users were found with the given parameters. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + "/_matrix/app/unstable/thirdparty/location/{protocol}": + get: + summary: Retreive Matrix-side portal rooms leading to a third party location. + description: |- + Retrieve a list of Matrix portal rooms that lead to the matched third party location. + operationId: queryLocationByProtocol + parameters: + - in: path + name: protocol + type: string + description: The protocol ID. + required: true + x-example: irc + - in: query + name: fields... + type: string + description: |- + One or more custom fields that are passed to the application + service to help identify the third party location. + responses: + 200: + description: At least one portal room was found. + schema: + $ref: definitions/location_batch.yaml + 401: + description: |- + The homeserver has not supplied credentials to the application service. + Optional error information can be included in the body of this response. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 403: + description: |- + The credentials supplied by the homeserver were rejected. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 404: + description: No mappings were found with the given parameters. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + "/_matrix/app/unstable/thirdparty/location": + get: + summary: Reverse-lookup third party locations given a Matrix room alias. + description: |- + Retreive an array of third party network locations from a Matrix room + alias. + operationId: queryLocationByAlias + parameters: + - in: query + name: alias + type: string + description: The Matrix room alias to look up. + responses: + 200: + description: |- + All found third party locations. + schema: + $ref: definitions/location_batch.yaml + 401: + description: |- + The homeserver has not supplied credentials to the application service. + Optional error information can be included in the body of this response. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 403: + description: |- + The credentials supplied by the homeserver were rejected. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_FORBIDDEN" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 404: + description: No mappings were found with the given parameters. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + "/_matrix/app/unstable/thirdparty/user": + get: + summary: Reverse-lookup third party users given a Matrix User ID. + description: |- + Retreive an array of third party users from a Matrix User ID. + operationId: queryUserByID + parameters: + - in: query + name: userid + type: string + description: The Matrix User ID to look up. + responses: + 200: + description: |- + An array of third party users. + schema: + $ref: definitions/user_batch.yaml + 401: + description: |- + The homeserver has not supplied credentials to the application service. + Optional error information can be included in the body of this response. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 403: + description: |- + The credentials supplied by the homeserver were rejected. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_UNAUTHORIZED" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml + 404: + description: No mappings were found with the given parameters. + examples: + application/json: { + "errcode": "COM.EXAMPLE.MYAPPSERVICE_NOT_FOUND" + } + schema: + $ref: ../client-server/definitions/errors/error.yaml diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 08e3b0626..c5f8be720 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -180,6 +180,26 @@ this request (e.g. to join a room alias). {{query_room_as_http_api}} +Third party networks +++++++++++++++++++++ + +Application services may declare which protocols they support via their registration +file. These networks are generally for third party services such as IRC that the +application service is managing. Application services may populate a Matrix room +directory for their registered protocols, as defined in the Client-Server API Extensions. + +Each protocol may have several "locations". A location within a protocol is a place +in the third party network, such as an IRC channel. Users of the third party network +may also be represented by the application service. + +Locations and users can be searched by fields defined by the application service, such +as by display name or other attribute. When clients request the homeserver to search +in a particular "network" (protocol), the search fields will be passed along to the +application service for filtering. + +{{protocols_as_http_api}} + + HTTP APIs +++++++++ From 2d43ff123400a54f087a30179af7cb5077ab8cf5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 10:22:10 -0600 Subject: [PATCH 042/219] Update third party network schemas Some information was missed when this was reviewed. This commit adds some additional documentation for how these objects interact with each other. --- .../definitions/location.yaml | 8 +- .../definitions/protocol.yaml | 88 +++++++++++++------ .../definitions/protocol_metadata.yaml | 2 + api/application-service/definitions/user.yaml | 6 +- 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/api/application-service/definitions/location.yaml b/api/application-service/definitions/location.yaml index 4967ef61f..5a0f92c88 100644 --- a/api/application-service/definitions/location.yaml +++ b/api/application-service/definitions/location.yaml @@ -19,12 +19,14 @@ properties: protocol: description: The protocol ID that the third party location is a part of. type: string - example: irc + example: "irc" fields: description: Information used to identify this third party location. type: object - example: - "network": "freenode" + example: { + "network": "freenode", "channel": "#matrix" + } +required: ['alias', 'protocol', 'fields'] title: Location type: object \ No newline at end of file diff --git a/api/application-service/definitions/protocol.yaml b/api/application-service/definitions/protocol.yaml index 231e8288a..851091d69 100644 --- a/api/application-service/definitions/protocol.yaml +++ b/api/application-service/definitions/protocol.yaml @@ -11,41 +11,60 @@ # 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: Protocol +type: object properties: user_fields: - description: Fields used to identify a third party user. + description: |- + Fields which may be used to identify a third party user. These should be + ordered to suggest the way that entities may be grouped, where higher + groupings are ordered first. For example, the name of a network should be + searched before the nickname of a user. type: array items: type: string description: Field used to identify a third party user. example: ["network", "nickname"] location_fields: - description: Fields used to identify a third party location. + description: |- + Fields which may be used to identify a third party location. These should be + ordered to suggest the way that entities may be grouped, where higher + groupings are ordered first. For example, the name of a network should be + searched before the name of a channel. type: array items: type: string description: Field used to identify a third party location. example: ["network", "channel"] icon: - description: An icon representing the third party protocol. + description: A content URI representing an icon for the third party protocol. type: string example: "mxc://example.org/aBcDeFgH" field_types: title: Field Types - description: All location or user fields should have an entry here. + description: |- + The type definitions for the fields defined in the ``user_fields`` and + ``location_fields``. Each entry in those arrays MUST have an entry here. The + ``string`` key for this object is field name itself. + + May be an empty object if no fields are defined. type: object - properties: - fieldname: - title: Field Type - description: Definition of valid values for a field. - type: object - properties: - regexp: - description: A regular expression for validation of a field's value. - type: string - placeholder: - description: An placeholder serving as a valid example of the field value. - type: string + additionalProperties: + title: Field Type + description: Definition of valid values for a field. + type: object + properties: + regexp: + description: |- + A regular expression for validation of a field's value. This may be relatively + coarse to verify the value as the application service providing this protocol + may apply additional validation or filtering. + type: string + placeholder: + description: An placeholder serving as a valid example of the field value. + type: string + required: ['regexp', 'placeholder'] + required: ['fieldname'] example: { "network": { "regexp": "([a-z0-9]+\\.)*[a-z0-9]+", @@ -63,17 +82,32 @@ properties: instances: description: |- A list of objects representing independent instances of configuration. - For instance multiple networks on IRC if multiple are bridged by the - same bridge. + For example, multiple networks on IRC if multiple are provided by the + same application service. type: array items: type: object - example: { - "desc": "Freenode", - "icon": "mxc://example.org/JkLmNoPq", - "fields": { - "network": "freenode.net", - } - } -title: Protocol -type: object \ No newline at end of file + title: Protocol Instance + properties: + desc: + type: string + description: A human-readable description for the protocol, such as the name. + example: "Freenode" + icon: + type: string + description: |- + An optional content URI representing the protocol. Overrides the one provided + at the higher level Protocol object. + example: "mxc://example.org/JkLmNoPq" + fields: + type: object + description: Preset values for ``fields`` the client may use to search by. + example: { + "network": "freenode" + } + network_id: + type: string + description: A unique identifier across all instances. + example: "freenode" + required: ['desc', 'fields', 'network_id'] +required: ['user_fields', 'location_fields', 'icon', 'field_types', 'instances'] diff --git a/api/application-service/definitions/protocol_metadata.yaml b/api/application-service/definitions/protocol_metadata.yaml index 2b2c8f4e7..e7bf45da6 100644 --- a/api/application-service/definitions/protocol_metadata.yaml +++ b/api/application-service/definitions/protocol_metadata.yaml @@ -36,6 +36,7 @@ example: { }, "instances": [ { + "network_id": "freenode", "desc": "Freenode", "icon": "mxc://example.org/JkLmNoPq", "fields": { @@ -59,6 +60,7 @@ example: { }, "instances": [ { + "network_id": "gitter", "desc": "Gitter", "icon": "mxc://example.org/zXyWvUt", "fields": {} diff --git a/api/application-service/definitions/user.yaml b/api/application-service/definitions/user.yaml index a7b2287ef..258e7c138 100644 --- a/api/application-service/definitions/user.yaml +++ b/api/application-service/definitions/user.yaml @@ -21,11 +21,13 @@ properties: protocol: description: The protocol ID that the third party location is a part of. type: string - example: gitter + example: "gitter" fields: description: Information used to identify this third party location. type: object - example: + example: { "user": "jim" + } +required: ['userid', 'protocol', 'fields'] title: User type: object \ No newline at end of file From 017d6db7370f87b5b72e9ce19d6f8962462ab525 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 11:07:30 -0600 Subject: [PATCH 043/219] Document third party network/protocol directories (for appservices) Fixes https://github.com/matrix-org/matrix-doc/issues/869 --- .../appservice_room_directory.yaml | 87 +++++++++++++++++++ api/client-server/list_public_rooms.yaml | 20 ++++- api/server-server/public_rooms.yaml | 14 +++ specification/application_service_api.rst | 12 +++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 api/client-server/appservice_room_directory.yaml diff --git a/api/client-server/appservice_room_directory.yaml b/api/client-server/appservice_room_directory.yaml new file mode 100644 index 000000000..0225ecd85 --- /dev/null +++ b/api/client-server/appservice_room_directory.yaml @@ -0,0 +1,87 @@ +# 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. +swagger: '2.0' +info: + title: "Matrix Client-Server Application Service Room Directory API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: /_matrix/client/%CLIENT_MAJOR_VERSION% +consumes: + - application/json +produces: + - application/json +securityDefinitions: + # Note: this is the same access_token definition used elsewhere in the client + # server API, however this expects an access token for an application service. + $ref: definitions/security.yaml +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 + 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 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 + users who are not identified as application services. + operationId: updateAppserviceRoomDirectoryVsibility + parameters: + - in: path + type: string + name: networkId + description: |- + The protocol (network) ID to update the room list for. This would + have been provided by the application service as being listed as + a supported protocol. + required: true + x-example: "irc" + - in: path + type: string + name: roomId + description: The room ID to add to the directory. + required: true + x-example: "!somewhere:domain.com" + - in: body + name: body + schema: + type: object + properties: + visibility: + type: enum + enum: ["public", "private"] + description: |- + Whether the room should be visible (public) in the directory + or not (private). + example: "public" + required: ['visibility'] + security: + # again, this is the appservice's token - not a typical client's + - accessToken: [] + responses: + 200: + description: The room's directory visibility has been updated. + schema: + type: object + examples: + application/json: {} + tags: + - Application service room directory management diff --git a/api/client-server/list_public_rooms.yaml b/api/client-server/list_public_rooms.yaml index 72a120609..d1abc68ec 100644 --- a/api/client-server/list_public_rooms.yaml +++ b/api/client-server/list_public_rooms.yaml @@ -194,8 +194,26 @@ paths: description: |- A string to search for in the room metadata, e.g. name, topic, canonical alias etc. (Optional). + include_all_networks: + type: boolean + description: |- + Whether or not to include all known networks/protocols from + application services on the homeserver. Defaults to false. + example: false + third_party_instance_id: + type: string + description: |- + The specific third party network/protocol to request from the + homeserver. Can only be used if ``include_all_networks`` is false. + example: "irc" example: { - "limit": 10, "filter": {"generic_search_term": "foo"}} + "limit": 10, + "filter": { + "generic_search_term": "foo" + }, + "include_all_networks": false, + "third_party_instance_id": "irc" + } responses: 200: description: A list of the rooms on the server. diff --git a/api/server-server/public_rooms.yaml b/api/server-server/public_rooms.yaml index d162568f8..b76910236 100644 --- a/api/server-server/public_rooms.yaml +++ b/api/server-server/public_rooms.yaml @@ -49,6 +49,20 @@ paths: A pagination token from a previous call to this endpoint to fetch more rooms. x-example: "GetMoreRoomsTokenHere" + - in: query + name: include_all_networks + type: boolean + description: |- + Whether or not to include all networks/protocols defined by application + services on the homeserver. Defaults to false. + x-example: false + - in: query + name: third_party_instance_id + type: string + description: |- + The specific third party network/protocol to request from the homeserver. + Can only be used if ``include_all_networks`` is false. + x-example: "irc" responses: 200: description: The public room list for the homeserver. diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index c5f8be720..9d467e879 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -218,6 +218,9 @@ Application services can use a more powerful version of the client-server API by identifying itself as an application service to the homeserver. +Endpoints defined in this section MUST be supported by homeservers in the +client-server API as accessible only by application services. + Identity assertion ++++++++++++++++++ The client-server API infers the user ID from the ``access_token`` provided in @@ -314,6 +317,15 @@ API MUST do so with a virtual user (provide a ``user_id`` via the query string). 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 +++++++++++++++++++++++++++++++++++++ + +Application services can maintain their own room directories for their defined +third party protocols. These room directories may be accessed by clients through +additional parameters on the ``/publicRooms`` client-server endpoint. + +{{appservice_room_directory_cs_http_api}} + Event fields ~~~~~~~~~~~~ From 9b19fc27def683ec1f64014aa1686096cf7ee716 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 11:09:55 -0600 Subject: [PATCH 044/219] changelog --- changelogs/client_server/newsfragments/1554.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1554.feature diff --git a/changelogs/client_server/newsfragments/1554.feature b/changelogs/client_server/newsfragments/1554.feature new file mode 100644 index 000000000..ec7ffe71c --- /dev/null +++ b/changelogs/client_server/newsfragments/1554.feature @@ -0,0 +1 @@ +Add third party network room directories, as provided by application services. From 811998735cf2af6ea12ee27427b929ffa3491d93 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 15:51:23 -0600 Subject: [PATCH 045/219] Define common error codes in the Identity Service API Fixes https://github.com/matrix-org/matrix-doc/issues/1407 --- specification/identity_service_api.rst | 69 ++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index 3b037caf0..fb08f6377 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -56,6 +56,75 @@ is left as an exercise for the client. 3PID types are described in `3PID Types`_ Appendix. +API Standards +------------- + +The mandatory baseline for identity service communication in Matrix is exchanging +JSON objects over HTTP APIs. HTTPS is required for communication, and all API calls +use a Content-Type of ``application/json``. In addition, strings MUST be encoded as +UTF-8. + +Any errors which occur at the Matrix API level MUST return a "standard error response". +This is a JSON object which looks like: + +.. code:: json + + { + "errcode": "", + "error": "" + } + +The ``error`` string will be a human-readable error message, usually a sentence +explaining what went wrong. The ``errcode`` string will be a unique string +which can be used to handle an error message e.g. ``M_FORBIDDEN``. There may be +additional keys depending on the error, but the keys ``error`` and ``errcode`` +MUST always be present. + +Some standard error codes are below: + +:``M_NOT_FOUND``: + The resource requested could not be located. + +:``M_MISSING_PARAMS``: + The request was missing one or more parameters. + +:``M_INVALID_PARAM``: + The request contained one or more invalid parameters. + +:``M_SESSION_NOT_VALIDATED``: + The session has not been validated. + +:``M_NO_VALID_SESSION``: + A session could not be located for the given parameters. + +:``M_SESSION_EXPIRED``: + The session has expired and must be renewed. + +:``M_INVALID_EMAIL``: + The email address provided was not valid. + +:``M_EMAIL_SEND_ERROR``: + There was an error sending an email. Typically seen when attempting to verify + ownership of a given email address. + +:``M_INVALID_ADDRESS``: + The provided third party address was not valid. + +:``M_SEND_ERROR``: + There was an error sending a notification. Typically seen when attempting to + verify ownership of a given third party address. + +:``M_UNRECOGNIZED``: + The request contained an unrecognised value, such as an unknown token or medium. + +:``M_THREEPID_IN_USE``: + The third party identifier is already in use by another user. Typically this + error will have an additional ``mxid`` property to indicate who owns the + third party identifier. + +:``M_UNKNOWN``: + An unknown error has occurred. + Privacy ------- From 4abd618147618abc73502f1bd84ee55da5b139e5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 15:53:00 -0600 Subject: [PATCH 046/219] Flag response fields in the Identity Service spec as required --- api/identity/associations.yaml | 9 +++++++++ api/identity/email_associations.yaml | 2 ++ api/identity/invitation_signing.yaml | 1 + api/identity/lookup.yaml | 8 ++++++++ api/identity/phone_associations.yaml | 2 ++ api/identity/pubkey.yaml | 2 ++ api/identity/store_invite.yaml | 1 + 7 files changed, 25 insertions(+) diff --git a/api/identity/associations.yaml b/api/identity/associations.yaml index 784bb5d63..6d282e8dc 100644 --- a/api/identity/associations.yaml +++ b/api/identity/associations.yaml @@ -62,6 +62,7 @@ paths: validated_at: type: integer description: Timestamp indicating the time that the 3pid was validated. + required: ['medium', 'address', 'validated_at'] 400: description: |- The session has not been validated. @@ -158,6 +159,14 @@ paths: signatures: type: object description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. + required: + - address + - medium + - mxid + - not_before + - not_after + - ts + - signatures 400: description: |- The association was not published. diff --git a/api/identity/email_associations.yaml b/api/identity/email_associations.yaml index 8431c9e83..c9fb0cd70 100644 --- a/api/identity/email_associations.yaml +++ b/api/identity/email_associations.yaml @@ -93,6 +93,7 @@ paths: sid: type: string description: The session ID. + required: ['sid'] 400: description: | An error ocurred. Some possible errors are: @@ -151,6 +152,7 @@ paths: success: type: boolean description: Whether the validation was successful or not. + required: ['success'] get: summary: Validate ownership of an email address. description: |- diff --git a/api/identity/invitation_signing.yaml b/api/identity/invitation_signing.yaml index 982dbff78..c595299f5 100644 --- a/api/identity/invitation_signing.yaml +++ b/api/identity/invitation_signing.yaml @@ -71,6 +71,7 @@ paths: token: type: string description: The token for the invitation. + required: ['mxid', 'sender', 'signatures', 'token'] examples: application/json: { "mxid": "@foo:bar.com", diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index bfd2153ec..3bc58be59 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -86,6 +86,14 @@ paths: signatures: type: object description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. + required: + - address + - medium + - mxid + - not_before + - not_after + - ts + - signatures "/bulk_lookup": post: summary: Lookup Matrix user IDs for a list of 3pids. diff --git a/api/identity/phone_associations.yaml b/api/identity/phone_associations.yaml index c2cc6cfe7..605dadcc5 100644 --- a/api/identity/phone_associations.yaml +++ b/api/identity/phone_associations.yaml @@ -99,6 +99,7 @@ paths: sid: type: string description: The session ID. + required: ['sid'] 400: description: | An error ocurred. Some possible errors are: @@ -157,6 +158,7 @@ paths: success: type: boolean description: Whether the validation was successful or not. + required: ['success'] get: summary: Validate ownership of a phone number. description: |- diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 00796975d..45f8b99ac 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -80,6 +80,7 @@ paths: valid: type: boolean description: Whether the public key is recognised and is currently valid. + required: ['valid'] "/pubkey/ephemeral/isvalid": get: summary: Check whether a short-term public key is valid. @@ -108,3 +109,4 @@ paths: valid: type: boolean description: Whether the public key is recognised and is currently valid. + required: ['valid'] diff --git a/api/identity/store_invite.yaml b/api/identity/store_invite.yaml index 6b847b5b0..d6fae7a76 100644 --- a/api/identity/store_invite.yaml +++ b/api/identity/store_invite.yaml @@ -90,6 +90,7 @@ paths: display_name: type: string description: The generated (redacted) display_name. + required: ['token', 'public_keys', 'display_name'] example: application/json: { "token": "sometoken", From dafea96621d6383f6b44d9368024bb95c8ab94a7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 15:53:27 -0600 Subject: [PATCH 047/219] Fix indentation and schema references in the identity service spec --- api/identity/associations.yaml | 69 +++++++++++++++----------- api/identity/email_associations.yaml | 31 +++++++----- api/identity/invitation_signing.yaml | 6 ++- api/identity/lookup.yaml | 35 +++++++------ api/identity/phone_associations.yaml | 33 +++++++----- api/identity/pubkey.yaml | 20 ++++++-- api/identity/store_invite.yaml | 34 +++++++------ schemas/server-signatures.yaml | 24 +++++++++ specification/identity_service_api.rst | 2 +- 9 files changed, 162 insertions(+), 92 deletions(-) create mode 100644 schemas/server-signatures.yaml diff --git a/api/identity/associations.yaml b/api/identity/associations.yaml index 6d282e8dc..4225919b1 100644 --- a/api/identity/associations.yaml +++ b/api/identity/associations.yaml @@ -46,10 +46,10 @@ paths: description: Validation information for the session. examples: application/json: { - "medium": "email", - "validated_at": 1457622739026, - "address": "louise@bobs.burgers" - } + "medium": "email", + "validated_at": 1457622739026, + "address": "louise@bobs.burgers" + } schema: type: object properties: @@ -72,16 +72,20 @@ paths: ``errcode`` will be ``M_SESSION_EXPIRED``. examples: application/json: { - "errcode": "M_SESSION_NOT_VALIDATED", - "error": "This validation session has not yet been completed" - } + "errcode": "M_SESSION_NOT_VALIDATED", + "error": "This validation session has not yet been completed" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" 404: description: The Session ID or client secret were not found examples: application/json: { - "errcode": "M_NO_VALID_SESSION", - "error": "No valid session was found matching that sid and client secret" - } + "errcode": "M_NO_VALID_SESSION", + "error": "No valid session was found matching that sid and client secret" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" "/bind": post: summary: Publish an association between a session and a Matrix user ID. @@ -102,10 +106,10 @@ paths: schema: type: object example: { - "sid": "1234", - "client_secret": "monkeys_are_GREAT", - "mxid": "@ears:matrix.org" - } + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "mxid": "@ears:matrix.org" + } properties: sid: type: string @@ -122,19 +126,19 @@ paths: description: The association was published. examples: application/json: { - "address": "louise@bobs.burgers", - "medium": "email", - "mxid": "@ears:matrix.org", - "not_before": 1428825849161, - "not_after": 4582425849161, - "ts": 1428825849161, + "address": "louise@bobs.burgers", + "medium": "email", + "mxid": "@ears:matrix.org", + "not_before": 1428825849161, + "not_after": 4582425849161, + "ts": 1428825849161, - "signatures": { - "matrix.org": { - "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" - } + "signatures": { + "matrix.org": { + "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" } } + } schema: type: object properties: @@ -159,6 +163,7 @@ paths: signatures: type: object description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. + $ref: "../../schemas/server-signatures.yaml" required: - address - medium @@ -176,13 +181,17 @@ paths: ``errcode`` will be ``M_SESSION_EXPIRED``. examples: application/json: { - "errcode": "M_SESSION_NOT_VALIDATED", - "error": "This validation session has not yet been completed" - } + "errcode": "M_SESSION_NOT_VALIDATED", + "error": "This validation session has not yet been completed" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" 404: description: The Session ID or client secret were not found examples: application/json: { - "errcode": "M_NO_VALID_SESSION", - "error": "No valid session was found matching that sid and client secret" - } + "errcode": "M_NO_VALID_SESSION", + "error": "No valid session was found matching that sid and client secret" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" diff --git a/api/identity/email_associations.yaml b/api/identity/email_associations.yaml index c9fb0cd70..28f5e6809 100644 --- a/api/identity/email_associations.yaml +++ b/api/identity/email_associations.yaml @@ -51,10 +51,10 @@ paths: schema: type: object example: { - "client_secret": "monkeys_are_GREAT", - "email": "foo@example.com", - "send_attempt": 1 - } + "client_secret": "monkeys_are_GREAT", + "email": "foo@example.com", + "send_attempt": 1 + } properties: client_secret: type: string @@ -85,8 +85,8 @@ paths: Session created. examples: application/json: { - "sid": "1234" - } + "sid": "1234" + } schema: type: object properties: @@ -100,6 +100,13 @@ paths: - ``M_INVALID_EMAIL``: The email address provided was invalid. - ``M_EMAIL_SEND_ERROR``: The validation email could not be sent. + examples: + application/json: { + "errcode": "M_INVALID_EMAIL", + "error": "The email address is not valid" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" "/validate/email/submitToken": post: summary: Validate ownership of an email address. @@ -123,10 +130,10 @@ paths: schema: type: object example: { - "sid": "1234", - "client_secret": "monkeys_are_GREAT", - "token": "atoken" - } + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "token": "atoken" + } properties: sid: type: string @@ -144,8 +151,8 @@ paths: The success of the validation. examples: application/json: { - "success": true - } + "success": true + } schema: type: object properties: diff --git a/api/identity/invitation_signing.yaml b/api/identity/invitation_signing.yaml index c595299f5..7de62dd41 100644 --- a/api/identity/invitation_signing.yaml +++ b/api/identity/invitation_signing.yaml @@ -68,6 +68,7 @@ paths: signatures: type: object description: The signature of the mxid, sender, and token. + $ref: "../../schemas/server-signatures.yaml" token: type: string description: The token for the invitation. @@ -85,7 +86,10 @@ paths: } 404: description: Token was not found. - example: { + examples: + application/json: { "errcode": "M_UNRECOGNIZED", "error": "Didn't recognize token" } + schema: + $ref: "../client-server/definitions/errors/error.yaml" diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index 3bc58be59..6f993ac7a 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -49,19 +49,18 @@ paths: The association for that 3pid, or the empty object if no association is known. examples: application/json: { - "address": "louise@bobs.burgers", - "medium": "email", - "mxid": "@ears:matrix.org", - "not_before": 1428825849161, - "not_after": 4582425849161, - "ts": 1428825849161, - - "signatures": { - "matrix.org": { - "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" - } + "address": "louise@bobs.burgers", + "medium": "email", + "mxid": "@ears:matrix.org", + "not_before": 1428825849161, + "not_after": 4582425849161, + "ts": 1428825849161, + "signatures": { + "matrix.org": { + "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" } } + } schema: type: object properties: @@ -86,6 +85,7 @@ paths: signatures: type: object description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. + $ref: "../../schemas/server-signatures.yaml" required: - address - medium @@ -118,9 +118,11 @@ paths: items: type: array title: 3PID mappings + minItems: 2 + maxItems: 2 items: - type: string - title: 3PID medium or address + - type: 3PID Medium + - type: 3PID Address description: an array of arrays containing the `3PID Types`_ with the ``medium`` in first position and the ``address`` in second position. required: - "threepids" @@ -142,9 +144,12 @@ paths: items: type: array title: 3PID mappings + minItems: 3 + maxItems: 3 items: - type: string - title: 3PID medium or address or the Matrix ID + - type: 3PID Medium + - type: 3PID Address + - type: Matrix User ID description: an array of array containing the `3PID Types`_ with the ``medium`` in first position, the ``address`` in second position and Matrix ID in third position. required: - "threepids" diff --git a/api/identity/phone_associations.yaml b/api/identity/phone_associations.yaml index 605dadcc5..f6b1bd45b 100644 --- a/api/identity/phone_associations.yaml +++ b/api/identity/phone_associations.yaml @@ -51,11 +51,11 @@ paths: schema: type: object example: { - "client_secret": "monkeys_are_GREAT", - "country": "GB", - "phone_number": "07700900001", - "send_attempt": 1 - } + "client_secret": "monkeys_are_GREAT", + "country": "GB", + "phone_number": "07700900001", + "send_attempt": 1 + } properties: client_secret: type: string @@ -91,8 +91,8 @@ paths: Session created. examples: application/json: { - "sid": "1234" - } + "sid": "1234" + } schema: type: object properties: @@ -106,6 +106,13 @@ paths: - ``M_INVALID_ADDRESS``: The phone number provided was invalid. - ``M_SEND_ERROR``: The validation SMS could not be sent. + examples: + application/json: { + "errcode": "M_INVALID_ADDRESS", + "error": "The phone number is not valid" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" "/validate/msisdn/submitToken": post: summary: Validate ownership of a phone number. @@ -129,10 +136,10 @@ paths: schema: type: object example: { - "sid": "1234", - "client_secret": "monkeys_are_GREAT", - "token": "atoken" - } + "sid": "1234", + "client_secret": "monkeys_are_GREAT", + "token": "atoken" + } properties: sid: type: string @@ -150,8 +157,8 @@ paths: The success of the validation. examples: application/json: { - "success": true - } + "success": true + } schema: type: object properties: diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 45f8b99ac..9cb7c74e9 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -45,13 +45,25 @@ paths: The public key exists. examples: application/json: { - "public_key": "VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c" - } + "public_key": "VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c" + } schema: type: object properties: public_key: type: string + description: Unpadded Base64 encoded public key. + required: ['public_key'] + 404: + description: + The public key was not found. + examples: + application/json: { + "errcode": "M_NOT_FOUND", + "error": "The public key was not found" + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" "/pubkey/isvalid": get: summary: Check whether a long-term public key is valid. @@ -72,8 +84,8 @@ paths: The validity of the public key. examples: application/json: { - "valid": true - } + "valid": true + } schema: type: object properties: diff --git a/api/identity/store_invite.yaml b/api/identity/store_invite.yaml index d6fae7a76..1eca7198e 100644 --- a/api/identity/store_invite.yaml +++ b/api/identity/store_invite.yaml @@ -54,11 +54,11 @@ paths: schema: type: object example: { - "medium": "email", - "address": "foo@bar.baz", - "room_id": "!something:example.tld", - "sender": "@bob:example.com" - } + "medium": "email", + "address": "foo@bar.baz", + "room_id": "!something:example.tld", + "sender": "@bob:example.com" + } properties: medium: type: string @@ -93,13 +93,13 @@ paths: required: ['token', 'public_keys', 'display_name'] example: application/json: { - "token": "sometoken", - "public_keys": [ - "serverpublickey", - "ephemeralpublickey" - ], - "display_name": "f...@b..." - } + "token": "sometoken", + "public_keys": [ + "serverpublickey", + "ephemeralpublickey" + ], + "display_name": "f...@b..." + } 400: description: | An error has occured. @@ -109,7 +109,9 @@ paths: error code will be ``M_UNRECOGNIZED``. examples: application/json: { - "errcode": "M_THREEPID_IN_USE", - "error": "Binding already known", - "mxid": mxid - } + "errcode": "M_THREEPID_IN_USE", + "error": "Binding already known", + "mxid": mxid + } + schema: + $ref: "../client-server/definitions/errors/error.yaml" diff --git a/schemas/server-signatures.yaml b/schemas/server-signatures.yaml new file mode 100644 index 000000000..a18552566 --- /dev/null +++ b/schemas/server-signatures.yaml @@ -0,0 +1,24 @@ +# 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 +example: { + "example.com": { + "ed25519:0": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus" + } +} +additionalProperties: + type: object + title: Server Signatures + additionalProperties: + type: string \ No newline at end of file diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index fb08f6377..7bbd8ae8c 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -23,7 +23,7 @@ user identifiers. From time to time, it is useful to refer to users by other number. This identity service specification describes how mappings between third-party identifiers and Matrix user identifiers can be established, validated, and used. This description technically may apply to any 3pid, but in -practice has only been applied specifically to email addresses. +practice has only been applied specifically to email addresses and phone numbers. .. contents:: Table of Contents .. sectnum:: From d370a2c6fd0dd91ca43227c91ceeb1c02ad0bccb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 17:11:40 -0600 Subject: [PATCH 048/219] Prepare the identity service and server-server APIs for r0 * Create the changelog scaffolding * Set up the variables for versioning --- api/identity/associations.yaml | 2 +- api/identity/email_associations.yaml | 2 +- api/identity/invitation_signing.yaml | 2 +- api/identity/lookup.yaml | 2 +- api/identity/phone_associations.yaml | 2 +- api/identity/ping.yaml | 2 +- api/identity/pubkey.yaml | 2 +- api/identity/store_invite.yaml | 4 +-- api/server-server/backfill.yaml | 2 +- api/server-server/event_auth.yaml | 2 +- api/server-server/events.yaml | 2 +- api/server-server/invites.yaml | 2 +- api/server-server/joins.yaml | 2 +- api/server-server/keys_query.yaml | 2 +- api/server-server/keys_server.yaml | 2 +- api/server-server/leaving.yaml | 2 +- api/server-server/openid.yaml | 2 +- api/server-server/public_rooms.yaml | 2 +- api/server-server/query.yaml | 2 +- api/server-server/third_party_invite.yaml | 2 +- api/server-server/transactions.yaml | 2 +- api/server-server/version.yaml | 2 +- changelogs/identity_service.rst | 0 .../identity_service/newsfragments/.gitignore | 1 + changelogs/identity_service/pyproject.toml | 30 +++++++++++++++++ changelogs/server_server.rst | 0 .../server_server/newsfragments/.gitignore | 1 + changelogs/server_server/pyproject.toml | 30 +++++++++++++++++ scripts/gendoc.py | 15 ++++++--- .../templating/matrix_templates/sections.py | 8 +++++ scripts/templating/matrix_templates/units.py | 3 +- specification/identity_service_api.rst | 20 ++++++++++-- specification/server_server_api.rst | 32 +++++++++++++------ 33 files changed, 146 insertions(+), 40 deletions(-) create mode 100644 changelogs/identity_service.rst create mode 100644 changelogs/identity_service/newsfragments/.gitignore create mode 100644 changelogs/identity_service/pyproject.toml create mode 100644 changelogs/server_server.rst create mode 100644 changelogs/server_server/newsfragments/.gitignore create mode 100644 changelogs/server_server/pyproject.toml diff --git a/api/identity/associations.yaml b/api/identity/associations.yaml index 784bb5d63..59185c839 100644 --- a/api/identity/associations.yaml +++ b/api/identity/associations.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/identity/email_associations.yaml b/api/identity/email_associations.yaml index 8431c9e83..9649f6ef8 100644 --- a/api/identity/email_associations.yaml +++ b/api/identity/email_associations.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/identity/invitation_signing.yaml b/api/identity/invitation_signing.yaml index 982dbff78..bc06b89a3 100644 --- a/api/identity/invitation_signing.yaml +++ b/api/identity/invitation_signing.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index bfd2153ec..1dc79d859 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -21,7 +21,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/identity/phone_associations.yaml b/api/identity/phone_associations.yaml index c2cc6cfe7..6d30ee3d9 100644 --- a/api/identity/phone_associations.yaml +++ b/api/identity/phone_associations.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/identity/ping.yaml b/api/identity/ping.yaml index 005160a35..b630c7332 100644 --- a/api/identity/ping.yaml +++ b/api/identity/ping.yaml @@ -23,7 +23,7 @@ basePath: /_matrix/identity produces: - application/json paths: - "/api/v1": + "/api/%IDENTITY_MAJOR_VERSION%": get: summary: Checks that an Identity server is available at this API endpopint. description: |- diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 00796975d..3884b63af 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/identity/store_invite.yaml b/api/identity/store_invite.yaml index 6b847b5b0..c4056acbb 100644 --- a/api/identity/store_invite.yaml +++ b/api/identity/store_invite.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/v1 +basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% produces: - application/json paths: @@ -46,7 +46,7 @@ paths: ``address`` parameter, notifying them of the invitation. Also, the generated ephemeral public key will be listed as valid on - requests to ``/_matrix/identity/api/v1/pubkey/ephemeral/isvalid``. + requests to ``/_matrix/identity/api/%IDENTITY_MAJOR_VERSION%/pubkey/ephemeral/isvalid``. operationId: storeInvite parameters: - in: body diff --git a/api/server-server/backfill.yaml b/api/server-server/backfill.yaml index 6b3cfaef0..5c88f554b 100644 --- a/api/server-server/backfill.yaml +++ b/api/server-server/backfill.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/event_auth.yaml b/api/server-server/event_auth.yaml index 8857131fa..0248fb1e7 100644 --- a/api/server-server/event_auth.yaml +++ b/api/server-server/event_auth.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/events.yaml b/api/server-server/events.yaml index cf3988a20..0b3183730 100644 --- a/api/server-server/events.yaml +++ b/api/server-server/events.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% produces: - application/json securityDefinitions: diff --git a/api/server-server/invites.yaml b/api/server-server/invites.yaml index 6d905e178..d55ccb5b5 100644 --- a/api/server-server/invites.yaml +++ b/api/server-server/invites.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/joins.yaml b/api/server-server/joins.yaml index 4902ea9e1..66a071e58 100644 --- a/api/server-server/joins.yaml +++ b/api/server-server/joins.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/keys_query.yaml b/api/server-server/keys_query.yaml index e616915bd..face2bd63 100644 --- a/api/server-server/keys_query.yaml +++ b/api/server-server/keys_query.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/key/v2 +basePath: /_matrix/key/%KEYS_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/keys_server.yaml b/api/server-server/keys_server.yaml index 8734f2edd..d09ba8e27 100644 --- a/api/server-server/keys_server.yaml +++ b/api/server-server/keys_server.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/key/v2 +basePath: /_matrix/key/%KEYS_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/server-server/leaving.yaml b/api/server-server/leaving.yaml index be08acba6..739f4962c 100644 --- a/api/server-server/leaving.yaml +++ b/api/server-server/leaving.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/openid.yaml b/api/server-server/openid.yaml index 0eac48c84..942a5d5e6 100644 --- a/api/server-server/openid.yaml +++ b/api/server-server/openid.yaml @@ -20,7 +20,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% produces: - application/json paths: diff --git a/api/server-server/public_rooms.yaml b/api/server-server/public_rooms.yaml index d162568f8..be9428a47 100644 --- a/api/server-server/public_rooms.yaml +++ b/api/server-server/public_rooms.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% produces: - application/json securityDefinitions: diff --git a/api/server-server/query.yaml b/api/server-server/query.yaml index dc14724c5..af70a9c36 100644 --- a/api/server-server/query.yaml +++ b/api/server-server/query.yaml @@ -20,7 +20,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% produces: - application/json securityDefinitions: diff --git a/api/server-server/third_party_invite.yaml b/api/server-server/third_party_invite.yaml index 5c12247cf..9e3bba2c2 100644 --- a/api/server-server/third_party_invite.yaml +++ b/api/server-server/third_party_invite.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/transactions.yaml b/api/server-server/transactions.yaml index 8d810ad59..bb6254e75 100644 --- a/api/server-server/transactions.yaml +++ b/api/server-server/transactions.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% consumes: - application/json produces: diff --git a/api/server-server/version.yaml b/api/server-server/version.yaml index 199755290..17110f19e 100644 --- a/api/server-server/version.yaml +++ b/api/server-server/version.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/v1 +basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% produces: - application/json paths: diff --git a/changelogs/identity_service.rst b/changelogs/identity_service.rst new file mode 100644 index 000000000..e69de29bb diff --git a/changelogs/identity_service/newsfragments/.gitignore b/changelogs/identity_service/newsfragments/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/changelogs/identity_service/newsfragments/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/changelogs/identity_service/pyproject.toml b/changelogs/identity_service/pyproject.toml new file mode 100644 index 000000000..7a64eb0b9 --- /dev/null +++ b/changelogs/identity_service/pyproject.toml @@ -0,0 +1,30 @@ +[tool.towncrier] + filename = "../identity_service.rst" + directory = "newsfragments" + issue_format = "`#{issue} `_" + title_format = "{version}" + + [[tool.towncrier.type]] + directory = "breaking" + name = "Breaking Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "new" + name = "New Endpoints" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Backwards Compatible Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "clarification" + name = "Spec Clarifications" + showcontent = true diff --git a/changelogs/server_server.rst b/changelogs/server_server.rst new file mode 100644 index 000000000..e69de29bb diff --git a/changelogs/server_server/newsfragments/.gitignore b/changelogs/server_server/newsfragments/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/changelogs/server_server/newsfragments/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/changelogs/server_server/pyproject.toml b/changelogs/server_server/pyproject.toml new file mode 100644 index 000000000..984785273 --- /dev/null +++ b/changelogs/server_server/pyproject.toml @@ -0,0 +1,30 @@ +[tool.towncrier] + filename = "../server_server.rst" + directory = "newsfragments" + issue_format = "`#{issue} `_" + title_format = "{version}" + + [[tool.towncrier.type]] + directory = "breaking" + name = "Breaking Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "new" + name = "New Endpoints" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Backwards Compatible Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "clarification" + name = "Spec Clarifications" + showcontent = true diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 16c40af5d..e2f788ccc 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -518,6 +518,10 @@ if __name__ == '__main__': "--server_release", "-s", action="store", default="unstable", help="The server-server release tag to generate, e.g. r1.2" ) + parser.add_argument( + "--identity_release", "-i", action="store", default="unstable", + help="The identity service release tag to generate, e.g. r1.2" + ) parser.add_argument( "--list_targets", action="store_true", help="Do not update the specification. Instead print a list of targets.", @@ -536,12 +540,15 @@ if __name__ == '__main__': substitutions = { "%CLIENT_RELEASE_LABEL%": args.client_release, - # we hardcode a major version of r0. This ends up in the - # example API URLs. When we have released a new major version, - # we'll have to bump it. + # we hardcode the major versions. This ends up in the example + # API URLs. When we have released a new major version, we'll + # have to bump them. "%CLIENT_MAJOR_VERSION%": "r0", + "%SERVER_MAJOR_VERSION%": "v1", + "%IDENTITY_MAJOR_VERSION%": "v1", + "%KEYS_MAJOR_VERSION%": "v2", "%SERVER_RELEASE_LABEL%": args.server_release, - "%SERVER_MAJOR_VERSION%": extract_major(args.server_release), + "%IDENTITY_RELEASE_LABEL%": args.identity_release, } exit (main(args.target or ["all"], args.dest, args.nodelete, substitutions)) diff --git a/scripts/templating/matrix_templates/sections.py b/scripts/templating/matrix_templates/sections.py index 1a93c7237..7c982f809 100644 --- a/scripts/templating/matrix_templates/sections.py +++ b/scripts/templating/matrix_templates/sections.py @@ -32,6 +32,14 @@ class MatrixSections(Sections): changelogs = self.units.get("changelogs") return changelogs["client_server"] + def render_identity_service_changelog(self): + changelogs = self.units.get("changelogs") + return changelogs["identity_service"] + + def render_server_server_changelog(self): + changelogs = self.units.get("changelogs") + return changelogs["server_server"] + def _render_events(self, filterFn, sortFn): template = self.env.get_template("events.tmpl") examples = self.units.get("event_examples") diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 90a87cd47..ed8943e0c 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -754,6 +754,7 @@ class MatrixUnits(Units): def load_apis(self, substitutions): cs_ver = substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable") fed_ver = substitutions.get("%SERVER_RELEASE_LABEL%", "unstable") + is_ver = substitutions.get("%IDENTITY_RELEASE_LABEL%", "unstable") # we abuse the typetable to return this info to the templates return TypeTable(rows=[ @@ -770,7 +771,7 @@ class MatrixUnits(Units): "unstable", "Privileged server plugins", ), TypeTableRow( - "`Identity Service API `_", + "`Identity Service API `_", "unstable", "Mapping of third party IDs to Matrix IDs", ), TypeTableRow( diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index 3b037caf0..49d68834f 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -28,13 +28,27 @@ practice has only been applied specifically to email addresses. .. contents:: Table of Contents .. sectnum:: -Specification version ---------------------- +Changelog +--------- + +.. topic:: Version: %IDENTITY_RELEASE_LABEL% +{{identity_service_changelog}} This version of the specification is generated from `matrix-doc `_ as of Git commit `{{git_version}} `_. +For the full historical changelog, see +https://github.com/matrix-org/matrix-doc/blob/master/changelogs/identity_service.rst + + +Other versions of this specification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following other versions are also available, in reverse chronological order: + +- `HEAD `_: Includes all changes since the latest versioned release. + General principles ------------------ @@ -138,7 +152,7 @@ associated with a Matrix user ID. At a later point, if the owner of that particular 3pid binds it with a Matrix user ID, the identity server will attempt to make an HTTP POST to the Matrix user's homeserver which looks roughly as below:: - POST https://bar.com:8448/_matrix/federation/v1/3pid/onbind + POST https://bar.com:8448/_matrix/federation/%SERVER_MAJOR_VERSION%/3pid/onbind Content-Type: application/json { diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index dbde8b104..ccebc313c 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -64,13 +64,27 @@ request. .. contents:: Table of Contents .. sectnum:: -Specification version ---------------------- +Changelog +--------- + +.. topic:: Version: %SERVER_RELEASE_LABEL% +{{server_server_changelog}} This version of the specification is generated from `matrix-doc `_ as of Git commit `{{git_version}} `_. +For the full historical changelog, see +https://github.com/matrix-org/matrix-doc/blob/master/changelogs/server_server.rst + + +Other versions of this specification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following other versions are also available, in reverse chronological order: + +- `HEAD `_: Includes all changes since the latest versioned release. + Server Discovery ---------------- @@ -118,11 +132,11 @@ Retrieving Server Keys specification due to lack of significance. It may be reviewed `here `_. -Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``. -Homeservers query for keys by either getting ``/_matrix/key/v2/server/{keyId}`` +Each homeserver publishes its public keys under ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}``. +Homeservers query for keys by either getting ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}`` directly or by querying an intermediate notary server using a -``/_matrix/key/v2/query/{serverName}/{keyId}`` API. Intermediate notary servers -query the ``/_matrix/key/v2/server/{keyId}`` API on behalf of another server and +``/_matrix/key/%KEYS_MAJOR_VERSION%/query/{serverName}/{keyId}`` API. Intermediate notary servers +query the ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}`` API on behalf of another server and sign the response with their own key. A server may query multiple notary servers to ensure that they all report the same public keys. @@ -138,7 +152,7 @@ Publishing Keys +++++++++++++++ Homeservers publish the allowed TLS fingerprints and signing keys in a JSON -object at ``/_matrix/key/v2/server/{key_id}``. The response contains a list of +object at ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{key_id}``. The response contains a list of ``verify_keys`` that are valid for signing federation requests made by the homeserver and for signing events. It contains a list of ``old_verify_keys`` which are only valid for signing events. Finally the response contains a list of TLS @@ -152,7 +166,7 @@ Querying Keys Through Another Server Servers may query another server's keys through a notary server. The notary server may be another homeserver. The notary server will retrieve keys from -the queried servers through use of the ``/_matrix/key/v2/server/{keyId}`` +the queried servers through use of the ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}`` API. The notary server will additionally sign the response from the queried server before returning the results. @@ -1073,7 +1087,7 @@ that are too long. known hash functions like SHA-256 when none of the keys have been redacted]] .. |/query/directory| replace:: ``/query/directory`` -.. _/query/directory: #get-matrix-federation-v1-query-directory +.. _/query/directory: #get-matrix-federation-%SERVER_MAJOR_VERSION%-query-directory .. _`Invitation storage`: ../identity_service/unstable.html#invitation-storage .. _`Identity Service API`: ../identity_service/unstable.html From 0f28f8327021c43632678d4d54f5753c7cd021ec Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 17:59:48 -0600 Subject: [PATCH 049/219] Fix client-server event schemas: remove `age`, dedupe fields This commit adds support for event schema examples to have references to help reduce the chance of fields being forgotten. This also helps reduce duplication of fields, allowing for a more consistent spec that uses the same values everywhere. This also removes both `unsigned` and `age` from the examples as per: * https://github.com/matrix-org/matrix-doc/issues/1524 * https://github.com/matrix-org/matrix-doc/issues/630 Finally, this replaces "localhost" in the examples with an example domain. This is really just a nitpick thing on my part where seeing a "real world" domain is preferred. Fixes https://github.com/matrix-org/matrix-doc/issues/1524 Fixes https://github.com/matrix-org/matrix-doc/issues/630 Step towards https://github.com/matrix-org/matrix-doc/issues/1530 --- event-schemas/examples/core/event.json | 6 ++++++ event-schemas/examples/core/room_edu.json | 4 ++++ event-schemas/examples/core/room_event.json | 7 +++++++ event-schemas/examples/core/state_event.json | 4 ++++ event-schemas/examples/m.call.answer | 10 +++------- event-schemas/examples/m.call.candidates | 10 +++------- event-schemas/examples/m.call.hangup | 10 +++------- event-schemas/examples/m.call.invite | 10 +++------- event-schemas/examples/m.direct | 7 ++++--- event-schemas/examples/m.ignored_user_list | 1 + event-schemas/examples/m.presence | 7 ++++--- event-schemas/examples/m.receipt | 18 +++++++++--------- event-schemas/examples/m.room.aliases | 14 +++++--------- event-schemas/examples/m.room.avatar | 14 +++++--------- event-schemas/examples/m.room.canonical_alias | 12 ++++-------- event-schemas/examples/m.room.create | 16 +++++++--------- event-schemas/examples/m.room.encrypted#megolm | 9 +++------ event-schemas/examples/m.room.encrypted#olm | 2 +- event-schemas/examples/m.room.encryption | 11 ++++------- event-schemas/examples/m.room.guest_access | 12 ++++-------- .../examples/m.room.history_visibility | 12 ++++-------- event-schemas/examples/m.room.join_rules | 12 ++++-------- event-schemas/examples/m.room.member | 14 +++++--------- .../examples/m.room.member#invite_room_state | 12 +++--------- .../examples/m.room.member#third_party_invite | 14 ++++---------- event-schemas/examples/m.room.message#m.audio | 12 ++++-------- event-schemas/examples/m.room.message#m.emote | 10 +++------- event-schemas/examples/m.room.message#m.file | 12 ++++-------- event-schemas/examples/m.room.message#m.image | 12 ++++-------- .../examples/m.room.message#m.location | 12 ++++-------- event-schemas/examples/m.room.message#m.notice | 10 +++------- event-schemas/examples/m.room.message#m.text | 10 +++------- event-schemas/examples/m.room.message#m.video | 14 +++++--------- event-schemas/examples/m.room.message.feedback | 10 +++------- event-schemas/examples/m.room.name | 12 ++++-------- event-schemas/examples/m.room.pinned_events | 14 +++++--------- event-schemas/examples/m.room.power_levels | 12 ++++-------- event-schemas/examples/m.room.redaction | 14 ++++---------- .../examples/m.room.third_party_invite | 12 ++++-------- event-schemas/examples/m.room.topic | 12 ++++-------- event-schemas/examples/m.room_key | 5 +++-- event-schemas/examples/m.sticker | 10 +++------- event-schemas/examples/m.tag | 1 + event-schemas/examples/m.typing | 10 +++++----- scripts/templating/matrix_templates/units.py | 2 +- 45 files changed, 175 insertions(+), 279 deletions(-) create mode 100644 event-schemas/examples/core/event.json create mode 100644 event-schemas/examples/core/room_edu.json create mode 100644 event-schemas/examples/core/room_event.json create mode 100644 event-schemas/examples/core/state_event.json diff --git a/event-schemas/examples/core/event.json b/event-schemas/examples/core/event.json new file mode 100644 index 000000000..8a469a5cb --- /dev/null +++ b/event-schemas/examples/core/event.json @@ -0,0 +1,6 @@ +{ + "content": { + "key": "value" + }, + "type": "org.example.custom.event" +} diff --git a/event-schemas/examples/core/room_edu.json b/event-schemas/examples/core/room_edu.json new file mode 100644 index 000000000..80575f5d7 --- /dev/null +++ b/event-schemas/examples/core/room_edu.json @@ -0,0 +1,4 @@ +{ + "$ref": "event.json", + "room_id": "!jEsUZKDJdhlrceRyVU:domain.com" +} diff --git a/event-schemas/examples/core/room_event.json b/event-schemas/examples/core/room_event.json new file mode 100644 index 000000000..fe9ff7ee6 --- /dev/null +++ b/event-schemas/examples/core/room_event.json @@ -0,0 +1,7 @@ +{ + "$ref": "event.json", + "event_id": "$143273582443PhrSn:domain.com", + "room_id": "!jEsUZKDJdhlrceRyVU:domain.com", + "sender": "@example:domain.com", + "origin_server_ts": 1432735824653 +} diff --git a/event-schemas/examples/core/state_event.json b/event-schemas/examples/core/state_event.json new file mode 100644 index 000000000..910747ee2 --- /dev/null +++ b/event-schemas/examples/core/state_event.json @@ -0,0 +1,4 @@ +{ + "$ref": "room_event.json", + "state_key": "ArbitraryString" +} diff --git a/event-schemas/examples/m.call.answer b/event-schemas/examples/m.call.answer index f7d144394..a4cfc1e16 100644 --- a/event-schemas/examples/m.call.answer +++ b/event-schemas/examples/m.call.answer @@ -1,5 +1,6 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.call.answer", "content": { "version" : 0, "call_id": "12345", @@ -8,10 +9,5 @@ "type" : "answer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.call.answer", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.call.candidates b/event-schemas/examples/m.call.candidates index 8e6849bb1..8f1f807ad 100644 --- a/event-schemas/examples/m.call.candidates +++ b/event-schemas/examples/m.call.candidates @@ -1,5 +1,6 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.call.candidates", "content": { "version" : 0, "call_id": "12345", @@ -10,10 +11,5 @@ "candidate": "candidate:863018703 1 udp 2122260223 10.9.64.156 43670 typ host generation 0" } ] - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.call.candidates", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.call.hangup b/event-schemas/examples/m.call.hangup index 42e1f346c..295f16e48 100644 --- a/event-schemas/examples/m.call.hangup +++ b/event-schemas/examples/m.call.hangup @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.call.hangup", "content": { "version" : 0, "call_id": "12345" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.call.hangup", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.call.invite b/event-schemas/examples/m.call.invite index 974a5b4cd..fa482bd94 100644 --- a/event-schemas/examples/m.call.invite +++ b/event-schemas/examples/m.call.invite @@ -1,5 +1,6 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.call.invite", "content": { "version" : 0, "call_id": "12345", @@ -8,10 +9,5 @@ "type" : "offer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.call.invite", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.direct b/event-schemas/examples/m.direct index 92f13daa2..e453dd599 100644 --- a/event-schemas/examples/m.direct +++ b/event-schemas/examples/m.direct @@ -1,9 +1,10 @@ { + "$ref": "core/event.json", "type": "m.direct", "content": { "@bob:example.com": [ - "!abcdefgh:example.com", - "!hgfedcba:example.com" - ] + "!abcdefgh:example.com", + "!hgfedcba:example.com" + ] } } diff --git a/event-schemas/examples/m.ignored_user_list b/event-schemas/examples/m.ignored_user_list index f3a328f7f..9963d13aa 100644 --- a/event-schemas/examples/m.ignored_user_list +++ b/event-schemas/examples/m.ignored_user_list @@ -1,4 +1,5 @@ { + "$ref": "core/event.json", "type": "m.ignored_user_list", "content": { "ignored_users": { diff --git a/event-schemas/examples/m.presence b/event-schemas/examples/m.presence index 824ffcb71..36093cd92 100644 --- a/event-schemas/examples/m.presence +++ b/event-schemas/examples/m.presence @@ -1,10 +1,11 @@ { + "$ref": "core/event.json", + "sender": "@example:localhost", + "type": "m.presence", "content": { "avatar_url": "mxc://localhost:wefuiwegh8742w", "last_active_ago": 2478593, "presence": "online", "currently_active": false - }, - "sender": "@example:localhost", - "type": "m.presence" + } } diff --git a/event-schemas/examples/m.receipt b/event-schemas/examples/m.receipt index bd0b726c3..c52d8540f 100644 --- a/event-schemas/examples/m.receipt +++ b/event-schemas/examples/m.receipt @@ -1,13 +1,13 @@ { - "type": "m.receipt", - "room_id": "!KpjVgQyZpzBwvMBsnT:matrix.org", - "content": { - "$1435641916114394fHBLK:matrix.org": { - "m.read": { - "@rikj:jki.re": { - "ts": 1436451550453 - } - } + "$ref": "core/room_edu.json", + "type": "m.receipt", + "content": { + "$1435641916114394fHBLK:matrix.org": { + "m.read": { + "@rikj:jki.re": { + "ts": 1436451550453 } + } } + } } diff --git a/event-schemas/examples/m.room.aliases b/event-schemas/examples/m.room.aliases index ca87510e3..bb2fe21c5 100644 --- a/event-schemas/examples/m.room.aliases +++ b/event-schemas/examples/m.room.aliases @@ -1,12 +1,8 @@ { - "age": 242352, - "content": { - "aliases": ["#somewhere:localhost", "#another:localhost"] - }, - "state_key": "localhost", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", + "$ref": "core/state_event.json", + "state_key": "domain.com", "type": "m.room.aliases", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + "content": { + "aliases": ["#somewhere:domain.com", "#another:domain.com"] + } } diff --git a/event-schemas/examples/m.room.avatar b/event-schemas/examples/m.room.avatar index 2080d96ef..9b51e01fd 100644 --- a/event-schemas/examples/m.room.avatar +++ b/event-schemas/examples/m.room.avatar @@ -1,5 +1,7 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.avatar", + "state_key": "", "content": { "info": { "h": 398, @@ -7,12 +9,6 @@ "mimetype": "image/jpeg", "size": 31037 }, - "url": "mxc://localhost/JWEIFJgwEIhweiWJE" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.avatar", - "state_key": "", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + "url": "mxc://domain.com/JWEIFJgwEIhweiWJE" + } } diff --git a/event-schemas/examples/m.room.canonical_alias b/event-schemas/examples/m.room.canonical_alias index 59df586d9..06c3226c9 100644 --- a/event-schemas/examples/m.room.canonical_alias +++ b/event-schemas/examples/m.room.canonical_alias @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.canonical_alias", + "state_key": "", "content": { "alias": "#somewhere:localhost" - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.canonical_alias", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.create b/event-schemas/examples/m.room.create index 34dabb536..181274977 100644 --- a/event-schemas/examples/m.room.create +++ b/event-schemas/examples/m.room.create @@ -1,12 +1,10 @@ { - "age": 242352, - "content": { - "creator": "@example:localhost" - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", + "$ref": "core/state_event.json", "type": "m.room.create", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + "state_key": "", + "content": { + "creator": "@example:domain.com", + "room_version": "1", + "m.federate": true + } } diff --git a/event-schemas/examples/m.room.encrypted#megolm b/event-schemas/examples/m.room.encrypted#megolm index 1f9b75208..ac542e254 100644 --- a/event-schemas/examples/m.room.encrypted#megolm +++ b/event-schemas/examples/m.room.encrypted#megolm @@ -1,14 +1,11 @@ { + "$ref": "core/room_event.json", + "type": "m.room.encrypted", "content": { "algorithm": "m.megolm.v1.aes-sha2", "ciphertext": "AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...", "device_id": "RJYKSTBOIE", "sender_key": "IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA", "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ" - }, - "event_id": "$WLGTSEFSEF:localhost", - "room_id": "!Cuyf34gef24t:localhost", - "origin_server_ts": 1476648761524, - "sender": "@example:localhost", - "type": "m.room.encrypted" + } } diff --git a/event-schemas/examples/m.room.encrypted#olm b/event-schemas/examples/m.room.encrypted#olm index abb23c31e..381651d95 100644 --- a/event-schemas/examples/m.room.encrypted#olm +++ b/event-schemas/examples/m.room.encrypted#olm @@ -1,6 +1,6 @@ { + "$ref": "core/room_event.json", "type": "m.room.encrypted", - "sender": "@example:localhost", "content": { "algorithm": "m.olm.v1.curve25519-aes-sha2", "sender_key": "Szl29ksW/L8yZGWAX+8dY1XyFi+i5wm+DRhTGkbMiwU", diff --git a/event-schemas/examples/m.room.encryption b/event-schemas/examples/m.room.encryption index 08f152396..6158b9379 100644 --- a/event-schemas/examples/m.room.encryption +++ b/event-schemas/examples/m.room.encryption @@ -1,13 +1,10 @@ { + "$ref": "core/state_event.json", + "type": "m.room.encryption", + "state_key": "", "content": { "algorithm": "m.megolm.v1.aes-sha2", "rotation_period_ms": 604800000, "rotation_period_msgs": 100 - }, - "event_id": "$WLGTSEFJJKJ:localhost", - "origin_server_ts": 1476648761524, - "sender": "@example:localhost", - "room_id": "!Cuyf34gef24t:localhost", - "state_key": "", - "type": "m.room.encryption" + } } diff --git a/event-schemas/examples/m.room.guest_access b/event-schemas/examples/m.room.guest_access index c636ff395..a6deff8c0 100644 --- a/event-schemas/examples/m.room.guest_access +++ b/event-schemas/examples/m.room.guest_access @@ -1,12 +1,8 @@ { - "age": 242353, + "$ref": "core/state_event.json", + "type": "m.room.guest_access", + "state_key": "", "content": { "guest_access": "can_join" - }, - "state_key": "", - "origin_server_ts": 1431961217938, - "event_id": "$WLGTSEFSEG:localhost", - "type": "m.room.guest_access", - "room_id": "!Cuyf34gef24u:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.history_visibility b/event-schemas/examples/m.room.history_visibility index 6fedc5dc6..27c4fec35 100644 --- a/event-schemas/examples/m.room.history_visibility +++ b/event-schemas/examples/m.room.history_visibility @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.history_visibility", + "state_key": "", "content": { "history_visibility": "shared" - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.history_visibility", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.join_rules b/event-schemas/examples/m.room.join_rules index 39e14fc5d..2873be781 100644 --- a/event-schemas/examples/m.room.join_rules +++ b/event-schemas/examples/m.room.join_rules @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.join_rules", + "state_key": "", "content": { "join_rule": "public" - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.join_rules", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.member b/event-schemas/examples/m.room.member index 2495145ba..ce31ab8fe 100644 --- a/event-schemas/examples/m.room.member +++ b/event-schemas/examples/m.room.member @@ -1,14 +1,10 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "state_key": "@alice:domain.com", + "type": "m.room.member", "content": { "membership": "join", - "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto", + "avatar_url": "mxc://domain.com/SEsfnsuifSDFSSEF#auto", "displayname": "Alice Margatroid" - }, - "state_key": "@alice:localhost", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.member", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.member#invite_room_state b/event-schemas/examples/m.room.member#invite_room_state index 1a93b395b..54d71ca7e 100644 --- a/event-schemas/examples/m.room.member#invite_room_state +++ b/event-schemas/examples/m.room.member#invite_room_state @@ -1,8 +1,8 @@ { - "age": 242352, + "$ref": "m.room.member", "content": { "membership": "invite", - "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto", + "avatar_url": "mxc://domain.com/SEsfnsuifSDFSSEF#auto", "displayname": "Alice Margatroid" }, "invite_room_state": [ @@ -20,11 +20,5 @@ "join_rule": "invite" } } - ], - "state_key": "@alice:localhost", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.member", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + ] } diff --git a/event-schemas/examples/m.room.member#third_party_invite b/event-schemas/examples/m.room.member#third_party_invite index 244e15562..92b5d2ef9 100644 --- a/event-schemas/examples/m.room.member#third_party_invite +++ b/event-schemas/examples/m.room.member#third_party_invite @@ -1,13 +1,13 @@ { - "age": 242352, + "$ref": "m.room.member", "content": { "membership": "invite", - "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto", + "avatar_url": "mxc://domain.com/SEsfnsuifSDFSSEF#auto", "displayname": "Alice Margatroid", "third_party_invite": { "display_name": "alice", "signed": { - "mxid": "@alice:localhost", + "mxid": "@alice:domain.com", "signatures": { "magic.forest": { "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg" @@ -16,11 +16,5 @@ "token": "abc123" } } - }, - "state_key": "@alice:localhost", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.member", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.audio b/event-schemas/examples/m.room.message#m.audio index 367eb9540..4ce5a2a8a 100644 --- a/event-schemas/examples/m.room.message#m.audio +++ b/event-schemas/examples/m.room.message#m.audio @@ -1,18 +1,14 @@ { - "age": 146, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "Bee Gees - Stayin' Alive", - "url": "mxc://localhost/ffed755USFFxlgbQYZGtryd", + "url": "mxc://domain.com/ffed755USFFxlgbQYZGtryd", "info": { "duration": 2140786, "size": 1563685, "mimetype": "audio/mpeg" }, "msgtype": "m.audio" - }, - "event_id": "$143273582443PhrSn:localhost", - "origin_server_ts": 1432735824653, - "room_id": "!jEsUZKDJdhlrceRyVU:localhost", - "type": "m.room.message", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.emote b/event-schemas/examples/m.room.message#m.emote index 79292ddf8..5fecb9a3f 100644 --- a/event-schemas/examples/m.room.message#m.emote +++ b/event-schemas/examples/m.room.message#m.emote @@ -1,14 +1,10 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "thinks this is an example emote", "msgtype": "m.emote", "format": "org.matrix.custom.html", "formatted_body": "thinks this is an example emote" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.message", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.file b/event-schemas/examples/m.room.message#m.file index e52c3a947..b518550aa 100644 --- a/event-schemas/examples/m.room.message#m.file +++ b/event-schemas/examples/m.room.message#m.file @@ -1,5 +1,6 @@ { - "age": 146, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "something-important.doc", "filename": "something-important.doc", @@ -8,11 +9,6 @@ "size": 46144 }, "msgtype": "m.file", - "url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe" - }, - "event_id": "$143273582443PhrSn:localhost", - "origin_server_ts": 1432735824653, - "room_id": "!jEsUZKDJdhlrceRyVU:localhost", - "type": "m.room.message", - "sender": "@example:localhost" + "url": "mxc://domain.com/FHyPlCeYUSFFxlgbQYZmoEoe" + } } diff --git a/event-schemas/examples/m.room.message#m.image b/event-schemas/examples/m.room.message#m.image index 91e72be26..60402effc 100644 --- a/event-schemas/examples/m.room.message#m.image +++ b/event-schemas/examples/m.room.message#m.image @@ -1,5 +1,6 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "filename.jpg", "info": { @@ -8,12 +9,7 @@ "mimetype": "image/jpeg", "size": 31037 }, - "url": "mxc://localhost/JWEIFJgwEIhweiWJE", + "url": "mxc://domain.com/JWEIFJgwEIhweiWJE", "msgtype": "m.image" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.message", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.location b/event-schemas/examples/m.room.message#m.location index 75363f6fd..1461a305d 100644 --- a/event-schemas/examples/m.room.message#m.location +++ b/event-schemas/examples/m.room.message#m.location @@ -1,10 +1,11 @@ { - "age": 146, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "Big Ben, London, UK", "geo_uri": "geo:51.5008,0.1247", "info": { - "thumbnail_url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe", + "thumbnail_url": "mxc://domain.com/FHyPlCeYUSFFxlgbQYZmoEoe", "thumbnail_info": { "mimetype": "image/jpeg", "size": 46144, @@ -13,10 +14,5 @@ } }, "msgtype": "m.location" - }, - "event_id": "$143273582443PhrSn:localhost", - "origin_server_ts": 1432735824653, - "room_id": "!jEsUZKDJdhlrceRyVU:localhost", - "type": "m.room.message", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.notice b/event-schemas/examples/m.room.message#m.notice index 978c67e6b..78e9dea67 100644 --- a/event-schemas/examples/m.room.message#m.notice +++ b/event-schemas/examples/m.room.message#m.notice @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "This is an example notice", "msgtype": "m.notice" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.message", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.text b/event-schemas/examples/m.room.message#m.text index 48a97db80..ba1fb7697 100644 --- a/event-schemas/examples/m.room.message#m.text +++ b/event-schemas/examples/m.room.message#m.text @@ -1,14 +1,10 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "This is an example text message", "msgtype": "m.text", "format": "org.matrix.custom.html", "formatted_body": "This is an example text message" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.message", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message#m.video b/event-schemas/examples/m.room.message#m.video index 576d80de4..304fbfbd1 100644 --- a/event-schemas/examples/m.room.message#m.video +++ b/event-schemas/examples/m.room.message#m.video @@ -1,10 +1,11 @@ { - "age": 146, + "$ref": "core/room_event.json", + "type": "m.room.message", "content": { "body": "Gangnam Style", - "url": "mxc://localhost/a526eYUSFFxlgbQYZmo442", + "url": "mxc://domain.com/a526eYUSFFxlgbQYZmo442", "info": { - "thumbnail_url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe", + "thumbnail_url": "mxc://domain.com/FHyPlCeYUSFFxlgbQYZmoEoe", "thumbnail_info": { "mimetype": "image/jpeg", "size": 46144, @@ -18,10 +19,5 @@ "mimetype": "video/mp4" }, "msgtype": "m.video" - }, - "event_id": "$143273582443PhrSn:localhost", - "origin_server_ts": 1432735824653, - "room_id": "!jEsUZKDJdhlrceRyVU:localhost", - "type": "m.room.message", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.message.feedback b/event-schemas/examples/m.room.message.feedback index 16fe0ee09..e146e8743 100644 --- a/event-schemas/examples/m.room.message.feedback +++ b/event-schemas/examples/m.room.message.feedback @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.room.message.feedback", "content": { "type": "delivered", "target_event_id": "$WEIGFHFW:localhost" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.message.feedback", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.name b/event-schemas/examples/m.room.name index 87db2008e..e77e2b53a 100644 --- a/event-schemas/examples/m.room.name +++ b/event-schemas/examples/m.room.name @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.name", + "state_key": "", "content": { "name": "The room name" - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.name", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.pinned_events b/event-schemas/examples/m.room.pinned_events index 6f41e97da..10d71a8d6 100644 --- a/event-schemas/examples/m.room.pinned_events +++ b/event-schemas/examples/m.room.pinned_events @@ -1,12 +1,8 @@ { - "age": 242352, - "content": { - "pinned": ["$someevent:localhost"] - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", + "$ref": "core/state_event.json", "type": "m.room.pinned_events", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + "state_key": "", + "content": { + "pinned": ["$someevent:domain.com"] + } } diff --git a/event-schemas/examples/m.room.power_levels b/event-schemas/examples/m.room.power_levels index 0c8f8bc53..37c27845e 100644 --- a/event-schemas/examples/m.room.power_levels +++ b/event-schemas/examples/m.room.power_levels @@ -1,5 +1,7 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.power_levels", + "state_key": "", "content": { "ban": 50, "events": { @@ -15,11 +17,5 @@ "@example:localhost": 100 }, "users_default": 0 - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.power_levels", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.redaction b/event-schemas/examples/m.room.redaction index e24a8cdbe..42bc84115 100644 --- a/event-schemas/examples/m.room.redaction +++ b/event-schemas/examples/m.room.redaction @@ -1,14 +1,8 @@ { - "unsigned": { - "age": 242352 - }, - "content": { - "reason": "Spamming" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", + "$ref": "core/room_event.json", "type": "m.room.redaction", - "room_id": "!Cuyf34gef24t:localhost", "redacts": "$fukweghifu23:localhost", - "sender": "@example:localhost" + "content": { + "reason": "Spamming" + } } diff --git a/event-schemas/examples/m.room.third_party_invite b/event-schemas/examples/m.room.third_party_invite index 3f9d48fef..03f35375e 100644 --- a/event-schemas/examples/m.room.third_party_invite +++ b/event-schemas/examples/m.room.third_party_invite @@ -1,5 +1,7 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.third_party_invite", + "state_key": "pc98", "content": { "display_name": "Alice Margatroid", "key_validity_url": "https://magic.forest/verifykey", @@ -8,11 +10,5 @@ "public_key": "def456", "key_validity_url": "https://magic.forest/verifykey" }] - }, - "state_key": "pc98", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.third_party_invite", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room.topic b/event-schemas/examples/m.room.topic index 65daa9872..69e5d4f1c 100644 --- a/event-schemas/examples/m.room.topic +++ b/event-schemas/examples/m.room.topic @@ -1,12 +1,8 @@ { - "age": 242352, + "$ref": "core/state_event.json", + "type": "m.room.topic", + "state_key": "", "content": { "topic": "A room topic" - }, - "state_key": "", - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.room.topic", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.room_key b/event-schemas/examples/m.room_key index 53f83e522..dba497b42 100644 --- a/event-schemas/examples/m.room_key +++ b/event-schemas/examples/m.room_key @@ -1,9 +1,10 @@ { + "$ref": "core/event.json", + "type": "m.room_key", "content": { "algorithm": "m.megolm.v1.aes-sha2", "room_id": "!Cuyf34gef24t:localhost", "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ", "session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8LlfJL7qNBEY..." - }, - "type": "m.room_key" + } } diff --git a/event-schemas/examples/m.sticker b/event-schemas/examples/m.sticker index f00e5b238..971cdc905 100644 --- a/event-schemas/examples/m.sticker +++ b/event-schemas/examples/m.sticker @@ -1,5 +1,6 @@ { - "age": 242352, + "$ref": "core/room_event.json", + "type": "m.sticker", "content": { "body": "Landing", "info": { @@ -16,10 +17,5 @@ "size": 73602 }, "url": "mxc://matrix.org/sHhqkFCvSkFwtmvtETOtKnLP" - }, - "origin_server_ts": 1431961217939, - "event_id": "$WLGTSEFSEF:localhost", - "type": "m.sticker", - "room_id": "!Cuyf34gef24t:localhost", - "sender": "@example:localhost" + } } diff --git a/event-schemas/examples/m.tag b/event-schemas/examples/m.tag index 53dbc921a..0d61d91b6 100644 --- a/event-schemas/examples/m.tag +++ b/event-schemas/examples/m.tag @@ -1,4 +1,5 @@ { + "$ref": "core/event.json", "type": "m.tag", "content": { "tags": { diff --git a/event-schemas/examples/m.typing b/event-schemas/examples/m.typing index 1d2c517b9..416b99688 100644 --- a/event-schemas/examples/m.typing +++ b/event-schemas/examples/m.typing @@ -1,7 +1,7 @@ { - "type": "m.typing", - "room_id": "!z0mnsuiwhifuhwwfw:matrix.org", - "content": { - "user_ids": ["@alice:matrix.org", "@bob:example.com"] - } + "$ref": "core/room_edu.json", + "type": "m.typing", + "content": { + "user_ids": ["@alice:matrix.org", "@bob:example.com"] + } } diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 90a87cd47..9a6f35692 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -792,7 +792,7 @@ class MatrixUnits(Units): logger.info("Reading event example: %s" % filepath) try: with open(filepath, "r") as f: - example = json.load(f) + example = resolve_references(filepath, json.load(f)) examples[filename] = examples.get(filename, []) examples[filename].append(example) if filename != event_name: From 06d43aef173cf4f821c459d04e2d8885bbdfd714 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 18:08:05 -0600 Subject: [PATCH 050/219] Changelog --- changelogs/client_server/newsfragments/1558.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1558.clarification diff --git a/changelogs/client_server/newsfragments/1558.clarification b/changelogs/client_server/newsfragments/1558.clarification new file mode 100644 index 000000000..3482d89cc --- /dev/null +++ b/changelogs/client_server/newsfragments/1558.clarification @@ -0,0 +1 @@ +Update all event examples to be accurate representations of their associated events. From 337316445f444e03311916dfe18316b979005123 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Sat, 25 Aug 2018 16:55:00 +0200 Subject: [PATCH 051/219] fixup! document m.forwarded_room_key --- event-schemas/schema/m.forwarded_room_key | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-schemas/schema/m.forwarded_room_key b/event-schemas/schema/m.forwarded_room_key index 02d91f4ef..3b1c59006 100644 --- a/event-schemas/schema/m.forwarded_room_key +++ b/event-schemas/schema/m.forwarded_room_key @@ -21,7 +21,7 @@ properties: The Curve25519 key of the device which initiated the session originally. session_id: type: string - description: The ID of the session holding the key. + description: The ID of the session that the key is for. session_key: type: string description: The key to be exchanged. From 768f33dc2d5bd9854a932cc83f726c1fe85af8ea Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Sat, 25 Aug 2018 16:55:28 +0200 Subject: [PATCH 052/219] fixup! document key sharing and m.room_key_request --- event-schemas/schema/m.room_key_request | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-schemas/schema/m.room_key_request b/event-schemas/schema/m.room_key_request index 6893dd783..f495a11d4 100644 --- a/event-schemas/schema/m.room_key_request +++ b/event-schemas/schema/m.room_key_request @@ -25,7 +25,7 @@ properties: The Curve25519 key of the device which initiated the session originally. session_id: type: string - description: The ID of the session holding the key. + description: The ID of the session that the key is for. required: - algorithm - room_id From 8ae137e82ee197414ad8f904db441ffc612b87f2 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Sat, 25 Aug 2018 17:26:00 +0200 Subject: [PATCH 053/219] fixup! document m.forwarded_room_key --- event-schemas/schema/m.forwarded_room_key | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/event-schemas/schema/m.forwarded_room_key b/event-schemas/schema/m.forwarded_room_key index 3b1c59006..f0beed2b3 100644 --- a/event-schemas/schema/m.forwarded_room_key +++ b/event-schemas/schema/m.forwarded_room_key @@ -4,7 +4,8 @@ allOf: description: |- This event type is used to forward keys for end-to-end encryption. Typically - it is encrypted as an ``m.room.encrypted`` event. + it is encrypted as an ``m.room.encrypted`` event, then sent as a `to-device`_ + event. properties: content: properties: From 579f5ea928f5bffb74969a9b736113529a0334e0 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Sat, 25 Aug 2018 17:26:40 +0200 Subject: [PATCH 054/219] fixup! document key sharing and m.room_key_request --- event-schemas/schema/m.room_key_request | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/event-schemas/schema/m.room_key_request b/event-schemas/schema/m.room_key_request index f495a11d4..007d0086e 100644 --- a/event-schemas/schema/m.room_key_request +++ b/event-schemas/schema/m.room_key_request @@ -9,7 +9,9 @@ properties: content: properties: body: - description: Information about the requested key. + description: |- + Information about the requested key. Required when ``action`` is + ``request``. properties: algorithm: type: string From f6b5aee3e2e39b028b893da1745f15a56c993c73 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Sat, 25 Aug 2018 17:27:18 +0200 Subject: [PATCH 055/219] explain how to use key sharing events --- specification/modules/end_to_end_encryption.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/specification/modules/end_to_end_encryption.rst b/specification/modules/end_to_end_encryption.rst index e235e2e9e..26e677ddd 100644 --- a/specification/modules/end_to_end_encryption.rst +++ b/specification/modules/end_to_end_encryption.rst @@ -291,6 +291,17 @@ through his phone for the first time, he may want to have access to the previous exchanged messages. To address this issue, events exist for requesting and sending keys from device to device. +When a device is missing keys to decrypt messages, it can request the keys by +sending `m.room_key_request`_ to-device messages to other devices with +``action`` set to ``request``. If a device wishes to share the keys with that +device, it can forward the keys to the first device by sending an encrypted +`m.forwarded_room_key`_ to-device message. The first device should then send an +`m.room_key_request`_ to-device message with ``action`` set to +``cancel_request`` to the other devices that it had originally sent the key +request to; a device that receives a ``cancel_request`` should disregard any +previously-received ``request`` message with the same ``request_id`` and +``requesting_device_id``. + .. NOTE:: Key sharing can be a big attack vector, thus it must be done very carefully. From faa13aaa40cd0c2cf561f3e1cae5952ffcbe09d0 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Sat, 25 Aug 2018 17:28:01 +0200 Subject: [PATCH 056/219] fixup! add key sharing changelog --- changelogs/client_server/newsfragments/1465.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/client_server/newsfragments/1465.feature b/changelogs/client_server/newsfragments/1465.feature index 61a7ed396..649cf2227 100644 --- a/changelogs/client_server/newsfragments/1465.feature +++ b/changelogs/client_server/newsfragments/1465.feature @@ -1 +1 @@ -Share room encryption keys between devices +Share room decryption keys between devices From 295b1322e245bc3cdd020d19691f969f4389e132 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 22:26:23 -0600 Subject: [PATCH 057/219] Add back the unsigned.age property to voip event examples --- event-schemas/examples/m.call.answer | 3 +++ event-schemas/examples/m.call.candidates | 3 +++ event-schemas/examples/m.call.hangup | 3 +++ event-schemas/examples/m.call.invite | 3 +++ 4 files changed, 12 insertions(+) diff --git a/event-schemas/examples/m.call.answer b/event-schemas/examples/m.call.answer index a4cfc1e16..e616ba344 100644 --- a/event-schemas/examples/m.call.answer +++ b/event-schemas/examples/m.call.answer @@ -9,5 +9,8 @@ "type" : "answer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } + }, + "unsigned": { + "age": 1234, } } diff --git a/event-schemas/examples/m.call.candidates b/event-schemas/examples/m.call.candidates index 8f1f807ad..4a4e66885 100644 --- a/event-schemas/examples/m.call.candidates +++ b/event-schemas/examples/m.call.candidates @@ -11,5 +11,8 @@ "candidate": "candidate:863018703 1 udp 2122260223 10.9.64.156 43670 typ host generation 0" } ] + }, + "unsigned": { + "age": 1234, } } diff --git a/event-schemas/examples/m.call.hangup b/event-schemas/examples/m.call.hangup index 295f16e48..f88a7308d 100644 --- a/event-schemas/examples/m.call.hangup +++ b/event-schemas/examples/m.call.hangup @@ -4,5 +4,8 @@ "content": { "version" : 0, "call_id": "12345" + }, + "unsigned": { + "age": 1234, } } diff --git a/event-schemas/examples/m.call.invite b/event-schemas/examples/m.call.invite index fa482bd94..182a255f3 100644 --- a/event-schemas/examples/m.call.invite +++ b/event-schemas/examples/m.call.invite @@ -9,5 +9,8 @@ "type" : "offer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } + }, + "unsigned": { + "age": 1234, } } From 312799ae78a27112077753db9782e9193e12e2a7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 22:30:49 -0600 Subject: [PATCH 058/219] General clarification for mention and how matrix.to URIs are meant to work --- specification/appendices/identifier_grammar.rst | 5 +++++ specification/modules/mentions.rst | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index 013afa799..0412c065b 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -274,6 +274,11 @@ parameter is only used in the case of permalinks where an event ID is referenced The matrix.to URI, when referenced, must always start with ``https://matrix.to/#/`` followed by the identifier. +Clients should not rely on matrix.to URIs falling back to a web server if accessed +and instead should perform some sort of action within the client. For example, if +the user where to click on a matrix.to URI for a room alias, the client may open +a view for the user to participate in the room. + Examples of matrix.to URIs are: * Room: ``https://matrix.to/#/!somewhere:domain.com`` diff --git a/specification/modules/mentions.rst b/specification/modules/mentions.rst index e7483ae4f..4501b7766 100644 --- a/specification/modules/mentions.rst +++ b/specification/modules/mentions.rst @@ -41,7 +41,8 @@ Client behaviour ---------------- In addition to using the appropriate ``matrix.to URI`` for the mention, -clients should use the following guidelines when making mentions: +clients should use the following guidelines when making mentions in events +to be sent: * When mentioning users, use the user's potentially ambigious display name for the anchor's text. If the user does not have a display name, use the user's From aa294fac064e7bb8e36932a666c529fdd996f2bc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 22:57:52 -0600 Subject: [PATCH 059/219] Define the supported HTML subset for message events Also clarify that `m.notice` messages can support HTML. Fixes https://github.com/matrix-org/matrix-doc/issues/1559 Fixes https://github.com/matrix-org/matrix-doc/issues/1560 --- .../examples/m.room.message#m.notice | 4 +- specification/modules/instant_messaging.rst | 48 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/event-schemas/examples/m.room.message#m.notice b/event-schemas/examples/m.room.message#m.notice index 978c67e6b..876cbbb7d 100644 --- a/event-schemas/examples/m.room.message#m.notice +++ b/event-schemas/examples/m.room.message#m.notice @@ -2,7 +2,9 @@ "age": 242352, "content": { "body": "This is an example notice", - "msgtype": "m.notice" + "msgtype": "m.notice", + "format": "org.matrix.custom.html", + "formatted_body": "This is an example notice" }, "origin_server_ts": 1431961217939, "event_id": "$WLGTSEFSEF:localhost", diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index ff87f74be..29d33c558 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -56,6 +56,54 @@ of message being sent. Each type has their own required and optional keys, as outlined below. If a client cannot display the given ``msgtype`` then it SHOULD display the fallback plain text ``body`` key instead. +Some message types support HTML in the event content that clients should prefer +to display if available. Currently ``m.text``, ``m.emote``, and ``m.notice`` +support an additional ``format`` parameter of ``org.matrix.custom.html``. When +this field is present, a ``formatted_body`` with the HTML must be provided. The +plain text version of the HTML should be provided in the ``body``. + +Clients should limit the HTML they render to avoid Cross-Site Scripting, HTML +injection, and similar attacks. The strongly suggested set of HTML tags to permit, +denying the use and rendering of anything else, is: ``font``, ``del``, ``h1``, +``h2``, ``h3``, ``h4``, ``h5``, ``h6``, ``blockquote``, ``p``, ``a``, ``ul``, +``ol``, ``sup``, ``sub``, ``nl``, ``li``, ``b``, ``i``, ``u``, ``strong``, ``em``, +``strike``, ``code``, ``hr``, ``br``, ``div``, ``table``, ``thead``, ``tbody``, +``tr``, ``th``, ``td``, ``caption``, ``pre``, ``span``, ``img``. + +Not all attributes on those tags should be permitted as they may be avenues for +other disruption attempts, such as adding ``onclick`` handlers or excessively +large text. Clients should only permit the attributes listed for the tags below. +Where ``data-mx-bg-color`` and ``data-mx-color`` are listed, clients should +translate the value (a 6-character hex color code) to the appropriate CSS/attributes +for the tag. + + +:``font``: + ``data-mx-bg-color``, ``data-mx-color`` + +:``span``: + ``data-mx-bg-color``, ``data-mx-color`` + +:``a``: + ``name``, ``target``, ``href`` (provided the value is not relative and has a scheme + matching one of: ``https``, ``http``, ``ftp``, ``mailto``, ``magnet``) + +:``img``: + ``width``, ``height``, ``alt``, ``title``, ``src`` (provided it is a Matrix Content + URI) + +:``ol``: + ``start`` + +:``code``: + ``class`` (only classes which start with ``language-`` for syntax highlighting) + + +Additionally, clients should ensure that *all* ``a`` tags get a ``rel="noopener"`` +to prevent the target page from referencing the client's tab/window. + + + {{msgtype_events}} From 3c472f70e3aa0f29aa95c05887d50970a9cb2de5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 22:59:22 -0600 Subject: [PATCH 060/219] Changelog --- changelogs/client_server/newsfragments/1562.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1562.clarification diff --git a/changelogs/client_server/newsfragments/1562.clarification b/changelogs/client_server/newsfragments/1562.clarification new file mode 100644 index 000000000..c46e189d0 --- /dev/null +++ b/changelogs/client_server/newsfragments/1562.clarification @@ -0,0 +1 @@ +Clarify the supported HTML features for room messages. From e5a7dd1c45a2547efcbaced3aa1ccd06a85b3cdc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 23:00:26 -0600 Subject: [PATCH 061/219] Remove excess commas from JSON --- event-schemas/examples/m.call.answer | 2 +- event-schemas/examples/m.call.candidates | 2 +- event-schemas/examples/m.call.hangup | 2 +- event-schemas/examples/m.call.invite | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/event-schemas/examples/m.call.answer b/event-schemas/examples/m.call.answer index e616ba344..a7b9e883f 100644 --- a/event-schemas/examples/m.call.answer +++ b/event-schemas/examples/m.call.answer @@ -11,6 +11,6 @@ } }, "unsigned": { - "age": 1234, + "age": 1234 } } diff --git a/event-schemas/examples/m.call.candidates b/event-schemas/examples/m.call.candidates index 4a4e66885..1a3fdedf0 100644 --- a/event-schemas/examples/m.call.candidates +++ b/event-schemas/examples/m.call.candidates @@ -13,6 +13,6 @@ ] }, "unsigned": { - "age": 1234, + "age": 1234 } } diff --git a/event-schemas/examples/m.call.hangup b/event-schemas/examples/m.call.hangup index f88a7308d..cf2d68595 100644 --- a/event-schemas/examples/m.call.hangup +++ b/event-schemas/examples/m.call.hangup @@ -6,6 +6,6 @@ "call_id": "12345" }, "unsigned": { - "age": 1234, + "age": 1234 } } diff --git a/event-schemas/examples/m.call.invite b/event-schemas/examples/m.call.invite index 182a255f3..069d334e9 100644 --- a/event-schemas/examples/m.call.invite +++ b/event-schemas/examples/m.call.invite @@ -11,6 +11,6 @@ } }, "unsigned": { - "age": 1234, + "age": 1234 } } From 0a6c1c4ddaa28a6ce169c1f38f22ddcde7fa0291 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 23:18:43 -0600 Subject: [PATCH 062/219] Ensure the event examples and matrix.org assets are tested Otherwise we go nearly a week without realizing the build is failing due to bad schemas/examples. This also helps us ensure a PR is up to par. This commit is expected to cause a build failure at this time. A future commit will actually fix the project and address concerns raised by the testing. --- .circleci/config.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3a0b60325..f79449f38 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -23,9 +23,29 @@ buildswaggerui: &buildswaggerui wget https://raw.githubusercontent.com/matrix-org/matrix.org/master/scripts/swagger-ui.patch patch api/client-server/index.html swagger-ui.patch +checkexamples: &checkexamples + name: Check Event Examples + command: | + source /env/bin/activate + cd event-schemas + ./check_examples.py + +genmatrixassets: &genmatrixassets + name: Generate/Verify matrix.org assets + command: | + source /env/bin/activate + ./scripts/generate-matrix-org-assets + version: 2 jobs: + check-docs: + docker: + - image: uhoreg/matrix-doc-build + steps: + - checkout + - run: *checkexamples + - run: *genmatrixassets # We don't actually use the assets, but we do want to make sure they build build-docs: docker: - image: uhoreg/matrix-doc-build From be9f6042e527a44cd1b4315a208380adef7e1507 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 23:21:50 -0600 Subject: [PATCH 063/219] Fix encrypted event examples --- event-schemas/examples/m.room.encrypted#megolm | 2 +- event-schemas/examples/m.room.encrypted#olm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/event-schemas/examples/m.room.encrypted#megolm b/event-schemas/examples/m.room.encrypted#megolm index 1f9b75208..726763181 100644 --- a/event-schemas/examples/m.room.encrypted#megolm +++ b/event-schemas/examples/m.room.encrypted#megolm @@ -1,6 +1,6 @@ { "content": { - "algorithm": "m.megolm.v1.aes-sha2", + "algorithm": "m.megolm.v1.aes-sha256", "ciphertext": "AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...", "device_id": "RJYKSTBOIE", "sender_key": "IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA", diff --git a/event-schemas/examples/m.room.encrypted#olm b/event-schemas/examples/m.room.encrypted#olm index abb23c31e..23f657385 100644 --- a/event-schemas/examples/m.room.encrypted#olm +++ b/event-schemas/examples/m.room.encrypted#olm @@ -2,7 +2,7 @@ "type": "m.room.encrypted", "sender": "@example:localhost", "content": { - "algorithm": "m.olm.v1.curve25519-aes-sha2", + "algorithm": "m.olm.v1.curve25519-aes-sha256", "sender_key": "Szl29ksW/L8yZGWAX+8dY1XyFi+i5wm+DRhTGkbMiwU", "ciphertext": { "7qZcfnBmbEGzxxaWfBjElJuvn7BZx+lSz/SvFrDF/z8": { From a803d9d07753d58137369a72aaab00e9535da9e4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 20:39:53 -0600 Subject: [PATCH 064/219] Document `validated_at` and `added_at` on GET /3pid Fixes https://github.com/matrix-org/matrix-doc/issues/661 --- api/client-server/administrative_contact.yaml | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index 1cf66fe1f..1b809c119 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -47,13 +47,15 @@ paths: description: The lookup was successful. examples: application/json: { - "threepids": [ - { - "medium": "email", - "address": "monkey@banana.island" - } - ] - } + "threepids": [ + { + "medium": "email", + "address": "monkey@banana.island", + "validated_at": 1535176800000, + "added_at": 1535336848756 + } + ] + } schema: type: object properties: @@ -70,6 +72,19 @@ paths: address: type: string description: The third party identifier address. + validated_at: + type: integer + format: int64 + description: |- + The timestamp, in milliseconds, when the identifier was + validated by the identity service. + added_at: + type: integer + format: int64 + description: + The timestamp, in milliseconds, when the homeserver + associated the third party identifier with the user. + required: ['medium', 'address', 'validated_at', 'added_at'] tags: - User data post: From b4be11af4283aad8533f367a0c7a8fc3a98ff1e2 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 20:41:34 -0600 Subject: [PATCH 065/219] Document POST /account/3pid/delete Fixes https://github.com/matrix-org/matrix-doc/issues/985 Includes documentation for https://github.com/matrix-org/synapse/pull/3667 Raises https://github.com/matrix-org/matrix-doc/issues/1566 --- api/client-server/administrative_contact.yaml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index 1b809c119..c1ecf337e 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -148,6 +148,51 @@ paths: "$ref": "definitions/errors/error.yaml" tags: - User data + "/account/3pid/delete": + post: + summary: Deletes a third party identifier from the user's account + description: |- + Removes a third party identifier from the user's account. The homeserver + should attempt to unbind the identifier from the identity service, if the + homeserver is able to reasonably determine the identity service used. + operationId: delete3pidFromAccount + security: + - accessToken: [] + parameters: + - in: body + name: body + schema: + type: object + properties: + medium: + type: string + description: The medium of the third party identifier being removed. + enum: ["email", "msisdn"] + example: "email" + address: + type: string + description: The third party address being removed. + example: "example@domain.com" + required: ['medium', 'address'] + responses: + 200: + description: |- + The homeserver has disassociated the third party identifier from the + user. + schema: + type: object + properties: + id_server_unbind_result: + type: string + description: |- + The result of the homeserver's attempt to unbind the identifier from + the identity service. ``success`` indicates that the homeserver was + able to unbind the identifier while ``no-support`` means the homeserver + was not able to unbind, likely due to the identity service not supporting + the operation. Defaults to ``no-support``. + example: "success" + tags: + - User data "/account/3pid/email/requestToken": post: summary: Requests a validation token be sent to the given email address for the purpose of adding an email address to an account From e9e93b0eecad5546efef33d46bdbe214c47d8c31 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 20:51:39 -0600 Subject: [PATCH 066/219] Move `invite_room_state` to the correct place in the client-server API Fixes https://github.com/matrix-org/matrix-doc/issues/1350 --- .../examples/m.room.member#invite_room_state | 32 +++++------ event-schemas/schema/m.room.member | 53 +++++++++++-------- scripts/templating/matrix_templates/units.py | 9 ---- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/event-schemas/examples/m.room.member#invite_room_state b/event-schemas/examples/m.room.member#invite_room_state index 1a93b395b..965669adb 100644 --- a/event-schemas/examples/m.room.member#invite_room_state +++ b/event-schemas/examples/m.room.member#invite_room_state @@ -5,22 +5,24 @@ "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto", "displayname": "Alice Margatroid" }, - "invite_room_state": [ - { - "type": "m.room.name", - "state_key": "", - "content": { - "name": "Forest of Magic" + "unsigned": { + "invite_room_state": [ + { + "type": "m.room.name", + "state_key": "", + "content": { + "name": "Forest of Magic" + } + }, + { + "type": "m.room.join_rules", + "state_key": "", + "content": { + "join_rule": "invite" + } } - }, - { - "type": "m.room.join_rules", - "state_key": "", - "content": { - "join_rule": "invite" - } - } - ], + ] + }, "state_key": "@alice:localhost", "origin_server_ts": 1431961217939, "event_id": "$WLGTSEFSEF:localhost", diff --git a/event-schemas/schema/m.room.member b/event-schemas/schema/m.room.member index 4f4077a76..5fb5356d8 100644 --- a/event-schemas/schema/m.room.member +++ b/event-schemas/schema/m.room.member @@ -18,7 +18,9 @@ description: |- 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. - This event may also include an ``invite_room_state`` key **outside the** ``content`` **key**. If present, this contains an array of ``StrippedState`` Events. These events provide information on a subset of state events such as the room name. + This event may also include an ``invite_room_state`` key inside the event's ``unsigned`` data. + If present, this contains an array of ``StrippedState`` Events. These events provide information + on a subset of state events such as the room name. properties: content: properties: @@ -71,32 +73,37 @@ properties: - signed title: Invite type: object + unsigned: + type: object + title: UnsignedData + description: Contains optional extra information about the event. + properties: + invite_room_state: + description: 'A subset of the state of the room at the time of the invite, if ``membership`` is ``invite``. Note that this state is informational, and SHOULD NOT be trusted; once the client has joined the room, it SHOULD fetch the live state from the server and discard the invite_room_state. Also, clients must not rely on any particular state being present here; they SHOULD behave properly (with possibly a degraded but not a broken experience) in the absence of any particular events here. If they are set on the room, at least the state for ``m.room.avatar``, ``m.room.canonical_alias``, ``m.room.join_rules``, and ``m.room.name`` SHOULD be included.' + items: + description: 'A stripped down state event, with only the ``type``, ``state_key`` and ``content`` keys.' + properties: + content: + description: The ``content`` for the event. + title: EventContent + type: object + state_key: + description: The ``state_key`` for the event. + type: string + type: + description: The ``type`` for the event. + type: string + required: + - type + - state_key + - content + title: StrippedState + type: object + type: array required: - membership title: EventContent type: object - invite_room_state: - description: 'A subset of the state of the room at the time of the invite, if ``membership`` is ``invite``. Note that this state is informational, and SHOULD NOT be trusted; once the client has joined the room, it SHOULD fetch the live state from the server and discard the invite_room_state. Also, clients must not rely on any particular state being present here; they SHOULD behave properly (with possibly a degraded but not a broken experience) in the absence of any particular events here. If they are set on the room, at least the state for ``m.room.avatar``, ``m.room.canonical_alias``, ``m.room.join_rules``, and ``m.room.name`` SHOULD be included.' - items: - description: 'A stripped down state event, with only the ``type``, ``state_key`` and ``content`` keys.' - properties: - content: - description: The ``content`` for the event. - title: EventContent - type: object - state_key: - description: The ``state_key`` for the event. - type: string - type: - description: The ``type`` for the event. - type: string - required: - - type - - state_key - - content - title: StrippedState - type: object - type: array state_key: description: The ``user_id`` this membership event relates to. type: string diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 90a87cd47..81da3f6ab 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -875,15 +875,6 @@ class MatrixUnits(Units): Units.prop(json_schema, "properties/content") ) - # This is horrible because we're special casing a key on m.room.member. - # We need to do this because we want to document a non-content object. - if schema["type"] == "m.room.member": - invite_room_state = get_tables_for_schema( - json_schema["properties"]["invite_room_state"]["items"], - ) - schema["content_fields"].extend(invite_room_state) - - # grab msgtype if it is the right kind of event msgtype = Units.prop( json_schema, "properties/content/properties/msgtype/enum" From 5ceb1321107f9ff0760902e4aa4287da59c8510d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 20:52:59 -0600 Subject: [PATCH 067/219] Changelog --- changelogs/client_server/newsfragments/1568.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1568.clarification diff --git a/changelogs/client_server/newsfragments/1568.clarification b/changelogs/client_server/newsfragments/1568.clarification new file mode 100644 index 000000000..4b7a6eafb --- /dev/null +++ b/changelogs/client_server/newsfragments/1568.clarification @@ -0,0 +1 @@ +Move the ``invite_room_state`` definition under ``unsigned`` where it actually resides. From 3b2bf18c67c6953d8f7552a4d88f96f69afe4996 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 20:54:22 -0600 Subject: [PATCH 068/219] Changelog --- changelogs/client_server/newsfragments/1567.feature | 1 + changelogs/client_server/newsfragments/1567.new | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelogs/client_server/newsfragments/1567.feature create mode 100644 changelogs/client_server/newsfragments/1567.new diff --git a/changelogs/client_server/newsfragments/1567.feature b/changelogs/client_server/newsfragments/1567.feature new file mode 100644 index 000000000..0c19b4bea --- /dev/null +++ b/changelogs/client_server/newsfragments/1567.feature @@ -0,0 +1 @@ +Document the ``validated_at`` and ``added_at`` fields on ``GET /acount/3pid``. diff --git a/changelogs/client_server/newsfragments/1567.new b/changelogs/client_server/newsfragments/1567.new new file mode 100644 index 000000000..15e3305b1 --- /dev/null +++ b/changelogs/client_server/newsfragments/1567.new @@ -0,0 +1 @@ +Add ``POST /account/3pid/delete`` From 1bc0f63bfb26f7f60f034c6bdcf38b901005516b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:03:48 -0600 Subject: [PATCH 069/219] Clarify the homeserver's behaviour for user searching The homeserver can implement its own algorithm, but is suggested to ensure the requesting user can reasonably see the other users. The text is intentionally left vague for whether or not the API is local users only to give the homeserver some flexibility in this area. General cleanup is also included in this commit. Fixes https://github.com/matrix-org/matrix-doc/issues/1108 --- api/client-server/users.yaml | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/api/client-server/users.yaml b/api/client-server/users.yaml index a682b4358..ef527a23b 100644 --- a/api/client-server/users.yaml +++ b/api/client-server/users.yaml @@ -31,8 +31,13 @@ paths: post: summary: Searches the user directory. description: |- - This API performs a server-side search over all users registered on the server. - It searches user ID and displayname case-insensitively for users that you share a room with or that are in public rooms. + Performs a search for users on the homeserver. The homeserver may + determine which subset of users are searched, however the homeserver + is encouraged to only consider users the requesting user shares a + room with and those who reside in public rooms. + + The search is performed case-insensitively on user IDs and display + names. operationId: searchUserDirectory security: - accessToken: [] @@ -48,7 +53,7 @@ paths: example: "foo" limit: type: number - description: The maximum number of results to return (Defaults to 10). + description: The maximum number of results to return. Defaults to 10. example: 10 required: ["search_term"] responses: @@ -56,15 +61,15 @@ paths: description: The results of the search. examples: application/json: { - "results": [ - { - "user_id": "@foo:bar.com", - "display_name": "Foo", - "avatar_url": "mxc://bar.com/foo" - } - ], - "limited": false - } + "results": [ + { + "user_id": "@foo:bar.com", + "display_name": "Foo", + "avatar_url": "mxc://bar.com/foo" + } + ], + "limited": false + } schema: type: object required: ["results", "limited"] From e926b4a84011332a698189ec421993d4d5605388 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:05:09 -0600 Subject: [PATCH 070/219] Changelog --- changelogs/client_server/newsfragments/1569.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1569.clarification diff --git a/changelogs/client_server/newsfragments/1569.clarification b/changelogs/client_server/newsfragments/1569.clarification new file mode 100644 index 000000000..83185e027 --- /dev/null +++ b/changelogs/client_server/newsfragments/1569.clarification @@ -0,0 +1 @@ +Clarify the homeserver's behaviour for searching users. From 7d08ef73d09de2e37b9be9d602277c4f336be35b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:19:07 -0600 Subject: [PATCH 071/219] Fix naming of the Filter schemas EventFilter !== Filter Fixes https://github.com/matrix-org/matrix-doc/issues/1509 --- api/client-server/definitions/event_filter.yaml | 2 +- api/client-server/definitions/sync_filter.yaml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/api/client-server/definitions/event_filter.yaml b/api/client-server/definitions/event_filter.yaml index 1cae3ea90..8c96917fd 100644 --- a/api/client-server/definitions/event_filter.yaml +++ b/api/client-server/definitions/event_filter.yaml @@ -11,7 +11,7 @@ # 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: Filter +title: EventFilter properties: limit: description: The maximum number of events to return. diff --git a/api/client-server/definitions/sync_filter.yaml b/api/client-server/definitions/sync_filter.yaml index 69b245a31..33bead262 100644 --- a/api/client-server/definitions/sync_filter.yaml +++ b/api/client-server/definitions/sync_filter.yaml @@ -11,6 +11,8 @@ # 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: Filter properties: event_fields: description: List of event fields to include. If this list is absent then all @@ -40,6 +42,7 @@ properties: room: title: RoomFilter description: Filters to be applied to room data. + type: object properties: not_rooms: description: A list of room IDs to exclude. If this list is absent then no rooms @@ -76,5 +79,3 @@ properties: allOf: - $ref: room_event_filter.yaml description: The per user account data to include for rooms. - type: object -type: object From 97e3dd443b5bc38a8ec166b9ae3642460f960e1c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:20:01 -0600 Subject: [PATCH 072/219] Update room_event_filter.yaml to use the OpenAPI allOf definition This is just maintenance. --- .../definitions/room_event_filter.yaml | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/api/client-server/definitions/room_event_filter.yaml b/api/client-server/definitions/room_event_filter.yaml index 7d9184b58..9817db0c0 100644 --- a/api/client-server/definitions/room_event_filter.yaml +++ b/api/client-server/definitions/room_event_filter.yaml @@ -13,23 +13,23 @@ # limitations under the License. allOf: - $ref: event_filter.yaml -title: RoomEventFilter -properties: - not_rooms: - description: A list of room IDs to exclude. If this list is absent then no rooms - are excluded. A matching room will be excluded even if it is listed in the ``'rooms'`` - filter. - items: - type: string - type: array - rooms: - description: A list of room IDs to include. If this list is absent then all rooms - are included. - items: - type: string - type: array - contains_url: - type: boolean +- type: object + title: RoomEventFilter + properties: + not_rooms: + description: A list of room IDs to exclude. If this list is absent then no rooms + are excluded. A matching room will be excluded even if it is listed in the ``'rooms'`` + filter. + items: + type: string + type: array + rooms: + description: A list of room IDs to include. If this list is absent then all rooms + are included. + items: + type: string + type: array + contains_url: + type: boolean description: If ``true``, includes only events with a url key in their content. If ``false``, excludes those events. -type: object From 26a7a341f0f56e8ac16edf0b8ee7b57bae26b298 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:20:28 -0600 Subject: [PATCH 073/219] Mark the filter_id in the response of POST /filter as required --- api/client-server/filter.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/client-server/filter.yaml b/api/client-server/filter.yaml index b34da7b62..58d9e55cb 100644 --- a/api/client-server/filter.yaml +++ b/api/client-server/filter.yaml @@ -91,7 +91,12 @@ paths: filter_id: type: string description: |- - The ID of the filter that was created. + The ID of the filter that was created. Cannot start + with a ``{`` as this character is used to determine + if the filter provided is inline JSON or a previously + declared filter by homeservers on some APIs. + example: "66696p746572" + required: ['filter_id'] tags: - Room participation "/user/{userId}/filter/{filterId}": From 1cbcaba2c70fa41bc8f478113932fdcd642957af Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:21:27 -0600 Subject: [PATCH 074/219] Clean up examples in filter.yaml Indentation, excess examples. --- api/client-server/filter.yaml | 48 ++++++++++++++++------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/api/client-server/filter.yaml b/api/client-server/filter.yaml index 58d9e55cb..db2151960 100644 --- a/api/client-server/filter.yaml +++ b/api/client-server/filter.yaml @@ -54,37 +54,33 @@ paths: allOf: - $ref: "definitions/sync_filter.yaml" example: { - "room": { - "state": { - "types": ["m.room.*"], - "not_rooms": ["!726s6s6q:example.com"] - }, - "timeline": { - "limit": 10, - "types": ["m.room.message"], - "not_rooms": ["!726s6s6q:example.com"], - "not_senders": ["@spam:example.com"] - }, - "ephemeral": { - "types": ["m.receipt", "m.typing"], - "not_rooms": ["!726s6s6q:example.com"], - "not_senders": ["@spam:example.com"] - } + "room": { + "state": { + "types": ["m.room.*"], + "not_rooms": ["!726s6s6q:example.com"] }, - "presence": { - "types": ["m.presence"], - "not_senders": ["@alice:example.com"] + "timeline": { + "limit": 10, + "types": ["m.room.message"], + "not_rooms": ["!726s6s6q:example.com"], + "not_senders": ["@spam:example.com"] }, - "event_format": "client", - "event_fields": ["type", "content", "sender"] - } + "ephemeral": { + "types": ["m.receipt", "m.typing"], + "not_rooms": ["!726s6s6q:example.com"], + "not_senders": ["@spam:example.com"] + } + }, + "presence": { + "types": ["m.presence"], + "not_senders": ["@alice:example.com"] + }, + "event_format": "client", + "event_fields": ["type", "content", "sender"] + } responses: 200: description: The filter was created. - examples: - application/json: { - "filter_id": "66696p746572" - } schema: type: object properties: From b68ed5d594d37fa0c76e1592805f64e3030b1ca4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:21:49 -0600 Subject: [PATCH 075/219] Define the default for the contains_url filter param Fixes https://github.com/matrix-org/matrix-doc/issues/1553 --- api/client-server/definitions/room_event_filter.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/client-server/definitions/room_event_filter.yaml b/api/client-server/definitions/room_event_filter.yaml index 9817db0c0..c36b3768f 100644 --- a/api/client-server/definitions/room_event_filter.yaml +++ b/api/client-server/definitions/room_event_filter.yaml @@ -31,5 +31,5 @@ allOf: type: array contains_url: type: boolean - description: If ``true``, includes only events with a url key in their content. If - ``false``, excludes those events. + description: If ``true``, includes only events with a ``url`` key in their content. If + ``false``, excludes those events. Defaults to ``false``. From b0fbd7be7c4cb3abe80cc5b6218a6de0f6fb1ff8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:24:33 -0600 Subject: [PATCH 076/219] Changelog --- changelogs/client_server/newsfragments/1570.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1570.clarification diff --git a/changelogs/client_server/newsfragments/1570.clarification b/changelogs/client_server/newsfragments/1570.clarification new file mode 100644 index 000000000..dbf8a821c --- /dev/null +++ b/changelogs/client_server/newsfragments/1570.clarification @@ -0,0 +1 @@ +Clarify the object structures and defaults for Filters. From 667fa082af81b612748180e92e5fe8e6aad4aa55 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:30:33 -0600 Subject: [PATCH 077/219] Replace applicable types of 'number' to 'integer' `number` implies/represents a float where `integer` does not. The only remaining `type: number` in the project appear on power levels: those have been left untouched pending clarification. Fixes https://github.com/matrix-org/matrix-doc/issues/746 --- api/client-server/admin.yaml | 3 ++- api/client-server/content-repo.yaml | 9 ++++++--- api/client-server/definitions/public_rooms_response.yaml | 4 ++-- api/client-server/list_public_rooms.yaml | 8 ++++---- api/client-server/notifications.yaml | 2 +- api/client-server/registration.yaml | 4 ++-- api/client-server/search.yaml | 4 ++-- api/client-server/users.yaml | 2 +- event-schemas/schema/core-event-schema/room_event.yaml | 3 ++- 9 files changed, 22 insertions(+), 17 deletions(-) diff --git a/api/client-server/admin.yaml b/api/client-server/admin.yaml index 2fdac82b0..09942a101 100644 --- a/api/client-server/admin.yaml +++ b/api/client-server/admin.yaml @@ -105,7 +105,8 @@ paths: type: string description: Most recently seen IP address of the session. last_seen: - type: number + type: integer + format: int64 description: Unix timestamp that the session was last active. user_agent: type: string diff --git a/api/client-server/content-repo.yaml b/api/client-server/content-repo.yaml index b3e9517b1..5f4e9111a 100644 --- a/api/client-server/content-repo.yaml +++ b/api/client-server/content-repo.yaml @@ -259,7 +259,8 @@ paths: description: "The URL to get a preview of" required: true - in: query - type: number + type: integer + format: int64 x-example: 1510610716656 name: ts description: |- @@ -276,7 +277,8 @@ paths: type: object properties: "matrix:image:size": - type: number + type: integer + format: int64 description: |- The byte-size of the image. Omitted if there is no image attached. "og:image": @@ -324,7 +326,8 @@ paths: type: object properties: m.upload.size: - type: number + type: integer + format: int64 description: |- The maximum size an upload can be in bytes. Clients SHOULD use this as a guide when uploading content. diff --git a/api/client-server/definitions/public_rooms_response.yaml b/api/client-server/definitions/public_rooms_response.yaml index fc6ccb44c..ab7010516 100644 --- a/api/client-server/definitions/public_rooms_response.yaml +++ b/api/client-server/definitions/public_rooms_response.yaml @@ -45,7 +45,7 @@ properties: description: |- The name of the room, if any. num_joined_members: - type: number + type: integer description: |- The number of members joined to the room. room_id: @@ -82,7 +82,7 @@ properties: absence of this token means there are no results before this batch, i.e. this is the first batch. total_room_count_estimate: - type: number + type: integer description: |- An estimate on the total number of public rooms, if the server has an estimate. diff --git a/api/client-server/list_public_rooms.yaml b/api/client-server/list_public_rooms.yaml index 72a120609..8f0e80d55 100644 --- a/api/client-server/list_public_rooms.yaml +++ b/api/client-server/list_public_rooms.yaml @@ -123,7 +123,7 @@ paths: parameters: - in: query name: limit - type: number + type: integer description: |- Limit the number of results returned. - in: query @@ -173,7 +173,7 @@ paths: type: object properties: limit: - type: number + type: integer description: |- Limit the number of results returned. since: @@ -233,7 +233,7 @@ paths: description: |- The name of the room, if any. num_joined_members: - type: number + type: integer description: |- The number of members joined to the room. room_id: @@ -270,7 +270,7 @@ paths: absence of this token means there are no results before this batch, i.e. this is the first batch. total_room_count_estimate: - type: number + type: integer description: |- An estimate on the total number of public rooms, if the server has an estimate. diff --git a/api/client-server/notifications.yaml b/api/client-server/notifications.yaml index e10e5bfde..b450885b8 100644 --- a/api/client-server/notifications.yaml +++ b/api/client-server/notifications.yaml @@ -45,7 +45,7 @@ paths: required: false x-example: "xxxxx" - in: query - type: number + type: integer name: limit description: Limit on the number of events to return in this request. required: false diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index 56da9addb..e4b056291 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -218,7 +218,7 @@ paths: description: The email address example: "example@example.com" send_attempt: - type: number + type: integer description: Used to distinguish protocol level retries from requests to re-send the email. example: 1 required: ["client_secret", "email", "send_attempt"] @@ -283,7 +283,7 @@ paths: description: The phone number. example: "example@example.com" send_attempt: - type: number + type: integer description: Used to distinguish protocol level retries from requests to re-send the SMS message. example: 1 required: ["client_secret", "country", "phone_number", "send_attempt"] diff --git a/api/client-server/search.yaml b/api/client-server/search.yaml index e4118c32b..0d3a78841 100644 --- a/api/client-server/search.yaml +++ b/api/client-server/search.yaml @@ -179,7 +179,7 @@ paths: description: Mapping of category name to search criteria. properties: count: - type: number + type: integer description: An approximate count of the total number of results found. highlights: type: array @@ -197,7 +197,7 @@ paths: description: The result object. properties: rank: - type: number + type: integer description: A number that describes how closely this result matches the search. Higher is closer. diff --git a/api/client-server/users.yaml b/api/client-server/users.yaml index a682b4358..fc6d233bd 100644 --- a/api/client-server/users.yaml +++ b/api/client-server/users.yaml @@ -47,7 +47,7 @@ paths: description: The term to search for example: "foo" limit: - type: number + type: integer description: The maximum number of results to return (Defaults to 10). example: 10 required: ["search_term"] diff --git a/event-schemas/schema/core-event-schema/room_event.yaml b/event-schemas/schema/core-event-schema/room_event.yaml index a8a23f549..ebf970ad7 100644 --- a/event-schemas/schema/core-event-schema/room_event.yaml +++ b/event-schemas/schema/core-event-schema/room_event.yaml @@ -16,7 +16,8 @@ properties: origin_server_ts: description: Timestamp in milliseconds on originating homeserver when this event was sent. - type: number + type: integer + format: int64 unsigned: description: Contains optional extra information about the event. properties: From e75a1836b86b04e0670c8e648055be5d1d0cf54d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:33:43 -0600 Subject: [PATCH 078/219] Changelog --- changelogs/client_server/newsfragments/1571.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1571.clarification diff --git a/changelogs/client_server/newsfragments/1571.clarification b/changelogs/client_server/newsfragments/1571.clarification new file mode 100644 index 000000000..2410baf39 --- /dev/null +++ b/changelogs/client_server/newsfragments/1571.clarification @@ -0,0 +1 @@ +Clarify instances of ``type: number`` in the swagger/OpenAPI schema definitions. From 008ebb8c1ac1d1958a3809d3757bbb06c66a9718 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:55:30 -0600 Subject: [PATCH 079/219] Add `account_data` to left rooms in /sync Fixes https://github.com/matrix-org/matrix-doc/issues/1392 --- api/client-server/sync.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/client-server/sync.yaml b/api/client-server/sync.yaml index 4b44c20e1..f1997b617 100644 --- a/api/client-server/sync.yaml +++ b/api/client-server/sync.yaml @@ -227,6 +227,14 @@ paths: room up to the point when the user left. allOf: - $ref: "definitions/timeline_batch.yaml" + account_data: + title: Account Data + type: object + description: |- + The private data that this user has attached to + this room. + allOf: + - $ref: "definitions/event_batch.yaml" presence: title: Presence type: object From e8edfba11438a211ec7bcc1cebf1192dffae105b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 21:57:04 -0600 Subject: [PATCH 080/219] Changelog --- changelogs/client_server/newsfragments/1572.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1572.clarification diff --git a/changelogs/client_server/newsfragments/1572.clarification b/changelogs/client_server/newsfragments/1572.clarification new file mode 100644 index 000000000..7e84098f4 --- /dev/null +++ b/changelogs/client_server/newsfragments/1572.clarification @@ -0,0 +1 @@ +Clarify that left rooms also have account data in ``/sync``. From e60b44e27fe9e83e5c6edca9e4c778fd244da0fa Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 22:27:34 -0600 Subject: [PATCH 081/219] Clean up PUT /directory/room Fixes https://github.com/matrix-org/matrix-doc/issues/933 The issue references two problems: a `roomInfo` and lack of a `room_id`. It appears the `room_id` has been fixed since reporting, however the `roomInfo` remained (and is now fixed). --- api/client-server/directory.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api/client-server/directory.yaml b/api/client-server/directory.yaml index ee42cf845..78ddfa291 100644 --- a/api/client-server/directory.yaml +++ b/api/client-server/directory.yaml @@ -41,7 +41,7 @@ paths: required: true x-example: "#monkeys:matrix.org" - in: body - name: roomInfo + name: body description: Information about this room alias. required: true schema: @@ -50,24 +50,24 @@ paths: room_id: type: string description: The room ID to set. + required: ['room_id'] example: { - "room_id": "!abnjk1jdasj98:capuchins.com" - } + "room_id": "!abnjk1jdasj98:capuchins.com" + } responses: 200: description: The mapping was created. examples: - application/json: { - } + application/json: {} schema: type: object 409: description: A room alias with that name already exists. examples: application/json: { - "errcode": "M_UNKNOWN", - "error": "Room alias #monkeys:matrix.org already exists." - } + "errcode": "M_UNKNOWN", + "error": "Room alias #monkeys:matrix.org already exists." + } schema: "$ref": "definitions/errors/error.yaml" tags: From ce0befd7d059e1b91389bfa4692cbb4c6dfd2d84 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sun, 26 Aug 2018 22:28:52 -0600 Subject: [PATCH 082/219] Changelog --- changelogs/client_server/newsfragments/1574.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1574.clarification diff --git a/changelogs/client_server/newsfragments/1574.clarification b/changelogs/client_server/newsfragments/1574.clarification new file mode 100644 index 000000000..8d07ef56f --- /dev/null +++ b/changelogs/client_server/newsfragments/1574.clarification @@ -0,0 +1 @@ +Fix naming of the body field in ``PUT /directory/room``. From d7d28f7e5bf9c263fa0b5d9c04638ec02ae6f6dd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 09:16:30 -0600 Subject: [PATCH 083/219] Remove nl as a supported HTML tag --- specification/modules/instant_messaging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index 29d33c558..6d1b1b355 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -66,7 +66,7 @@ Clients should limit the HTML they render to avoid Cross-Site Scripting, HTML injection, and similar attacks. The strongly suggested set of HTML tags to permit, denying the use and rendering of anything else, is: ``font``, ``del``, ``h1``, ``h2``, ``h3``, ``h4``, ``h5``, ``h6``, ``blockquote``, ``p``, ``a``, ``ul``, -``ol``, ``sup``, ``sub``, ``nl``, ``li``, ``b``, ``i``, ``u``, ``strong``, ``em``, +``ol``, ``sup``, ``sub``, ``li``, ``b``, ``i``, ``u``, ``strong``, ``em``, ``strike``, ``code``, ``hr``, ``br``, ``div``, ``table``, ``thead``, ``tbody``, ``tr``, ``th``, ``td``, ``caption``, ``pre``, ``span``, ``img``. From c7822cc9a8d18ddcdd17473e2369f93bd7a7307c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 09:16:53 -0600 Subject: [PATCH 084/219] Link to the content repo when referencing MXC URIs in images --- specification/modules/instant_messaging.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index 6d1b1b355..88326999d 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -89,8 +89,7 @@ for the tag. matching one of: ``https``, ``http``, ``ftp``, ``mailto``, ``magnet``) :``img``: - ``width``, ``height``, ``alt``, ``title``, ``src`` (provided it is a Matrix Content - URI) + ``width``, ``height``, ``alt``, ``title``, ``src`` (provided it is a `Matrix Content (MXC) URI`_) :``ol``: ``start`` @@ -345,3 +344,4 @@ Clients should sanitise **all displayed keys** for unsafe HTML to prevent Cross- Scripting (XSS) attacks. This includes room names and topics. .. _`E2E module`: `module:e2e`_ +.. _`Matrix Content (MXC) URI`: `module:content`_ \ No newline at end of file From 5bf99aeb349f0af80e7f4b8f3a0c189304054e92 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 09:17:08 -0600 Subject: [PATCH 085/219] Add a note that formatted_body is not forever --- specification/modules/instant_messaging.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index 88326999d..9de890717 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -102,6 +102,9 @@ Additionally, clients should ensure that *all* ``a`` tags get a ``rel="noopener" to prevent the target page from referencing the client's tab/window. +.. Note:: + A future iteration of the specification will support more powerful and extensible + message formatting options, such as the proposal `MSC1225 `_. {{msgtype_events}} From 89daa3c5ce0c745219d8cdb9e92e693fc24f1663 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 09:17:40 -0600 Subject: [PATCH 086/219] Clarify that clients aren't required to render all the tags This commit also includes minor clarifications to surrounding text. --- specification/modules/instant_messaging.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index 9de890717..079a4801d 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -98,9 +98,13 @@ for the tag. ``class`` (only classes which start with ``language-`` for syntax highlighting) -Additionally, clients should ensure that *all* ``a`` tags get a ``rel="noopener"`` +Additionally, web clients should ensure that *all* ``a`` tags get a ``rel="noopener"`` to prevent the target page from referencing the client's tab/window. +Tags must not be nested more than 100 levels deep. Clients should only support the subset +of tags they can render, falling back to other representations of the tags where possible. +For example, a client may not be able to render tables correctly and instead could fall +back to rendering tab-delimited text. .. Note:: A future iteration of the specification will support more powerful and extensible From 80699812525655fa1f251eb527993af3c71df955 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 14:19:10 -0600 Subject: [PATCH 087/219] Add federation /user/* endpoints Fixes https://github.com/matrix-org/matrix-doc/issues/1438 --- api/server-server/user_devices.yaml | 84 +++++++++++++ api/server-server/user_keys.yaml | 188 ++++++++++++++++++++++++++++ specification/server_server_api.rst | 17 ++- 3 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 api/server-server/user_devices.yaml create mode 100644 api/server-server/user_keys.yaml diff --git a/api/server-server/user_devices.yaml b/api/server-server/user_devices.yaml new file mode 100644 index 000000000..d16442706 --- /dev/null +++ b/api/server-server/user_devices.yaml @@ -0,0 +1,84 @@ +# 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. + +swagger: '2.0' +info: + title: "Matrix Federation User Device Management API" + version: "1.0.0" +host: localhost:8448 +schemes: + - https +basePath: /_matrix/federation/v1 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/user/devices/{userId}": + get: + summary: Gets all of the user's devices + description: Gets information on all of the user's devices + operationId: getUserDevices + security: + - signedRequest: [] + parameters: + - in: path + name: userId + type: string + required: true + description: |- + The user ID to retrieve devices for. Must be a user local to the + receiving homeserver. + required: true + x-example: "@alice:example.org" + responses: + 200: + description: The user's devices. + schema: + type: object + properties: + user_id: + type: string + description: The user ID devices were requested for. + example: "@alice:example.org" + stream_id: + type: integer + description: |- + An ID the requesting homeserver may use to detect changes in the + device list. This should increase as time goes on, and always + produce the same ``devices`` list if not incremented. + example: 334608 + devices: + type: array + description: The user's devices. May be empty. + items: + type: object + title: User Device + properties: + device_id: + type: string + description: The device ID. + example: "JLAFKJWSCS" + keys: + type: object + description: Identity keys for the device. + $ref: "../client-server/definitions/device_keys.yaml" + device_display_name: + type: string + description: Optional display name for the device. + example: "Alice's Mobile Phone" + required: ['device_id', 'keys'] + required: ['user_id', 'stream_id', 'devices'] \ No newline at end of file diff --git a/api/server-server/user_keys.yaml b/api/server-server/user_keys.yaml new file mode 100644 index 000000000..869934331 --- /dev/null +++ b/api/server-server/user_keys.yaml @@ -0,0 +1,188 @@ +# 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. + +swagger: '2.0' +info: + title: "Matrix Federation User Key Management API" + version: "1.0.0" +host: localhost:8448 +schemes: + - https +basePath: /_matrix/federation/v1 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + "/user/keys/claim": + post: + summary: Claims one-time encryption keys for a user. + description: |- + Claims one-time keys for use in pre-key messages. + operationId: claimUserEncryptionKeys + security: + - signedRequest: [] + parameters: + - in: body + name: body + type: object + required: true + schema: + type: object + properties: + one_time_keys: + type: object + description: |- + The keys to be claimed. A map from user ID, to a map from + device ID to algorithm name. + additionalProperties: + type: object + additionalProperties: + type: string + description: algorithm + example: "signed_curve25519" + example: { + "@alice:example.com": { + "JLAFKJWSCS": "signed_curve25519" + } + } + required: + - one_time_keys + responses: + 200: + description: The claimed keys + schema: + type: object + properties: + one_time_keys: + type: object + description: |- + One-time keys for the queried devices. A map from user ID, to a + map from devices to a map from ``:`` to the key object. + additionalProperties: + type: object + additionalProperties: + type: + - string + - object + required: ['one_time_keys'] + examples: + application/json: { + "one_time_keys": { + "@alice:example.com": { + "JLAFKJWSCS": { + "signed_curve25518:AAAAHg": { + "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", + "signatures": { + "@alice:example.com": { + "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" + } + } + } + } + } + } + } + "/user/keys/query": + post: + summary: Download device identity keys. + description: |- + Returns the current devices and identity keys for the given users. + operationId: queryUserEncryptionKeys + security: + - signedRequest: [] + parameters: + - in: body + name: body + type: object + required: true + schema: + type: object + properties: + device_keys: + type: object + description: |- + The keys to be downloaded. A map from user ID, to a list of + device IDs, or to an empty list to indicate all devices for the + corresponding user. + additionalProperties: + type: array + items: + type: string + description: "Device ID" + example: { + "@alice:example.com": [] + } + responses: + 200: + description: The device information. + schema: + type: object + properties: + device_keys: + type: object + description: |- + Information on the queried devices. A map from user ID, to a + map from device ID to device information. For each device, + the information returned will be the same as uploaded via + ``/keys/upload``, with the addition of an ``unsigned`` + property. + additionalProperties: + type: object + additionalProperties: + allOf: + - $ref: ../client-server/definitions/device_keys.yaml + properties: + unsigned: + title: UnsignedDeviceInfo + type: object + description: |- + Additional data added to the device key information + by intermediate servers, and not covered by the + signatures. + properties: + device_display_name: + type: string + description: + The display name which the user set on the device. + required: ['device_keys'] + examples: + application/json: { + "device_keys": { + "@alice:example.com": { + "JLAFKJWSCS": { + "user_id": "@alice:example.com", + "device_id": "JLAFKJWSCS", + "algorithms": [ + "m.olm.v1.curve25519-aes-sha256", + "m.megolm.v1.aes-sha" + ], + "keys": { + "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", + "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" + }, + "signatures": { + "@alice:example.com": { + "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" + } + }, + "unsigned": { + "device_display_name": "Alice's mobile phone" + } + } + } + } + } diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index dbde8b104..634b8fd01 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -890,6 +890,20 @@ nothing else. {{openid_ss_http_api}} +End-to-End Encryption +--------------------- + +This section compliments the `End-to-End Encryption module`_ of the Client-Server +API. For detailed information about end-to-end encryption, please see that module. + +The APIs defined here are designed to be able to proxy much of the client's request +through to federation, and have the response also be proxied through to the client. + +{{user_keys_ss_http_api}} + +{{user_devices_ss_http_api}} + + Send-to-device messaging ------------------------ @@ -1077,7 +1091,8 @@ that are too long. .. _`Invitation storage`: ../identity_service/unstable.html#invitation-storage .. _`Identity Service API`: ../identity_service/unstable.html -.. _`Client-Server API`: ../client_server/unstable.html +.. _`Client-Server API`: ../client_server/%CLIENT_RELEASE_LABEL%.html .. _`Inviting to a room`: #inviting-to-a-room .. _`Canonical JSON`: ../appendices.html#canonical-json .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 +.. _`End-to-End Encryption module`: ../client-server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption From be97e95dc123080514a07ef6b90a4842616b8921 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 14:49:38 -0600 Subject: [PATCH 088/219] Promote device management to be a dedicated section --- specification/server_server_api.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 634b8fd01..cc23a83dc 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -890,6 +890,19 @@ nothing else. {{openid_ss_http_api}} + +Device Management +----------------- + +.. TODO: TravisR - Incorporate https://github.com/matrix-org/matrix-doc/issues/1212 + +A user's devices may need to be queried over federation for different purposes, such +as end-to-end encryption or for utilizing send-to-device messaging. This section is +intended to compliment the `Device Management module`_ of the Client-Server API. + +{{user_devices_ss_http_api}} + + End-to-End Encryption --------------------- @@ -901,8 +914,6 @@ through to federation, and have the response also be proxied through to the clie {{user_keys_ss_http_api}} -{{user_devices_ss_http_api}} - Send-to-device messaging ------------------------ @@ -1095,4 +1106,5 @@ that are too long. .. _`Inviting to a room`: #inviting-to-a-room .. _`Canonical JSON`: ../appendices.html#canonical-json .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 +.. _`Device Management module`: ../client-server/%CLIENT_RELEASE_LABEL%.html#device-management .. _`End-to-End Encryption module`: ../client-server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption From 17bdc0c740612e0476663129617ee11f0026fb86 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Sat, 25 Aug 2018 23:21:50 -0600 Subject: [PATCH 089/219] Revert "Fix encrypted event examples" This reverts commit be9f6042e527a44cd1b4315a208380adef7e1507. --- event-schemas/examples/m.room.encrypted#megolm | 2 +- event-schemas/examples/m.room.encrypted#olm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/event-schemas/examples/m.room.encrypted#megolm b/event-schemas/examples/m.room.encrypted#megolm index 726763181..1f9b75208 100644 --- a/event-schemas/examples/m.room.encrypted#megolm +++ b/event-schemas/examples/m.room.encrypted#megolm @@ -1,6 +1,6 @@ { "content": { - "algorithm": "m.megolm.v1.aes-sha256", + "algorithm": "m.megolm.v1.aes-sha2", "ciphertext": "AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...", "device_id": "RJYKSTBOIE", "sender_key": "IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA", diff --git a/event-schemas/examples/m.room.encrypted#olm b/event-schemas/examples/m.room.encrypted#olm index 23f657385..abb23c31e 100644 --- a/event-schemas/examples/m.room.encrypted#olm +++ b/event-schemas/examples/m.room.encrypted#olm @@ -2,7 +2,7 @@ "type": "m.room.encrypted", "sender": "@example:localhost", "content": { - "algorithm": "m.olm.v1.curve25519-aes-sha256", + "algorithm": "m.olm.v1.curve25519-aes-sha2", "sender_key": "Szl29ksW/L8yZGWAX+8dY1XyFi+i5wm+DRhTGkbMiwU", "ciphertext": { "7qZcfnBmbEGzxxaWfBjElJuvn7BZx+lSz/SvFrDF/z8": { From 438f5825ae82ff8ac454db26e3076fce6242daf5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 14:55:59 -0600 Subject: [PATCH 090/219] Add more supported encryption algorithms to message events --- event-schemas/schema/m.room.encrypted | 2 ++ 1 file changed, 2 insertions(+) diff --git a/event-schemas/schema/m.room.encrypted b/event-schemas/schema/m.room.encrypted index 6825be1d2..9c2fa7be3 100644 --- a/event-schemas/schema/m.room.encrypted +++ b/event-schemas/schema/m.room.encrypted @@ -14,7 +14,9 @@ properties: type: string enum: - m.olm.curve25519-aes-sha256 + - m.olm.v1.curve25519-aes-sha2 - m.megolm.v1.aes-sha + - m.megolm.v1.aes-sha2 description: |- The encryption algorithm used to encrypt this event. The value of this field determines which other properties will be From 72de8bec5c1703d1e425dd29c6463810d3641a0a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 15:05:56 -0600 Subject: [PATCH 091/219] Remove unused algorithms for encrypted messages --- event-schemas/schema/m.room.encrypted | 2 -- 1 file changed, 2 deletions(-) diff --git a/event-schemas/schema/m.room.encrypted b/event-schemas/schema/m.room.encrypted index 9c2fa7be3..44b09c3f6 100644 --- a/event-schemas/schema/m.room.encrypted +++ b/event-schemas/schema/m.room.encrypted @@ -13,9 +13,7 @@ properties: algorithm: type: string enum: - - m.olm.curve25519-aes-sha256 - m.olm.v1.curve25519-aes-sha2 - - m.megolm.v1.aes-sha - m.megolm.v1.aes-sha2 description: |- The encryption algorithm used to encrypt this event. The From 5fa6b493653cdf831183d994f272e7978fda341d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 15:56:47 -0600 Subject: [PATCH 092/219] Specify the type of filter the search API expects Note: This is badly named until https://github.com/matrix-org/matrix-doc/pull/1570 lands Fixes https://github.com/matrix-org/matrix-doc/issues/598 --- api/client-server/search.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/client-server/search.yaml b/api/client-server/search.yaml index e4118c32b..6feb57783 100644 --- a/api/client-server/search.yaml +++ b/api/client-server/search.yaml @@ -41,7 +41,7 @@ paths: type: string description: |- The point to return events from. If given, this should be a - `next_batch` result from a previous call to this endpoint. + ``next_batch`` result from a previous call to this endpoint. x-example: "YWxsCgpOb25lLDM1ODcwOA" - in: body name: body @@ -95,6 +95,7 @@ paths: # for now :/ description: |- This takes a `filter`_. + $ref: "definitions/room_event_filter.yaml" order_by: title: "Ordering" type: string From 7b7933327a2e66ff360858ae8a98cc754bc44ef7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 15:57:51 -0600 Subject: [PATCH 093/219] Changelog --- changelogs/client_server/newsfragments/1577.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1577.clarification diff --git a/changelogs/client_server/newsfragments/1577.clarification b/changelogs/client_server/newsfragments/1577.clarification new file mode 100644 index 000000000..aec3248fe --- /dev/null +++ b/changelogs/client_server/newsfragments/1577.clarification @@ -0,0 +1 @@ +Clarify the filter object schema used in room searching. From be2e0fc9d416348b411c21a8fc394387a1194ebc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 16:12:42 -0600 Subject: [PATCH 094/219] Clarify that ACLs are required to manually deny unsupported hosts --- event-schemas/schema/m.room.server_acl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/event-schemas/schema/m.room.server_acl b/event-schemas/schema/m.room.server_acl index ed64038ca..29a91f4b3 100644 --- a/event-schemas/schema/m.room.server_acl +++ b/event-schemas/schema/m.room.server_acl @@ -4,8 +4,8 @@ description: |- An event to indicate which servers are permitted to participate in the room. Server ACLs may allow or deny groups of hosts. All servers participating in the room, including those that are denied, are expected to uphold the - server ACL. Servers that do not uphold the ACLs are recommended to be - added to the denied hosts list. + server ACL. Servers that do not uphold the ACLs MUST be added to the denied hosts + list in order for the ACLs to remain effective. The ``allow`` and ``deny`` lists are lists of globs supporting ``?`` and ``*`` as wildcards. When comparing against the server ACLs, the suspect server's port @@ -27,6 +27,14 @@ description: |- servers from participating in the room, including the sender. This renders the room unusable. A common allow rule is ``[ "*" ]`` which would still permit the use of the ``deny`` list without losing the room. + + .. WARNING:: + Servers that do not uphold the ACLs MUST be manually appended to the denied hosts + list. To accomplish this, events should have their ``prev_events`` inspected for + denied hosts, therefore detecting servers which are not upholding the ACLs. Server + versions can also be used to detect hosts that will not uphold the ACLs, although + this is less effective. Server ACLs were added in Synapse v0.32.0 although other + server implementations and versions exist in the world. allOf: - $ref: core-event-schema/state_event.yaml type: object From 82be6077ffc941bfce0a26fb4f631618046ea8de Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 16:13:42 -0600 Subject: [PATCH 095/219] Add a note that ACLs don't operate at the auth level; Fix glob definition --- event-schemas/schema/m.room.server_acl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/event-schemas/schema/m.room.server_acl b/event-schemas/schema/m.room.server_acl index 29a91f4b3..9e7ccc3b4 100644 --- a/event-schemas/schema/m.room.server_acl +++ b/event-schemas/schema/m.room.server_acl @@ -22,6 +22,11 @@ description: |- #. If the server name matches an entry in the ``allow`` list, allow. #. Otherwise, deny. + .. Note:: + Server ACLs do not restrict the events relative to the room DAG via authorisation + rules, but instead act purely at the network layer to determine which servers are + allowed to connect and interact with a given room. + .. WARNING:: Failing to provide an ``allow`` rule of some kind will prevent **all** servers from participating in the room, including the sender. This renders @@ -51,7 +56,7 @@ properties: description: |- The server names to allow in the room, excluding any port information. Wildcards may be used to cover a wider range of hosts, where ``*`` - matches zero or more characters and ``?`` matches one or more characters. + matches zero or more characters and ``?`` matches exactly one character. **This defaults to an empty list when not provided, effectively disallowing every server.** @@ -62,7 +67,7 @@ properties: description: |- The server names to disallow in the room, excluding any port information. Wildcards may be used to cover a wider range of hosts, where ``*`` - matches zero or more characters and ``?`` matches one or more characters. + matches zero or more characters and ``?`` matches exactly one character. This defaults to an empty list when not provided. items: From 76afef79f8f09809b8dafecc37b7804f52d610e7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 16:14:37 -0600 Subject: [PATCH 096/219] Clarify the rationale and motive for blanket IP banning and port exclusion --- event-schemas/schema/m.room.server_acl | 4 ++++ specification/modules/server_acls.rst | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/event-schemas/schema/m.room.server_acl b/event-schemas/schema/m.room.server_acl index 9e7ccc3b4..317031cdc 100644 --- a/event-schemas/schema/m.room.server_acl +++ b/event-schemas/schema/m.room.server_acl @@ -51,6 +51,10 @@ properties: description: |- True to allow server names that are IP address literals. False to deny. Defaults to true if missing or otherwise not a boolean. + + This is strongly recommended to be set to ``false`` as servers running + with IP literal names are strongly discouraged in order to require + legitimate homeservers to be backed by a valid registered domain name. allow: type: array description: |- diff --git a/specification/modules/server_acls.rst b/specification/modules/server_acls.rst index 72892fce5..f26b8c6b1 100644 --- a/specification/modules/server_acls.rst +++ b/specification/modules/server_acls.rst @@ -17,7 +17,7 @@ Server Access Control Lists (ACLs) for rooms .. _module:server-acls: -In some scenarios room operators may wish to prevent a malicous or untrusted +In some scenarios room operators may wish to prevent a malicious or untrusted server from participating in their room. Sending an `m.room.server_acl`_ state event into a room is an effective way to prevent the server from participating in the room at the federation level. @@ -30,7 +30,10 @@ similar to setting the ``m.federate`` value on the `m.room.create`_ event. .. Note:: Port numbers are not supported because it is unclear to parsers whether a - port number should be matched or an IP address literal. + port number should be matched or an IP address literal. Additionally, it + is unlikely that one would trust a server running on a particular domain's + port but not a different port, especially considering the server host can + easily change ports. .. Note:: CIDR notation is not supported for IP addresses because Matrix does not From d7397ccd563fb886c48944c1f3869e0d617aadc8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 16:21:10 -0600 Subject: [PATCH 097/219] Provide additional rationale for kicking users when they are ACLd --- specification/modules/server_acls.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specification/modules/server_acls.rst b/specification/modules/server_acls.rst index f26b8c6b1..2b2d8f351 100644 --- a/specification/modules/server_acls.rst +++ b/specification/modules/server_acls.rst @@ -47,7 +47,8 @@ event. Clients should describe changes to the server ACLs to the user in the user interface, such as in the timeline. Clients may wish to kick affected users from the room prior to denying a server -access to the room to help prevent those servers from participating. +access to the room to help prevent those servers from participating and to +provide feedback to the users that they have been excluded from the room. Server behaviour ---------------- From 313e6de48bb99afefa8adb18d6dd097a4d88a849 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 27 Aug 2018 23:36:48 +0100 Subject: [PATCH 098/219] tweak wording to spell out that handling legacy/noncompliant servers. --- event-schemas/schema/m.room.server_acl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/event-schemas/schema/m.room.server_acl b/event-schemas/schema/m.room.server_acl index 317031cdc..c6adaf054 100644 --- a/event-schemas/schema/m.room.server_acl +++ b/event-schemas/schema/m.room.server_acl @@ -34,12 +34,14 @@ description: |- permit the use of the ``deny`` list without losing the room. .. WARNING:: - Servers that do not uphold the ACLs MUST be manually appended to the denied hosts - list. To accomplish this, events should have their ``prev_events`` inspected for - denied hosts, therefore detecting servers which are not upholding the ACLs. Server - versions can also be used to detect hosts that will not uphold the ACLs, although - this is less effective. Server ACLs were added in Synapse v0.32.0 although other - server implementations and versions exist in the world. + All compliant servers must implement server ACLs. However, legacy or noncompliant + servers exist which do not uphold ACLs, and these MUST be manually appended to + the denied hosts list when setting an ACL to prevent them from leaking events from + banned servers into a room. Currently, the only way to determine noncompliant hosts is + to check the ``prev_events`` of leaked events, therefore detecting servers which + are not upholding the ACLs. Server versions can also be used to try to detect hosts that + will not uphold the ACLs, although this is not comprehensive. Server ACLs were added + in Synapse v0.32.0, although other server implementations and versions exist in the world. allOf: - $ref: core-event-schema/state_event.yaml type: object From bac0392a2d98662b19f32f2955daca145e42a499 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 17:28:08 -0600 Subject: [PATCH 099/219] General clarity for push rule defaults and where to get information Include moving a roaming condition that was under the wrong rule. --- specification/modules/push.rst | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/specification/modules/push.rst b/specification/modules/push.rst index 408eabe62..1972fa17b 100644 --- a/specification/modules/push.rst +++ b/specification/modules/push.rst @@ -468,6 +468,10 @@ Definition: ``.m.rule.encrypted_room_one_to_one`` ````````````````````````````````````` Matches any encrypted event sent in a room with exactly two members. +Unlike other push rules, this rule cannot be matched against the content +of the event by nature of it being encrypted. This causes the rule to +be an "all or nothing" match where it either matches *all* events that +are encrypted (in 1:1 rooms) or none. Definition: @@ -492,6 +496,11 @@ Definition: { "set_tweak": "highlight", "value": false + }, + { + "kind": "event_match", + "key": "type", + "pattern": "m.room.encrypted" } ] } @@ -512,11 +521,6 @@ Definition: { "kind": "room_member_count", "is": "2" - }, - { - "kind": "event_match", - "key": "type", - "pattern": "m.room.encrypted" } ], "actions": [ @@ -562,7 +566,10 @@ Definition: ``.m.rule.encrypted`` ````````````````````` -Matches all encrypted events. +Matches all encrypted events. Unlike other push rules, this rule cannot +be matched against the content of the event by nature of it being encrypted. +This causes the rule to be an "all or nothing" match where it either +matches *all* events that are encrypted (in 1:1 rooms) or none. Definition: @@ -628,11 +635,11 @@ rule determines its behaviour. The following conditions are defined: Parameters: - * ``key``: The notification power level to require the sender to have. Refer to - the `m.room.power_levels`_ event schema for information about what the defaults - are and how to interpret the event. The ``key`` is used to look up a specific - notification type from the ``notifications`` object in the power level event - content. + * ``key``: A string that determines the power level the sender must have to trigger + notifications of a given type, such as ``room``. Refer to the `m.room.power_levels`_ + event schema for information about what the defaults are and how to interpret the event. + The ``key`` is used to look up the power level required to send a notification type + from the ``notifications`` object in the power level event content. Unrecognised conditions MUST NOT match any events, effectively making the push rule disabled. From 32ac81c5883ba7e7fff2b896a34d6ad7f829e4fd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 17:41:27 -0600 Subject: [PATCH 100/219] Spelling --- api/application-service/protocols.yaml | 6 +++--- api/client-server/third_party_lookup.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/application-service/protocols.yaml b/api/application-service/protocols.yaml index 376e66c0b..e6489cc5b 100644 --- a/api/application-service/protocols.yaml +++ b/api/application-service/protocols.yaml @@ -127,7 +127,7 @@ paths: $ref: ../client-server/definitions/errors/error.yaml "/_matrix/app/unstable/thirdparty/location/{protocol}": get: - summary: Retreive Matrix-side portal rooms leading to a third party location. + summary: Retrieve Matrix-side portal rooms leading to a third party location. description: |- Retrieve a list of Matrix portal rooms that lead to the matched third party location. operationId: queryLocationByProtocol @@ -180,7 +180,7 @@ paths: get: summary: Reverse-lookup third party locations given a Matrix room alias. description: |- - Retreive an array of third party network locations from a Matrix room + Retrieve an array of third party network locations from a Matrix room alias. operationId: queryLocationByAlias parameters: @@ -225,7 +225,7 @@ paths: get: summary: Reverse-lookup third party users given a Matrix User ID. description: |- - Retreive an array of third party users from a Matrix User ID. + Retrieve an array of third party users from a Matrix User ID. operationId: queryUserByID parameters: - in: query diff --git a/api/client-server/third_party_lookup.yaml b/api/client-server/third_party_lookup.yaml index cba9ce22a..3d348df2f 100644 --- a/api/client-server/third_party_lookup.yaml +++ b/api/client-server/third_party_lookup.yaml @@ -73,7 +73,7 @@ paths: $ref: definitions/errors/error.yaml "/thirdparty/location/{protocol}": get: - summary: Retreive Matrix-side portals rooms leading to a third party location. + summary: Retrieve Matrix-side portals rooms leading to a third party location. description: |- Requesting this endpoint with a valid protocol name results in a list of successful mapping results in a JSON array. Each result contains @@ -151,7 +151,7 @@ paths: get: summary: Reverse-lookup third party locations given a Matrix room alias. description: |- - Retreive an array of third party network locations from a Matrix room + Retrieve an array of third party network locations from a Matrix room alias. operationId: queryLocationByAlias security: @@ -181,7 +181,7 @@ paths: get: summary: Reverse-lookup third party users given a Matrix User ID. description: |- - Retreive an array of third party users from a Matrix User ID. + Retrieve an array of third party users from a Matrix User ID. operationId: queryUserByID security: - accessToken: [] From 54032964fc89a356fef1d679d94e6e8bbdeabfc6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 17:41:52 -0600 Subject: [PATCH 101/219] Misc clarity for 3rd party appservice protocols/locations --- specification/application_service_api.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 9d467e879..6e3c5374c 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -184,13 +184,14 @@ Third party networks ++++++++++++++++++++ Application services may declare which protocols they support via their registration -file. These networks are generally for third party services such as IRC that the -application service is managing. Application services may populate a Matrix room -directory for their registered protocols, as defined in the Client-Server API Extensions. - -Each protocol may have several "locations". A location within a protocol is a place -in the third party network, such as an IRC channel. Users of the third party network -may also be represented by the application service. +configuration for the homeserver. These networks are generally for third party services +such as IRC that the application service is managing. Application services may populate +a Matrix room directory for their registered protocols, as defined in the Client-Server +API Extensions. + +Each protocol may have several "locations" (also known as "third party locations" or "3PLs"). +A location within a protocol is a place in the third party network, such as an IRC channel. +Users of the third party network may also be represented by the application service. Locations and users can be searched by fields defined by the application service, such as by display name or other attribute. When clients request the homeserver to search From 17e0ef4b91034b0cdb010416225ffac65b4107fc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 17:58:47 -0600 Subject: [PATCH 102/219] Remove empty file and now-empty section from the appservice spec This commit has approval under https://github.com/matrix-org/matrix-doc/pull/1555 although is being included in this branch/PR so the build passes, permitting a merge. --- .../application_service.yaml | 28 ------------------- specification/application_service_api.rst | 9 ------ 2 files changed, 37 deletions(-) delete mode 100644 api/application-service/application_service.yaml diff --git a/api/application-service/application_service.yaml b/api/application-service/application_service.yaml deleted file mode 100644 index 67b5b1b5c..000000000 --- a/api/application-service/application_service.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2016 OpenMarket Ltd -# 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. -swagger: '2.0' -info: - title: "Matrix Application Service API" - version: "1.0.0" -host: localhost:8008 -schemes: - - https - - http -basePath: "/" -consumes: - - application/json -produces: - - application/json -paths: diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 48e6896d2..51280341c 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -246,15 +246,6 @@ application service for filtering. {{protocols_as_http_api}} -HTTP APIs -+++++++++ - -This contains application service APIs which are used by the homeserver. All -application services MUST implement these APIs. These APIs are defined below. - -{{application_service_as_http_api}} - - .. _create the user: `sect:asapi-permissions`_ Client-Server API Extensions From fa96d8629bcce201b1ef32a8b969e0f0ae60343f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 11:36:04 -0600 Subject: [PATCH 103/219] Prepare the appservice spec for an r0 release This puts the scaffolding in place for an r0 release to happen, such as the changelog and version variables. --- changelogs/application_service.rst | 0 .../newsfragments/.gitignore | 1 + changelogs/application_service/pyproject.toml | 30 +++++++++++++++++++ scripts/gendoc.py | 6 ++++ .../templating/matrix_templates/sections.py | 4 +++ scripts/templating/matrix_templates/units.py | 5 ++-- specification/application_service_api.rst | 12 ++++++-- specification/targets.yaml | 2 +- 8 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 changelogs/application_service.rst create mode 100644 changelogs/application_service/newsfragments/.gitignore create mode 100644 changelogs/application_service/pyproject.toml diff --git a/changelogs/application_service.rst b/changelogs/application_service.rst new file mode 100644 index 000000000..e69de29bb diff --git a/changelogs/application_service/newsfragments/.gitignore b/changelogs/application_service/newsfragments/.gitignore new file mode 100644 index 000000000..b722e9e13 --- /dev/null +++ b/changelogs/application_service/newsfragments/.gitignore @@ -0,0 +1 @@ +!.gitignore \ No newline at end of file diff --git a/changelogs/application_service/pyproject.toml b/changelogs/application_service/pyproject.toml new file mode 100644 index 000000000..44d430e8f --- /dev/null +++ b/changelogs/application_service/pyproject.toml @@ -0,0 +1,30 @@ +[tool.towncrier] + filename = "../application_service.rst" + directory = "newsfragments" + issue_format = "`#{issue} `_" + title_format = "{version}" + + [[tool.towncrier.type]] + directory = "breaking" + name = "Breaking Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations" + showcontent = true + + [[tool.towncrier.type]] + directory = "new" + name = "New Endpoints" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Backwards Compatible Changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "clarification" + name = "Spec Clarifications" + showcontent = true diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 16c40af5d..8bd8537f3 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -518,6 +518,10 @@ if __name__ == '__main__': "--server_release", "-s", action="store", default="unstable", help="The server-server release tag to generate, e.g. r1.2" ) + parser.add_argument( + "--appservice_release", "-a", action="store", default="unstable", + help="The appservice release tag to generate, e.g. r1.2" + ) parser.add_argument( "--list_targets", action="store_true", help="Do not update the specification. Instead print a list of targets.", @@ -542,6 +546,8 @@ if __name__ == '__main__': "%CLIENT_MAJOR_VERSION%": "r0", "%SERVER_RELEASE_LABEL%": args.server_release, "%SERVER_MAJOR_VERSION%": extract_major(args.server_release), + "%APPSERVICE_MAJOR_VERSION%": "unstable", + "%APPSERVICE_RELEASE_LABEL%": args.appservice_release, } exit (main(args.target or ["all"], args.dest, args.nodelete, substitutions)) diff --git a/scripts/templating/matrix_templates/sections.py b/scripts/templating/matrix_templates/sections.py index 1a93c7237..b3c7d4029 100644 --- a/scripts/templating/matrix_templates/sections.py +++ b/scripts/templating/matrix_templates/sections.py @@ -32,6 +32,10 @@ class MatrixSections(Sections): changelogs = self.units.get("changelogs") return changelogs["client_server"] + def render_application_service_changelog(self): + changelogs = self.units.get("changelogs") + return changelogs["application_service"] + def _render_events(self, filterFn, sortFn): template = self.env.get_template("events.tmpl") examples = self.units.get("event_examples") diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 90a87cd47..9423dfc87 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -754,6 +754,7 @@ class MatrixUnits(Units): def load_apis(self, substitutions): cs_ver = substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable") fed_ver = substitutions.get("%SERVER_RELEASE_LABEL%", "unstable") + as_ver = substitutions.get("%APPSERVICE_RELEASE_LABEL%", "unstable") # we abuse the typetable to return this info to the templates return TypeTable(rows=[ @@ -766,8 +767,8 @@ class MatrixUnits(Units): fed_ver, "Federation between servers", ), TypeTableRow( - "`Application Service API `_", - "unstable", + "`Application Service API `_", + as_ver, "Privileged server plugins", ), TypeTableRow( "`Identity Service API `_", diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 51280341c..97a2c04a8 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -30,13 +30,21 @@ irrespective of the underlying homeserver implementation. .. contents:: Table of Contents .. sectnum:: -Specification version ---------------------- +Changelog +--------- + + +.. topic:: Version: unstable +{{application_service_changelog}} This version of the specification is generated from `matrix-doc `_ as of Git commit `{{git_version}} `_. +For the full historical changelog, see +https://github.com/matrix-org/matrix-doc/blob/master/changelogs/application_service.rst + + Application Services -------------------- Application services are passive and can only observe events from a given diff --git a/specification/targets.yaml b/specification/targets.yaml index acf4b6ac9..42a50e35e 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -13,7 +13,7 @@ targets: application_service: files: - application_service_api.rst - version_label: unstable + version_label: "%APPSERVICE_RELEASE_LABEL%" server_server: files: - server_server_api.rst From f01cfa2c7bdd1d43109ac3acfc7b016b661e29db Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 11:39:39 -0600 Subject: [PATCH 104/219] Add security definitions to hs->as endpoints --- .../definitions/security.yaml | 18 ++++++++++++++++++ api/application-service/protocols.yaml | 12 ++++++++++++ api/application-service/query_room.yaml | 4 ++++ api/application-service/query_user.yaml | 4 ++++ api/application-service/transactions.yaml | 4 ++++ 5 files changed, 42 insertions(+) create mode 100644 api/application-service/definitions/security.yaml diff --git a/api/application-service/definitions/security.yaml b/api/application-service/definitions/security.yaml new file mode 100644 index 000000000..bcfc69c06 --- /dev/null +++ b/api/application-service/definitions/security.yaml @@ -0,0 +1,18 @@ +# 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. +homeserverAccessToken: + type: apiKey + description: The ``hs_token`` provided by the application service's registration. + name: access_token + in: query diff --git a/api/application-service/protocols.yaml b/api/application-service/protocols.yaml index e6489cc5b..d58710a49 100644 --- a/api/application-service/protocols.yaml +++ b/api/application-service/protocols.yaml @@ -24,6 +24,8 @@ consumes: - application/json produces: - application/json +securityDefinitions: + $ref: definitions/security.yaml paths: "/_matrix/app/unstable/thirdparty/protocol/{protocol}": get: @@ -33,6 +35,8 @@ paths: with specific information about the various third party networks that an application service supports. operationId: getProtocolMetadata + security: + - homeserverAccessToken: [] parameters: - in: path name: protocol @@ -80,6 +84,8 @@ paths: User ID linked to a user on the third party network, given a set of user parameters. operationId: queryUserByProtocol + security: + - homeserverAccessToken: [] parameters: - in: path name: protocol @@ -131,6 +137,8 @@ paths: description: |- Retrieve a list of Matrix portal rooms that lead to the matched third party location. operationId: queryLocationByProtocol + security: + - homeserverAccessToken: [] parameters: - in: path name: protocol @@ -183,6 +191,8 @@ paths: Retrieve an array of third party network locations from a Matrix room alias. operationId: queryLocationByAlias + security: + - homeserverAccessToken: [] parameters: - in: query name: alias @@ -227,6 +237,8 @@ paths: description: |- Retrieve an array of third party users from a Matrix User ID. operationId: queryUserByID + security: + - homeserverAccessToken: [] parameters: - in: query name: userid diff --git a/api/application-service/query_room.yaml b/api/application-service/query_room.yaml index b885cb860..f388affe2 100644 --- a/api/application-service/query_room.yaml +++ b/api/application-service/query_room.yaml @@ -25,6 +25,8 @@ consumes: - application/json produces: - application/json +securityDefinitions: + $ref: definitions/security.yaml paths: "/rooms/{roomAlias}": get: @@ -36,6 +38,8 @@ paths: homeserver will send this request when it receives a request to join a room alias within the application service's namespace. operationId: queryRoomByAlias + security: + - homeserverAccessToken: [] parameters: - in: path name: roomAlias diff --git a/api/application-service/query_user.yaml b/api/application-service/query_user.yaml index 0431b5e49..5cb8d9001 100644 --- a/api/application-service/query_user.yaml +++ b/api/application-service/query_user.yaml @@ -25,6 +25,8 @@ consumes: - application/json produces: - application/json +securityDefinitions: + $ref: definitions/security.yaml paths: "/users/{userId}": get: @@ -36,6 +38,8 @@ paths: send this request when it receives an event for an unknown user ID in the application service's namespace, such as a room invite. operationId: queryUserById + security: + - homeserverAccessToken: [] parameters: - in: path name: userId diff --git a/api/application-service/transactions.yaml b/api/application-service/transactions.yaml index 8735cc8f7..532911161 100644 --- a/api/application-service/transactions.yaml +++ b/api/application-service/transactions.yaml @@ -23,6 +23,8 @@ schemes: basePath: "/" produces: - application/json +securityDefinitions: + $ref: definitions/security.yaml paths: "/transactions/{txnId}": put: @@ -35,6 +37,8 @@ paths: from message events via the presence of a ``state_key``, rather than via the event type. operationId: sendTransaction + security: + - homeserverAccessToken: [] parameters: - in: path name: txnId From 07153c22a941a8de243031b2ef661c4e6e4b6866 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 16:54:53 -0600 Subject: [PATCH 105/219] Misc. cleanup of the appservice spec --- specification/application_service_api.rst | 24 +++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 97a2c04a8..f32053025 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -48,12 +48,12 @@ https://github.com/matrix-org/matrix-doc/blob/master/changelogs/application_serv Application Services -------------------- Application services are passive and can only observe events from a given -homeserver (HS). They can inject events into rooms they are participating in. +homeserver. They can inject events into rooms they are participating in. They cannot prevent events from being sent, nor can they modify the content of the event being sent. In order to observe events from a homeserver, the homeserver needs to be configured to pass certain types of traffic to the application service. This is achieved by manually configuring the homeserver -with information about the application service (AS). +with information about the application service. Registration ~~~~~~~~~~~~ @@ -187,24 +187,24 @@ events. Each list of events includes a transaction ID, which works as follows: Typical HS ---> AS : Homeserver sends events with transaction ID T. - <--- : AS sends back 200 OK. + <--- : Application Service sends back 200 OK. AS ACK Lost HS ---> AS : Homeserver sends events with transaction ID T. <-/- : AS 200 OK is lost. HS ---> AS : Homeserver retries with the same transaction ID of T. - <--- : AS sends back 200 OK. If the AS had processed these events - already, it can NO-OP this request (and it knows if it is the same - events based on the transaction ID). + <--- : Application Service sends back 200 OK. If the AS had processed these + events already, it can NO-OP this request (and it knows if it is the + same events based on the transaction ID). The events sent to the application service should be linearised, as if they were from the event stream. The homeserver MUST maintain a queue of transactions to -send to the AS. If the application service cannot be reached, the homeserver -SHOULD backoff exponentially until the application service is reachable again. +send to the application service. If the application service cannot be reached, the +homeserver SHOULD backoff exponentially until the application service is reachable again. As application services cannot *modify* the events in any way, these requests can be made without blocking other aspects of the homeserver. Homeservers MUST NOT alter (e.g. add more) events they were going to send within that transaction ID -on retries, as the AS may have already processed the events. +on retries, as the application service may have already processed the events. {{transactions_as_http_api}} @@ -313,7 +313,7 @@ Notes: :: - PUT /_matrix/client/r0/rooms/!somewhere:domain.com/send/m.room.message/txnId?ts=1534535223283 + PUT /_matrix/client/r0/rooms/!somewhere:domain.com/send/m.room.message/txnId?ts=1534535223283 Authorization: Bearer YourApplicationServiceTokenHere Content: The event to send, as per the Client-Server API. @@ -334,7 +334,7 @@ users needs API changes in order to: - Have a 'passwordless' user. This involves bypassing the registration flows entirely. This is achieved by -including the AS token on a ``/register`` request, along with a login type of +including the ``as_token`` on a ``/register`` request, along with a login type of ``m.login.application_service`` to set the desired user ID without a password. :: @@ -374,8 +374,6 @@ additional parameters on the ``/publicRooms`` client-server endpoint. Event fields ~~~~~~~~~~~~ -.. TODO-TravisR: Fix this section to be a general "3rd party networks" section - We recommend that any events that originated from a remote network should include an ``external_url`` field in their content to provide a way for Matrix clients to link into the 'native' client from which the event originated. From 6f80db5ddf1a9851cdc3b8f9e167a3e805db28c1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 24 Aug 2018 17:21:12 -0600 Subject: [PATCH 106/219] Include the "other versions" section of the changelog --- specification/application_service_api.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index f32053025..4b42707db 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -44,6 +44,13 @@ This version of the specification is generated from For the full historical changelog, see https://github.com/matrix-org/matrix-doc/blob/master/changelogs/application_service.rst +Other versions of this specification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following other versions are also available, in reverse chronological order: + +- `HEAD `_: Includes all changes since the latest versioned release. + Application Services -------------------- From 39e674ccb355af61bcfef92be4b557f53db46ea4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 18:27:48 -0600 Subject: [PATCH 107/219] Clarify what matrix.to is and mention that room IDs are not routable Also actually render the warning saying that this scheme is temporary. --- specification/appendices/identifier_grammar.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index eba443e29..e72fdadaa 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -287,8 +287,10 @@ domain). matrix.to navigation ++++++++++++++++++++ -.. NOTE: +.. NOTE:: This namespacing is in place pending a ``matrix://`` (or similar) URI scheme. + This is **not** meant to be interpreted as an available web service - see + below for more details. Rooms, users, aliases, and groups may be represented as a "matrix.to" URI. This URI can be used to reference particular objects in a given context, such @@ -307,14 +309,19 @@ followed by the identifier. Clients should not rely on matrix.to URIs falling back to a web server if accessed and instead should perform some sort of action within the client. For example, if -the user where to click on a matrix.to URI for a room alias, the client may open +the user were to click on a matrix.to URI for a room alias, the client may open a view for the user to participate in the room. Examples of matrix.to URIs are: -* Room: ``https://matrix.to/#/!somewhere:domain.com`` * Room alias: ``https://matrix.to/#/#somewhere:domain.com`` +* Room: ``https://matrix.to/#/!somewhere:domain.com`` * Permalink by room: ``https://matrix.to/#/!somewhere:domain.com/$event:example.org`` * Permalink by room alias: ``https://matrix.to/#/#somewhere:domain.com/$event:example.org`` * User: ``https://matrix.to/#/@alice:example.org`` * Group: ``https://matrix.to/#/+example:domain.com`` + +.. Note:: + Room ID permalinks are unroutable as there is no reliable domain to send requests + to upon receipt of the permalink. Clients should do their best route Room IDs to + where they need to go, however they should also be aware of `issue #1579 `_. \ No newline at end of file From bb515d15a40470fc2c9a9290428b8fcf675ec0c1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 18:55:54 -0600 Subject: [PATCH 108/219] Clarify which collation to use for user directory searching --- api/client-server/users.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/client-server/users.yaml b/api/client-server/users.yaml index ef527a23b..619263ffe 100644 --- a/api/client-server/users.yaml +++ b/api/client-server/users.yaml @@ -37,7 +37,8 @@ paths: room with and those who reside in public rooms. The search is performed case-insensitively on user IDs and display - names. + names preferably using a collation determined based upon the + ``Accept-Language`` header provided in the request, if present. operationId: searchUserDirectory security: - accessToken: [] From f2332d242aeb079e77396bd6bd8c5d7f2a629b7e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 18:58:16 -0600 Subject: [PATCH 109/219] Add some SHOULDs and MUSTs to the user directory requirements --- api/client-server/users.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/client-server/users.yaml b/api/client-server/users.yaml index 619263ffe..8a60a7bcc 100644 --- a/api/client-server/users.yaml +++ b/api/client-server/users.yaml @@ -33,8 +33,10 @@ paths: description: |- Performs a search for users on the homeserver. The homeserver may determine which subset of users are searched, however the homeserver - is encouraged to only consider users the requesting user shares a - room with and those who reside in public rooms. + 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). + The search MUST consider local users to the homeserver, and SHOULD + query remote users as part of the search. The search is performed case-insensitively on user IDs and display names preferably using a collation determined based upon the From 439b9d2925b306652a75240173fb9f0aec161dd7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 18:59:35 -0600 Subject: [PATCH 110/219] Power levels are also integers --- event-schemas/schema/m.room.power_levels | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/event-schemas/schema/m.room.power_levels b/event-schemas/schema/m.room.power_levels index 13a44c709..b00d86a9a 100644 --- a/event-schemas/schema/m.room.power_levels +++ b/event-schemas/schema/m.room.power_levels @@ -46,10 +46,10 @@ properties: properties: ban: description: The level required to ban a user. Defaults to 50 if unspecified. - type: number + type: integer events: additionalProperties: - type: number + type: integer description: The level required to send specific event types. This is a mapping from event type to power level required. title: Event power levels type: object @@ -57,25 +57,25 @@ properties: description: |- The default level required to send message events. Can be overridden by the ``events`` key. Defaults to 0 if unspecified. - type: number + type: integer invite: description: The level required to invite a user. Defaults to 50 if unspecified. - type: number + type: integer kick: description: The level required to kick a user. Defaults to 50 if unspecified. - type: number + type: integer redact: description: The level required to redact an event. Defaults to 50 if unspecified. - type: number + type: integer state_default: description: |- The default level required to send state events. Can be overridden by the ``events`` key. Defaults to 50 if unspecified, but 0 if there is no ``m.room.power_levels`` event at all. - type: number + type: integer users: additionalProperties: - type: number + type: integer description: The power levels for specific users. This is a mapping from ``user_id`` to power level for that user. title: User power levels type: object @@ -84,7 +84,7 @@ properties: The default power level for every user in the room, unless their ``user_id`` is mentioned in the ``users`` key. Defaults to 0 if unspecified. - type: number + type: integer type: object state_key: description: A zero-length string. From 4b05194a913e210585febe3df1864d2b6e384eab Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 19:18:14 -0600 Subject: [PATCH 111/219] Fix bad merge --- event-schemas/examples/m.room.member#invite_room_state | 7 ------- 1 file changed, 7 deletions(-) diff --git a/event-schemas/examples/m.room.member#invite_room_state b/event-schemas/examples/m.room.member#invite_room_state index 44f160c23..7055d0a09 100644 --- a/event-schemas/examples/m.room.member#invite_room_state +++ b/event-schemas/examples/m.room.member#invite_room_state @@ -21,13 +21,6 @@ "join_rule": "invite" } } - }, - { - "type": "m.room.join_rules", - "state_key": "", - "content": { - "join_rule": "invite" - } } ] } From 8e42f3ab3a3de8a7eba1d9f5354a140d45c3ec65 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 19:26:08 -0600 Subject: [PATCH 112/219] Fix bad merge on brackets --- event-schemas/examples/m.room.member#invite_room_state | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/event-schemas/examples/m.room.member#invite_room_state b/event-schemas/examples/m.room.member#invite_room_state index 7055d0a09..cbd76100e 100644 --- a/event-schemas/examples/m.room.member#invite_room_state +++ b/event-schemas/examples/m.room.member#invite_room_state @@ -21,6 +21,6 @@ "join_rule": "invite" } } - } - ] + ] + } } From cff5b8b205d8b86bacc3ab75171f47f7b427a2dc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 19:30:46 -0600 Subject: [PATCH 113/219] More versioned links --- specification/server_server_api.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index ccebc313c..d04c04073 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -1089,9 +1089,9 @@ that are too long. .. |/query/directory| replace:: ``/query/directory`` .. _/query/directory: #get-matrix-federation-%SERVER_MAJOR_VERSION%-query-directory -.. _`Invitation storage`: ../identity_service/unstable.html#invitation-storage -.. _`Identity Service API`: ../identity_service/unstable.html -.. _`Client-Server API`: ../client_server/unstable.html +.. _`Invitation storage`: ../identity_service/%IDENTITY_RELEASE_LABEL%.html#invitation-storage +.. _`Identity Service API`: ../identity_service/%IDENTITY_RELEASE_LABEL%.html +.. _`Client-Server API`: ../client_server/%CLIENT_RELEASE_LABEL%.html .. _`Inviting to a room`: #inviting-to-a-room .. _`Canonical JSON`: ../appendices.html#canonical-json .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 From 72c6fa2aaf73af1af9da40c3bdbc31de8369ce7c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 27 Aug 2018 19:33:03 -0600 Subject: [PATCH 114/219] More versioned links --- specification/modules/push.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/modules/push.rst b/specification/modules/push.rst index e9ee8c90d..492e8291e 100644 --- a/specification/modules/push.rst +++ b/specification/modules/push.rst @@ -623,4 +623,4 @@ should send a "sync" command to instruct the client to get new events from the homeserver directly. -.. _`Push Gateway Specification`: ../push_gateway/unstable.html +.. _`Push Gateway Specification`: ../push_gateway/%PUSH_GATEWAY_RELEASE_LABEL%.html From fc1fdc95afb96d3b74844355d4ceada7a96b9bfa Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Tue, 28 Aug 2018 17:29:58 +0100 Subject: [PATCH 115/219] Specify a limit on the number of EDUs and PDUs a transaction can contain --- api/server-server/definitions/transaction.yaml | 2 +- api/server-server/transactions.yaml | 4 ++-- specification/server_server_api.rst | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/api/server-server/definitions/transaction.yaml b/api/server-server/definitions/transaction.yaml index 7df8b6464..9833f7852 100644 --- a/api/server-server/definitions/transaction.yaml +++ b/api/server-server/definitions/transaction.yaml @@ -31,7 +31,7 @@ properties: example: 1532991320875 pdus: type: array - description: List of persistent updates to rooms. + description: List of persistent updates to rooms. Must not include more than 50 PDUs. items: $ref: "pdu.yaml" required: ['origin', 'origin_server_ts', 'pdus'] diff --git a/api/server-server/transactions.yaml b/api/server-server/transactions.yaml index 8d810ad59..ad10ec0b9 100644 --- a/api/server-server/transactions.yaml +++ b/api/server-server/transactions.yaml @@ -60,8 +60,8 @@ paths: edus: type: array description: |- - List of ephemeral messages. May be omitted if there are no ephemeral - messages to be sent. + List of ephemeral messages. May be omitted if there are no ephemeral + messages to be sent. Must not include more than 100 EDUs. items: $ref: "definitions/edu.yaml" example: { diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 439b35f90..f281c21a2 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -262,6 +262,8 @@ of Transaction messages, which are encoded as JSON objects, passed over an HTTP PUT request. A Transaction is meaningful only to the pair of homeservers that exchanged it; they are not globally-meaningful. +Transactions are limited in size; they can have at most 50 PDUs and 100 EDUs. + {{transactions_ss_http_api}} PDUs From ee3b0f42dbc566e911b6fc0c193cb160a653c7e4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 10:34:49 -0600 Subject: [PATCH 116/219] Fix server ACL schema: The type is a string It cannot be an enum otherwise the build starts screaming. --- event-schemas/schema/m.room.server_acl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-schemas/schema/m.room.server_acl b/event-schemas/schema/m.room.server_acl index c6adaf054..86d83832e 100644 --- a/event-schemas/schema/m.room.server_acl +++ b/event-schemas/schema/m.room.server_acl @@ -85,4 +85,4 @@ properties: type: string type: enum: ['m.room.server_acl'] - type: enum + type: string From 80edda1666063f574c211a0c992ad1ff1ec1dded Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 10:35:54 -0600 Subject: [PATCH 117/219] Actually run the check-docs circle job --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index f79449f38..22a5a90a3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -78,6 +78,7 @@ workflows: jobs: - build-docs - build-swagger + - check-docs notify: webhooks: From e9579a7840692529f5fd32548cfd1beb22ee1aff Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 11:01:43 -0600 Subject: [PATCH 118/219] The `rank` in search results is actually a floating point number This was accidentally changed in https://github.com/matrix-org/matrix-doc/pull/1571 and appears to be the only instance. --- api/client-server/search.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/client-server/search.yaml b/api/client-server/search.yaml index 6594a9139..4a5f45150 100644 --- a/api/client-server/search.yaml +++ b/api/client-server/search.yaml @@ -198,7 +198,7 @@ paths: description: The result object. properties: rank: - type: integer + type: number description: A number that describes how closely this result matches the search. Higher is closer. From 17ae84d06443405e2dce679021f80f5fb158779c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 11:05:59 -0600 Subject: [PATCH 119/219] Check the API examples too --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 22a5a90a3..776375834 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,6 +29,8 @@ checkexamples: &checkexamples source /env/bin/activate cd event-schemas ./check_examples.py + cd ../api + ./check_examples.py genmatrixassets: &genmatrixassets name: Generate/Verify matrix.org assets From 791a2f2b171b4bd7762a7b051317d5790fd678ce Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 12:04:20 -0600 Subject: [PATCH 120/219] Run the validator on the spec --- .circleci/config.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 776375834..785941c7d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,9 +38,21 @@ genmatrixassets: &genmatrixassets source /env/bin/activate ./scripts/generate-matrix-org-assets +validateapi: &validateapi + name: Validate OpenAPI specifications + command: | + cd api + npm install + node validator.js -s "client-server" version: 2 jobs: + validate-docs: + docker: + - image: node:alpine + steps: + - checkout + - run: *validateapi check-docs: docker: - image: uhoreg/matrix-doc-build @@ -81,6 +93,7 @@ workflows: - build-docs - build-swagger - check-docs + - validate-docs notify: webhooks: From ad068bcd2269df4c11fb79f7c0ce571332341251 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 12:11:36 -0600 Subject: [PATCH 121/219] Fix the appservice directory visibility type parameter type --- api/client-server/appservice_room_directory.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/client-server/appservice_room_directory.yaml b/api/client-server/appservice_room_directory.yaml index 0225ecd85..49393cd4f 100644 --- a/api/client-server/appservice_room_directory.yaml +++ b/api/client-server/appservice_room_directory.yaml @@ -62,11 +62,12 @@ paths: x-example: "!somewhere:domain.com" - in: body name: body + required: true schema: type: object properties: visibility: - type: enum + type: string enum: ["public", "private"] description: |- Whether the room should be visible (public) in the directory From 349696fc1d3ce0cfe0bb7b70aeaec3b362573512 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 12:16:29 -0600 Subject: [PATCH 122/219] Test building of the speculator and continuserv --- .circleci/config.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 785941c7d..d92b88901 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,6 +45,18 @@ validateapi: &validateapi npm install node validator.js -s "client-server" +buildspeculator: &buildspeculator + name: Build Speculator + command: | + cd scripts/speculator + go build + +buildcontinuserv: &buildcontinuserv + name: Build Continuserv + command: | + cd scripts/continuserv + go build + version: 2 jobs: validate-docs: @@ -71,7 +83,6 @@ jobs: - run: name: "Doc build is available at:" command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/scripts/gen/index.html"; echo $DOCS_URL - build-swagger: docker: - image: uhoreg/matrix-doc-build @@ -84,6 +95,18 @@ jobs: - run: name: "Swagger UI is available at:" command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/api/client-server/index.html"; echo $DOCS_URL + build-dev-scripts: + docker: + - image: golang:1.8 + steps: + - checkout + - run: + name: Install Dependencies + command: | + go get github.com/hashicorp/golang-lru + go get gopkg.in/fsnotify/fsnotify.v1 + - run: *buildcontinuserv + - run: *buildspeculator workflows: version: 2 From e97a1b4af029a672905ba8c0ff8102ca9c50c9ae Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 12:17:41 -0600 Subject: [PATCH 123/219] Actually add the dev scripts build to the workflow --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d92b88901..4a8505b7e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -117,6 +117,7 @@ workflows: - build-swagger - check-docs - validate-docs + - build-dev-scripts notify: webhooks: From 132c5b0f48d2e29bbefed62ff1108ae6aba34957 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 12:20:30 -0600 Subject: [PATCH 124/219] Verbose building for go scripts --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4a8505b7e..659380b05 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -49,13 +49,13 @@ buildspeculator: &buildspeculator name: Build Speculator command: | cd scripts/speculator - go build + go build -v buildcontinuserv: &buildcontinuserv name: Build Continuserv command: | cd scripts/continuserv - go build + go build -v version: 2 jobs: @@ -103,8 +103,8 @@ jobs: - run: name: Install Dependencies command: | - go get github.com/hashicorp/golang-lru - go get gopkg.in/fsnotify/fsnotify.v1 + go get -v github.com/hashicorp/golang-lru + go get -v gopkg.in/fsnotify/fsnotify.v1 - run: *buildcontinuserv - run: *buildspeculator From c297c6a35d831f52e0518952725c0992858219e1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 13:06:52 -0600 Subject: [PATCH 125/219] Update schemas and auth rules to cover the @ state key restriction Fixes https://github.com/matrix-org/matrix-doc/issues/1305 Also fixes an issue regarding the `_` being restricted previously, which is false. --- event-schemas/schema/core-event-schema/state_event.yaml | 6 +++++- event-schemas/schema/m.room.member | 5 ++++- specification/server_server_api.rst | 5 ++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/event-schemas/schema/core-event-schema/state_event.yaml b/event-schemas/schema/core-event-schema/state_event.yaml index 020e9087a..71c4137b7 100644 --- a/event-schemas/schema/core-event-schema/state_event.yaml +++ b/event-schemas/schema/core-event-schema/state_event.yaml @@ -11,7 +11,11 @@ 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. The key MUST NOT start with '_'. + 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 diff --git a/event-schemas/schema/m.room.member b/event-schemas/schema/m.room.member index 5fb5356d8..de14644d4 100644 --- a/event-schemas/schema/m.room.member +++ b/event-schemas/schema/m.room.member @@ -105,7 +105,10 @@ properties: title: EventContent type: object state_key: - description: The ``user_id`` this membership event relates to. + description: |- + The ``user_id`` this membership event relates to. In all cases except for when ``membership`` is + ``join``, the user ID sending the event does not need to match the user ID in the ``state_key``, + unlike other events. Regular authorisation rules still apply. type: string type: enum: diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 439b35f90..a66f249c6 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -450,7 +450,10 @@ The rules are as follows: #. Otherwise, reject. -7. Otherwise, allow. +7. If the ``state_key`` starts with ``@`` and the ``state_key`` does not match + the ``sender``, reject. + +8. Otherwise, allow. .. NOTE:: From 85b9769cd9ea101f7d6b10259a983e0b620c9e61 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 14:06:55 -0600 Subject: [PATCH 126/219] Comment out the timestamp massaging section for now Pending discussion on https://github.com/matrix-org/matrix-doc/issues/1585 --- specification/application_service_api.rst | 31 ++++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 51280341c..0da00b87d 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -289,26 +289,27 @@ An example request would be:: GET /_matrix/client/%CLIENT_MAJOR_VERSION%/account/whoami?user_id=@_irc_user:example.org Authorization: Bearer YourApplicationServiceTokenHere +.. TODO-TravisR: Temporarily take out timestamp massaging while we're releasing r0. + See https://github.com/matrix-org/matrix-doc/issues/1585 +.. Timestamp massaging + +++++++++++++++++++ + The application service may want to inject events at a certain time (reflecting + the time on the network they are tracking e.g. irc, xmpp). Application services + need to be able to adjust the ``origin_server_ts`` value to do this. -Timestamp massaging -+++++++++++++++++++ -The application service may want to inject events at a certain time (reflecting -the time on the network they are tracking e.g. irc, xmpp). Application services -need to be able to adjust the ``origin_server_ts`` value to do this. + Inputs: + - Application service token (``as_token``) + - Desired timestamp (in milliseconds since the unix epoch) -Inputs: - - Application service token (``as_token``) - - Desired timestamp (in milliseconds since the unix epoch) - -Notes: - - This will only apply when sending events. + Notes: + - This will only apply when sending events. -:: + :: - PUT /_matrix/client/r0/rooms/!somewhere:domain.com/send/m.room.message/txnId?ts=1534535223283 - Authorization: Bearer YourApplicationServiceTokenHere + PUT /_matrix/client/r0/rooms/!somewhere:domain.com/send/m.room.message/txnId?ts=1534535223283 + Authorization: Bearer YourApplicationServiceTokenHere - Content: The event to send, as per the Client-Server API. + Content: The event to send, as per the Client-Server API. Server admin style permissions ++++++++++++++++++++++++++++++ From 436544b8f8b8b6cf2e05744fa6f9b14ef4db40ed Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 14:19:55 -0600 Subject: [PATCH 127/219] Clarify behaviour of `?set_presence=unavailable` for /sync --- api/client-server/sync.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/client-server/sync.yaml b/api/client-server/sync.yaml index f20798c00..21af0d1e6 100644 --- a/api/client-server/sync.yaml +++ b/api/client-server/sync.yaml @@ -83,7 +83,8 @@ paths: polling this API. If this parameter is omitted then the client is automatically marked as online when it uses this API. Otherwise if the parameter is set to "offline" then the client is not marked as - being online when it uses this API. + being online when it uses this API. When set to "unavailable", the + client is marked as being idle. x-example: "offline" - in: query name: timeout From 4df67d9305d53d05fcbb355d9527030d64e6dd64 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 14:20:02 -0600 Subject: [PATCH 128/219] changelog --- changelogs/client_server/newsfragments/780.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/780.feature diff --git a/changelogs/client_server/newsfragments/780.feature b/changelogs/client_server/newsfragments/780.feature new file mode 100644 index 000000000..747257541 --- /dev/null +++ b/changelogs/client_server/newsfragments/780.feature @@ -0,0 +1 @@ +Add more presence options to the ``set_presence`` parameter of ``/sync``. (Thanks @mujx!) From b402608b41ee1e6a73f8e89296ebbfed4bbff3e9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 14:40:14 -0600 Subject: [PATCH 129/219] Don't reference the major version for the push gateway specification If we ever have a v2 endpoint for the push gateway, we'd likely spec it alongside the v1 stuff, updating applicable references elsewhere. --- api/push-gateway/push_notifier.yaml | 2 +- scripts/gendoc.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/api/push-gateway/push_notifier.yaml b/api/push-gateway/push_notifier.yaml index 21c1ea29b..4a6cb8f75 100644 --- a/api/push-gateway/push_notifier.yaml +++ b/api/push-gateway/push_notifier.yaml @@ -20,7 +20,7 @@ host: localhost:8008 schemes: - https - http -basePath: /_matrix/push/%PUSH_GATEWAY_MAJOR_VERSION% +basePath: /_matrix/push/v1 consumes: - application/json produces: diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 042e3d9dd..8745d3e2b 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -546,7 +546,6 @@ if __name__ == '__main__': "%CLIENT_MAJOR_VERSION%": "r0", "%SERVER_RELEASE_LABEL%": args.server_release, "%SERVER_MAJOR_VERSION%": extract_major(args.server_release), - "%PUSH_GATEWAY_MAJOR_VERSION%": "v1", "%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release, } From dad037170a24219aa76bfdeca2c7b5b6b577b1e8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 15:45:50 -0600 Subject: [PATCH 130/219] Clarify that the requested event is excluded from /state and /state_ids Fixes https://github.com/matrix-org/matrix-doc/issues/1564 --- api/server-server/events.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/server-server/events.yaml b/api/server-server/events.yaml index cf3988a20..f0b301781 100644 --- a/api/server-server/events.yaml +++ b/api/server-server/events.yaml @@ -50,7 +50,7 @@ paths: 200: description: |- The fully resolved state for the room, including the authorization - chain for the events. + chain for the events, excluding the requested event. schema: type: object properties: @@ -97,7 +97,7 @@ paths: 200: description: |- The fully resolved state for the room, including the authorization - chain for the events. + chain for the events, excluding the requested event. schema: type: object properties: From 6f3b42a457c7fc7973fb07847840143ffc7164e3 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 28 Aug 2018 23:56:20 +0100 Subject: [PATCH 131/219] Server names cannot be %-encoded They aren't URLs; it was a thinko to refer to the URL spec for this. --- .../appendices/identifier_grammar.rst | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index fc89f031b..d068b7686 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -23,13 +23,38 @@ A homeserver is uniquely identified by its server name. This value is used in a number of identifiers, as described below. The server name represents the address at which the homeserver in question can -be reached by other homeservers. The complete grammar is:: +be reached by other homeservers. All valid server names are included by the +following grammar:: - server_name = host [ ":" port] - port = *DIGIT + server_name = host [ ":" port ] -where ``host`` is as defined by `RFC3986, section 3.2.2 -`_. + port = *DIGIT + + host = IPv4address / "[" IPv6address "]" / dns-name + + IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT + + IPv6address = 2*45IPv6char + + IPv6char = DIGIT / %x41-46 / %x61-66 / ":" / "." + ; 0-9, A-F, a-f, :, . + + dns-name = *255dns-char + + dns-char = DIGIT / ALPHA / "-" / "." + +-- in other words, the server name is the hostname, followed by an optional +numeric port specifier. The hostname may be a dotted-quad IPv4 address literal, +an IPv6 address literal surrounded with square brackets, or a DNS name. + +IPv4 literals must be a sequence of four decimal numbers in the +range 0 to 255, separated by ".". IPv6 literals must be as specified by +`RFC3513, section 2.2 `_. + +DNS names for use with Matrix should follow the conventional restrictions for +internet hostnames: they should consist of a series of labels separated by +dots, where each label consists of the alphanumeric characters or +hyphens. Examples of valid server names are: @@ -40,6 +65,20 @@ Examples of valid server names are: * ``[1234:5678::abcd]`` (IPv6 literal) * ``[1234:5678::abcd]:5678`` (IPv6 literal with explicit port) +.. Note:: + + This grammar is based on the standard for internet host names, as specified + by `RFC1123, section 2.1 `_, + with an extension for IPv6 literals. + +Server names must be treated case-sensitively: in other words, +``@user:matrix.org`` is a different person from ``@user:MATRIX.ORG``. + +Some recommendations for a choice of server name follow: + +* The length of the complete server name should not exceed 230 characters. +* Server names should not use upper-case characters. + Room Versions ~~~~~~~~~~~~~ @@ -51,7 +90,7 @@ not understanding the new rules. A room version is defined as a string of characters which MUST NOT exceed 32 codepoints in length. Room versions MUST NOT be empty and SHOULD contain only -the characters ``a-z``, ``0-9``, ``.``, and ``-``. +the characters ``a-z``, ``0-9``, ``.``, and ``-``. Room versions are not intended to be parsed and should be treated as opaque identifiers. Room versions consisting only of the characters ``0-9`` and ``.`` From 7f9524f8016f4cdfb35c0434cd45619859326f87 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 00:07:36 +0100 Subject: [PATCH 132/219] =?UTF-8?q?s/--/=E2=80=94/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- specification/appendices/identifier_grammar.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index d068b7686..e686f0c6a 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -43,7 +43,7 @@ following grammar:: dns-char = DIGIT / ALPHA / "-" / "." --- in other words, the server name is the hostname, followed by an optional +— in other words, the server name is the hostname, followed by an optional numeric port specifier. The hostname may be a dotted-quad IPv4 address literal, an IPv6 address literal surrounded with square brackets, or a DNS name. From 8679a642b49d865c628ef6f598f374f273e6e8b1 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 00:19:05 +0100 Subject: [PATCH 133/219] clarity --- specification/appendices/identifier_grammar.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index e686f0c6a..92db2fecc 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -48,13 +48,12 @@ numeric port specifier. The hostname may be a dotted-quad IPv4 address literal, an IPv6 address literal surrounded with square brackets, or a DNS name. IPv4 literals must be a sequence of four decimal numbers in the -range 0 to 255, separated by ".". IPv6 literals must be as specified by +range 0 to 255, separated by ``.``. IPv6 literals must be as specified by `RFC3513, section 2.2 `_. DNS names for use with Matrix should follow the conventional restrictions for internet hostnames: they should consist of a series of labels separated by -dots, where each label consists of the alphanumeric characters or -hyphens. +``.``, where each label consists of the alphanumeric characters or hyphens. Examples of valid server names are: From 1051aff108ba814b62feaf01e978da288dc90ee7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 18:36:07 -0600 Subject: [PATCH 134/219] Document the inhibit_login registration option Fixes https://github.com/matrix-org/matrix-doc/issues/1351 --- api/client-server/registration.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index e4b056291..72ec1fb67 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -117,6 +117,13 @@ paths: A display name to assign to the newly-created device. Ignored if ``device_id`` corresponds to a known device. example: Jungle Phone + inhibit_login: + type: boolean + description: |- + If true, an ``access_token`` and ``device_id`` should not be + returned from this call, therefore preventing an automatic + login. Defaults to false. + example: false responses: 200: description: The account has been registered. @@ -141,6 +148,7 @@ paths: description: |- An access token for the account. This access token can then be used to authorize other requests. + Required if the ``inhibit_login`` option is false. home_server: type: string description: |- @@ -155,6 +163,8 @@ paths: description: |- ID of the registered device. Will be the same as the corresponding parameter in the request, if one was specified. + Required if the ``inhibit_login`` option is false. + required: ['user_id'] 400: description: |- Part of the request was invalid. This may include one of the following error codes: From 5d0f77de3abc058a12386e6fef2ff24d105d68a8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 18:38:12 -0600 Subject: [PATCH 135/219] changelog --- changelogs/client_server/newsfragments/1589.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1589.feature diff --git a/changelogs/client_server/newsfragments/1589.feature b/changelogs/client_server/newsfragments/1589.feature new file mode 100644 index 000000000..8c8b1a862 --- /dev/null +++ b/changelogs/client_server/newsfragments/1589.feature @@ -0,0 +1 @@ +Add an ``inhibit_login`` registration option. From d91395cf9fe0c368436fd810a11959412b2aa979 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 19:33:45 -0600 Subject: [PATCH 136/219] Document 403 error for sending state events Fixes https://github.com/matrix-org/matrix-doc/issues/1399 --- api/client-server/room_state.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/api/client-server/room_state.yaml b/api/client-server/room_state.yaml index c04fb8039..bda66eb81 100644 --- a/api/client-server/room_state.yaml +++ b/api/client-server/room_state.yaml @@ -87,6 +87,16 @@ paths: type: string description: |- A unique identifier for the event. + 403: + description: |- + The sender doesn't have permission to send the event into the room. + schema: + $ref: "definitions/errors/error.yaml" + examples: + application/json: { + "errcode": "M_FORBIDDEN", + "error": "You do not have permission to send the event." + } tags: - Room participation "/rooms/{roomId}/state/{eventType}": @@ -142,5 +152,15 @@ paths: type: string description: |- A unique identifier for the event. + 403: + description: |- + The sender doesn't have permission to send the event into the room. + schema: + $ref: "definitions/errors/error.yaml" + examples: + application/json: { + "errcode": "M_FORBIDDEN", + "error": "You do not have permission to send the event." + } tags: - Room participation From d1add1f58c983c5ece0994c7d7c3ef80d0841d0a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 28 Aug 2018 19:34:58 -0600 Subject: [PATCH 137/219] Changelog --- changelogs/client_server/newsfragments/1590.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1590.clarification diff --git a/changelogs/client_server/newsfragments/1590.clarification b/changelogs/client_server/newsfragments/1590.clarification new file mode 100644 index 000000000..27999193b --- /dev/null +++ b/changelogs/client_server/newsfragments/1590.clarification @@ -0,0 +1 @@ +Document the 403 error for sending state events. From 120bb8dc8eb3261f71dfc0b27e4b42c76003f808 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 09:24:24 +0100 Subject: [PATCH 138/219] s/host/hostname/ --- specification/appendices/identifier_grammar.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index 92db2fecc..1a46ae1ab 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -26,11 +26,11 @@ The server name represents the address at which the homeserver in question can be reached by other homeservers. All valid server names are included by the following grammar:: - server_name = host [ ":" port ] + server_name = hostname [ ":" port ] port = *DIGIT - host = IPv4address / "[" IPv6address "]" / dns-name + hostname = IPv4address / "[" IPv6address "]" / dns-name IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT From 08fba5de51b09e3abecf6247218146fa917f9576 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 09:25:38 +0100 Subject: [PATCH 139/219] Link to grammar rather than duplicating. --- specification/server_server_api.rst | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 439b35f90..910dab1d2 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -78,14 +78,7 @@ Resolving Server Names ~~~~~~~~~~~~~~~~~~~~~~ Each matrix homeserver is identified by a server name consisting of a hostname -and an optional TLS port. - -.. code:: - - server_name = hostname [ ":" tls_port] - tls_port = *DIGIT - -.. ** +and an optional port, as described by the `grammar <../appendices.html#server-name>`_. If the port is present then the server is discovered by looking up an AAAA or A record for the hostname and connecting to the specified TLS port. If the port From f15eafae7fbc2f38bc8142c7067fbbda4e654b4a Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 09:26:31 +0100 Subject: [PATCH 140/219] Remove trailing spaces --- specification/server_server_api.rst | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 439b35f90..b4da56322 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -26,9 +26,9 @@ to communicate with each other. Homeservers use these APIs to push messages to each other in real-time, to retrieve historic messages from each other, and to query profile and presence information about users on each other's servers. -The APIs are implemented using HTTPS requests between each of the servers. -These HTTPS requests are strongly authenticated using public key signatures -at the TLS transport layer and using public key signatures in HTTP +The APIs are implemented using HTTPS requests between each of the servers. +These HTTPS requests are strongly authenticated using public key signatures +at the TLS transport layer and using public key signatures in HTTP Authorization headers at the HTTP layer. There are three main kinds of communication that occur between homeservers: @@ -121,7 +121,7 @@ Retrieving Server Keys Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``. Homeservers query for keys by either getting ``/_matrix/key/v2/server/{keyId}`` directly or by querying an intermediate notary server using a -``/_matrix/key/v2/query/{serverName}/{keyId}`` API. Intermediate notary servers +``/_matrix/key/v2/query/{serverName}/{keyId}`` API. Intermediate notary servers query the ``/_matrix/key/v2/server/{keyId}`` API on behalf of another server and sign the response with their own key. A server may query multiple notary servers to ensure that they all report the same public keys. @@ -590,9 +590,9 @@ To cover this case, the federation API provides a server-to-server analog of the ``/messages`` client API, allowing one homeserver to fetch history from another. This is the ``/backfill`` API. -To request more history, the requesting homeserver picks another homeserver -that it thinks may have more (most likely this should be a homeserver for -some of the existing users in the room at the earliest point in history it +To request more history, the requesting homeserver picks another homeserver +that it thinks may have more (most likely this should be a homeserver for +some of the existing users in the room at the earliest point in history it has currently), and makes a ``/backfill`` request. Similar to backfilling a room's history, a server may not have all the events @@ -669,10 +669,10 @@ homeservers, though most in practice will use just two. The first part of the handshake usually involves using the directory server to request the room ID and join candidates through the |/query/directory|_ API endpoint. In the case of a new user joining a room as a result of a received -invite, the joining user's homeserver could optimise this step away by picking -the origin server of that invite message as the join candidate. However, the +invite, the joining user's homeserver could optimise this step away by picking +the origin server of that invite message as the join candidate. However, the joining server should be aware that the origin server of the invite might since -have left the room, so should be prepared to fall back on the regular join flow +have left the room, so should be prepared to fall back on the regular join flow if this optimisation fails. Once the joining server has the room ID and the join candidates, it then needs @@ -692,7 +692,7 @@ event to a resident homeserver, by using the ``PUT /send_join`` endpoint. The resident homeserver then accepts this event into the room's event graph, and responds to the joining server with the full set of state for the newly-joined room. The resident server must also send the event to other servers -participating in the room. +participating in the room. {{joins_ss_http_api}} @@ -716,8 +716,8 @@ Leaving Rooms (Rejecting Invites) Normally homeservers can send appropriate ``m.room.member`` events to have users leave the room, or to reject local invites. Remote invites from other homeservers -do not involve the server in the graph and therefore need another approach to -reject the invite. Joining the room and promptly leaving is not recommended as +do not involve the server in the graph and therefore need another approach to +reject the invite. Joining the room and promptly leaving is not recommended as clients and servers will interpret that as accepting the invite, then leaving the room rather than rejecting the invite. @@ -829,7 +829,7 @@ EDUs. There are no PDUs or Federation Queries involved. Servers should only send presence updates for users that the receiving server would be interested in. This can include the receiving server sharing a room -with a given user, or a user on the receiving server has added one of the +with a given user, or a user on the receiving server has added one of the sending server's users to their presence list. Clients may define lists of users that they are interested in via "Presence @@ -848,7 +848,7 @@ or ``m.presence_deny`` EDU back. {{definition_ss_event_schemas_m_presence_invite}} -{{definition_ss_event_schemas_m_presence_accept}} +{{definition_ss_event_schemas_m_presence_accept}} {{definition_ss_event_schemas_m_presence_deny}} @@ -881,11 +881,11 @@ that can be made. OpenID ------ -Third party services can exchange an access token previously generated by the +Third party services can exchange an access token previously generated by the `Client-Server API` for information about a user. This can help verify that a user is who they say they are without granting full access to the user's account. -Access tokens generated by the OpenID API are only good for the OpenID API and +Access tokens generated by the OpenID API are only good for the OpenID API and nothing else. {{openid_ss_http_api}} From 78d81188468ba80e2a6d75566a70472d35a81089 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 09:36:50 +0100 Subject: [PATCH 141/219] Further server_name clarification --- specification/server_server_api.rst | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 910dab1d2..d9edfcb38 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -80,18 +80,22 @@ Resolving Server Names Each matrix homeserver is identified by a server name consisting of a hostname and an optional port, as described by the `grammar <../appendices.html#server-name>`_. -If the port is present then the server is discovered by looking up an AAAA or -A record for the hostname and connecting to the specified TLS port. If the port -is absent then the server is discovered by looking up a ``_matrix._tcp`` SRV -record for the hostname. If this record does not exist then the server is -discovered by looking up an AAAA or A record on the hostname and taking the -default fallback port number of 8448. +If the hostname is an IP literal, then that IP address should be used, together +with the given port number, or 8448 if no port is given. + +Otherwise, if the port is present, then an IP address is discovered by looking +up an AAAA or A record for the hostname, and the specified port is used. + +If the hostname is not an IP literal and no port is given, the server is +discovered by first looking up a ``_matrix._tcp`` SRV record for the hostname, +which may give a hostname (to be looked up using AAAA or A queries) and port. +If the SRV record does not exist, then the server is discovered by looking up +an AAAA or A record on the hostname and taking the default fallback port number +of 8448. + Homeservers may use SRV records to load balance requests between multiple TLS endpoints or to failover to another endpoint if an endpoint fails. -If the DNS name is a literal IP address, the port specified or the fallback -port should be used. - When making requests to servers, use the DNS name of the target server in the ``Host`` header, regardless of the host given in the SRV record. For example, if making a request to ``example.org``, and the SRV record resolves to ``matrix. From d493c82e82c49c8f252cb06554a51f7ef136be11 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 10:04:02 +0100 Subject: [PATCH 142/219] even more clarification --- specification/server_server_api.rst | 54 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index d9edfcb38..8cce792ba 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -71,36 +71,40 @@ This version of the specification is generated from `matrix-doc `_ as of Git commit `{{git_version}} `_. -Server Discovery +Server discovery ---------------- -Resolving Server Names +Resolving server names ~~~~~~~~~~~~~~~~~~~~~~ Each matrix homeserver is identified by a server name consisting of a hostname -and an optional port, as described by the `grammar <../appendices.html#server-name>`_. - -If the hostname is an IP literal, then that IP address should be used, together -with the given port number, or 8448 if no port is given. - -Otherwise, if the port is present, then an IP address is discovered by looking -up an AAAA or A record for the hostname, and the specified port is used. - -If the hostname is not an IP literal and no port is given, the server is -discovered by first looking up a ``_matrix._tcp`` SRV record for the hostname, -which may give a hostname (to be looked up using AAAA or A queries) and port. -If the SRV record does not exist, then the server is discovered by looking up -an AAAA or A record on the hostname and taking the default fallback port number -of 8448. - -Homeservers may use SRV records to load balance requests between multiple TLS -endpoints or to failover to another endpoint if an endpoint fails. - -When making requests to servers, use the DNS name of the target server in the -``Host`` header, regardless of the host given in the SRV record. For example, -if making a request to ``example.org``, and the SRV record resolves to ``matrix. -example.org``, the ``Host`` header in the request should be ``example.org``. The -port number for target server should not appear in the ``Host`` header. +and an optional port, as described by the `grammar +<../appendices.html#server-name>`_. Server names should be resolved to an IP +address and port using the following process: + +* If the hostname is an IP literal, then that IP address should be used, + together with the given port number, or 8448 if no port is given. + +* Otherwise, if the port is present, then an IP address is discovered by + looking up an AAAA or A record for the hostname, and the specified port is + used. + +* If the hostname is not an IP literal and no port is given, the server is + discovered by first looking up a ``_matrix._tcp`` SRV record for the + hostname, which may give a hostname (to be looked up using AAAA or A queries) + and port. If the SRV record does not exist, then the server is discovered by + looking up an AAAA or A record on the hostname and taking the default + fallback port number of 8448. + + Homeservers may use SRV records to load balance requests between multiple TLS + endpoints or to failover to another endpoint if an endpoint fails. + +When making requests to servers, use the hostname of the target server in the +``Host`` header, regardless of the any hostname given in the SRV record. For +example, if the server name is ``example.org``, and the SRV record resolves to +``matrix.example.org``, the ``Host`` header in the request should be +``example.org``. The port number for target server should **not** appear in the +``Host`` header. Server implementation ~~~~~~~~~~~~~~~~~~~~~~ From 0b7b3bfcb0c2da63ef0eff799e83bbaf00ce40f0 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 29 Aug 2018 11:20:33 +0100 Subject: [PATCH 143/219] Reindent auth rules section RST expects sub lists to be indented by three or more spaces. By doing so we can then rely on `#.` for automatic numbering. --- specification/server_server_api.rst | 112 ++++++++++++++-------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 9440f2f20..c67bea3de 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -359,100 +359,100 @@ The rules are as follows: 1. If type is ``m.room.create``, allow if and only if it has no previous events - *i.e.* it is the first event in the room. -2. If type is ``m.room.member``: +#. If type is ``m.room.member``: - a. If ``membership`` is ``join``: + a. If ``membership`` is ``join``: - i. If the only previous event is an ``m.room.create`` - and the ``state_key`` is the creator, allow. + i. If the only previous event is an ``m.room.create`` + and the ``state_key`` is the creator, allow. - #. If the ``sender`` does not match ``state_key``, reject. + #. If the ``sender`` does not match ``state_key``, reject. - #. If the user's current membership state is ``invite`` or ``join``, - allow. + #. If the user's current membership state is ``invite`` or ``join``, + allow. - #. If the ``join_rule`` is ``public``, allow. + #. If the ``join_rule`` is ``public``, allow. - #. Otherwise, reject. + #. Otherwise, reject. - b. If ``membership`` is ``invite``: + #. If ``membership`` is ``invite``: - i. If the ``sender``'s current membership state is not ``join``, reject. + i. If the ``sender``'s current membership state is not ``join``, reject. - #. If *target user*'s current membership state is ``join`` or ``ban``, - reject. + #. If *target user*'s current membership state is ``join`` or ``ban``, + reject. - #. If the ``sender``'s power level is greater than or equal to the *invite - level*, allow. + #. If the ``sender``'s power level is greater than or equal to the *invite + level*, allow. - #. Otherwise, reject. + #. Otherwise, reject. - c. If ``membership`` is ``leave``: + #. If ``membership`` is ``leave``: - i. If the ``sender`` matches ``state_key``, allow if and only if that user's - current membership state is ``invite`` or ``join``. + i. If the ``sender`` matches ``state_key``, allow if and only if that user's + current membership state is ``invite`` or ``join``. - #. If the ``sender``'s current membership state is not ``join``, reject. + #. If the ``sender``'s current membership state is not ``join``, reject. - #. If the *target user*'s current membership state is ``ban``, and the - ``sender``'s power level is less than the *ban level*, reject. + #. If the *target user*'s current membership state is ``ban``, and the + ``sender``'s power level is less than the *ban level*, reject. - #. If the ``sender``'s power level is greater than or equal to the *kick - level*, and the *target user*'s power level is less than the - ``sender``'s power level, allow. + #. If the ``sender``'s power level is greater than or equal to the *kick + level*, and the *target user*'s power level is less than the + ``sender``'s power level, allow. - #. Otherwise, reject. + #. Otherwise, reject. - d. If ``membership`` is ``ban``: + #. If ``membership`` is ``ban``: - i. If the ``sender``'s current membership state is not ``join``, reject. + i. If the ``sender``'s current membership state is not ``join``, reject. - #. If the ``sender``'s power level is greater than or equal to the *ban - level*, and the *target user*'s power level is less than the - ``sender``'s power level, allow. + #. If the ``sender``'s power level is greater than or equal to the *ban + level*, and the *target user*'s power level is less than the + ``sender``'s power level, allow. - #. Otherwise, reject. + #. Otherwise, reject. - e. Otherwise, the membership is unknown. Reject. + #. Otherwise, the membership is unknown. Reject. -3. If the ``sender``'s current membership state is not ``join``, reject. +#. If the ``sender``'s current membership state is not ``join``, reject. -4. If the event type's *required power level* is greater than the ``sender``'s power +#. If the event type's *required power level* is greater than the ``sender``'s power level, reject. -5. If type is ``m.room.power_levels``: +#. If type is ``m.room.power_levels``: - a. If there is no previous ``m.room.power_levels`` event in the room, allow. + a. If there is no previous ``m.room.power_levels`` event in the room, allow. - b. For each of the keys ``users_default``, ``events_default``, - ``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as - each entry being changed under the ``events`` or ``users`` keys: + #. For each of the keys ``users_default``, ``events_default``, + ``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as + each entry being changed under the ``events`` or ``users`` keys: - i. If the current value is higher than the ``sender``'s current power level, - reject. + i. If the current value is higher than the ``sender``'s current power level, + reject. - #. If the new value is higher than the ``sender``'s current power level, - reject. + #. If the new value is higher than the ``sender``'s current power level, + reject. - c. For each entry being changed under the ``users`` key, other than the - ``sender``'s own entry: + #. For each entry being changed under the ``users`` key, other than the + ``sender``'s own entry: - i. If the current value is equal to the ``sender``'s current power level, - reject. + i. If the current value is equal to the ``sender``'s current power level, + reject. - d. Otherwise, allow. + #. Otherwise, allow. -6. If type is ``m.room.redaction``: +#. If type is ``m.room.redaction``: - a. If the ``sender``'s power level is greater than or equal to the *redact - level*, allow. + a. If the ``sender``'s power level is greater than or equal to the *redact + level*, allow. - #. If the ``sender`` of the event being redacted is the same as the - ``sender`` of the ``m.room.redaction``, allow. + #. If the ``sender`` of the event being redacted is the same as the + ``sender`` of the ``m.room.redaction``, allow. - #. Otherwise, reject. + #. Otherwise, reject. -7. Otherwise, allow. +#. Otherwise, allow. .. NOTE:: From 86b5486445cbe5fc8d7092b2aba30486850da9a8 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 29 Aug 2018 11:32:14 +0100 Subject: [PATCH 144/219] Add missing clauses to and fix authorization rules They are still missing third party invites. --- specification/server_server_api.rst | 39 +++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index c67bea3de..e6e4625c4 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -356,20 +356,36 @@ the state of the room. The rules are as follows: -1. If type is ``m.room.create``, allow if and only if it has no - previous events - *i.e.* it is the first event in the room. +1. If type is ``m.room.create``: + + a. Reject if it has any previous events + b. Reject if the domain of the ``room_id`` does not match the domain of the + ``sender``. + c. Reject if ``content.room_version`` key is an unrecognized version + d. Otherwise, allow. + +#. Reject if event does not have a ``m.room.create`` in its ``auth_events`` + +#. If type is ``m.room.aliases``: + + a. Reject if event has no ``state_key`` + b. Allow if and only if sender's domain matches ``state_key`` #. If type is ``m.room.member``: - a. If ``membership`` is ``join``: + a. Reject if no ``state_key`` key or ``membership`` key in ``content``. + + #. If ``membership`` is ``join``: i. If the only previous event is an ``m.room.create`` and the ``state_key`` is the creator, allow. #. If the ``sender`` does not match ``state_key``, reject. - #. If the user's current membership state is ``invite`` or ``join``, - allow. + #. If the ``sender`` is banned, reject. + + #. If the ``join_rule`` is ``invite`` then allow if membership state + is ``invite`` or ``join``. #. If the ``join_rule`` is ``public``, allow. @@ -420,9 +436,16 @@ The rules are as follows: #. If the event type's *required power level* is greater than the ``sender``'s power level, reject. +#. If the event has a ``state_key`` that starts with an ``@`` and does not match + the ``sender``, reject. + #. If type is ``m.room.power_levels``: - a. If there is no previous ``m.room.power_levels`` event in the room, allow. + a. If ``users`` key in ``content`` is not a dictionary with keys that are + valid user IDs with values that are integers (or a string that is an + integer), reject. + + #. If there is no previous ``m.room.power_levels`` event in the room, allow. #. For each of the keys ``users_default``, ``events_default``, ``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as @@ -447,8 +470,8 @@ The rules are as follows: a. If the ``sender``'s power level is greater than or equal to the *redact level*, allow. - #. If the ``sender`` of the event being redacted is the same as the - ``sender`` of the ``m.room.redaction``, allow. + #. If the domain of the ``event_id`` of the event being redacted is the same + as the domain of the ``event_id`` of the ``m.room.redaction``, allow. #. Otherwise, reject. From 5d40af7ecff9f862fddb79ec2243e1b4167f1795 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 29 Aug 2018 13:24:02 +0100 Subject: [PATCH 145/219] Update rules on which events to add to `auth_events` --- specification/server_server_api.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 9440f2f20..a2a2274d0 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -299,8 +299,15 @@ following subset of the room state: - The ``m.room.create`` event. - The current ``m.room.power_levels`` event, if any. -- The current ``m.room.join_rules`` event, if any. - The sender's current ``m.room.member`` event, if any. +- If type is ``m.room.member``: + + - The target's current ``m.room.member`` event, if any. + - If ``join`` or ``invite`` then the current ``m.room.join_rules`` event, + if any. + - If ``invite`` with ``third_party_invite`` in ``content``, then add + ``m.room.third_party_invite`` with state_key of ``token`` in ``signed`` + field of ``third_party_invite``, if any. {{definition_ss_pdu}} From 073ebb051b84ead1be988c5dec03fb11ceddc356 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 29 Aug 2018 13:08:07 +0100 Subject: [PATCH 146/219] Spec third party invites in auth rules --- specification/server_server_api.rst | 37 +++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index e6e4625c4..f2d14738b 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -342,6 +342,7 @@ be inserted. The types of state events that affect authorization are: - ``m.room.member`` - ``m.room.join_rules`` - ``m.room.power_levels`` +- ``m.room.third_party_invite`` Servers should not create new events that reference unauthorized events. However, any event that does reference an unauthorized event is not itself @@ -393,7 +394,33 @@ The rules are as follows: #. If ``membership`` is ``invite``: - i. If the ``sender``'s current membership state is not ``join``, reject. + i. If ``content`` has ``third_party_invite`` key: + + #. Reject if *target user* is banned. + + #. Reject if ``content.third_party_invite`` does not have a + ``signed`` key. + + #. Reject if ``signed`` does not have ``mxid`` and ``token`` keys. + + #. Reject if ``mxid`` does not match ``state_key`` + + #. Reject if no ``m.room.third_party_invite`` event in + current state with ``state_key`` matching ``token``. + + #. Reject if ``sender`` does not match ``sender`` of third party + invite. + + #. If any signature in ``signed`` matches any public key in third + party invite, allow. The public keys are in ``content`` of + third party invite under: + + #. A single public key in ``public_key`` field + #. A list of public keys in ``public_keys`` field + + #. Otherwise, reject. + + #. If the ``sender``'s current membership state is not ``join``, reject. #. If *target user*'s current membership state is ``join`` or ``ban``, reject. @@ -433,6 +460,11 @@ The rules are as follows: #. If the ``sender``'s current membership state is not ``join``, reject. +#. If type is ``m.room.third_party_invite``: + + a. Allow if and only if ``sender``'s current power level is greater than + or equal to the *invite level*. + #. If the event type's *required power level* is greater than the ``sender``'s power level, reject. @@ -489,9 +521,6 @@ The rules are as follows: the kick *and* ban levels, *and* greater than the target user's power level. -.. TODO-spec - - I think there is some magic about 3pid invites too. Retrieving event authorization information ++++++++++++++++++++++++++++++++++++++++++ From d921b81c703d8845dc6ea5894880d47564e90a21 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 29 Aug 2018 14:17:52 +0100 Subject: [PATCH 147/219] Reject events with superfluous auth_events entries --- specification/server_server_api.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index f2d14738b..fb221357e 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -365,6 +365,12 @@ The rules are as follows: c. Reject if ``content.room_version`` key is an unrecognized version d. Otherwise, allow. +#. Reject if event has ``auth_events`` that: + + a. have duplicate entries for a given ``type`` and ``state_key`` pair + #. have entries whose ``type`` and ``state_key`` don't match those + specified by the algorithm described previously. + #. Reject if event does not have a ``m.room.create`` in its ``auth_events`` #. If type is ``m.room.aliases``: From 688c8ebcd348736d97cad2970e2e0b7533a3e103 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 29 Aug 2018 10:17:20 -0400 Subject: [PATCH 148/219] specify how to handle multiple olm sessions with the same device --- specification/modules/end_to_end_encryption.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/specification/modules/end_to_end_encryption.rst b/specification/modules/end_to_end_encryption.rst index fa461cc28..6f1925968 100644 --- a/specification/modules/end_to_end_encryption.rst +++ b/specification/modules/end_to_end_encryption.rst @@ -391,6 +391,12 @@ 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 a message. A client may expire old +sessions by defining a 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. + ``m.megolm.v1.aes-sha2`` ~~~~~~~~~~~~~~~~~~~~~~~~ From 9d0fec3645fb83647b15eeb9a0819696674b259f Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 29 Aug 2018 10:25:24 -0400 Subject: [PATCH 149/219] add changelog --- changelogs/client_server/newsfragments/1596.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1596.clarification diff --git a/changelogs/client_server/newsfragments/1596.clarification b/changelogs/client_server/newsfragments/1596.clarification new file mode 100644 index 000000000..3dde069f9 --- /dev/null +++ b/changelogs/client_server/newsfragments/1596.clarification @@ -0,0 +1 @@ +specify how to handle multiple olm sessions with the same device \ No newline at end of file From de36d978397d9056c9e50e46a16998fbc308b627 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 08:53:20 -0600 Subject: [PATCH 150/219] Clarify which event is actually be excluded from /state_ids --- api/server-server/events.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/server-server/events.yaml b/api/server-server/events.yaml index f0b301781..5a5ce7174 100644 --- a/api/server-server/events.yaml +++ b/api/server-server/events.yaml @@ -49,8 +49,8 @@ paths: responses: 200: description: |- - The fully resolved state for the room, including the authorization - chain for the events, excluding the requested event. + The fully resolved state for the room (excluding the requested event), + including the authorization chain for the events. schema: type: object properties: @@ -96,8 +96,8 @@ paths: responses: 200: description: |- - The fully resolved state for the room, including the authorization - chain for the events, excluding the requested event. + The fully resolved state for the room (excluding the requested event), + including the authorization chain for the events. schema: type: object properties: From 5ff244f06b106a72fe209a26e7059922f096bdb1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 09:00:46 -0600 Subject: [PATCH 151/219] More clarification about how /state_ids works --- api/server-server/events.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api/server-server/events.yaml b/api/server-server/events.yaml index 5a5ce7174..c23163d78 100644 --- a/api/server-server/events.yaml +++ b/api/server-server/events.yaml @@ -49,8 +49,9 @@ paths: responses: 200: description: |- - The fully resolved state for the room (excluding the requested event), - including the authorization chain for the events. + The fully resolved state for the room, prior to considering any state + changes induced by the requested event. Includes the authorization + chain for the events. schema: type: object properties: @@ -96,8 +97,9 @@ paths: responses: 200: description: |- - The fully resolved state for the room (excluding the requested event), - including the authorization chain for the events. + The fully resolved state for the room, prior to considering any state + changes induced by the requested event. Includes the authorization + chain for the events. schema: type: object properties: From 62b1b8b66097f3d8be2f9cc465335f28641d15fb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 09:32:14 -0600 Subject: [PATCH 152/219] Have unsigned.age appear on all room events This is useful for a lot of things, like bridges (appservices), VoIP handling, and clients which generally may wish to do something with the field. Might as well include it on every event, despite the recommendation of https://github.com/matrix-org/matrix-doc/issues/1524 --- event-schemas/examples/core/room_event.json | 5 ++++- event-schemas/examples/m.call.answer | 3 --- event-schemas/examples/m.call.candidates | 3 --- event-schemas/examples/m.call.hangup | 3 --- event-schemas/examples/m.call.invite | 3 --- 5 files changed, 4 insertions(+), 13 deletions(-) diff --git a/event-schemas/examples/core/room_event.json b/event-schemas/examples/core/room_event.json index fe9ff7ee6..41837afb5 100644 --- a/event-schemas/examples/core/room_event.json +++ b/event-schemas/examples/core/room_event.json @@ -3,5 +3,8 @@ "event_id": "$143273582443PhrSn:domain.com", "room_id": "!jEsUZKDJdhlrceRyVU:domain.com", "sender": "@example:domain.com", - "origin_server_ts": 1432735824653 + "origin_server_ts": 1432735824653, + "unsigned": { + "age": 1234 + } } diff --git a/event-schemas/examples/m.call.answer b/event-schemas/examples/m.call.answer index a7b9e883f..a4cfc1e16 100644 --- a/event-schemas/examples/m.call.answer +++ b/event-schemas/examples/m.call.answer @@ -9,8 +9,5 @@ "type" : "answer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } - }, - "unsigned": { - "age": 1234 } } diff --git a/event-schemas/examples/m.call.candidates b/event-schemas/examples/m.call.candidates index 1a3fdedf0..8f1f807ad 100644 --- a/event-schemas/examples/m.call.candidates +++ b/event-schemas/examples/m.call.candidates @@ -11,8 +11,5 @@ "candidate": "candidate:863018703 1 udp 2122260223 10.9.64.156 43670 typ host generation 0" } ] - }, - "unsigned": { - "age": 1234 } } diff --git a/event-schemas/examples/m.call.hangup b/event-schemas/examples/m.call.hangup index cf2d68595..295f16e48 100644 --- a/event-schemas/examples/m.call.hangup +++ b/event-schemas/examples/m.call.hangup @@ -4,8 +4,5 @@ "content": { "version" : 0, "call_id": "12345" - }, - "unsigned": { - "age": 1234 } } diff --git a/event-schemas/examples/m.call.invite b/event-schemas/examples/m.call.invite index 069d334e9..fa482bd94 100644 --- a/event-schemas/examples/m.call.invite +++ b/event-schemas/examples/m.call.invite @@ -9,8 +9,5 @@ "type" : "offer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } - }, - "unsigned": { - "age": 1234 } } From 25b34e1d7bb06188f6ecb9bedef527082a06d4a6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 09:55:43 -0600 Subject: [PATCH 153/219] Mention that ts massaging was in a draft, but not in the release --- specification/application_service_api.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 0da00b87d..5b7abf4a5 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -311,6 +311,16 @@ An example request would be:: Content: The event to send, as per the Client-Server API. +Timestamp massaging ++++++++++++++++++++ + +Previous drafts of the Application Service API permitted application services +to alter the timestamp of their sent events by providing a ``ts`` query parameter +when sending an event. This API has been excluded from the first release due to +design concerns, however some servers may still support the feature. Please visit +`issue #1585 `_ for more +information. + Server admin style permissions ++++++++++++++++++++++++++++++ From 90fe395aeb51390c16422df1474b9c206b0a7f99 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 10:26:02 -0600 Subject: [PATCH 154/219] Take out the @ state_key restriction from the auth rules This is being handled in https://github.com/matrix-org/matrix-doc/pull/1591 --- specification/server_server_api.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index a66f249c6..439b35f90 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -450,10 +450,7 @@ The rules are as follows: #. Otherwise, reject. -7. If the ``state_key`` starts with ``@`` and the ``state_key`` does not match - the ``sender``, reject. - -8. Otherwise, allow. +7. Otherwise, allow. .. NOTE:: From ec20c43220d0683d7f25514cbe0e8a2ddd4a43d8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 10:55:34 -0600 Subject: [PATCH 155/219] Specify the minimum CSP for media Fixes https://github.com/matrix-org/matrix-doc/issues/1066 --- specification/modules/content_repo.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/specification/modules/content_repo.rst b/specification/modules/content_repo.rst index 0f1a9944f..f6da38fff 100644 --- a/specification/modules/content_repo.rst +++ b/specification/modules/content_repo.rst @@ -33,6 +33,11 @@ recipient's local homeserver, which must first transfer the content from the origin homeserver using the same API (unless the origin and destination homeservers are the same). +When serving content, the server MUST provide a ``Content-Security-Policy`` +header. The policy may be more restrictive, however the minimum policy is +``default-src 'none'; script-src 'none'; plugin-types application/pdf; +style-src 'unsafe-inline'; object-src 'self';``. + Client behaviour ---------------- From 348b549f9f7694a39be0c6f83200332b179788e5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 11:19:37 -0600 Subject: [PATCH 156/219] Add the other fields the server is expected to keep on events Fixes https://github.com/matrix-org/matrix-doc/issues/839 Reference: https://github.com/matrix-org/synapse/blob/d69decd5c78c72abef50b597a689e2bc55a39702/synapse/events/utils.py#L44-L91 --- specification/client_server_api.rst | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index b377cbb8d..cbe7d24ab 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -1328,16 +1328,30 @@ the following list: - ``state_key`` - ``prev_content`` - ``content`` +- ``hashes`` +- ``signatures`` +- ``depth`` +- ``prev_events`` +- ``prev_state`` +- ``auth_events`` +- ``origin`` +- ``origin_server_ts`` +- ``membership`` + +.. Note: + Some of the keys, such as ``hashes``, will appear on the federation-formatted + event and therefore the client may not be aware of them. The content object should also be stripped of all keys, unless it is one of one of the following event types: -- ``m.room.member`` allows key ``membership`` -- ``m.room.create`` allows key ``creator`` -- ``m.room.join_rules`` allows key ``join_rule`` +- ``m.room.member`` allows key ``membership``. +- ``m.room.create`` allows key ``creator``. +- ``m.room.join_rules`` allows key ``join_rule``. - ``m.room.power_levels`` allows keys ``ban``, ``events``, ``events_default``, ``kick``, ``redact``, ``state_default``, ``users``, ``users_default``. -- ``m.room.aliases`` allows key ``aliases`` +- ``m.room.aliases`` allows key ``aliases``. +- ``m.room.history_visibility`` allows key ``history_visibility``. The server should add the event causing the redaction to the ``unsigned`` property of the redacted event, under the ``redacted_because`` key. When a From 86f616bb31041a6b49f6239adc9193c60cb4b46f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 11:20:51 -0600 Subject: [PATCH 157/219] Changelog --- changelogs/client_server/newsfragments/1602.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1602.clarification diff --git a/changelogs/client_server/newsfragments/1602.clarification b/changelogs/client_server/newsfragments/1602.clarification new file mode 100644 index 000000000..def503cb7 --- /dev/null +++ b/changelogs/client_server/newsfragments/1602.clarification @@ -0,0 +1 @@ +Add the other keys that redactions are expected to preserve. From 8e88d82a4b66f4b18aa32cd5b8700da786350aaf Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 29 Aug 2018 19:15:05 +0100 Subject: [PATCH 158/219] fix typo in anchor. fixes #1603 --- specification/modules/send_to_device.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/modules/send_to_device.rst b/specification/modules/send_to_device.rst index 232becae9..862885461 100644 --- a/specification/modules/send_to_device.rst +++ b/specification/modules/send_to_device.rst @@ -63,7 +63,7 @@ If the client sends messages to users on remote domains, those messages should be sent on to the remote servers via `federation`_. -.. _`federation`: ../server_server/latest.html#send-to-device-messages +.. _`federation`: ../server_server/latest.html#send-to-device-messaging .. TODO-spec: From 2234e0b0978283f6c26ac4b0da71519a72e1e085 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 12:38:15 -0600 Subject: [PATCH 159/219] Mention that clients should not be producing invalid HTML Fixes https://github.com/matrix-org/matrix-doc/issues/1595 --- specification/modules/instant_messaging.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index 079a4801d..f3deb2202 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -106,6 +106,11 @@ of tags they can render, falling back to other representations of the tags where For example, a client may not be able to render tables correctly and instead could fall back to rendering tab-delimited text. +In addition to not rendering unsafe HTML, clients should not emit unsafe HTML in events. +Likewise, clients should not generate HTML that is not needed, such as extra paragraph tags +surrounding text due to Rich Text Editors. HTML included in events should otherwise be valid, +such as having appropriate closing tags, valid attributes, and generally valid structure. + .. Note:: A future iteration of the specification will support more powerful and extensible message formatting options, such as the proposal `MSC1225 `_. From 60b97fcf26158f2ab05af4c98dc03d9df9dd6b30 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 12:39:25 -0600 Subject: [PATCH 160/219] Changelog --- changelogs/client_server/newsfragments/1605.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1605.clarification diff --git a/changelogs/client_server/newsfragments/1605.clarification b/changelogs/client_server/newsfragments/1605.clarification new file mode 100644 index 000000000..ce9f967d0 --- /dev/null +++ b/changelogs/client_server/newsfragments/1605.clarification @@ -0,0 +1 @@ +Clarify that clients should not be generating invalid HTML for formatted events. From c83da453b565a6f1c7c5a4a8c0e4459d5aa19795 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 14:18:41 -0600 Subject: [PATCH 161/219] s/number/integer --- event-schemas/schema/m.room.power_levels | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/event-schemas/schema/m.room.power_levels b/event-schemas/schema/m.room.power_levels index ae4e5589e..9bb12993a 100644 --- a/event-schemas/schema/m.room.power_levels +++ b/event-schemas/schema/m.room.power_levels @@ -88,10 +88,10 @@ properties: notifications: properties: room: - type: number + type: integer description: The level required to trigger an ``@room`` notification. Defaults to 50 if unspecified. additionalProperties: - type: number + type: integer description: |- The power level requirements for specific notification types. This is a mapping from ``key`` to power level for that notifications key. From 8950f0b2cc08d96f9d835804f78b59b08273b8c5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 14:36:43 -0600 Subject: [PATCH 162/219] Spelling --- specification/server_server_api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index cc23a83dc..9a68f33c2 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -804,7 +804,7 @@ identifier. Public Room Directory --------------------- -To compliment the `Client-Server API`_'s room directory, homeservers need a +To complement the `Client-Server API`_'s room directory, homeservers need a way to query the public rooms for another server. This can be done by making a request to the ``/publicRooms`` endpoint for the server the room directory should be retrieved for. @@ -906,7 +906,7 @@ intended to compliment the `Device Management module`_ of the Client-Server API. End-to-End Encryption --------------------- -This section compliments the `End-to-End Encryption module`_ of the Client-Server +This section complements the `End-to-End Encryption module`_ of the Client-Server API. For detailed information about end-to-end encryption, please see that module. The APIs defined here are designed to be able to proxy much of the client's request From f2d02c9559339f51b7ed0f75d2b408132df7f757 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 14:37:30 -0600 Subject: [PATCH 163/219] Take out device management section for now This will be handled by the implementation of https://github.com/matrix-org/matrix-doc/issues/1212 --- api/server-server/user_devices.yaml | 84 ----------------------------- specification/server_server_api.rst | 12 ----- 2 files changed, 96 deletions(-) delete mode 100644 api/server-server/user_devices.yaml diff --git a/api/server-server/user_devices.yaml b/api/server-server/user_devices.yaml deleted file mode 100644 index d16442706..000000000 --- a/api/server-server/user_devices.yaml +++ /dev/null @@ -1,84 +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. - -swagger: '2.0' -info: - title: "Matrix Federation User Device Management API" - version: "1.0.0" -host: localhost:8448 -schemes: - - https -basePath: /_matrix/federation/v1 -consumes: - - application/json -produces: - - application/json -securityDefinitions: - $ref: definitions/security.yaml -paths: - "/user/devices/{userId}": - get: - summary: Gets all of the user's devices - description: Gets information on all of the user's devices - operationId: getUserDevices - security: - - signedRequest: [] - parameters: - - in: path - name: userId - type: string - required: true - description: |- - The user ID to retrieve devices for. Must be a user local to the - receiving homeserver. - required: true - x-example: "@alice:example.org" - responses: - 200: - description: The user's devices. - schema: - type: object - properties: - user_id: - type: string - description: The user ID devices were requested for. - example: "@alice:example.org" - stream_id: - type: integer - description: |- - An ID the requesting homeserver may use to detect changes in the - device list. This should increase as time goes on, and always - produce the same ``devices`` list if not incremented. - example: 334608 - devices: - type: array - description: The user's devices. May be empty. - items: - type: object - title: User Device - properties: - device_id: - type: string - description: The device ID. - example: "JLAFKJWSCS" - keys: - type: object - description: Identity keys for the device. - $ref: "../client-server/definitions/device_keys.yaml" - device_display_name: - type: string - description: Optional display name for the device. - example: "Alice's Mobile Phone" - required: ['device_id', 'keys'] - required: ['user_id', 'stream_id', 'devices'] \ No newline at end of file diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 9a68f33c2..558a5f8d7 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -891,18 +891,6 @@ nothing else. {{openid_ss_http_api}} -Device Management ------------------ - -.. TODO: TravisR - Incorporate https://github.com/matrix-org/matrix-doc/issues/1212 - -A user's devices may need to be queried over federation for different purposes, such -as end-to-end encryption or for utilizing send-to-device messaging. This section is -intended to compliment the `Device Management module`_ of the Client-Server API. - -{{user_devices_ss_http_api}} - - End-to-End Encryption --------------------- From 9bc14703058adc3558d83f16fadcdf5f92cf8c3a Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 26 Aug 2018 20:25:05 +0900 Subject: [PATCH 164/219] Elaborate the structure of m.tag events ...and corresponding structures in tag-related CS API calls Signed-off-by: Alexey Rusakov --- api/client-server/tags.yaml | 27 +++++++++++++++++++++++---- event-schemas/schema/m.tag | 10 +++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/api/client-server/tags.yaml b/api/client-server/tags.yaml index b7bafab60..108095720 100644 --- a/api/client-server/tags.yaml +++ b/api/client-server/tags.yaml @@ -60,13 +60,23 @@ paths: type: object properties: tags: - title: Tags type: object + additionalProperties: + title: Tag + type: object + properties: + order: + type: number + format: float + description: |- + A number in a range ``[0,1]`` describing a relative + position of the room under the given tag. + additionalProperties: true examples: application/json: { "tags": { - "m.favourite": {}, - "u.Work": {"order": "1"}, + "m.favourite": {"order": 0.1}, + "u.Work": {"order": 0.7}, "u.Customers": {} } } @@ -110,8 +120,17 @@ paths: Extra data for the tag, e.g. ordering. schema: type: object + properties: + order: + type: number + format: float + description: |- + A number in a range ``[0,1]`` describing a relative + position of the room under the given tag. + additionalProperties: true example: { - "order": "1"} + "order": 0.25 + } responses: 200: description: diff --git a/event-schemas/schema/m.tag b/event-schemas/schema/m.tag index 80d3f9dd3..8da093bd5 100644 --- a/event-schemas/schema/m.tag +++ b/event-schemas/schema/m.tag @@ -18,7 +18,15 @@ "description": "The tags on the room and their contents.", "additionalProperties": { "title": "Tag", - "type": "object" + "type": "object", + "properties": { + "order": { + "type": "number", + "format": "float", + "description": + "A number in a range ``[0,1]`` describing a relative position of the room under the given tag." + } + } } } } From c03f2f8d79ac9f589249890382a204ad1158972b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 14:53:55 -0600 Subject: [PATCH 165/219] Minor touchups to the room tagging API Fixes some of https://github.com/matrix-org/matrix-doc/issues/1565 --- api/client-server/tags.yaml | 34 ++++++++++++++++------------------ event-schemas/examples/m.tag | 2 +- specification/modules/tags.rst | 2 +- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/api/client-server/tags.yaml b/api/client-server/tags.yaml index 108095720..081d8a848 100644 --- a/api/client-server/tags.yaml +++ b/api/client-server/tags.yaml @@ -43,14 +43,14 @@ paths: required: true description: |- The id of the user to get tags for. The access token must be - authorized to make requests for this user id. + authorized to make requests for this user ID. x-example: "@alice:example.com" - in: path type: string name: roomId required: true description: |- - The id of the room to get tags for. + The ID of the room to get tags for. x-example: "!726s6s6q:example.com" responses: 200: @@ -74,12 +74,12 @@ paths: additionalProperties: true examples: application/json: { - "tags": { - "m.favourite": {"order": 0.1}, - "u.Work": {"order": 0.7}, - "u.Customers": {} - } + "tags": { + "m.favourite": {"order": 0.1}, + "u.Work": {"order": 0.7}, + "u.Customers": {} } + } tags: - User data "/user/{userId}/rooms/{roomId}/tags/{tag}": @@ -97,14 +97,14 @@ paths: required: true description: |- The id of the user to add a tag for. The access token must be - authorized to make requests for this user id. + authorized to make requests for this user ID. x-example: "@alice:example.com" - in: path type: string name: roomId required: true description: |- - The id of the room to add a tag to. + The ID of the room to add a tag to. x-example: "!726s6s6q:example.com" - in: path type: string @@ -112,7 +112,7 @@ paths: required: true description: |- The tag to add. - x-example: "work" + x-example: "u.work" - in: body name: body required: true @@ -138,8 +138,7 @@ paths: schema: type: object examples: - application/json: { - } + application/json: {} tags: - User data delete: @@ -156,14 +155,14 @@ paths: required: true description: |- The id of the user to remove a tag for. The access token must be - authorized to make requests for this user id. + authorized to make requests for this user ID. x-example: "@alice:example.com" - in: path type: string name: roomId required: true description: |- - The id of the room to remove a tag from. + The ID of the room to remove a tag from. x-example: "!726s6s6q:example.com" - in: path type: string @@ -171,15 +170,14 @@ paths: required: true description: |- The tag to remove. - x-example: "work" + x-example: "u.work" responses: 200: description: - The tag was successfully removed + The tag was successfully removed. schema: type: object examples: - application/json: { - } + application/json: {} tags: - User data diff --git a/event-schemas/examples/m.tag b/event-schemas/examples/m.tag index 53dbc921a..e5564a4b4 100644 --- a/event-schemas/examples/m.tag +++ b/event-schemas/examples/m.tag @@ -2,7 +2,7 @@ "type": "m.tag", "content": { "tags": { - "u.work": {"order": 1} + "u.work": {"order": 0.9} } } } diff --git a/specification/modules/tags.rst b/specification/modules/tags.rst index f965c2e82..739ead2c7 100644 --- a/specification/modules/tags.rst +++ b/specification/modules/tags.rst @@ -39,7 +39,7 @@ with an ``order`` of ``0.2`` would be displayed before a room with an ``order`` of ``0.7``. If a room has a tag without an ``order`` key then it should appear after the rooms with that tag that have an ``order`` key. -The name of a tag MUST not exceed 255 bytes. +The name of a tag MUST NOT exceed 255 bytes. The tag namespace is defined as follows: From 30ff020ac75d480d3025748fc803546bb784c415 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 14:57:05 -0600 Subject: [PATCH 166/219] Changelog --- changelogs/client_server/newsfragments/1606.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1606.clarification diff --git a/changelogs/client_server/newsfragments/1606.clarification b/changelogs/client_server/newsfragments/1606.clarification new file mode 100644 index 000000000..f65ed257e --- /dev/null +++ b/changelogs/client_server/newsfragments/1606.clarification @@ -0,0 +1 @@ +Clarify the room tag structure (thanks @KitsuneRal!) From 196159be9116f2d82626296bd7eef44ee845f473 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 29 Aug 2018 22:15:38 +0100 Subject: [PATCH 167/219] We should include the Host header if the port was explicit. --- specification/server_server_api.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 8cce792ba..7239c12dc 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -100,11 +100,12 @@ address and port using the following process: endpoints or to failover to another endpoint if an endpoint fails. When making requests to servers, use the hostname of the target server in the -``Host`` header, regardless of the any hostname given in the SRV record. For +``Host`` header, regardless of any hostname given in the SRV record. For example, if the server name is ``example.org``, and the SRV record resolves to ``matrix.example.org``, the ``Host`` header in the request should be -``example.org``. The port number for target server should **not** appear in the -``Host`` header. +``example.org``. If an explicit port was given in the server name, it should be +included in the ``Host`` header; otherwise, no port number should be given in +the ``Host`` header. Server implementation ~~~~~~~~~~~~~~~~~~~~~~ From 684d80c4228f87b0268581f3f52660e8fbbbb165 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 17:52:02 -0600 Subject: [PATCH 168/219] Revert changes to 3pid lookup types in the IS spec The validator doesn't know what a "3PID Medium" is, for example, so it throws exceptions. This does reduce clarity in the spec though. --- api/identity/lookup.yaml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index 6f993ac7a..f04436ef3 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -121,8 +121,11 @@ paths: minItems: 2 maxItems: 2 items: - - type: 3PID Medium - - type: 3PID Address + # TODO: Give real names to these values. Adding a `title` does not work. + #- type: 3PID Medium + #- type: 3PID Address + - type: string + - type: string description: an array of arrays containing the `3PID Types`_ with the ``medium`` in first position and the ``address`` in second position. required: - "threepids" @@ -147,9 +150,13 @@ paths: minItems: 3 maxItems: 3 items: - - type: 3PID Medium - - type: 3PID Address - - type: Matrix User ID + # TODO: Give real names to these values. Adding a `title` does not work. + #- type: 3PID Medium + #- type: 3PID Address + #- type: Matrix User ID + - type: string + - type: string + - type: string description: an array of array containing the `3PID Types`_ with the ``medium`` in first position, the ``address`` in second position and Matrix ID in third position. required: - "threepids" From 2a20c11467db2e03851b456ec32bdf456273caab Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 17:47:09 -0600 Subject: [PATCH 169/219] Take out the reference to the current version from the changelog --- specification/push_gateway.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/specification/push_gateway.rst b/specification/push_gateway.rst index e46238875..74f9e35ed 100644 --- a/specification/push_gateway.rst +++ b/specification/push_gateway.rst @@ -41,7 +41,6 @@ Other versions of this specification The following other versions are also available, in reverse chronological order: - `HEAD `_: Includes all changes since the latest versioned release. -- `r0.1.0 `_ Overview -------- From a46783eb2460198bef94ad004b99c6bfb247a0ec Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 17:47:09 -0600 Subject: [PATCH 170/219] Revert "Take out the reference to the current version from the changelog" This reverts commit 2a20c11467db2e03851b456ec32bdf456273caab. --- specification/push_gateway.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/push_gateway.rst b/specification/push_gateway.rst index 74f9e35ed..e46238875 100644 --- a/specification/push_gateway.rst +++ b/specification/push_gateway.rst @@ -41,6 +41,7 @@ Other versions of this specification The following other versions are also available, in reverse chronological order: - `HEAD `_: Includes all changes since the latest versioned release. +- `r0.1.0 `_ Overview -------- From c7a228bf7ba1551e0df04e583a0d86644ad1b352 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 19:32:52 -0600 Subject: [PATCH 171/219] Don't make the major version a variable We are likely to want to maintain v1 when we release a v2, so we'll avoid a variable for now. --- api/identity/associations.yaml | 2 +- api/identity/email_associations.yaml | 2 +- api/identity/invitation_signing.yaml | 2 +- api/identity/lookup.yaml | 2 +- api/identity/phone_associations.yaml | 2 +- api/identity/ping.yaml | 2 +- api/identity/pubkey.yaml | 2 +- api/identity/store_invite.yaml | 4 ++-- api/server-server/backfill.yaml | 2 +- api/server-server/event_auth.yaml | 2 +- api/server-server/events.yaml | 2 +- api/server-server/invites.yaml | 2 +- api/server-server/joins.yaml | 2 +- api/server-server/keys_query.yaml | 2 +- api/server-server/keys_server.yaml | 2 +- api/server-server/leaving.yaml | 2 +- api/server-server/openid.yaml | 2 +- api/server-server/public_rooms.yaml | 2 +- api/server-server/query.yaml | 2 +- api/server-server/third_party_invite.yaml | 2 +- api/server-server/transactions.yaml | 2 +- api/server-server/version.yaml | 2 +- scripts/gendoc.py | 3 --- specification/identity_service_api.rst | 2 +- specification/server_server_api.rst | 10 +++++----- 25 files changed, 29 insertions(+), 32 deletions(-) diff --git a/api/identity/associations.yaml b/api/identity/associations.yaml index e99ec8714..4225919b1 100644 --- a/api/identity/associations.yaml +++ b/api/identity/associations.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/email_associations.yaml b/api/identity/email_associations.yaml index ef3e01eae..28f5e6809 100644 --- a/api/identity/email_associations.yaml +++ b/api/identity/email_associations.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/invitation_signing.yaml b/api/identity/invitation_signing.yaml index 3a48485b5..7de62dd41 100644 --- a/api/identity/invitation_signing.yaml +++ b/api/identity/invitation_signing.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index c17516449..f04436ef3 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -21,7 +21,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/phone_associations.yaml b/api/identity/phone_associations.yaml index e7991ceef..f6b1bd45b 100644 --- a/api/identity/phone_associations.yaml +++ b/api/identity/phone_associations.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/ping.yaml b/api/identity/ping.yaml index b630c7332..005160a35 100644 --- a/api/identity/ping.yaml +++ b/api/identity/ping.yaml @@ -23,7 +23,7 @@ basePath: /_matrix/identity produces: - application/json paths: - "/api/%IDENTITY_MAJOR_VERSION%": + "/api/v1": get: summary: Checks that an Identity server is available at this API endpopint. description: |- diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 071564d84..9cb7c74e9 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/store_invite.yaml b/api/identity/store_invite.yaml index e631d60d7..1eca7198e 100644 --- a/api/identity/store_invite.yaml +++ b/api/identity/store_invite.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/api/%IDENTITY_MAJOR_VERSION% +basePath: /_matrix/identity/api/v1 produces: - application/json paths: @@ -46,7 +46,7 @@ paths: ``address`` parameter, notifying them of the invitation. Also, the generated ephemeral public key will be listed as valid on - requests to ``/_matrix/identity/api/%IDENTITY_MAJOR_VERSION%/pubkey/ephemeral/isvalid``. + requests to ``/_matrix/identity/api/v1/pubkey/ephemeral/isvalid``. operationId: storeInvite parameters: - in: body diff --git a/api/server-server/backfill.yaml b/api/server-server/backfill.yaml index 5c88f554b..6b3cfaef0 100644 --- a/api/server-server/backfill.yaml +++ b/api/server-server/backfill.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/event_auth.yaml b/api/server-server/event_auth.yaml index 0248fb1e7..8857131fa 100644 --- a/api/server-server/event_auth.yaml +++ b/api/server-server/event_auth.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/events.yaml b/api/server-server/events.yaml index 0b3183730..cf3988a20 100644 --- a/api/server-server/events.yaml +++ b/api/server-server/events.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 produces: - application/json securityDefinitions: diff --git a/api/server-server/invites.yaml b/api/server-server/invites.yaml index d55ccb5b5..6d905e178 100644 --- a/api/server-server/invites.yaml +++ b/api/server-server/invites.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/joins.yaml b/api/server-server/joins.yaml index 66a071e58..4902ea9e1 100644 --- a/api/server-server/joins.yaml +++ b/api/server-server/joins.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/keys_query.yaml b/api/server-server/keys_query.yaml index face2bd63..e616915bd 100644 --- a/api/server-server/keys_query.yaml +++ b/api/server-server/keys_query.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/key/%KEYS_MAJOR_VERSION% +basePath: /_matrix/key/v2 consumes: - application/json produces: diff --git a/api/server-server/keys_server.yaml b/api/server-server/keys_server.yaml index d09ba8e27..8734f2edd 100644 --- a/api/server-server/keys_server.yaml +++ b/api/server-server/keys_server.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/key/%KEYS_MAJOR_VERSION% +basePath: /_matrix/key/v2 produces: - application/json paths: diff --git a/api/server-server/leaving.yaml b/api/server-server/leaving.yaml index 739f4962c..be08acba6 100644 --- a/api/server-server/leaving.yaml +++ b/api/server-server/leaving.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/openid.yaml b/api/server-server/openid.yaml index 942a5d5e6..0eac48c84 100644 --- a/api/server-server/openid.yaml +++ b/api/server-server/openid.yaml @@ -20,7 +20,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 produces: - application/json paths: diff --git a/api/server-server/public_rooms.yaml b/api/server-server/public_rooms.yaml index 98736977b..b76910236 100644 --- a/api/server-server/public_rooms.yaml +++ b/api/server-server/public_rooms.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 produces: - application/json securityDefinitions: diff --git a/api/server-server/query.yaml b/api/server-server/query.yaml index af70a9c36..dc14724c5 100644 --- a/api/server-server/query.yaml +++ b/api/server-server/query.yaml @@ -20,7 +20,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 produces: - application/json securityDefinitions: diff --git a/api/server-server/third_party_invite.yaml b/api/server-server/third_party_invite.yaml index 9e3bba2c2..5c12247cf 100644 --- a/api/server-server/third_party_invite.yaml +++ b/api/server-server/third_party_invite.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/transactions.yaml b/api/server-server/transactions.yaml index edfecac13..ad10ec0b9 100644 --- a/api/server-server/transactions.yaml +++ b/api/server-server/transactions.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 consumes: - application/json produces: diff --git a/api/server-server/version.yaml b/api/server-server/version.yaml index 17110f19e..199755290 100644 --- a/api/server-server/version.yaml +++ b/api/server-server/version.yaml @@ -19,7 +19,7 @@ info: host: localhost:8448 schemes: - https -basePath: /_matrix/federation/%SERVER_MAJOR_VERSION% +basePath: /_matrix/federation/v1 produces: - application/json paths: diff --git a/scripts/gendoc.py b/scripts/gendoc.py index b7fe8155d..8f5b51542 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -548,9 +548,6 @@ if __name__ == '__main__': # API URLs. When we have released a new major version, we'll # have to bump them. "%CLIENT_MAJOR_VERSION%": "r0", - "%SERVER_MAJOR_VERSION%": "v1", - "%IDENTITY_MAJOR_VERSION%": "v1", - "%KEYS_MAJOR_VERSION%": "v2", "%SERVER_RELEASE_LABEL%": args.server_release, "%IDENTITY_RELEASE_LABEL%": args.identity_release, "%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release, diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index 3aa50c815..3f2eb21d5 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -221,7 +221,7 @@ associated with a Matrix user ID. At a later point, if the owner of that particular 3pid binds it with a Matrix user ID, the identity server will attempt to make an HTTP POST to the Matrix user's homeserver which looks roughly as below:: - POST https://bar.com:8448/_matrix/federation/%SERVER_MAJOR_VERSION%/3pid/onbind + POST https://bar.com:8448/_matrix/federation/v1/3pid/onbind Content-Type: application/json { diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index f91b71797..81fe301b3 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -132,8 +132,8 @@ Retrieving Server Keys specification due to lack of significance. It may be reviewed `here `_. -Each homeserver publishes its public keys under ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}``. -Homeservers query for keys by either getting ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}`` +Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``. +Homeservers query for keys by either getting ``/_matrix/key/v2/server/{keyId}`` directly or by querying an intermediate notary server using a ``/_matrix/key/v2/query/{serverName}/{keyId}`` API. Intermediate notary servers query the ``/_matrix/key/v2/server/{keyId}`` API on behalf of another server and @@ -152,7 +152,7 @@ Publishing Keys +++++++++++++++ Homeservers publish the allowed TLS fingerprints and signing keys in a JSON -object at ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{key_id}``. The response contains a list of +object at ``/_matrix/key/v2/server/{key_id}``. The response contains a list of ``verify_keys`` that are valid for signing federation requests made by the homeserver and for signing events. It contains a list of ``old_verify_keys`` which are only valid for signing events. Finally the response contains a list of TLS @@ -166,7 +166,7 @@ Querying Keys Through Another Server Servers may query another server's keys through a notary server. The notary server may be another homeserver. The notary server will retrieve keys from -the queried servers through use of the ``/_matrix/key/%KEYS_MAJOR_VERSION%/server/{keyId}`` +the queried servers through use of the ``/_matrix/key/v2/server/{keyId}`` API. The notary server will additionally sign the response from the queried server before returning the results. @@ -1115,7 +1115,7 @@ that are too long. known hash functions like SHA-256 when none of the keys have been redacted]] .. |/query/directory| replace:: ``/query/directory`` -.. _/query/directory: #get-matrix-federation-%SERVER_MAJOR_VERSION%-query-directory +.. _/query/directory: #get-matrix-federation-v1-query-directory .. _`Invitation storage`: ../identity_service/%IDENTITY_RELEASE_LABEL%.html#invitation-storage .. _`Identity Service API`: ../identity_service/%IDENTITY_RELEASE_LABEL%.html From f030d19f3c137be7d70319763c16c0eaee78fd39 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 20:57:41 -0600 Subject: [PATCH 172/219] Clean up identity service swagger * Add `consumes` (swagger) * Remove `http` as a supported scheme (the spec specifically says clients MUST use https) * Clarify various descriptions * Full stops * Additional wording * s/older versions/previous drafts - we haven't had a release yet * Indentation on examples --- api/identity/associations.yaml | 20 +++++++++++++------- api/identity/email_associations.yaml | 11 ++++++----- api/identity/invitation_signing.yaml | 19 ++++++++++--------- api/identity/lookup.yaml | 19 +++++++++++++------ api/identity/phone_associations.yaml | 11 +++++++---- api/identity/ping.yaml | 13 +++++++------ api/identity/pubkey.yaml | 7 ++++--- api/identity/store_invite.yaml | 13 ++++++++----- 8 files changed, 68 insertions(+), 45 deletions(-) diff --git a/api/identity/associations.yaml b/api/identity/associations.yaml index 4225919b1..a400bf953 100644 --- a/api/identity/associations.yaml +++ b/api/identity/associations.yaml @@ -18,15 +18,17 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: "/3pid/getValidated3pid": get: summary: Check whether ownership of a 3pid was validated. - description: A client can check whether ownership of a 3pid was validated + description: |- + Determines if a given 3pid has been validated by a user. operationId: getValidated3pid parameters: - in: query @@ -61,7 +63,9 @@ paths: description: The address of the 3pid being looked up. validated_at: type: integer - description: Timestamp indicating the time that the 3pid was validated. + description: |- + Timestamp, in milliseconds, indicating the time that the 3pid + was validated. required: ['medium', 'address', 'validated_at'] 400: description: |- @@ -78,7 +82,7 @@ paths: schema: $ref: "../client-server/definitions/errors/error.yaml" 404: - description: The Session ID or client secret were not found + description: The Session ID or client secret were not found. examples: application/json: { "errcode": "M_NO_VALID_SESSION", @@ -95,7 +99,7 @@ paths: Future calls to ``/lookup`` for any of the session\'s 3pids will return this association. - Note: for backwards compatibility with older versions of this + Note: for backwards compatibility with previous drafts of this specification, the parameters may also be specified as ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. @@ -132,7 +136,6 @@ paths: "not_before": 1428825849161, "not_after": 4582425849161, "ts": 1428825849161, - "signatures": { "matrix.org": { "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" @@ -162,7 +165,10 @@ paths: description: The unix timestamp at which the association was verified. signatures: type: object - description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. + description: |- + The signatures of the verifying identity services which show that the + association should be trusted, if you trust the verifying identity + services. $ref: "../../schemas/server-signatures.yaml" required: - address diff --git a/api/identity/email_associations.yaml b/api/identity/email_associations.yaml index 28f5e6809..dc3cd78eb 100644 --- a/api/identity/email_associations.yaml +++ b/api/identity/email_associations.yaml @@ -18,8 +18,9 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: @@ -34,13 +35,13 @@ paths: that that user was able to read the email for that email address, and so we validate ownership of the email address. - Note that Home Servers offer APIs that proxy this API, adding + Note that homeservers offer APIs that proxy this API, adding additional behaviour on top, for example, ``/register/email/requestToken`` is designed specifically for use when registering an account and therefore will inform the user if the email address given is already registered on the server. - Note: for backwards compatibility with older versions of this + Note: for backwards compatibility with previous drafts of this specification, the parameters may also be specified as ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. @@ -58,7 +59,7 @@ paths: properties: client_secret: type: string - description: A unique string used to identify the validation attempt + description: A unique string used to identify the validation attempt. email: type: string description: The email address to validate. @@ -119,7 +120,7 @@ paths: associate the email address with any Matrix user ID. Specifically, calls to ``/lookup`` will not show a binding. - Note: for backwards compatibility with older versions of this + Note: for backwards compatibility with previous drafts of this specification, the parameters may also be specified as ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. diff --git a/api/identity/invitation_signing.yaml b/api/identity/invitation_signing.yaml index 7de62dd41..0b76a773d 100644 --- a/api/identity/invitation_signing.yaml +++ b/api/identity/invitation_signing.yaml @@ -18,8 +18,9 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: @@ -29,7 +30,7 @@ paths: description: |- Sign invitation details. - The identity server will look up ``token`` which was stored in a call + The identity service will look up ``token`` which was stored in a call to ``store-invite``, and fetch the sender of the invite. operationId: blindlySignStuff parameters: @@ -38,24 +39,24 @@ paths: schema: type: object example: { - "mxid": "@foo:bar.com", - "token": "sometoken", - "private_key": "base64encodedkey" - } + "mxid": "@foo:bar.com", + "token": "sometoken", + "private_key": "base64encodedkey" + } properties: mxid: type: string description: The Matrix user ID of the user accepting the invitation. token: type: string - description: Token from the call to ``store-invite`` + description: The token from the call to ``store-invite``. private_key: type: string description: The private key, encoded as `Unpadded base64`_. required: ["mxid", "token", "private_key"] responses: 200: - description: The signedjson of the mxid, sender, and token. + description: The signed JSON of the mxid, sender, and token. schema: type: object properties: @@ -85,7 +86,7 @@ paths: "token": "abc123" } 404: - description: Token was not found. + description: The token was not found. examples: application/json: { "errcode": "M_UNRECOGNIZED", diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index f04436ef3..1870a31f9 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -1,6 +1,7 @@ # Copyright 2016 OpenMarket Ltd # Copyright 2017 Kamax.io # Copyright 2017 New Vector Ltd +# 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. @@ -20,8 +21,9 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: @@ -46,7 +48,7 @@ paths: responses: 200: description: - The association for that 3pid, or the empty object if no association is known. + The association for that 3pid, or an empty object if no association is known. examples: application/json: { "address": "louise@bobs.burgers", @@ -66,10 +68,10 @@ paths: properties: address: type: string - description: The 3pid address of the user being looked up. + description: The 3pid address of the user being looked up, matching the address requested. medium: type: string - description: The literal string "email". + description: A medium from the `3PID Types`_ Appendix, matching the medium requested. mxid: type: string description: The Matrix user ID associated with the 3pid. @@ -126,7 +128,9 @@ paths: #- type: 3PID Address - type: string - type: string - description: an array of arrays containing the `3PID Types`_ with the ``medium`` in first position and the ``address`` in second position. + description: |- + An array of arrays containing the `3PID Types`_ with the ``medium`` + in first position and the ``address`` in second position. required: - "threepids" responses: @@ -157,6 +161,9 @@ paths: - type: string - type: string - type: string - description: an array of array containing the `3PID Types`_ with the ``medium`` in first position, the ``address`` in second position and Matrix ID in third position. + description: |- + An array of array containing the `3PID Types`_ with the ``medium`` + in first position, the ``address`` in second position and Matrix user + ID in third position. required: - "threepids" diff --git a/api/identity/phone_associations.yaml b/api/identity/phone_associations.yaml index f6b1bd45b..836984d02 100644 --- a/api/identity/phone_associations.yaml +++ b/api/identity/phone_associations.yaml @@ -18,8 +18,9 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: @@ -34,13 +35,13 @@ paths: indicates that that user was able to read the SMS for that phone number, and so we validate ownership of the phone number. - Note that Home Servers offer APIs that proxy this API, adding + Note that homeservers offer APIs that proxy this API, adding additional behaviour on top, for example, ``/register/msisdn/requestToken`` is designed specifically for use when registering an account and therefore will inform the user if the phone number given is already registered on the server. - Note: for backwards compatibility with older versions of this + Note: for backwards compatibility with previous drafts of this specification, the parameters may also be specified as ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. @@ -106,6 +107,8 @@ paths: - ``M_INVALID_ADDRESS``: The phone number provided was invalid. - ``M_SEND_ERROR``: The validation SMS could not be sent. + - ``M_DESTINATION_REJECTED``: The identity service cannot deliver an + SMS to the provided country or region. examples: application/json: { "errcode": "M_INVALID_ADDRESS", @@ -125,7 +128,7 @@ paths: associate the phone number address with any Matrix user ID. Specifically, calls to ``/lookup`` will not show a binding. - Note: for backwards compatibility with older versions of this + Note: for backwards compatibility with previous drafts of this specification, the parameters may also be specified as ``application/x-form-www-urlencoded`` data. However, this usage is deprecated. diff --git a/api/identity/ping.yaml b/api/identity/ping.yaml index 005160a35..2788d9d32 100644 --- a/api/identity/ping.yaml +++ b/api/identity/ping.yaml @@ -1,4 +1,5 @@ # Copyright 2018 Kamax Sàrl +# 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. @@ -14,7 +15,7 @@ swagger: "2.0" info: - title: "Matrix Client-Identity Versions API" + title: "Matrix Identity Service Ping API" version: "1.0.0" host: localhost:8090 schemes: @@ -25,19 +26,19 @@ produces: paths: "/api/v1": get: - summary: Checks that an Identity server is available at this API endpopint. + summary: Checks that an Identity Service is available at this API endpoint. description: |- - Checks that an Identity server is available at this API endpopint. + Checks that an Identity Service is available at this API endpoint. - To discover that an Identity server is available at a specific URL, + To discover that an Identity Service is available at a specific URL, this endpoint can be queried and will return an empty object. This is primarly used for auto-discovery and health check purposes - by entities acting as a client for the Identity server. + by entities acting as a client for the Identity Service. operationId: ping responses: 200: - description: An Identity server is ready to serve requests. + description: An Identity Service is ready to serve requests. examples: application/json: {} schema: diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index 9cb7c74e9..6b17e7c64 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -18,8 +18,9 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: @@ -113,8 +114,8 @@ paths: The validity of the public key. examples: application/json: { - "valid": true - } + "valid": true + } schema: type: object properties: diff --git a/api/identity/store_invite.yaml b/api/identity/store_invite.yaml index 1eca7198e..89d437a47 100644 --- a/api/identity/store_invite.yaml +++ b/api/identity/store_invite.yaml @@ -18,16 +18,17 @@ info: host: localhost:8090 schemes: - https - - http basePath: /_matrix/identity/api/v1 +consumes: + - application/json produces: - application/json paths: "/store-invite": post: - summary: Store pending invitations to a user\'s 3pid. + summary: Store pending invitations to a user's 3pid. description: |- - Store pending invitations to a user\'s 3pid. + Store pending invitations to a user's 3pid. In addition to the request parameters specified below, an arbitrary number of other parameters may also be specified. These may be used in @@ -47,6 +48,8 @@ paths: Also, the generated ephemeral public key will be listed as valid on requests to ``/_matrix/identity/api/v1/pubkey/ephemeral/isvalid``. + + Currently, invites may only be issued for 3pids of the ``email`` medium. operationId: storeInvite parameters: - in: body @@ -84,7 +87,7 @@ paths: description: The generated token. public_keys: type: array - description: A list of [server\'s long-term public key, generated ephemeral public key]. + description: A list of [server's long-term public key, generated ephemeral public key]. items: type: string display_name: @@ -111,7 +114,7 @@ paths: application/json: { "errcode": "M_THREEPID_IN_USE", "error": "Binding already known", - "mxid": mxid + "mxid": "@alice:example.com" } schema: $ref: "../client-server/definitions/errors/error.yaml" From bbba7dedd6db353787646c490d3480bc73140470 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 21:00:47 -0600 Subject: [PATCH 173/219] Clean up identity service RST * Title casing * s/identity server/identity service * Rough column limit enforcement * Add some links (used by future commits) --- specification/identity_service_api.rst | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index 7bbd8ae8c..e842f877c 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -1,6 +1,7 @@ .. Copyright 2016 OpenMarket Ltd .. Copyright 2017 Kamax.io .. Copyright 2017 New Vector Ltd +.. 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. @@ -56,7 +57,7 @@ is left as an exercise for the client. 3PID types are described in `3PID Types`_ Appendix. -API Standards +API standards ------------- The mandatory baseline for identity service communication in Matrix is exchanging @@ -146,25 +147,24 @@ Key management An identity service has some long-term public-private keypairs. These are named in a scheme ``algorithm:identifier``, e.g. ``ed25519:0``. When signing an -association, the Matrix standard JSON signing format is used, as specified in -the server-server API specification under the heading "Signing Events". +association, the standard `Signing JSON`_ algorithm applies. In the event of key compromise, the identity service may revoke any of its keys. An HTTP API is offered to get public keys, and check whether a particular key is valid. -The identity server may also keep track of some short-term public-private +The identity service may also keep track of some short-term public-private keypairs, which may have different usage and lifetime characteristics than the service's long-term keys. {{pubkey_is_http_api}} -Association Lookup +Association lookup ------------------ {{lookup_is_http_api}} -Establishing Associations +Establishing associations ------------------------- The flow for creating an association is session-based. @@ -198,7 +198,7 @@ General {{associations_is_http_api}} -Invitation Storage +Invitation storage ------------------ An identity service can store pending invitations to a user's 3pid, which will @@ -241,10 +241,14 @@ Where the signature is produced using a long-term private key. Ephemeral invitation signing ---------------------------- -To aid clients who may not be able to perform crypto themselves, the identity service offers some crypto functionality to help in accepting invitations. -This is less secure than the client doing it itself, but may be useful where this isn't possible. +To aid clients who may not be able to perform crypto themselves, the identity +service offers some crypto functionality to help in accepting invitations. +This is less secure than the client doing it itself, but may be useful where +this isn't possible. {{invitation_signing_is_http_api}} .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 .. _`3PID Types`: ../appendices.html#pid-types +.. _`Signing JSON`: ../appendices.html#signing-json +.. _`/3pid/onbind`: ../server_server.html#put-matrix-federation-v1-3pid-onbind From 039cefdbeaedcc3ab51746555c55a9dbb2509613 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 21:01:14 -0600 Subject: [PATCH 174/219] Say that identity services should be nice to web browsers (CORS/OPTIONS) --- specification/identity_service_api.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index e842f877c..ea6077990 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -137,6 +137,22 @@ should allow a 3pid to be mapped to a Matrix user identity, but not in the other direction (i.e. one should not be able to get all 3pids associated with a Matrix user ID, or get all 3pids associated with a 3pid). +Web browser clients +------------------- + +It is realistic to expect that some clients will be written to be run within a web +browser or similar environment. In these cases, the identity service should respond to +pre-flight requests and supply Cross-Origin Resource Sharing (CORS) headers on all +requests. + +When a client approaches the server with a pre-flight (OPTIONS) request, the server +should respond with the CORS headers for that route. The recommended CORS headers +to be returned by servers on all requests are:: + + Access-Control-Allow-Origin: * + Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS + Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization + Status check ------------ From 0387da51e268ce79f0c27fa6e8cb7ea444ff6515 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 21:01:28 -0600 Subject: [PATCH 175/219] Clarify how sessions work when establishing associations --- specification/identity_service_api.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index ea6077990..ab7c9b0cb 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -199,6 +199,12 @@ session, within a 24 hour period since its most recent modification. Any attempts to perform these actions after the expiry will be rejected, and a new session should be created and used instead. +To start a session, the client makes a request to the appropriate ``/requestToken`` +endpoint. The user then receives a validation token which should be provided +to the client. The client then provides the token to the appropriate ``/submitToken`` +endpoint, completing the session. At this point, the client should ``/bind`` the +third party identifier or leave it for another entity to bind. + Email associations ~~~~~~~~~~~~~~~~~~ From dc602b74d2feae8fcc50463c790014bfdf96da9a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 21:01:49 -0600 Subject: [PATCH 176/219] Reference the server-server specification for /onbind --- specification/identity_service_api.rst | 34 +++----------------------- 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index ab7c9b0cb..f6997ea17 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -227,36 +227,10 @@ An identity service can store pending invitations to a user's 3pid, which will be retrieved and can be either notified on or look up when the 3pid is associated with a Matrix user ID. -At a later point, if the owner of that particular 3pid binds it with a Matrix user ID, the identity server will attempt to make an HTTP POST to the Matrix user's homeserver which looks roughly as below:: - - POST https://bar.com:8448/_matrix/federation/v1/3pid/onbind - Content-Type: application/json - - { - "medium": "email", - "address": "foo@bar.baz", - "mxid": "@alice:example.tld", - "invites": [ - { - "medium": "email", - "address": "foo@bar.baz", - "mxid": "@alice:example.tld", - "room_id": "!something:example.tld", - "sender": "@bob:example.tld", - "signed": { - "mxid": "@alice:example.tld", - "signatures": { - "vector.im": { - "ed25519:0": "somesignature" - } - }, - "token": "sometoken" - } - } - ] - } - -Where the signature is produced using a long-term private key. +At a later point, if the owner of that particular 3pid binds it with a Matrix user +ID, the identity service will attempt to make an HTTP POST to the Matrix user's +homeserver via the `/3pid/onbind`_ endpoint. The request MUST be signed with a +long-term private key for the identity service. {{store_invite_is_http_api}} From fd7cb22a282d2f0775212db86804d2ed334e6091 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 21:22:47 -0600 Subject: [PATCH 177/219] Fix event type example of m.forwarded_room_key --- event-schemas/examples/m.forwarded_room_key | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/event-schemas/examples/m.forwarded_room_key b/event-schemas/examples/m.forwarded_room_key index 8ab85c48d..ef1d6180b 100644 --- a/event-schemas/examples/m.forwarded_room_key +++ b/event-schemas/examples/m.forwarded_room_key @@ -10,5 +10,5 @@ "hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw" ] }, - "type": "m.room_key" + "type": "m.forwarded_room_key" } From b2092922e85ecf633092498dfa840c912d34c7f8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 21:51:26 -0600 Subject: [PATCH 178/219] Don't define a variable for the appservice major version --- scripts/gendoc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 7b9005627..00febdf24 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -550,7 +550,6 @@ if __name__ == '__main__': "%CLIENT_MAJOR_VERSION%": "r0", "%SERVER_RELEASE_LABEL%": args.server_release, "%SERVER_MAJOR_VERSION%": extract_major(args.server_release), - "%APPSERVICE_MAJOR_VERSION%": "unstable", "%APPSERVICE_RELEASE_LABEL%": args.appservice_release, "%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release, } From 78487a01ecae59439fec57a078ee29abeaf9362f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 29 Aug 2018 23:11:00 -0600 Subject: [PATCH 179/219] Remove references to initialSync from account data and receipts module Fixes https://github.com/matrix-org/matrix-doc/issues/695 Note: This commit leaves the /join endpoints alone because they say "and /sync" rather than just initialSync --- specification/modules/account_data.rst | 2 +- specification/modules/receipts.rst | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/specification/modules/account_data.rst b/specification/modules/account_data.rst index 1c031ee12..d0ed201a3 100644 --- a/specification/modules/account_data.rst +++ b/specification/modules/account_data.rst @@ -31,7 +31,7 @@ The client recieves the account data as events in the ``account_data`` sections of a ``/sync``. These events can also be received in a ``/events`` response or in the -``account_data`` section of a room in ``/initialSync``. ``m.tag`` +``account_data`` section of a room in ``/sync``. ``m.tag`` events appearing in ``/events`` will have a ``room_id`` with the room the tags are for. diff --git a/specification/modules/receipts.rst b/specification/modules/receipts.rst index a6d8cbf77..faba7b625 100644 --- a/specification/modules/receipts.rst +++ b/specification/modules/receipts.rst @@ -38,11 +38,10 @@ single ``event_id``. Client behaviour ---------------- -In ``/initialSync``, receipts are listed in a separate top level ``receipts`` -key. In ``/sync``, receipts are contained in the ``ephemeral`` block for a -room. New receipts that come down the event streams are deltas which update -existing mappings. Clients should replace older receipt acknowledgements based -on ``user_id`` and ``receipt_type`` pairs. For example:: +In ``/sync``, receipts are listed under the ``ephemeral`` array of events +for a given room. New receipts that come down the event streams are deltas +which update existing mappings. Clients should replace older receipt acknowledgements +based on ``user_id`` and ``receipt_type`` pairs. For example:: Client receives m.receipt: user = @alice:example.com From 55c4307f1291cb6aab353da8cf2e403eb2bc9a6c Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 30 Aug 2018 14:37:24 +0100 Subject: [PATCH 180/219] Rewrite the section on signing events ... for clarity and de-duplication. And to say a bit about validating the signatures. --- api/server-server/definitions/pdu.yaml | 3 +- .../definitions/unsigned_pdu.yaml | 6 +- specification/server_server_api.rst | 185 ++++++++---------- 3 files changed, 85 insertions(+), 109 deletions(-) diff --git a/api/server-server/definitions/pdu.yaml b/api/server-server/definitions/pdu.yaml index bb14ede27..d86b85384 100644 --- a/api/server-server/definitions/pdu.yaml +++ b/api/server-server/definitions/pdu.yaml @@ -23,7 +23,8 @@ allOf: hashes: type: object title: Event Hash - description: Hashes of the PDU, following the algorithm specified in `Signing Events`_. + description: |- + Content hashes of the PDU, following the algorithm specified in `Signing Events`_. example: { "sha256": "thishashcoversallfieldsincasethisisredacted" } diff --git a/api/server-server/definitions/unsigned_pdu.yaml b/api/server-server/definitions/unsigned_pdu.yaml index 64991d227..446973ed0 100644 --- a/api/server-server/definitions/unsigned_pdu.yaml +++ b/api/server-server/definitions/unsigned_pdu.yaml @@ -55,8 +55,8 @@ properties: prev_events: type: array description: |- - Event IDs and hashes of the most recent events in the room that the homeserver was aware - of when it made this event. + Event IDs and reference hashes for the most recent events in the room + that the homeserver was aware of when it made this event. items: type: array maxItems: 2 @@ -86,7 +86,7 @@ properties: auth_events: type: array description: |- - An event reference list containing the authorization events that would + Event IDs and reference hashes for the authorization events that would allow this event to be in the room. items: type: array diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 244a8b82e..e55b8113e 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -112,7 +112,7 @@ Server implementation {{version_ss_http_api}} -Retrieving Server Keys +Retrieving server keys ~~~~~~~~~~~~~~~~~~~~~~ .. NOTE:: @@ -965,142 +965,114 @@ Signing Events Signing events is complicated by the fact that servers can choose to redact non-essential parts of an event. -Before signing the event, the ``unsigned`` and ``signature`` members are -removed, it is encoded as `Canonical JSON`_, and then hashed using SHA-256. The -resulting hash is then stored in the event JSON in a ``hash`` object under a -``sha256`` key. +Adding hashes and signatures to outgoing events +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. code:: python - - def hash_event(event_json_object): - - # Keys under "unsigned" can be modified by other servers. - # They are useful for conveying information like the age of an - # event that will change in transit. - # Since they can be modifed we need to exclude them from the hash. - unsigned = event_json_object.pop("unsigned", None) - - # Signatures will depend on the current value of the "hashes" key. - # We cannot add new hashes without invalidating existing signatures. - signatures = event_json_object.pop("signatures", None) +Before signing the event, the *content hash* of the event is calculated as +described below. The hash is encoded using `Unpadded Base64`_ and stored in the +event object, in a ``hashes`` object, under a ``sha256`` key. - # The "hashes" key might contain multiple algorithms if we decide to - # migrate away from SHA-2. We don't want to include an existing hash - # output in our hash so we exclude the "hashes" dict from the hash. - hashes = event_json_object.pop("hashes", {}) - - # Encode the JSON using a canonical encoding so that we get the same - # bytes on every server for the same JSON object. - event_json_bytes = encode_canonical_json(event_json_bytes) +The event object is then *redacted*, following the `redaction +algorithm`_. Finally it is signed as described in `Signing JSON`_, using the +server's signing key (see also `Retrieving server keys`_). - # Add the base64 encoded bytes of the hash to the "hashes" dict. - hashes["sha256"] = encode_base64(sha256(event_json_bytes).digest()) +The signature is then copied back to the original event object. - # Add the "hashes" dict back the event JSON under a "hashes" key. - event_json_object["hashes"] = hashes - if unsigned is not None: - event_json_object["unsigned"] = unsigned - return event_json_object +See `Persistent Data Unit schema`_ for an example of a signed event. -The event is then stripped of all non-essential keys both at the top level and -within the ``content`` object. Any top-level keys not in the following list -MUST be removed: -.. code:: +Validating hashes and signatures on received events +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When a server receives an event over federation from another server, the +receiving server should check the hashes and signatures on that event. - auth_events - depth - event_id - hashes - membership - origin - origin_server_ts - prev_events - prev_state - room_id - sender - signatures - state_key - type - -A new ``content`` object is constructed for the resulting event that contains -only the essential keys of the original ``content`` object. If the original -event lacked a ``content`` object at all, a new empty JSON object is created -for it. - -The keys that are considered essential for the ``content`` object depend on the -the ``type`` of the event. These are: +First the signature is checked. The event is redacted following the `redaction +algorithm`_, and the resultant object is checked for a signature from the +originating server, following the algorithm described in `Checking for a signature`_. +Note that this step should succeed whether we have been sent the full event or +a redacted copy. -.. code:: +If the signature is found to be valid, the expected content hash is calculated +as described below. The content hash in the ``hashes`` property of the received +event is base64-decoded, and the two are compared for equality. - type is "m.room.aliases": - aliases +If the hash check fails, then it is assumed that this is because we have only +been given a redacted version of the event. To enforce this, the receiving +server should use the redacted copy it calculated rather than the full copy it +received. - type is "m.room.create": - creator +Calculating the content hash for an event +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - type is "m.room.history_visibility": - history_visibility +The *content hash* of an event covers the complete event including the +*unredacted* contents. It is calculated as follows. - type is "m.room.join_rules": - join_rule +First, any existing ``unsigned``, ``signature``, and ``hashes`` members are +removed. The resulting object is then encoded as `Canonical JSON`_, and the +JSON is hashed using SHA-256. - type is "m.room.member": - membership - type is "m.room.power_levels": - ban - events - events_default - kick - redact - state_default - users - users_default - -The resulting stripped object with the new ``content`` object and the original -``hashes`` key is then signed using the JSON signing algorithm outlined below: +Example code +~~~~~~~~~~~~ .. code:: python - def sign_event(event_json_object, name, key): - - # Make sure the event has a "hashes" key. - if "hashes" not in event_json_object: - event_json_object = hash_event(event_json_object) + def hash_and_sign_event(event_object, signing_key, signing_name): + # First we need to hash the event object. + content_hash = compute_content_hash(event_object) + event_object["hashes"] = {"sha256": encode_unpadded_base64(content_hash)} # Strip all the keys that would be removed if the event was redacted. # The hashes are not stripped and cover all the keys in the event. # This means that we can tell if any of the non-essential keys are # modified or removed. - stripped_json_object = strip_non_essential_keys(event_json_object) + stripped_object = strip_non_essential_keys(event_object) # Sign the stripped JSON object. The signature only covers the # essential keys and the hashes. This means that we can check the # signature even if the event is redacted. - signed_json_object = sign_json(stripped_json_object) + signed_object = sign_json(stripped_object, signing_key, signing_name) # Copy the signatures from the stripped event to the original event. - event_json_object["signatures"] = signed_json_oject["signatures"] - return event_json_object + event_object["signatures"] = signed_object["signatures"] -Servers can then transmit the entire event or the event with the non-essential -keys removed. If the entire event is present, receiving servers can then check -the event by computing the SHA-256 of the event, excluding the ``hash`` object. -If the keys have been redacted, then the ``hash`` object is included when -calculating the SHA-256 hash instead. + def compute_content_hash(event_object): + # take a copy of the event before we remove any keys. + event_object = dict(event_object) -New hash functions can be introduced by adding additional keys to the ``hash`` -object. Since the ``hash`` object cannot be redacted a server shouldn't allow -too many hashes to be listed, otherwise a server might embed illict data within -the ``hash`` object. For similar reasons a server shouldn't allow hash values -that are too long. + # Keys under "unsigned" can be modified by other servers. + # They are useful for conveying information like the age of an + # event that will change in transit. + # Since they can be modifed we need to exclude them from the hash. + event_object.pop("unsigned", None) + + # Signatures will depend on the current value of the "hashes" key. + # We cannot add new hashes without invalidating existing signatures. + event_object.pop("signatures", None) + + # The "hashes" key might contain multiple algorithms if we decide to + # migrate away from SHA-2. We don't want to include an existing hash + # output in our hash so we exclude the "hashes" dict from the hash. + event_object.pop("hashes", None) + + # Encode the JSON using a canonical encoding so that we get the same + # bytes on every server for the same JSON object. + event_json_bytes = encode_canonical_json(event_object) + + return hashlib.sha256(event_json_bytes) .. TODO - [[TODO(markjh): We might want to specify a maximum number of keys for the - ``hash`` and we might want to specify the maximum output size of a hash]] - [[TODO(markjh) We might want to allow the server to omit the output of well - known hash functions like SHA-256 when none of the keys have been redacted]] + + [[TODO(markjh): Since the ``hash`` object cannot be redacted a server + shouldn't allow too many hashes to be listed, otherwise a server might embed + illict data within the ``hash`` object. + + We might want to specify a maximum number of keys for the + ``hash`` and we might want to specify the maximum output size of a hash]] + + [[TODO(markjh) We might want to allow the server to omit the output of well + known hash functions like SHA-256 when none of the keys have been redacted]] + .. |/query/directory| replace:: ``/query/directory`` .. _/query/directory: #get-matrix-federation-v1-query-directory @@ -1111,3 +1083,6 @@ that are too long. .. _`Inviting to a room`: #inviting-to-a-room .. _`Canonical JSON`: ../appendices.html#canonical-json .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 +.. _`redaction algorithm`: ../client_server/unstable.html#redactions +.. _`Signing JSON`: ../appendices.html#signing-json +.. _`Checking for a signature`: ../appendices.html#checking-for-a-signature From 5c2b8e35693c311e77781e78b7b3dbfdc1fae244 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 30 Aug 2018 17:03:16 +0100 Subject: [PATCH 181/219] Explain how to handle rejeceted events --- specification/server_server_api.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 244a8b82e..4c40d6dce 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -472,6 +472,24 @@ The rules are as follows: I think there is some magic about 3pid invites too. +Rejection ++++++++++ + +If an event is rejected it should neither be relayed to clients nor be included +as a prev event in any new events generated by the server. Subsequent events +from other servers that reference rejected events should be allowed if they +still pass the auth rules. The state used in the checks should be calculated as +normal, except not updating with the rejected event where it is a state event. + +If an event in an incoming transaction is rejected, this should not cause the +transaction request to be responded to with an error response. + +.. NOTE:: + + This means that events may be included in the room DAG even though they + should be rejected. + + Retrieving event authorization information ++++++++++++++++++++++++++++++++++++++++++ From ab14f33060e372d176dc7c3ed5440193f46e4b81 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 07:58:10 -0600 Subject: [PATCH 182/219] Add link to the client-server ACLs module --- specification/server_server_api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 244a8b82e..983da62fe 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -1111,3 +1111,4 @@ that are too long. .. _`Inviting to a room`: #inviting-to-a-room .. _`Canonical JSON`: ../appendices.html#canonical-json .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 +.. _`Server ACLs`: ../client_server/unstable.html#module-server-acls From 4e90b32348155d6d09864cc66cf8c3b31abc809a Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 30 Aug 2018 17:18:07 +0100 Subject: [PATCH 183/219] Set the encoding to UTF-8 on all file I/O Hopefully this will resolve issues with building the spec on systems where the default encoding is somthing other than UTF-8. --- scripts/gendoc.py | 21 ++++++++++---------- scripts/templating/matrix_templates/units.py | 18 ++++++++--------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 8745d3e2b..0719b48fc 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -154,7 +154,7 @@ def get_rst(file_info, title_level, title_styles, spec_dir, adjust_titles): # string are file paths to RST blobs if isinstance(file_info, str): log("%s %s" % (">" * (1 + title_level), file_info)) - with open(os.path.join(spec_dir, file_info), "r") as f: + with open(os.path.join(spec_dir, file_info), "r", encoding="utf-8") as f: rst = None if adjust_titles: rst = load_with_adjusted_titles( @@ -186,7 +186,7 @@ def get_rst(file_info, title_level, title_styles, spec_dir, adjust_titles): def build_spec(target, out_filename): log("Building templated file %s" % out_filename) - with open(out_filename, "wb") as outfile: + with open(out_filename, "w", encoding="utf-8") as outfile: for file_info in target["files"]: section = get_rst( file_info=file_info, @@ -195,7 +195,7 @@ def build_spec(target, out_filename): spec_dir=spec_dir, adjust_titles=True ) - outfile.write(section.encode('UTF-8')) + outfile.write(section) """ @@ -223,8 +223,8 @@ def fix_relative_titles(target, filename, out_filename): "^[" + re.escape("".join(title_styles)) + "]{3,}$" ) current_title_style = None - with open(filename, "r") as infile: - with open(out_filename, "w") as outfile: + with open(filename, "r", encoding="utf-8") as infile: + with open(out_filename, "w", encoding="utf-8") as outfile: for line in infile.readlines(): if not relative_title_matcher.match(line): if title_matcher.match(line): @@ -263,8 +263,8 @@ def fix_relative_titles(target, filename, out_filename): def rst2html(i, o, stylesheets): log("rst2html %s -> %s" % (i, o)) - with open(i, "r") as in_file: - with open(o, "w") as out_file: + with open(i, "r", encoding="utf-8") as in_file: + with open(o, "w", encoding="utf-8") as out_file: publish_file( source=in_file, destination=out_file, @@ -280,16 +280,15 @@ def rst2html(i, o, stylesheets): def addAnchors(path): log("add anchors %s" % path) - with open(path, "rb") as f: + with open(path, "r", encoding="utf-8") as f: lines = f.readlines() replacement = r'

\n\1' - with open(path, "wb") as f: + with open(path, "w", encoding="utf-8") as f: for line in lines: - line = line.decode("UTF-8") line = re.sub(r'()', replacement, line.rstrip()) line = re.sub(r'(
)', replacement, line.rstrip()) - f.write((line + "\n").encode('UTF-8')) + f.write(line + "\n") def run_through_template(input_files, set_verbose, substitutions): diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 219299cdf..6f9eeaa2a 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -125,7 +125,7 @@ def resolve_references(path, schema): if '$ref' in schema: value = schema['$ref'] path = os.path.join(os.path.dirname(path), value) - with open(path) as f: + with open(path, encoding="utf-8") as f: ref = yaml.load(f, OrderedLoader) result = resolve_references(path, ref) del schema['$ref'] @@ -664,11 +664,11 @@ class MatrixUnits(Units): continue filepath = os.path.join(path, filename) logger.info("Reading swagger API: %s" % filepath) - with open(filepath, "r") as f: + with open(filepath, "r", encoding="utf-8") as f: # strip .yaml group_name = filename[:-5].replace("-", "_") group_name = "%s_%s" % (group_name, suffix) - api = yaml.load(f.read(), OrderedLoader) + api = yaml.load(f, OrderedLoader) api = resolve_references(filepath, api) api["__meta"] = self._load_swagger_meta( api, group_name @@ -698,11 +698,11 @@ class MatrixUnits(Units): continue filepath = os.path.join(path, filename) logger.info("Reading swagger definition: %s" % filepath) - with open(filepath, "r") as f: + with open(filepath, "r", encoding="utf-8") as f: # strip .yaml group_name = re.sub(r"[^a-zA-Z0-9_]", "_", filename[:-5]) group_name = "%s_%s" % (prefix, group_name) - definition = yaml.load(f.read(), OrderedLoader) + definition = yaml.load(f, OrderedLoader) definition = resolve_references(filepath, definition) if 'type' not in definition: continue @@ -741,7 +741,7 @@ class MatrixUnits(Units): event_type = filename[:-5] # strip the ".yaml" logger.info("Reading event schema: %s" % filepath) - with open(filepath) as f: + with open(filepath, encoding="utf-8") as f: event_schema = yaml.load(f, OrderedLoader) schema_info = process_data_type( @@ -792,7 +792,7 @@ class MatrixUnits(Units): filepath = os.path.join(path, filename) logger.info("Reading event example: %s" % filepath) try: - with open(filepath, "r") as f: + with open(filepath, "r", encoding="utf-8") as f: example = json.load(f) examples[filename] = examples.get(filename, []) examples[filename].append(example) @@ -830,7 +830,7 @@ class MatrixUnits(Units): def read_event_schema(self, filepath): logger.info("Reading %s" % filepath) - with open(filepath, "r") as f: + with open(filepath, "r", encoding="utf-8") as f: json_schema = yaml.load(f, OrderedLoader) schema = { @@ -942,7 +942,7 @@ class MatrixUnits(Units): title_part = None changelog_lines = [] - with open(path, "r") as f: + with open(path, "r", encoding="utf-8") as f: lines = f.readlines() prev_line = None for line in (tc_lines + lines): From 05b017276c81b2a0ce0edb23b6c5c8990b86557e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 10:23:12 -0600 Subject: [PATCH 184/219] Don't accidentally limit application services to one homeserver --- specification/application_service_api.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 09ecd4ff8..45ee75a9b 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -54,8 +54,8 @@ The following other versions are also available, in reverse chronological order: Application Services -------------------- -Application services are passive and can only observe events from a given -homeserver. They can inject events into rooms they are participating in. +Application services are passive and can only observe events from homeserver. +They can inject events into rooms they are participating in. They cannot prevent events from being sent, nor can they modify the content of the event being sent. In order to observe events from a homeserver, the homeserver needs to be configured to pass certain types of traffic to the From ecd3ce39e54dd35eab60b2c8c8da900bfbf34b8b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 10:29:59 -0600 Subject: [PATCH 185/219] Don't generate proposals.rst in Circle CI --- scripts/generate-matrix-org-assets | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/generate-matrix-org-assets b/scripts/generate-matrix-org-assets index ed08f81d3..76032850a 100755 --- a/scripts/generate-matrix-org-assets +++ b/scripts/generate-matrix-org-assets @@ -8,8 +8,11 @@ cd `dirname $0`/.. mkdir -p assets -# generate specification/proposals.rst -./scripts/proposals.py +if [ "$CIRCLECI" != "true" ] +then + # generate specification/proposals.rst + ./scripts/proposals.py +fi # generate the spec docs ./scripts/gendoc.py -d assets/spec From a48f7b9278d7810b8727e266e566b1a81b9c24c8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 10:49:05 -0600 Subject: [PATCH 186/219] Clarify how external_url is supposed to work Fixes https://github.com/matrix-org/matrix-doc/issues/1624 --- specification/application_service_api.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 5b7abf4a5..127b3ade6 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -374,13 +374,14 @@ additional parameters on the ``/publicRooms`` client-server endpoint. {{appservice_room_directory_cs_http_api}} -Event fields -~~~~~~~~~~~~ +Referencing messages from a third party network +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. TODO-TravisR: Fix this section to be a general "3rd party networks" section +Application services should include an ``external_url`` in the ``content`` of +events it emits to indicate where the message came from. This typically applies +to application services that bridge other networks into Matrix, such as IRC, +where an HTTP URL may be available to reference. -We recommend that any events that originated from a remote network should -include an ``external_url`` field in their content to provide a way for Matrix -clients to link into the 'native' client from which the event originated. -For instance, this could contain the message-ID for emails/nntp posts, or a link -to a blog comment when bridging blog comment traffic in & out of Matrix. +Clients should provide users with a way to access the ``external_url`` if it +is present. Clients should additionally ensure the URL has a scheme of ``https`` +or ``http`` before making use of it. From be5c5660282a74128047aa3ec98df1fcbffe0ca5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:03:42 -0600 Subject: [PATCH 187/219] Version all appservice endpoints and provide a fallback Fixes https://github.com/matrix-org/matrix-doc/issues/1616 --- api/application-service/protocols.yaml | 12 +++++----- api/application-service/query_room.yaml | 2 +- api/application-service/query_user.yaml | 2 +- api/application-service/transactions.yaml | 2 +- specification/application_service_api.rst | 28 +++++++++++++++++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/api/application-service/protocols.yaml b/api/application-service/protocols.yaml index e6489cc5b..f1dd39b0a 100644 --- a/api/application-service/protocols.yaml +++ b/api/application-service/protocols.yaml @@ -19,13 +19,13 @@ host: localhost:8008 schemes: - https - http -basePath: "/" +basePath: /_matrix/app/v1 consumes: - application/json produces: - application/json paths: - "/_matrix/app/unstable/thirdparty/protocol/{protocol}": + "/thirdparty/protocol/{protocol}": get: summary: Retrieve metadata about a specific protocol that the application service supports. description: |- @@ -72,7 +72,7 @@ paths: } schema: $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/user/{protocol}": + "/thirdparty/user/{protocol}": get: summary: Retrieve the Matrix User ID of a corresponding third party user. description: |- @@ -125,7 +125,7 @@ paths: } schema: $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/location/{protocol}": + "/thirdparty/location/{protocol}": get: summary: Retrieve Matrix-side portal rooms leading to a third party location. description: |- @@ -176,7 +176,7 @@ paths: } schema: $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/location": + "/thirdparty/location": get: summary: Reverse-lookup third party locations given a Matrix room alias. description: |- @@ -221,7 +221,7 @@ paths: } schema: $ref: ../client-server/definitions/errors/error.yaml - "/_matrix/app/unstable/thirdparty/user": + "/thirdparty/user": get: summary: Reverse-lookup third party users given a Matrix User ID. description: |- diff --git a/api/application-service/query_room.yaml b/api/application-service/query_room.yaml index b885cb860..22f15dcf0 100644 --- a/api/application-service/query_room.yaml +++ b/api/application-service/query_room.yaml @@ -20,7 +20,7 @@ host: localhost:8008 schemes: - https - http -basePath: "/" +basePath: /_matrix/app/v1 consumes: - application/json produces: diff --git a/api/application-service/query_user.yaml b/api/application-service/query_user.yaml index 0431b5e49..af7dec5c3 100644 --- a/api/application-service/query_user.yaml +++ b/api/application-service/query_user.yaml @@ -20,7 +20,7 @@ host: localhost:8008 schemes: - https - http -basePath: "/" +basePath: /_matrix/app/v1 consumes: - application/json produces: diff --git a/api/application-service/transactions.yaml b/api/application-service/transactions.yaml index 8735cc8f7..9bedc5029 100644 --- a/api/application-service/transactions.yaml +++ b/api/application-service/transactions.yaml @@ -20,7 +20,7 @@ host: localhost:8008 schemes: - https - http -basePath: "/" +basePath: /_matrix/app/v1 produces: - application/json paths: diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 5b7abf4a5..3aa8a8ed3 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -169,6 +169,34 @@ An example registration file for an IRC-bridging application service is below: Homeserver -> Application Service API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Legacy routes ++++++++++++++ + +Previous drafts of the application service specification had a mix of endpoints +that have been used in the wild for a significant amount of time. The application +service specification now defines a version on all endpoints to be more compatible +with the rest of the Matrix specification and the future. + +Homeservers should attempt to use the specified endpoints first when communicating +with application services. However, if the application service receives an http status +code that does not indicate success (ie: 404, 500, 501, etc) then the homeserver +should fall back to the older endpoints for the application service. + +The older endpoints have the exact same request body and response format, they +just belong at a different path. The equivalent path for each is as follows: + +* ``/_matrix/app/v1/transactions/{txnId}`` becomes ``/transactions/{txnId}`` +* ``/_matrix/app/v1/users/{userId}`` becomes ``/users/{userId}`` +* ``/_matrix/app/v1/rooms/{roomAlias}`` becomes ``/rooms/{roomAlias}`` +* ``/_matrix/app/v1/thirdparty/protocol/{protocol}`` becomes ``/_matrix/app/unstable/thirdparty/protocol/{protocol}`` +* ``/_matrix/app/v1/thirdparty/user/{user}`` becomes ``/_matrix/app/unstable/thirdparty/user/{user}`` +* ``/_matrix/app/v1/thirdparty/location/{location}`` becomes ``/_matrix/app/unstable/thirdparty/location/{location}`` +* ``/_matrix/app/v1/thirdparty/user`` becomes ``/_matrix/app/unstable/thirdparty/user`` +* ``/_matrix/app/v1/thirdparty/location`` becomes ``/_matrix/app/unstable/thirdparty/location`` + +Homeservers should periodically try again for the newer endpoints because the +application service may have been updated. + Pushing events ++++++++++++++ From 1a3f11233731d92a9dec01dd8b207c62c27c528e Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:07:09 -0600 Subject: [PATCH 188/219] Clarify that the external_url is unsafe --- specification/application_service_api.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/specification/application_service_api.rst b/specification/application_service_api.rst index 127b3ade6..cd65fad76 100644 --- a/specification/application_service_api.rst +++ b/specification/application_service_api.rst @@ -385,3 +385,7 @@ where an HTTP URL may be available to reference. Clients should provide users with a way to access the ``external_url`` if it is present. Clients should additionally ensure the URL has a scheme of ``https`` or ``http`` before making use of it. + +The presence of an ``external_url`` on an event does not necessarily mean the +event was sent from an application service. Clients should be wary of the URL +contained within, as it may not be a legitimate reference to the event's source. From 138419cdd48780e7b9b1e0e41704563eca179805 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:19:55 -0600 Subject: [PATCH 189/219] fix indentation on release process doc --- meta/releasing_a_spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/releasing_a_spec.md b/meta/releasing_a_spec.md index 3a9da8938..ac3d21faa 100644 --- a/meta/releasing_a_spec.md +++ b/meta/releasing_a_spec.md @@ -27,7 +27,7 @@ The remainder of the process is as follows: 1. Add the changes to the matrix-org/matrix.org repository (for historic tracking). * This is done by making a PR to the `unstyled_docs/spec` folder for the version and specification you're releasing. - * Don't forget to symlink the new release as `latest`. + * Don't forget to symlink the new release as `latest`. 1. Perform a release on GitHub to tag the release. 1. Yell from the mountaintop to the world about the new release. From 6aacec317867b64a6a00994ad8b222e0666c3e30 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:40:08 -0600 Subject: [PATCH 190/219] Fix power level JSON example --- event-schemas/examples/m.room.power_levels | 1 + 1 file changed, 1 insertion(+) diff --git a/event-schemas/examples/m.room.power_levels b/event-schemas/examples/m.room.power_levels index b09746dfb..ad741e88e 100644 --- a/event-schemas/examples/m.room.power_levels +++ b/event-schemas/examples/m.room.power_levels @@ -20,4 +20,5 @@ "notifications": { "room": 20 } + } } From 31ea4279d1fb776a0734eb47a28368330f895ce4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:53:39 -0600 Subject: [PATCH 191/219] Resolve references in the check_examples script --- event-schemas/check_examples.py | 47 ++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/event-schemas/check_examples.py b/event-schemas/check_examples.py index f2456d97e..be541aa97 100755 --- a/event-schemas/check_examples.py +++ b/event-schemas/check_examples.py @@ -44,16 +44,51 @@ except ImportError as e: raise +def load_file(path): + print("Loading reference: %s" % path) + if not path.startswith("file://"): + raise Exception("Bad ref: %s" % (path,)) + path = path[len("file://"):] + with open(path, "r") as f: + if path.endswith(".json"): + return json.load(f) + else: + # We have to assume it's YAML because some of the YAML examples + # do not have file extensions. + return yaml.load(f) + + +def resolve_references(path, schema): + if isinstance(schema, dict): + # do $ref first + if '$ref' in schema: + value = schema['$ref'] + path = os.path.abspath(os.path.join(os.path.dirname(path), value)) + ref = load_file("file://" + path) + result = resolve_references(path, ref) + del schema['$ref'] + else: + result = {} + + for key, value in schema.items(): + result[key] = resolve_references(path, value) + return result + elif isinstance(schema, list): + return [resolve_references(path, value) for value in schema] + else: + return schema + + def check_example_file(examplepath, schemapath): with open(examplepath) as f: - example = yaml.load(f) + example = resolve_references(examplepath, json.load(f)) with open(schemapath) as f: schema = yaml.load(f) fileurl = "file://" + os.path.abspath(schemapath) schema["id"] = fileurl - resolver = jsonschema.RefResolver(schemapath, schema, handlers={"file": load_yaml}) + resolver = jsonschema.RefResolver(schemapath, schema, handlers={"file": load_file}) print ("Checking schema for: %r %r" % (examplepath, schemapath)) try: @@ -85,14 +120,6 @@ def check_example_dir(exampledir, schemadir): raise ValueError("Error validating examples") -def load_yaml(path): - if not path.startswith("file:///"): - raise Exception("Bad ref: %s" % (path,)) - path = path[len("file://"):] - with open(path, "r") as f: - return yaml.load(f) - - if __name__ == '__main__': try: check_example_dir("examples", "schema") From c8a8f13623e8022f1eaa17f5dc76995d3366cbbb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:57:01 -0600 Subject: [PATCH 192/219] Don't check the underlying definitions Otherwise the script will try to find a schema for our templates, which don't exist. --- event-schemas/check_examples.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/event-schemas/check_examples.py b/event-schemas/check_examples.py index be541aa97..deb0433e5 100755 --- a/event-schemas/check_examples.py +++ b/event-schemas/check_examples.py @@ -106,6 +106,9 @@ def check_example_dir(exampledir, schemadir): if filename.startswith("."): # Skip over any vim .swp files. continue + if os.dirname(os.path.join(root, filename)) == "core": + # Skip checking the underlying definitions + continue examplepath = os.path.join(root, filename) schemapath = examplepath.replace(exampledir, schemadir) if schemapath.find("#") >= 0: From 464f4f5f2166608f573afb95a2299381f9ab477b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 12:05:56 -0600 Subject: [PATCH 193/219] Correctly check for the 'core' folder --- event-schemas/check_examples.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/event-schemas/check_examples.py b/event-schemas/check_examples.py index deb0433e5..3e536ec3b 100755 --- a/event-schemas/check_examples.py +++ b/event-schemas/check_examples.py @@ -106,7 +106,8 @@ def check_example_dir(exampledir, schemadir): if filename.startswith("."): # Skip over any vim .swp files. continue - if os.dirname(os.path.join(root, filename)) == "core": + cwd = os.path.basename(os.path.dirname(os.path.join(root, filename))) + if cwd == "core": # Skip checking the underlying definitions continue examplepath = os.path.join(root, filename) From 440841d1ffd0f3d4398019da26e61e7340cd12ef Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 12:13:21 -0600 Subject: [PATCH 194/219] Recommend a CSP rather than require it. --- changelogs/client_server/newsfragments/1600.feature | 1 + specification/modules/content_repo.rst | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 changelogs/client_server/newsfragments/1600.feature diff --git a/changelogs/client_server/newsfragments/1600.feature b/changelogs/client_server/newsfragments/1600.feature new file mode 100644 index 000000000..142a67b25 --- /dev/null +++ b/changelogs/client_server/newsfragments/1600.feature @@ -0,0 +1 @@ +Recommend that servers set a Content Security Policy for the content repository. diff --git a/specification/modules/content_repo.rst b/specification/modules/content_repo.rst index f6da38fff..51cf999a3 100644 --- a/specification/modules/content_repo.rst +++ b/specification/modules/content_repo.rst @@ -33,10 +33,9 @@ recipient's local homeserver, which must first transfer the content from the origin homeserver using the same API (unless the origin and destination homeservers are the same). -When serving content, the server MUST provide a ``Content-Security-Policy`` -header. The policy may be more restrictive, however the minimum policy is -``default-src 'none'; script-src 'none'; plugin-types application/pdf; -style-src 'unsafe-inline'; object-src 'self';``. +When serving content, the server SHOULD provide a ``Content-Security-Policy`` +header. The recommended policy is ``default-src 'none'; script-src 'none'; +plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';``. Client behaviour ---------------- From b8f2c721dc9bfbd44b6545c96a99755b490e58a7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 12:22:50 -0600 Subject: [PATCH 195/219] Clarify which attributes should be valid --- specification/modules/instant_messaging.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index f3deb2202..d6cc9f098 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -109,7 +109,8 @@ back to rendering tab-delimited text. In addition to not rendering unsafe HTML, clients should not emit unsafe HTML in events. Likewise, clients should not generate HTML that is not needed, such as extra paragraph tags surrounding text due to Rich Text Editors. HTML included in events should otherwise be valid, -such as having appropriate closing tags, valid attributes, and generally valid structure. +such as having appropriate closing tags, appropriate attributes (considering the custom ones +defined in this specification), and generally valid structure. .. Note:: A future iteration of the specification will support more powerful and extensible From 32cde24bcfdc9bc63fef0658b1669e1828cb0a2c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 12:26:24 -0600 Subject: [PATCH 196/219] Fix server-server link in IS spec --- specification/identity_service_api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index f6997ea17..e233e4fc0 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -247,4 +247,4 @@ this isn't possible. .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 .. _`3PID Types`: ../appendices.html#pid-types .. _`Signing JSON`: ../appendices.html#signing-json -.. _`/3pid/onbind`: ../server_server.html#put-matrix-federation-v1-3pid-onbind +.. _`/3pid/onbind`: ../server_server/unstable.html#put-matrix-federation-v1-3pid-onbind From 429f30274495bf4fee8c9e0d841db57466fcdfda Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 13:32:53 -0600 Subject: [PATCH 197/219] Add an `age` to the invite room state example --- event-schemas/examples/m.room.member#invite_room_state | 1 + 1 file changed, 1 insertion(+) diff --git a/event-schemas/examples/m.room.member#invite_room_state b/event-schemas/examples/m.room.member#invite_room_state index cbd76100e..c99c66c0f 100644 --- a/event-schemas/examples/m.room.member#invite_room_state +++ b/event-schemas/examples/m.room.member#invite_room_state @@ -6,6 +6,7 @@ "displayname": "Alice Margatroid" }, "unsigned": { + "age": 1234, "invite_room_state": [ { "type": "m.room.name", From 4630c067213c3c30b2a96c8c0383166e6ac8f56f Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 11:24:36 -0600 Subject: [PATCH 198/219] Appservice r0.1.0 changelog --- changelogs/application_service.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/changelogs/application_service.rst b/changelogs/application_service.rst index e69de29bb..9d098837a 100644 --- a/changelogs/application_service.rst +++ b/changelogs/application_service.rst @@ -0,0 +1,7 @@ +r0.1.0 +====== + +This is the first release of the Application Service specification. It +includes support for application services being able to interact with +homeservers and bridge third party networks, such as IRC, over to Matrix +in a standard and accessible way. From 5e6a2c30a2171366049fbde23c0b55711b2b1b79 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 15:00:14 -0600 Subject: [PATCH 199/219] Comment out the part where identity services can revoke their keys They can't because otherwise 3rd party invites can be rejected by homeservers, as per https://github.com/matrix-org/matrix-doc/issues/1633 --- specification/identity_service_api.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index cb0795939..d438f2c78 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -80,9 +80,11 @@ in a scheme ``algorithm:identifier``, e.g. ``ed25519:0``. When signing an association, the Matrix standard JSON signing format is used, as specified in the server-server API specification under the heading "Signing Events". -In the event of key compromise, the identity service may revoke any of its keys. -An HTTP API is offered to get public keys, and check whether a particular key is -valid. +.. TODO: Actually allow identity services to revoke all keys + See: https://github.com/matrix-org/matrix-doc/issues/1633 +.. In the event of key compromise, the identity service may revoke any of its keys. + An HTTP API is offered to get public keys, and check whether a particular key is + valid. The identity server may also keep track of some short-term public-private keypairs, which may have different usage and lifetime characteristics than the From 356626845ccadabdb5d9239eb80e010c505bde40 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 15:00:52 -0600 Subject: [PATCH 200/219] Remove unhelpful arrow from the 3rd party invite sequence dance This doesn't add anything in terms of clarity. --- specification/modules/third_party_invites.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/specification/modules/third_party_invites.rst b/specification/modules/third_party_invites.rst index a9b06258b..0af81844d 100644 --- a/specification/modules/third_party_invites.rst +++ b/specification/modules/third_party_invites.rst @@ -190,10 +190,6 @@ H3 is attempting to join. | | | (Federation) Emit m.room.member for invite | | | | | |----------------------------------------------->| | | | | | | | | - | | | | Accept event | | - | | | |------------- | | - | | | | | | | - | | | |<------------ | | | | | | | | | | | (Federation) Emit the m.room.member event sent to H2 | | | | |----------------------------------------------------------------->| | From 1f6499d563ab26af66f80a0d946cc0c07aa87176 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 15:01:20 -0600 Subject: [PATCH 201/219] Fix typo --- specification/modules/third_party_invites.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/modules/third_party_invites.rst b/specification/modules/third_party_invites.rst index 0af81844d..248b9ba92 100644 --- a/specification/modules/third_party_invites.rst +++ b/specification/modules/third_party_invites.rst @@ -138,7 +138,7 @@ validate that the public key used for signing is still valid, by checking No other homeservers may reject the joining of the room on the basis of ``key_validity_url``, this is so that all homeservers have a consistent view of -the room. They may, however, indicate to their clients that a member's' +the room. They may, however, indicate to their clients that a member's membership is questionable. For example, given H1, H2, and H3 as homeservers, UserA as a user of H1, and an From 390f1c16f73b94e47ee100c12fd88de31a7d2a14 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 15:27:36 -0600 Subject: [PATCH 202/219] Remove mentions of identity services from /3pid/delete This will be covered by https://github.com/matrix-org/matrix-doc/issues/1194 For now, we can accept that homeservers may try to unbind, however clients should not rely on it. --- api/client-server/administrative_contact.yaml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index c1ecf337e..78e5811b3 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -152,9 +152,8 @@ paths: post: summary: Deletes a third party identifier from the user's account description: |- - Removes a third party identifier from the user's account. The homeserver - should attempt to unbind the identifier from the identity service, if the - homeserver is able to reasonably determine the identity service used. + Removes a third party identifier from the user's account. This may not + cause an unbind of the identifier from the identity service. operationId: delete3pidFromAccount security: - accessToken: [] @@ -181,16 +180,6 @@ paths: user. schema: type: object - properties: - id_server_unbind_result: - type: string - description: |- - The result of the homeserver's attempt to unbind the identifier from - the identity service. ``success`` indicates that the homeserver was - able to unbind the identifier while ``no-support`` means the homeserver - was not able to unbind, likely due to the identity service not supporting - the operation. Defaults to ``no-support``. - example: "success" tags: - User data "/account/3pid/email/requestToken": From 8bcd7d26e349fd464f88282324411b9eced6d15d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 15:28:43 -0600 Subject: [PATCH 203/219] /3pid/delete returns an empty object --- api/client-server/administrative_contact.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index 78e5811b3..f0362f25b 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -180,6 +180,7 @@ paths: user. schema: type: object + properties: {} tags: - User data "/account/3pid/email/requestToken": From caaa688e37750fea10788aced24330cfc283e8f7 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 16:28:26 -0600 Subject: [PATCH 204/219] Fix links to client-server spec --- specification/server_server_api.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index a71240101..76aed91d4 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -1110,9 +1110,9 @@ Example code .. _`Inviting to a room`: #inviting-to-a-room .. _`Canonical JSON`: ../appendices.html#canonical-json .. _`Unpadded Base64`: ../appendices.html#unpadded-base64 -.. _`Server ACLs`: ../client_server/unstable.html#module-server-acls -.. _`redaction algorithm`: ../client_server/unstable.html#redactions +.. _`Server ACLs`: ../client_server/%CLIENT_RELEASE_LABEL%.html#module-server-acls +.. _`redaction algorithm`: ../client_server/%CLIENT_RELEASE_LABEL%.html#redactions .. _`Signing JSON`: ../appendices.html#signing-json .. _`Checking for a signature`: ../appendices.html#checking-for-a-signature -.. _`Device Management module`: ../client-server/%CLIENT_RELEASE_LABEL%.html#device-management -.. _`End-to-End Encryption module`: ../client-server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption +.. _`Device Management module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#device-management +.. _`End-to-End Encryption module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption From 2a08a308f34f7583534e3e9009f390471d1faf07 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 16:29:24 -0600 Subject: [PATCH 205/219] device_keys are required --- api/server-server/user_keys.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/server-server/user_keys.yaml b/api/server-server/user_keys.yaml index 869934331..63c74d20e 100644 --- a/api/server-server/user_keys.yaml +++ b/api/server-server/user_keys.yaml @@ -55,7 +55,7 @@ paths: description: algorithm example: "signed_curve25519" example: { - "@alice:example.com": { + "@alice:example.com": { "JLAFKJWSCS": "signed_curve25519" } } @@ -126,6 +126,7 @@ paths: example: { "@alice:example.com": [] } + required: ['device_keys'] responses: 200: description: The device information. @@ -178,7 +179,7 @@ paths: "@alice:example.com": { "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" } - }, + }, "unsigned": { "device_display_name": "Alice's mobile phone" } From 5da3072eef94129c0da1a216ef34421415c8f242 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 30 Aug 2018 16:32:14 -0600 Subject: [PATCH 206/219] Wording change ('may not' has a special meaning) --- api/client-server/administrative_contact.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/client-server/administrative_contact.yaml b/api/client-server/administrative_contact.yaml index f0362f25b..541df43c8 100644 --- a/api/client-server/administrative_contact.yaml +++ b/api/client-server/administrative_contact.yaml @@ -152,7 +152,7 @@ paths: post: summary: Deletes a third party identifier from the user's account description: |- - Removes a third party identifier from the user's account. This may not + Removes a third party identifier from the user's account. This might not cause an unbind of the identifier from the identity service. operationId: delete3pidFromAccount security: From ebb044674f0b83d41ce4c1a323a813162f3821f8 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 09:51:17 +0100 Subject: [PATCH 207/219] Remove duplicated explanation about event rejection --- specification/server_server_api.rst | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 4c40d6dce..2677cf3a6 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -345,17 +345,6 @@ be inserted. The types of state events that affect authorization are: - ``m.room.join_rules`` - ``m.room.power_levels`` -Servers should not create new events that reference unauthorized events. -However, any event that does reference an unauthorized event is not itself -automatically considered unauthorized. - -Unauthorized events that appear in the event graph do *not* have any effect on -the state of the room. - -.. Note:: This is in contrast to redacted events which can still affect the - state of the room. For example, a redacted ``join`` event will still - result in the user being considered joined. - The rules are as follows: 1. If type is ``m.room.create``, allow if and only if it has no From 6c8a45c165f72884bfc53a90566d77c495529ee0 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 09:57:00 +0100 Subject: [PATCH 208/219] Full stops --- specification/server_server_api.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index e6e4625c4..a69273eba 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -358,18 +358,18 @@ The rules are as follows: 1. If type is ``m.room.create``: - a. Reject if it has any previous events + a. Reject if it has any previous events. b. Reject if the domain of the ``room_id`` does not match the domain of the ``sender``. - c. Reject if ``content.room_version`` key is an unrecognized version + c. Reject if ``content.room_version`` key is an unrecognized version. d. Otherwise, allow. -#. Reject if event does not have a ``m.room.create`` in its ``auth_events`` +#. Reject if event does not have a ``m.room.create`` in its ``auth_events``. #. If type is ``m.room.aliases``: - a. Reject if event has no ``state_key`` - b. Allow if and only if sender's domain matches ``state_key`` + a. Reject if event has no ``state_key``. + b. Allow if and only if sender's domain matches ``state_key``. #. If type is ``m.room.member``: From f3aea32a243c04e79f52304273ab0050ed967872 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 09:59:45 +0100 Subject: [PATCH 209/219] Be consistent with 'If..., reject' --- specification/server_server_api.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index a69273eba..a72f5dc65 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -358,22 +358,23 @@ The rules are as follows: 1. If type is ``m.room.create``: - a. Reject if it has any previous events. - b. Reject if the domain of the ``room_id`` does not match the domain of the - ``sender``. - c. Reject if ``content.room_version`` key is an unrecognized version. + a. If it has any previous events, reject. + b. If the domain of the ``room_id`` does not match the domain of the + ``sender``, reject. + c. If ``content.room_version`` key is an unrecognised version, reject. d. Otherwise, allow. -#. Reject if event does not have a ``m.room.create`` in its ``auth_events``. +#. If event does not have a ``m.room.create`` in its ``auth_events``, reject. #. If type is ``m.room.aliases``: - a. Reject if event has no ``state_key``. - b. Allow if and only if sender's domain matches ``state_key``. + a. If event has no ``state_key``, reject + b. If sender's domain doesn't matches ``state_key``, reject. + c. Otherwise, allow. #. If type is ``m.room.member``: - a. Reject if no ``state_key`` key or ``membership`` key in ``content``. + a. If no ``state_key`` key or ``membership`` key in ``content``, reject. #. If ``membership`` is ``join``: From f4706c888986e3e20aa9c4a7b4a3bd77d8812c4b Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 10:06:26 +0100 Subject: [PATCH 210/219] Require creator field --- specification/server_server_api.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index a72f5dc65..54b6e07ca 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -362,7 +362,8 @@ The rules are as follows: b. If the domain of the ``room_id`` does not match the domain of the ``sender``, reject. c. If ``content.room_version`` key is an unrecognised version, reject. - d. Otherwise, allow. + d. If ``content`` has no ``creator`` field, reject. + e. Otherwise, allow. #. If event does not have a ``m.room.create`` in its ``auth_events``, reject. From 59f86ec8f2a3b7b07b742ccf5706b44d30c65767 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 10:07:53 +0100 Subject: [PATCH 211/219] Reindent as RST requires sublists to be three spaces --- specification/server_server_api.rst | 128 ++++++++++++++-------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 54b6e07ca..b82901bed 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -358,80 +358,80 @@ The rules are as follows: 1. If type is ``m.room.create``: - a. If it has any previous events, reject. - b. If the domain of the ``room_id`` does not match the domain of the - ``sender``, reject. - c. If ``content.room_version`` key is an unrecognised version, reject. - d. If ``content`` has no ``creator`` field, reject. - e. Otherwise, allow. + a. If it has any previous events, reject. + b. If the domain of the ``room_id`` does not match the domain of the + ``sender``, reject. + c. If ``content.room_version`` key is an unrecognised version, reject. + d. If ``content`` has no ``creator`` field, reject. + e. Otherwise, allow. #. If event does not have a ``m.room.create`` in its ``auth_events``, reject. #. If type is ``m.room.aliases``: - a. If event has no ``state_key``, reject - b. If sender's domain doesn't matches ``state_key``, reject. - c. Otherwise, allow. + a. If event has no ``state_key``, reject + b. If sender's domain doesn't matches ``state_key``, reject. + c. Otherwise, allow. #. If type is ``m.room.member``: - a. If no ``state_key`` key or ``membership`` key in ``content``, reject. + a. If no ``state_key`` key or ``membership`` key in ``content``, reject. - #. If ``membership`` is ``join``: + #. If ``membership`` is ``join``: - i. If the only previous event is an ``m.room.create`` - and the ``state_key`` is the creator, allow. + i. If the only previous event is an ``m.room.create`` + and the ``state_key`` is the creator, allow. - #. If the ``sender`` does not match ``state_key``, reject. + #. If the ``sender`` does not match ``state_key``, reject. - #. If the ``sender`` is banned, reject. + #. If the ``sender`` is banned, reject. - #. If the ``join_rule`` is ``invite`` then allow if membership state - is ``invite`` or ``join``. + #. If the ``join_rule`` is ``invite`` then allow if membership state + is ``invite`` or ``join``. - #. If the ``join_rule`` is ``public``, allow. + #. If the ``join_rule`` is ``public``, allow. - #. Otherwise, reject. + #. Otherwise, reject. - #. If ``membership`` is ``invite``: + #. If ``membership`` is ``invite``: - i. If the ``sender``'s current membership state is not ``join``, reject. + i. If the ``sender``'s current membership state is not ``join``, reject. - #. If *target user*'s current membership state is ``join`` or ``ban``, - reject. + #. If *target user*'s current membership state is ``join`` or ``ban``, + reject. - #. If the ``sender``'s power level is greater than or equal to the *invite - level*, allow. + #. If the ``sender``'s power level is greater than or equal to the *invite + level*, allow. - #. Otherwise, reject. + #. Otherwise, reject. - #. If ``membership`` is ``leave``: + #. If ``membership`` is ``leave``: - i. If the ``sender`` matches ``state_key``, allow if and only if that user's - current membership state is ``invite`` or ``join``. + i. If the ``sender`` matches ``state_key``, allow if and only if that user's + current membership state is ``invite`` or ``join``. - #. If the ``sender``'s current membership state is not ``join``, reject. + #. If the ``sender``'s current membership state is not ``join``, reject. - #. If the *target user*'s current membership state is ``ban``, and the - ``sender``'s power level is less than the *ban level*, reject. + #. If the *target user*'s current membership state is ``ban``, and the + ``sender``'s power level is less than the *ban level*, reject. - #. If the ``sender``'s power level is greater than or equal to the *kick - level*, and the *target user*'s power level is less than the - ``sender``'s power level, allow. + #. If the ``sender``'s power level is greater than or equal to the *kick + level*, and the *target user*'s power level is less than the + ``sender``'s power level, allow. - #. Otherwise, reject. + #. Otherwise, reject. - #. If ``membership`` is ``ban``: + #. If ``membership`` is ``ban``: - i. If the ``sender``'s current membership state is not ``join``, reject. + i. If the ``sender``'s current membership state is not ``join``, reject. - #. If the ``sender``'s power level is greater than or equal to the *ban - level*, and the *target user*'s power level is less than the - ``sender``'s power level, allow. + #. If the ``sender``'s power level is greater than or equal to the *ban + level*, and the *target user*'s power level is less than the + ``sender``'s power level, allow. - #. Otherwise, reject. + #. Otherwise, reject. - #. Otherwise, the membership is unknown. Reject. + #. Otherwise, the membership is unknown. Reject. #. If the ``sender``'s current membership state is not ``join``, reject. @@ -443,39 +443,39 @@ The rules are as follows: #. If type is ``m.room.power_levels``: - a. If ``users`` key in ``content`` is not a dictionary with keys that are - valid user IDs with values that are integers (or a string that is an - integer), reject. + a. If ``users`` key in ``content`` is not a dictionary with keys that are + valid user IDs with values that are integers (or a string that is an + integer), reject. - #. If there is no previous ``m.room.power_levels`` event in the room, allow. + #. If there is no previous ``m.room.power_levels`` event in the room, allow. - #. For each of the keys ``users_default``, ``events_default``, - ``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as - each entry being changed under the ``events`` or ``users`` keys: + #. For each of the keys ``users_default``, ``events_default``, + ``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as + each entry being changed under the ``events`` or ``users`` keys: - i. If the current value is higher than the ``sender``'s current power level, - reject. + i. If the current value is higher than the ``sender``'s current power level, + reject. - #. If the new value is higher than the ``sender``'s current power level, - reject. + #. If the new value is higher than the ``sender``'s current power level, + reject. - #. For each entry being changed under the ``users`` key, other than the - ``sender``'s own entry: + #. For each entry being changed under the ``users`` key, other than the + ``sender``'s own entry: - i. If the current value is equal to the ``sender``'s current power level, - reject. + i. If the current value is equal to the ``sender``'s current power level, + reject. - #. Otherwise, allow. + #. Otherwise, allow. #. If type is ``m.room.redaction``: - a. If the ``sender``'s power level is greater than or equal to the *redact - level*, allow. + a. If the ``sender``'s power level is greater than or equal to the *redact + level*, allow. - #. If the domain of the ``event_id`` of the event being redacted is the same - as the domain of the ``event_id`` of the ``m.room.redaction``, allow. + #. If the domain of the ``event_id`` of the event being redacted is the same + as the domain of the ``event_id`` of the ``m.room.redaction``, allow. - #. Otherwise, reject. + #. Otherwise, reject. #. Otherwise, allow. From 1a45bc4a8591365fd0ab8616d0194a49e21a4913 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 10:24:51 +0100 Subject: [PATCH 212/219] Reword --- specification/server_server_api.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index a2a2274d0..29d104d9e 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -303,11 +303,12 @@ following subset of the room state: - If type is ``m.room.member``: - The target's current ``m.room.member`` event, if any. - - If ``join`` or ``invite`` then the current ``m.room.join_rules`` event, - if any. - - If ``invite`` with ``third_party_invite`` in ``content``, then add - ``m.room.third_party_invite`` with state_key of ``token`` in ``signed`` - field of ``third_party_invite``, if any. + - If membership is ``join`` or ``invite``, the current ``m.room.join_rules`` + event, if any. + - If membership is ``invite`` and ``content`` contains a + ``third_party_invite`` property, the current + ``m.room.third_party_invite`` with state_key matching + ``content.third_party_invite.signed.token``, if any. {{definition_ss_pdu}} From 3c53e1910d87750ef1b8844298dc1e720aba6620 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 10:51:59 +0100 Subject: [PATCH 213/219] Fixup --- specification/server_server_api.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index f2d14738b..a9c2b1fb9 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -396,27 +396,27 @@ The rules are as follows: i. If ``content`` has ``third_party_invite`` key: - #. Reject if *target user* is banned. + #. If *target user* is banned, reject. - #. Reject if ``content.third_party_invite`` does not have a - ``signed`` key. + #. If ``content.third_party_invite`` does not have a + ``signed`` key, reject. - #. Reject if ``signed`` does not have ``mxid`` and ``token`` keys. + #. If ``signed`` does not have ``mxid`` and ``token`` keys, reject. - #. Reject if ``mxid`` does not match ``state_key`` + #. If ``mxid`` does not match ``state_key``, reject. - #. Reject if no ``m.room.third_party_invite`` event in - current state with ``state_key`` matching ``token``. + #. If no ``m.room.third_party_invite`` event in current state with + ``state_key`` matching ``token``, reject. - #. Reject if ``sender`` does not match ``sender`` of third party - invite. + #. If ``sender`` does not match ``sender`` of third party invite, + reject. - #. If any signature in ``signed`` matches any public key in third - party invite, allow. The public keys are in ``content`` of - third party invite under: + #. If any signature in ``signed`` matches any public key in the + ``m.room.third_party_invite``, allow. The public keys are in + ``content`` of ``m.room.third_party_invite`` as: - #. A single public key in ``public_key`` field - #. A list of public keys in ``public_keys`` field + #. A single public key in the ``public_key`` field. + #. A list of public keys in the ``public_keys`` field. #. Otherwise, reject. From d63184ebacc9ff16a620152fb9b057405fd91326 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 10:59:42 +0100 Subject: [PATCH 214/219] Fixup --- specification/server_server_api.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index b82901bed..4b099e11c 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -361,7 +361,8 @@ The rules are as follows: a. If it has any previous events, reject. b. If the domain of the ``room_id`` does not match the domain of the ``sender``, reject. - c. If ``content.room_version`` key is an unrecognised version, reject. + c. If ``content.room_version`` is present and is not a recognised version, + reject. d. If ``content`` has no ``creator`` field, reject. e. Otherwise, allow. @@ -369,7 +370,7 @@ The rules are as follows: #. If type is ``m.room.aliases``: - a. If event has no ``state_key``, reject + a. If event has no ``state_key``, reject. b. If sender's domain doesn't matches ``state_key``, reject. c. Otherwise, allow. From a1aedb386a5ce8ca20bbc2bd79de35262306eb88 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 11:04:44 +0100 Subject: [PATCH 215/219] Actually use proper sentences like a proper adult --- specification/server_server_api.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index a9c2b1fb9..c225874ed 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -405,15 +405,15 @@ The rules are as follows: #. If ``mxid`` does not match ``state_key``, reject. - #. If no ``m.room.third_party_invite`` event in current state with - ``state_key`` matching ``token``, reject. + #. If there is no ``m.room.third_party_invite`` event in the + current room state with ``state_key`` matching ``token``, reject. - #. If ``sender`` does not match ``sender`` of third party invite, - reject. + #. If ``sender`` does not match ``sender`` of the + ``m.room.third_party_invite``, reject. #. If any signature in ``signed`` matches any public key in the - ``m.room.third_party_invite``, allow. The public keys are in - ``content`` of ``m.room.third_party_invite`` as: + ``m.room.third_party_invite`` event, allow. The public keys are + in ``content`` of ``m.room.third_party_invite`` as: #. A single public key in the ``public_key`` field. #. A list of public keys in the ``public_keys`` field. From 4d653748d60abfb631ed1c8fbbd3c5a19eca7721 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 11:17:58 +0100 Subject: [PATCH 216/219] Add note back in --- specification/server_server_api.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 2677cf3a6..19f0fb78a 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -478,6 +478,12 @@ transaction request to be responded to with an error response. This means that events may be included in the room DAG even though they should be rejected. +.. NOTE:: + + This is in contrast to redacted events which can still affect the + state of the room. For example, a redacted ``join`` event will still + result in the user being considered joined. + Retrieving event authorization information ++++++++++++++++++++++++++++++++++++++++++ From d91dc6fbf628dc2e021abb5cc89d92cd6b3a2c89 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 11:20:26 +0100 Subject: [PATCH 217/219] Fixup --- specification/server_server_api.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 29d104d9e..727ac493c 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -303,11 +303,11 @@ 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 ``m.room.join_rules`` - event, if any. + - If ``membership`` is ``join`` or ``invite``, the current + ``m.room.join_rules`` event, if any. - If membership is ``invite`` and ``content`` contains a ``third_party_invite`` property, the current - ``m.room.third_party_invite`` with state_key matching + ``m.room.third_party_invite`` event with ``state_key`` matching ``content.third_party_invite.signed.token``, if any. {{definition_ss_pdu}} From b6ed25e4b4b2810f2a09582d9dce45821f967a33 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 11:32:29 +0100 Subject: [PATCH 218/219] Fix incorrect indent --- specification/server_server_api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index fbf483932..5eacba8a0 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -434,7 +434,7 @@ The rules are as follows: #. A single public key in the ``public_key`` field. #. A list of public keys in the ``public_keys`` field. - #. Otherwise, reject. + #. Otherwise, reject. #. If the ``sender``'s current membership state is not ``join``, reject. From 080845ac1c50dcc3479c819abced912aa20a8cd5 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 31 Aug 2018 11:53:21 +0100 Subject: [PATCH 219/219] Add link to previous section --- specification/server_server_api.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index e5bff6982..74704faf6 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -308,6 +308,8 @@ creating a new event in this room should populate the new event's | E4 +.. _`auth events selection`: + The ``auth_events`` field of a PDU identifies the set of events which give the sender permission to send the event. The ``auth_events`` for the ``m.room.create`` event in a room is empty; for other events, it should be the @@ -384,7 +386,7 @@ The rules are as follows: a. have duplicate entries for a given ``type`` and ``state_key`` pair #. have entries whose ``type`` and ``state_key`` don't match those - specified by the algorithm described previously. + specified by the `auth events selection`_ algorithm described above. #. If event does not have a ``m.room.create`` in its ``auth_events``, reject.