diff --git a/README.md b/README.md index c13d4eafd..75f55affa 100644 --- a/README.md +++ b/README.md @@ -5,44 +5,44 @@ This repository contains the Matrix Specification, rendered at [spec.matrix.org] Developers looking to use Matrix should join [#matrix-dev:matrix.org](https://matrix.to/#/#matrix-dev:matrix.org) on Matrix for help. -Spec authors and proposal writers are welcome to join [#matrix-spec:matrix.org](https://matrix.to/#/#matrix-spec:matrix.org). +Spec authors and proposal writers are welcome to join [#matrix-spec:matrix.org](https://matrix.to/#/#matrix-spec:matrix.org). We welcome contributions! See [CONTRIBUTING.rst](./CONTRIBUTING.rst) for details. ## Structure The Matrix spec is compiled with [Hugo](https://gohugo.io/) (a static site generator) with the following structure: -* `/assets`: assets that need postprocessing using [Hugo Pipes](https://gohugo.io/hugo-pipes/introduction/). +* `/assets`: assets that need postprocessing using [Hugo Pipes](https://gohugo.io/hugo-pipes/introduction/). For example, Sass files would go here. -* `/content`: files that will become pages in the site go here. Typically these are Markdown files with some YAML front - matter indicating, [among other things](https://gohugo.io/content-management/front-matter/), what layout should be - applied to this page. The organization of files under `/content` determines the organization of pages in the built +* `/content`: files that will become pages in the site go here. Typically these are Markdown files with some YAML front + matter indicating, [among other things](https://gohugo.io/content-management/front-matter/), what layout should be + applied to this page. The organization of files under `/content` determines the organization of pages in the built site. -* `/data`: this can contain TOML, YAML, or JSON files. Files kept here are directly available to template code as - [data objects](https://gohugo.io/templates/data-templates/), so templates don't need to load them from a file and +* `/data`: this can contain TOML, YAML, or JSON files. Files kept here are directly available to template code as + [data objects](https://gohugo.io/templates/data-templates/), so templates don't need to load them from a file and parse them. This is also where our Swagger/OpenAPI definitions and schemas are. -* `/layouts`: this contains [Hugo templates](https://gohugo.io/templates/). Some templates define the overall layout of +* `/layouts`: this contains [Hugo templates](https://gohugo.io/templates/). Some templates define the overall layout of a page: for example, whether it has header, footer, sidebar, and so on. - * `/layouts/partials`: these templates can be called from other templates, so they can be used to factor out - template code that's used in more than one template. An obvious example here is something like a sidebar, where - several different page layouts might all include the sidebar. But also, partial templates can return values: this + * `/layouts/partials`: these templates can be called from other templates, so they can be used to factor out + template code that's used in more than one template. An obvious example here is something like a sidebar, where + several different page layouts might all include the sidebar. But also, partial templates can return values: this means they can be used like functions, that can be called by multiple templates to do some common processing. * `/layouts/shortcodes`: these templates can be called directly from files in `/content`. * `/static`: static files which don't need preprocessing. JS or CSS files could live here. -* `/themes`: you can use just Hugo or use it with a theme. Themes primarily provide additional templates, which are - supplied in a `/themes/$theme_name/layouts` directory. You can use a theme but customise it by providing your own - versions of any of the theme layouts in the base `/layouts` directory. That is, if a theme provides - `/themes/$theme_name/layouts/sidebar.html` and you provide `/layouts/sidebar.html`, then your version of the +* `/themes`: you can use just Hugo or use it with a theme. Themes primarily provide additional templates, which are + supplied in a `/themes/$theme_name/layouts` directory. You can use a theme but customise it by providing your own + versions of any of the theme layouts in the base `/layouts` directory. That is, if a theme provides + `/themes/$theme_name/layouts/sidebar.html` and you provide `/layouts/sidebar.html`, then your version of the template will be used. It also has the following top-level file: -* `config.toml`: site-wide configuration settings. Some of these are built-in and you can add your own. Config settings +* `config.toml`: site-wide configuration settings. Some of these are built-in and you can add your own. Config settings defined here are available in templates. All these directories above are configurable via `config.toml` settings. Additionally, the following directories may be of interest: @@ -59,34 +59,40 @@ Additionally, the following directories may be of interest: Please read [CONTRIBUTING.rst](./CONTRIBUTING.rst) before authoring a change to the spec. Note that spec authoring takes place after an MSC has been accepted, not as part of a proposal itself. -1. Install the extended version (often the OS default) of Hugo: +1. Install the extended version (often the OS default) of Hugo: + . Note that at least Hugo + v0.74 is required. + + Alternatively, use the Docker image at https://hub.docker.com/r/klakegg/hugo/. 2. Run `git submodule update --init --recursive` for good measure. 3. Run `npm i` to install the dependencies. Note that this will require NodeJS to be installed. 4. Run `npm run get-proposals` to seed proposal data. This is merely for populating the content of the "Spec Change Proposals" page and is not required. -5. Run `hugo serve` to run a local webserver which builds whenever a file change is detected. If watching doesn't appear - to be working for you, try `hugo serve --disableFastRender` instead. +5. Run `hugo serve` (or `docker run --rm -it -v $(pwd):/src -p 1313:1313 + klakegg/hugo serve`) to run a local webserver which builds whenever a file + change is detected. If watching doesn't appear to be working for you, try + adding `--disableFastRender` to the commandline. 6. Edit the specification 🙂 -We use a highly customized [Docsy](https://www.docsy.dev/) theme for our generated site, which uses Bootstrap and Font -Awesome. If you're looking at making design-related changes to the spec site, please coordinate with us in +We use a highly customized [Docsy](https://www.docsy.dev/) theme for our generated site, which uses Bootstrap and Font +Awesome. If you're looking at making design-related changes to the spec site, please coordinate with us in [#matrix-docs:matrix.org](https://matrix.to/#/#matrix-docs:matrix.org) before opening a PR. ## Building the specification -If for some reason you're not a CI/CD system and want to render a static version of the spec for yourself, follow the above -steps for authoring changes to the specification and instead of `hugo serve` run `hugo -d "spec"` - this will generate the -spec to `/spec`. If you'd like to serve the spec off a path instead of a domain root (eg: `/unstable`), add `--baseURL "/unstable"` +If for some reason you're not a CI/CD system and want to render a static version of the spec for yourself, follow the above +steps for authoring changes to the specification and instead of `hugo serve` run `hugo -d "spec"` - this will generate the +spec to `/spec`. If you'd like to serve the spec off a path instead of a domain root (eg: `/unstable`), add `--baseURL "/unstable"` to the `hugo -d "spec"` command. -For building the swagger definitions, create a python3 virtualenv and activate it. Then run `pip install -r ./scripts/requirements.txt` -and finally `python ./scripts/dump-swagger.py` to generate it to `./scripts/swagger/api-docs.json`. To make use of the generated file, +For building the swagger definitions, create a python3 virtualenv and activate it. Then run `pip install -r ./scripts/requirements.txt` +and finally `python ./scripts/dump-swagger.py` to generate it to `./scripts/swagger/api-docs.json`. To make use of the generated file, there are a number of options: * It can be uploaded from your filesystem to an online editor/viewer such as [on the swagger website](http://editor.swagger.io/). * You can run a local HTTP server by running `./scripts/swagger-http-server.py`, and then view the documentation via an online viewer; for example, at . -* You can host the swagger UI yourself. See for advice on how to +* You can host the swagger UI yourself. See for advice on how to do so. ## Issue tracking diff --git a/assets-hugo/scss/custom.scss b/assets-hugo/scss/custom.scss index 3116762ed..62ae4532f 100644 --- a/assets-hugo/scss/custom.scss +++ b/assets-hugo/scss/custom.scss @@ -45,9 +45,6 @@ Custom SCSS for the Matrix spec scroll-behavior: smooth; overscroll-behavior: contain; - /* This overrides calc(100vh - 10rem);, which gives us a blank space at the bottom of the sidebar */ - max-height: calc(100vh - 6rem); - &>.td-sidebar-nav__section { margin-top: 1rem; } @@ -92,6 +89,15 @@ Custom SCSS for the Matrix spec } } +@media (min-width: 768px) { + @supports (position: sticky) { + .td-sidebar-nav { + /* This overrides calc(100vh - 10rem);, which gives us a blank space at the bottom of the sidebar */ + max-height: calc(100vh - 6rem); + } + } +} + /* Customise footer */ footer { box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25); diff --git a/changelogs/client_server/newsfragments/3199.deprecaation b/changelogs/client_server/newsfragments/3199.deprecaation new file mode 100644 index 000000000..6b51df6e3 --- /dev/null +++ b/changelogs/client_server/newsfragments/3199.deprecaation @@ -0,0 +1 @@ +Deprecate starting verifications that don't start with `m.key.verification.request` as per [MSC3122](https://github.com/matrix-org/matrix-doc/pull/3122). diff --git a/changelogs/client_server/newsfragments/3225.clarification b/changelogs/client_server/newsfragments/3225.clarification new file mode 100644 index 000000000..046b25cf1 --- /dev/null +++ b/changelogs/client_server/newsfragments/3225.clarification @@ -0,0 +1 @@ +Update `Access-Control-Allow-Headers` recommendation to fit CORS specification. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/3233.clarification b/changelogs/client_server/newsfragments/3233.clarification new file mode 100644 index 000000000..72a58f1b6 --- /dev/null +++ b/changelogs/client_server/newsfragments/3233.clarification @@ -0,0 +1 @@ +Explicitly state that `replacment_room` is a room ID in `m.room.tombstone` events. diff --git a/changelogs/client_server/newsfragments/3238.clarification b/changelogs/client_server/newsfragments/3238.clarification new file mode 100644 index 000000000..63e54ba6c --- /dev/null +++ b/changelogs/client_server/newsfragments/3238.clarification @@ -0,0 +1 @@ +Clarify that all request bodies are required. diff --git a/changelogs/client_server/newsfragments/3254.feature b/changelogs/client_server/newsfragments/3254.feature new file mode 100644 index 000000000..c73c27ec6 --- /dev/null +++ b/changelogs/client_server/newsfragments/3254.feature @@ -0,0 +1 @@ +Add support for knocking, as per [MSC2403](https://github.com/matrix-org/matrix-doc/pull/2403). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/3327.breaking b/changelogs/client_server/newsfragments/3327.breaking new file mode 100644 index 000000000..85c0da8ba --- /dev/null +++ b/changelogs/client_server/newsfragments/3327.breaking @@ -0,0 +1 @@ +Fix key_backup operation IDs in OpenAPI spec. diff --git a/changelogs/client_server/newsfragments/3330.clarification b/changelogs/client_server/newsfragments/3330.clarification new file mode 100644 index 000000000..5df676a14 --- /dev/null +++ b/changelogs/client_server/newsfragments/3330.clarification @@ -0,0 +1 @@ +Add titles for OpenAPI objects. diff --git a/changelogs/client_server/newsfragments/3331.clarification b/changelogs/client_server/newsfragments/3331.clarification new file mode 100644 index 000000000..4e0836b88 --- /dev/null +++ b/changelogs/client_server/newsfragments/3331.clarification @@ -0,0 +1 @@ +Add auth property to UIA endpoint uploadCrossSigningKeys. diff --git a/changelogs/client_server/newsfragments/3332.clarification b/changelogs/client_server/newsfragments/3332.clarification new file mode 100644 index 000000000..63e54ba6c --- /dev/null +++ b/changelogs/client_server/newsfragments/3332.clarification @@ -0,0 +1 @@ +Clarify that all request bodies are required. diff --git a/changelogs/client_server/newsfragments/3336.clarification b/changelogs/client_server/newsfragments/3336.clarification new file mode 100644 index 000000000..bb06ffec9 --- /dev/null +++ b/changelogs/client_server/newsfragments/3336.clarification @@ -0,0 +1 @@ +Disambiguate getEvents and peekEvents, and include both in swagger. diff --git a/changelogs/client_server/newsfragments/3337.clarification b/changelogs/client_server/newsfragments/3337.clarification new file mode 100644 index 000000000..9f8eb2f25 --- /dev/null +++ b/changelogs/client_server/newsfragments/3337.clarification @@ -0,0 +1 @@ +Mention that a canonical alias event should be added when a room is created with an alias. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/3339.clarification b/changelogs/client_server/newsfragments/3339.clarification new file mode 100644 index 000000000..3ccb23339 --- /dev/null +++ b/changelogs/client_server/newsfragments/3339.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/changelogs/client_server/newsfragments/3350.clarification b/changelogs/client_server/newsfragments/3350.clarification new file mode 100644 index 000000000..c5524f19b --- /dev/null +++ b/changelogs/client_server/newsfragments/3350.clarification @@ -0,0 +1 @@ +Add an 'API conventions' section to the Appendices. \ No newline at end of file diff --git a/changelogs/identity_service/newsfragments/3167.clarification b/changelogs/identity_service/newsfragments/3167.clarification index cc70fd710..16ed8dcdd 100644 --- a/changelogs/identity_service/newsfragments/3167.clarification +++ b/changelogs/identity_service/newsfragments/3167.clarification @@ -1 +1 @@ -Clarify that some identifiers may be lowercase prior to processing, as per [MSC2265](https://github.com/matrix-org/matrix-doc/pull/2265). \ No newline at end of file +Clarify that some identifiers must be case folded prior to processing, as per [MSC2265](https://github.com/matrix-org/matrix-doc/pull/2265). diff --git a/changelogs/identity_service/newsfragments/3176.clarification b/changelogs/identity_service/newsfragments/3176.clarification new file mode 100644 index 000000000..50fb7cd12 --- /dev/null +++ b/changelogs/identity_service/newsfragments/3176.clarification @@ -0,0 +1 @@ +Clarify that some identifiers must be case folded prior to processing, as per [MSC2265](https://github.com/matrix-org/matrix-doc/pull/2265). \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/3207.clarification b/changelogs/server_server/newsfragments/3207.clarification new file mode 100644 index 000000000..3ccb23339 --- /dev/null +++ b/changelogs/server_server/newsfragments/3207.clarification @@ -0,0 +1 @@ +Fix various typos throughout the specification. diff --git a/changelogs/server_server/newsfragments/3312.clarification b/changelogs/server_server/newsfragments/3312.clarification new file mode 100644 index 000000000..a9e1fe8df --- /dev/null +++ b/changelogs/server_server/newsfragments/3312.clarification @@ -0,0 +1 @@ +Correct the `/_matrix/federation/v1/user/devices/{userId}` response which actually returns `"self_signing_key"` instead of `"self_signing_keys"`. diff --git a/changelogs/server_server/newsfragments/3322.clarification b/changelogs/server_server/newsfragments/3322.clarification new file mode 100644 index 000000000..fdcd7db9b --- /dev/null +++ b/changelogs/server_server/newsfragments/3322.clarification @@ -0,0 +1 @@ +Explain the reasons why `` TLS certificate is needed rather than `` for SRV delegation. \ No newline at end of file diff --git a/config.toml b/config.toml index 1e4cb70e7..c18c024eb 100644 --- a/config.toml +++ b/config.toml @@ -43,7 +43,13 @@ privacy_policy = "https://matrix.org/legal/privacy-notice" # must be one of "unstable", "current", "historical" # this is used to decide whether to show a banner pointing to the current release status = "unstable" +# A URL pointing to the latest, stable release of the spec. To be shown in the unstable version warning banner. current_version_url = "https://matrix.org/docs/spec/" +# The following is used when status = "stable", and is displayed in various UI elements on a released version +# of the spec. CI will set these values here automatically when a release git tag (i.e `v1.5`) is created. +#major = "1" +#minor = "0" +#release_date = "April 01, 2021" # User interface configuration [params.ui] diff --git a/content/_index.md b/content/_index.md index 4f7c30515..b6cca494f 100644 --- a/content/_index.md +++ b/content/_index.md @@ -328,7 +328,7 @@ Federation maintains *shared data structures* per-room between multiple homeservers. The data is split into `message events` and `state events`. Message events: -These describe transient 'once-off' activity in a room such as an +These describe transient 'one-off' activity in a room such as an instant messages, VoIP call setups, file transfers, etc. They generally describe communication activity. diff --git a/content/appendices.md b/content/appendices.md index aa19aeaed..b97b1f91d 100644 --- a/content/appendices.md +++ b/content/appendices.md @@ -756,11 +756,11 @@ Represents E-Mail addresses. The `address` is the raw email address in other text such as real name, angle brackets or a mailto: prefix. In addition to lowercasing the domain component of an email address, -implementations are expected to lowercase the localpart as described -in [the unicode mapping file](https://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt) -prior to any processing. For example, `Strauß@Example.com` must be -considered to be `strauss@example.com` while processing the email -address. +implementations are expected to apply the unicode case-folding algorithm +as described under "Caseless Matching" in +[chapter 5 of the unicode standard](https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf#G21790). +For example, `Strauß@Example.com` must be considered to be `strauss@example.com` +while processing the email address. ### PSTN Phone numbers @@ -1039,3 +1039,22 @@ The event signing algorithm should emit the following signed event: } } ``` + +## Conventions for Matrix APIs + +This section is intended primarily to guide API designers when adding to Matrix, +setting guidelines to follow for how those APIs should work. This is important to +maintain consistency with the Matrix protocol, and thus improve developer +experience. + +### HTTP endpoint and JSON property naming + +The names of the API endpoints for the HTTP transport follow a convention of +using underscores to separate words (for example `/delete_devices`). + +The key names in JSON objects passed over the API also follow this convention. + +{{% boxes/note %}} +There are a few historical exceptions to this rule, such as `/createRoom`. +These inconsistencies may be addressed in future versions of this specification. +{{% /boxes/note %}} diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 07fe9d962..b81cb6080 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -4,7 +4,7 @@ weight: 10 type: docs --- -The client-server API provides a simple lightweight API to let clients +The client-server API allows clients to send messages, control rooms and synchronise conversation history. It is designed to support both lightweight clients which store no state and lazy-load data from the server as required - as well as heavyweight @@ -20,20 +20,15 @@ supported as optional extensions - e.g. a packed binary encoding over stream-cipher encrypted TCP socket for low-bandwidth/low-roundtrip mobile usage. For the default HTTP transport, all API calls use a Content-Type of `application/json`. In addition, all strings MUST be -encoded as UTF-8. Clients are authenticated using opaque `access_token` -strings (see [Client Authentication](#client-authentication) for -details), passed as a query string parameter on all requests. +encoded as UTF-8. -The names of the API endpoints for the HTTP transport follow a -convention of using underscores to separate words (for example -`/delete_devices`). The key names in JSON objects passed over the API -also follow this convention. +Clients are authenticated using opaque `access_token` strings (see [Client +Authentication](#client-authentication) for details). -{{% boxes/note %}} -There are a few historical exceptions to this rule, such as -`/createRoom`. A future version of this specification will address the -inconsistency. -{{% /boxes/note %}} +See also [Conventions for Matrix APIs](/appendices#conventions-for-matrix-apis) +in the Appendices for conventions which all Matrix APIs are expected to follow. + +### Standard error response Any errors which occur at the Matrix API level MUST return a "standard error response". This is a JSON object which looks like: @@ -46,15 +41,17 @@ error response". This is a JSON object which looks like: ``` 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`. These error codes should have their namespace first in -ALL CAPS, followed by a single \_ to ease separating the namespace from -the error code. For example, if there was a custom namespace -`com.mydomain.here`, and a `FORBIDDEN` code, the error code should look -like `COM.MYDOMAIN.HERE_FORBIDDEN`. There may be additional keys -depending on the error, but the keys `error` and `errcode` MUST always -be present. +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`. Error codes should have their namespace +first in ALL CAPS, followed by a single `_`. For example, if there was a custom +namespace `com.mydomain.here`, and a `FORBIDDEN` code, the error code should +look like `COM.MYDOMAIN.HERE_FORBIDDEN`. Error codes defined by this +specification should start `M_`. + +Some `errcode`s define additional keys which should be present in the error +response object, but the keys `error` and `errcode` MUST always be present. Errors are generally best expressed by their error code rather than the HTTP status code returned. When encountering the error code `M_UNKNOWN`, @@ -66,7 +63,9 @@ found. However, if the client were to receive an error code of `M_UNKNOWN` with a 400 Bad Request, the client should assume that the request being made was invalid. -The common error codes are: +#### Common error codes + +These error codes can be returned by any API endpoint: `M_FORBIDDEN` Forbidden access, e.g. joining a room without permission, failed login. @@ -98,7 +97,11 @@ then try again. `M_UNKNOWN` An unknown error has occurred. -Other error codes the client might encounter are: +#### Other error codes + +The following error codes are specific to certain endpoints. + +. `M_UNRECOGNIZED` The server did not understand the request. @@ -226,7 +229,7 @@ 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 + Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization ## Server Discovery diff --git a/content/client-server-api/modules/end_to_end_encryption.md b/content/client-server-api/modules/end_to_end_encryption.md index bbacad6e5..cbd4f161b 100644 --- a/content/client-server-api/modules/end_to_end_encryption.md +++ b/content/client-server-api/modules/end_to_end_encryption.md @@ -528,7 +528,9 @@ method, then the verification should be cancelled with a `code` of `m.unexpected_message`. An `m.key.verification.start` message can also be sent independently of any -request, specifying the verification method to use. +request, specifying the verification method to use. This behaviour is +deprecated, and new clients should not begin verifications in this way. +However, clients should handle such verifications started by other clients. Individual verification methods may add additional steps, events, and properties to the verification messages. Event types for methods defined diff --git a/content/server-server-api.md b/content/server-server-api.md index e87e80852..763c0e68f 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -134,6 +134,15 @@ to send. The process overall is as follows: 8448 and a `Host` header containing the ``. The target server must present a valid certificate for ``. +{{% boxes/note %}} +The reasons we require `` rather than `` for SRV +delegation are: + 1. DNS is insecure (not all domains have DNSSEC), so the target of the delegation + must prove that it is a valid delegate for `` via TLS. + 2. Consistency with the recommendations in [RFC6125](https://datatracker.ietf.org/doc/html/rfc6125#section-6.2.1) + and other applications using SRV records such [XMPP](https://datatracker.ietf.org/doc/html/rfc6120#section-13.7.2.1). +{{% /boxes/note %}} + The TLS certificate provided by the target server must be signed by a known Certificate Authority. Servers are ultimately responsible for determining the trusted Certificate Authorities, however are strongly @@ -500,15 +509,15 @@ Example As an example consider the event graph: - A - / + A + / B where `B` is a ban of a user `X`. If the user `X` tries to set the topic by sending an event `C` while evading the ban: - A - / \ + A + / \ B C servers that receive `C` after `B` should soft fail event `C`, and so @@ -518,11 +527,11 @@ will neither relay `C` to its clients nor send any events referencing If later another server sends an event `D` that references both `B` and `C` (this can happen if it received `C` before `B`): - A - / \ + A + / \ B C - \ / - D + \ / + D then servers will handle `D` as normal. `D` is sent to the servers' clients (assuming `D` passes auth checks). The state at `D` may resolve @@ -539,18 +548,18 @@ state of the `C` branch. Let's go back to the graph before `D` was sent: - A - / \ + A + / \ B C If all the servers in the room saw `B` before `C` and so soft fail `C`, then any new event `D'` will not reference `C`: - A - / \ + A + / \ B C | - D + D' #### Retrieving event authorization information @@ -584,15 +593,15 @@ state. For example, consider the following event graph (where the oldest event, E0, is at the top): - E0 - | - E1 - / \ + E0 + | + E1 + / \ E2 E4 | | E3 | - \ / - E5 + \ / + E5 Suppose E3 and E4 are both `m.room.name` events which set the name of the room. What should the name of the room be at E5? diff --git a/data/api/client-server/administrative_contact.yaml b/data/api/client-server/administrative_contact.yaml index 9966015b0..e6e1267b8 100644 --- a/data/api/client-server/administrative_contact.yaml +++ b/data/api/client-server/administrative_contact.yaml @@ -87,7 +87,7 @@ paths: associated the third party identifier with the user. required: ['medium', 'address', 'validated_at', 'added_at'] tags: - - User data + - Account management post: summary: Adds contact information to the user's account. description: |- @@ -154,6 +154,7 @@ paths: properties: submit_url: type: string + format: uri description: |- An optional field containing a URL where the client must submit the validation token to, with identical parameters @@ -178,7 +179,7 @@ paths: schema: "$ref": "definitions/errors/error.yaml" tags: - - User data + - Account management "/account/3pid/add": post: summary: Adds contact information to the user's account. @@ -234,7 +235,7 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Account management "/account/3pid/bind": post: summary: Binds a 3PID to the user's account through an Identity Service. @@ -288,7 +289,7 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Account management "/account/3pid/delete": post: summary: Deletes a third party identifier from the user's account @@ -345,7 +346,7 @@ paths: description: |- An indicator as to whether or not the homeserver was able to unbind the 3PID from the identity server. `success` indicates that the - indentity server has unbound the identifier whereas `no-support` + identity server has unbound the identifier whereas `no-support` indicates that the identity server refuses to support the request or the homeserver was not able to determine an identity server to unbind from. @@ -353,7 +354,7 @@ paths: required: - id_server_unbind_result tags: - - User data + - Account management "/account/3pid/unbind": post: summary: Removes a user's third party identifier from an identity server. @@ -417,7 +418,7 @@ paths: required: - id_server_unbind_result tags: - - User data + - Account management "/account/3pid/email/requestToken": post: summary: Begins the validation process for an email address for association with the user's account. @@ -469,6 +470,8 @@ paths: "errcode": "M_THREEPID_IN_USE", "error": "Third party identifier already in use" } + tags: + - Account management "/account/3pid/msisdn/requestToken": post: summary: Begins the validation process for a phone number for association with the user's account. @@ -517,3 +520,5 @@ paths: "errcode": "M_THREEPID_IN_USE", "error": "Third party identifier already in use" } + tags: + - Account management diff --git a/data/api/client-server/content-repo.yaml b/data/api/client-server/content-repo.yaml index c36fa837d..fb91c7c53 100644 --- a/data/api/client-server/content-repo.yaml +++ b/data/api/client-server/content-repo.yaml @@ -66,6 +66,7 @@ paths: properties: content_uri: type: string + format: uri description: "The [MXC URI](/client-server-api/#matrix-content-mxc-uris) to the uploaded content." examples: application/json: { @@ -360,6 +361,7 @@ paths: parameters: - in: query type: string + format: uri x-example: "https://matrix.org" name: url description: "The URL to get a preview of." @@ -389,6 +391,7 @@ paths: The byte-size of the image. Omitted if there is no image attached. "og:image": type: string + format: uri description: |- An [MXC URI](/client-server-api/#matrix-content-mxc-uris) to the image. Omitted if there is no image. examples: diff --git a/data/api/client-server/create_room.yaml b/data/api/client-server/create_room.yaml index fc558c03d..2a120f2c3 100644 --- a/data/api/client-server/create_room.yaml +++ b/data/api/client-server/create_room.yaml @@ -48,16 +48,18 @@ paths: (and not other members) permission to send state events. Overridden by the `power_level_content_override` parameter. - 4. Events set by the `preset`. Currently these are the `m.room.join_rules`, + 4. An `m.room.canonical_alias` event if `room_alias_name` is given. + + 5. Events set by the `preset`. Currently these are the `m.room.join_rules`, `m.room.history_visibility`, and `m.room.guest_access` state events. - 5. Events listed in `initial_state`, in the order that they are + 6. Events listed in `initial_state`, in the order that they are listed. - 6. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` + 7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` state events). - 7. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with + 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with `membership: invite` and `m.room.third_party_invite`). The available presets do the following with respect to room state: @@ -112,7 +114,8 @@ paths: would be `#foo:example.com`. The complete room alias will become the canonical alias for - the room. + the room and an `m.room.canonical_alias` event will be sent + into the room. name: type: string description: |- diff --git a/data/api/client-server/cross_signing.yaml b/data/api/client-server/cross_signing.yaml index a0516ef2c..3c17cd116 100644 --- a/data/api/client-server/cross_signing.yaml +++ b/data/api/client-server/cross_signing.yaml @@ -42,6 +42,7 @@ paths: name: keys description: |- The keys to be published. + required: true schema: type: object properties: @@ -66,6 +67,12 @@ paths: request. allOf: - $ref: definitions/cross_signing_key.yaml + auth: + description: |- + Additional authentication information for the + user-interactive authentication API. + allOf: + - $ref: "definitions/auth_data.yaml" example: { "master_key": { "user_id": "@alice:example.com", @@ -129,6 +136,8 @@ paths: "errcode": "M_FORBIDDEN", "error": "Key ID in use" } + tags: + - End-to-end encryption "/keys/signatures/upload": post: summary: Upload cross-signing signatures. @@ -143,6 +152,7 @@ paths: name: signatures description: |- The signatures to be published. + required: true schema: type: object title: Signatures @@ -222,3 +232,5 @@ paths: } } } + tags: + - End-to-end encryption diff --git a/data/api/client-server/definitions/errors/error.yaml b/data/api/client-server/definitions/errors/error.yaml index 7471da6f6..89a0d44f9 100644 --- a/data/api/client-server/definitions/errors/error.yaml +++ b/data/api/client-server/definitions/errors/error.yaml @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. type: object +title: Error description: A Matrix-level Error properties: errcode: @@ -22,4 +23,4 @@ properties: type: string description: A human-readable error message. example: An unknown error occurred -required: ["errcode"] \ No newline at end of file +required: ["errcode"] diff --git a/data/api/client-server/definitions/errors/rate_limited.yaml b/data/api/client-server/definitions/errors/rate_limited.yaml index aca82ce7b..1530458ba 100644 --- a/data/api/client-server/definitions/errors/rate_limited.yaml +++ b/data/api/client-server/definitions/errors/rate_limited.yaml @@ -13,6 +13,7 @@ # limitations under the License. $ref: error.yaml type: object +title: RateLimitError description: The rate limit was reached for this request properties: errcode: @@ -29,4 +30,4 @@ properties: The amount of time in milliseconds the client should wait before trying the request again. example: 2000 -required: ["errcode"] \ No newline at end of file +required: ["errcode"] diff --git a/data/api/client-server/definitions/event_batch.yaml b/data/api/client-server/definitions/event_batch.yaml index 1694652ca..e326184c5 100644 --- a/data/api/client-server/definitions/event_batch.yaml +++ b/data/api/client-server/definitions/event_batch.yaml @@ -21,3 +21,4 @@ properties: type: object type: array type: object +title: EventBatch diff --git a/data/api/client-server/definitions/openid_token.yaml b/data/api/client-server/definitions/openid_token.yaml index 32929ef6f..e74ddfff5 100644 --- a/data/api/client-server/definitions/openid_token.yaml +++ b/data/api/client-server/definitions/openid_token.yaml @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. type: object +title: OpenIdCredentials properties: access_token: type: string diff --git a/data/api/client-server/definitions/public_rooms_response.yaml b/data/api/client-server/definitions/public_rooms_response.yaml index 8cf9935c2..406f83b0e 100644 --- a/data/api/client-server/definitions/public_rooms_response.yaml +++ b/data/api/client-server/definitions/public_rooms_response.yaml @@ -68,6 +68,7 @@ properties: rules like any other user. avatar_url: type: string + format: uri description: The URL for the room's avatar, if one is set. join_rule: type: string @@ -110,4 +111,4 @@ example: { "next_batch": "p190q", "prev_batch": "p1902", "total_room_count_estimate": 115 -} \ No newline at end of file +} diff --git a/data/api/client-server/definitions/request_token_response.yaml b/data/api/client-server/definitions/request_token_response.yaml index b801af984..0f8c8cab9 100644 --- a/data/api/client-server/definitions/request_token_response.yaml +++ b/data/api/client-server/definitions/request_token_response.yaml @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. type: object +title: RequestTokenResponse properties: sid: type: string @@ -22,6 +23,7 @@ properties: example: "123abc" submit_url: type: string + format: uri description: |- An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service diff --git a/data/api/client-server/definitions/room_event_batch.yaml b/data/api/client-server/definitions/room_event_batch.yaml index 45bcb4231..4a7dab193 100644 --- a/data/api/client-server/definitions/room_event_batch.yaml +++ b/data/api/client-server/definitions/room_event_batch.yaml @@ -25,3 +25,4 @@ properties: - origin_server_ts type: array type: object +title: RoomEventBatch diff --git a/data/api/client-server/definitions/state_event_batch.yaml b/data/api/client-server/definitions/state_event_batch.yaml index 9518300fb..f3966dcda 100644 --- a/data/api/client-server/definitions/state_event_batch.yaml +++ b/data/api/client-server/definitions/state_event_batch.yaml @@ -26,3 +26,4 @@ properties: - state_key type: array type: object +title: StateEventBatch diff --git a/data/api/client-server/definitions/timeline_batch.yaml b/data/api/client-server/definitions/timeline_batch.yaml index e243b485f..65a7622a1 100644 --- a/data/api/client-server/definitions/timeline_batch.yaml +++ b/data/api/client-server/definitions/timeline_batch.yaml @@ -24,3 +24,4 @@ properties: rooms/{roomId}/messages endpoint. type: string type: object +title: TimelineBatch diff --git a/data/api/client-server/definitions/wellknown/homeserver.yaml b/data/api/client-server/definitions/wellknown/homeserver.yaml index 92ff34ed3..6f6d3cb9a 100644 --- a/data/api/client-server/definitions/wellknown/homeserver.yaml +++ b/data/api/client-server/definitions/wellknown/homeserver.yaml @@ -18,6 +18,7 @@ type: object properties: base_url: type: string + format: uri description: The base URL for the homeserver for client-server connections. example: https://matrix.example.com required: diff --git a/data/api/client-server/definitions/wellknown/identity_server.yaml b/data/api/client-server/definitions/wellknown/identity_server.yaml index a8f7c31cf..a86ad8b1b 100644 --- a/data/api/client-server/definitions/wellknown/identity_server.yaml +++ b/data/api/client-server/definitions/wellknown/identity_server.yaml @@ -18,6 +18,7 @@ type: object properties: base_url: type: string + format: uri description: The base URL for the identity server for client-server connections. example: https://identity.example.com required: diff --git a/data/api/client-server/key_backup.yaml b/data/api/client-server/key_backup.yaml index 7c42f6b53..438517913 100644 --- a/data/api/client-server/key_backup.yaml +++ b/data/api/client-server/key_backup.yaml @@ -375,7 +375,7 @@ paths: summary: Store a key in the backup. description: |- Store a key in the backup. - operationId: postRoomKeysKeyRoomIdSessionId + operationId: putRoomKeysBySessionId security: - accessToken: [] parameters: @@ -409,6 +409,7 @@ paths: description: The update succeeded. schema: type: object + title: RoomKeysUpdateResponse properties: etag: description: |- @@ -443,10 +444,10 @@ paths: tags: - End-to-end encryption get: - summary: Retrieve a key from the backup + summary: Retrieve a key from the backup. description: |- Retrieve a key from the backup. - operationId: getRoomKeysKeyRoomIdSessionId + operationId: getRoomKeysBySessionId security: - accessToken: [] parameters: @@ -487,11 +488,13 @@ paths: description: This request was rate-limited. schema: "$ref": "definitions/errors/rate_limited.yaml" + tags: + - End-to-end encryption delete: - summary: Delete a key from the backup + summary: Delete a key from the backup. description: |- Delete a key from the backup. - operationId: deleteRoomKeysKeyRoomIdSessionId + operationId: deleteRoomKeysBySessionId security: - accessToken: [] parameters: @@ -519,6 +522,7 @@ paths: description: The update succeeded schema: type: object + title: RoomKeysUpdateResponse properties: etag: description: |- @@ -547,12 +551,14 @@ paths: description: This request was rate-limited. schema: "$ref": "definitions/errors/rate_limited.yaml" + tags: + - End-to-end encryption "/room_keys/keys/{roomId}": put: summary: Store several keys in the backup for a given room. description: |- - Store a key in the backup. - operationId: postRoomKeysKeyRoomId + Store several keys in the backup for a given room. + operationId: putRoomKeysByRoomId security: - accessToken: [] parameters: @@ -580,6 +586,7 @@ paths: description: The update succeeded schema: type: object + title: RoomKeysUpdateResponse properties: etag: description: |- @@ -624,10 +631,10 @@ paths: tags: - End-to-end encryption get: - summary: Retrieve the keys from the backup for a given room + summary: Retrieve the keys from the backup for a given room. description: |- - Retrieve the keys from the backup for a given room - operationId: getRoomKeysKeyRoomId + Retrieve the keys from the backup for a given room. + operationId: getRoomKeysByRoomId security: - accessToken: [] parameters: @@ -666,11 +673,13 @@ paths: description: This request was rate-limited. schema: "$ref": "definitions/errors/rate_limited.yaml" + tags: + - End-to-end encryption delete: - summary: Delete a key from the backup + summary: Delete the keys from the backup for a given room. description: |- - Delete a key from the backup. - operationId: deleteRoomKeysKeyRoomId + Delete the keys from the backup for a given room. + operationId: deleteRoomKeysByRoomId security: - accessToken: [] parameters: @@ -692,6 +701,7 @@ paths: description: The update succeeded schema: type: object + title: RoomKeysUpdateResponse properties: etag: description: |- @@ -720,12 +730,14 @@ paths: description: This request was rate-limited. schema: "$ref": "definitions/errors/rate_limited.yaml" + tags: + - End-to-end encryption "/room_keys/keys": put: summary: Store several keys in the backup. description: |- Store several keys in the backup. - operationId: postRoomKeysKey + operationId: putRoomKeys security: - accessToken: [] parameters: @@ -773,6 +785,7 @@ paths: description: The update succeeded schema: type: object + title: RoomKeysUpdateResponse properties: etag: description: |- @@ -817,10 +830,10 @@ paths: tags: - End-to-end encryption get: - summary: Retrieve the keys from the backup for a given room + summary: Retrieve the keys from the backup. description: |- - Retrieve the keys from the backup for a given room - operationId: getRoomKeysKeyRoomId + Retrieve the keys from the backup. + operationId: getRoomKeys security: - accessToken: [] parameters: @@ -875,11 +888,13 @@ paths: description: This request was rate-limited. schema: "$ref": "definitions/errors/rate_limited.yaml" + tags: + - End-to-end encryption delete: - summary: Delete a key from the backup + summary: Delete the keys from the backup. description: |- - Delete a key from the backup. - operationId: deleteRoomKeysKeyRoomId + Delete the keys from the backup. + operationId: deleteRoomKeys security: - accessToken: [] parameters: @@ -895,6 +910,7 @@ paths: description: The update succeeded schema: type: object + title: RoomKeysUpdateResponse properties: etag: description: |- @@ -923,3 +939,5 @@ paths: description: This request was rate-limited. schema: "$ref": "definitions/errors/rate_limited.yaml" + tags: + - End-to-end encryption diff --git a/data/api/client-server/list_public_rooms.yaml b/data/api/client-server/list_public_rooms.yaml index 4175b0a96..87806e04a 100644 --- a/data/api/client-server/list_public_rooms.yaml +++ b/data/api/client-server/list_public_rooms.yaml @@ -61,6 +61,8 @@ paths: } schema: "$ref": "definitions/errors/error.yaml" + tags: + - Room discovery put: summary: Sets the visibility of a room in the room directory description: |- @@ -111,6 +113,8 @@ paths: } schema: "$ref": "definitions/errors/error.yaml" + tags: + - Room discovery "/publicRooms": get: summary: Lists the public rooms on the server. diff --git a/data/api/client-server/peeking_events.yaml b/data/api/client-server/peeking_events.yaml index 85eb87683..0bf303ef1 100644 --- a/data/api/client-server/peeking_events.yaml +++ b/data/api/client-server/peeking_events.yaml @@ -27,9 +27,11 @@ produces: securityDefinitions: $ref: definitions/security.yaml paths: - "/events": + # With an extra " " to disambiguate from the getEvents endpoint + # The extra space makes it sort first for what I'm sure is a good reason. + "/events ": get: - summary: Listen on the event stream. + summary: Listen on the event stream of a particular room. description: |- This will listen for new events related to a particular room and return them to the caller. This will block until an event is received, or until @@ -103,4 +105,5 @@ paths: - "$ref": "../../event-schemas/schema/core-event-schema/room_event.yaml" 400: description: "Bad pagination `from` parameter." - # No tags to exclude this from the swagger UI - use the normal version instead. + tags: + - Room participation diff --git a/data/api/client-server/profile.yaml b/data/api/client-server/profile.yaml index 6a8d6a775..d1d4306cf 100644 --- a/data/api/client-server/profile.yaml +++ b/data/api/client-server/profile.yaml @@ -129,6 +129,7 @@ paths: properties: avatar_url: type: string + format: uri description: The new avatar URL for this user. responses: 200: @@ -170,6 +171,7 @@ paths: properties: avatar_url: type: string + format: uri description: The user's avatar URL if they have set one, otherwise not present. 404: description: There is no avatar URL for this user or this user does not exist. @@ -204,6 +206,7 @@ paths: properties: avatar_url: type: string + format: uri description: The user's avatar URL if they have set one, otherwise not present. displayname: type: string diff --git a/data/api/client-server/pusher.yaml b/data/api/client-server/pusher.yaml index 69882066f..9feccb4f0 100644 --- a/data/api/client-server/pusher.yaml +++ b/data/api/client-server/pusher.yaml @@ -113,6 +113,7 @@ paths: properties: url: type: string + format: uri description: |- Required if `kind` is `http`. The URL to use to send notifications to. @@ -220,6 +221,7 @@ paths: properties: url: type: string + format: uri description: |- Required if `kind` is `http`. The URL to use to send notifications to. MUST be an HTTPS URL with a path of diff --git a/data/api/client-server/receipts.yaml b/data/api/client-server/receipts.yaml index 716946ace..66610092b 100644 --- a/data/api/client-server/receipts.yaml +++ b/data/api/client-server/receipts.yaml @@ -61,6 +61,7 @@ paths: description: |- Extra receipt information to attach to `content` if any. The server will automatically set the `ts` field. + required: true schema: type: object example: { diff --git a/data/api/client-server/registration.yaml b/data/api/client-server/registration.yaml index 925ad00b8..526233fa4 100644 --- a/data/api/client-server/registration.yaml +++ b/data/api/client-server/registration.yaml @@ -214,7 +214,7 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Account management "/register/email/requestToken": post: summary: Begins the validation process for an email to be used during registration. @@ -265,6 +265,8 @@ paths: } schema: "$ref": "definitions/errors/error.yaml" + tags: + - Account management "/register/msisdn/requestToken": post: summary: Requests a validation token be sent to the given phone number for the purpose of registering an account @@ -315,6 +317,8 @@ paths: } schema: "$ref": "definitions/errors/error.yaml" + tags: + - Account management "/account/password": post: summary: "Changes a user's password." @@ -378,7 +382,7 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Account management "/account/password/email/requestToken": post: summary: Requests a validation token be sent to the given email address for the purpose of resetting a user's password @@ -434,6 +438,8 @@ paths: "errcode": "M_THREEPID_NOT_FOUND", "error": "Email not found" } + tags: + - Account management "/account/password/msisdn/requestToken": post: summary: Requests a validation token be sent to the given phone number for the purpose of resetting a user's password. @@ -489,6 +495,8 @@ paths: "errcode": "M_THREEPID_NOT_FOUND", "error": "Phone number not found" } + tags: + - Account management "/account/deactivate": post: summary: "Deactivate a user's account." @@ -565,7 +573,7 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Account management "/register/available": get: summary: Checks to see if a username is available on the server. @@ -627,4 +635,4 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Account management diff --git a/data/api/client-server/report_content.yaml b/data/api/client-server/report_content.yaml index 380995ead..19d6b6d0c 100644 --- a/data/api/client-server/report_content.yaml +++ b/data/api/client-server/report_content.yaml @@ -49,6 +49,7 @@ paths: x-example: "$something:example.org" - in: body name: body + required: true schema: type: object example: { diff --git a/data/api/client-server/room_send.yaml b/data/api/client-server/room_send.yaml index c22fcfe47..18658f612 100644 --- a/data/api/client-server/room_send.yaml +++ b/data/api/client-server/room_send.yaml @@ -65,6 +65,7 @@ paths: x-example: "35" - in: body name: body + required: true schema: type: object example: { diff --git a/data/api/client-server/room_state.yaml b/data/api/client-server/room_state.yaml index 381c5c57e..016a82736 100644 --- a/data/api/client-server/room_state.yaml +++ b/data/api/client-server/room_state.yaml @@ -74,6 +74,7 @@ paths: x-example: "@alice:example.com" - in: body name: body + required: true schema: type: object example: { diff --git a/data/api/client-server/rooms.yaml b/data/api/client-server/rooms.yaml index 0dd60d8e6..2f161e2bf 100644 --- a/data/api/client-server/rooms.yaml +++ b/data/api/client-server/rooms.yaml @@ -206,6 +206,7 @@ paths: enum: - join - invite + - knock - leave - ban description: |- @@ -220,6 +221,7 @@ paths: enum: - join - invite + - knock - leave - ban description: |- @@ -301,6 +303,7 @@ paths: description: The display name of the user this object is representing. avatar_url: type: string + format: uri description: The mxc avatar url of the user this object is representing. description: A map from user ID to a RoomMember object. type: object diff --git a/data/api/client-server/search.yaml b/data/api/client-server/search.yaml index 1dc9804e2..8bc255286 100644 --- a/data/api/client-server/search.yaml +++ b/data/api/client-server/search.yaml @@ -238,6 +238,7 @@ paths: title: Display name avatar_url: type: string + format: uri title: Avatar Url events_before: type: array diff --git a/data/api/client-server/sso_login_redirect.yaml b/data/api/client-server/sso_login_redirect.yaml index 8c92a3ce6..b58d88fe4 100644 --- a/data/api/client-server/sso_login_redirect.yaml +++ b/data/api/client-server/sso_login_redirect.yaml @@ -46,6 +46,8 @@ paths: headers: Location: type: "string" + tags: + - Session management "/login/sso/redirect/{idpId}": get: summary: Redirect the user's browser to the SSO interface for an IdP. @@ -56,7 +58,7 @@ paths: The server MUST respond with an HTTP redirect to the SSO interface for that IdP. - operationId: redirectToSSO + operationId: redirectToIdP parameters: - in: path type: string @@ -83,3 +85,5 @@ paths: The IdP ID was not recognized by the server. The server is encouraged to provide a user-friendly page explaining the error given the user will be navigated to it. + tags: + - Session management diff --git a/data/api/client-server/third_party_lookup.yaml b/data/api/client-server/third_party_lookup.yaml index 3d348df2f..6f8829655 100644 --- a/data/api/client-server/third_party_lookup.yaml +++ b/data/api/client-server/third_party_lookup.yaml @@ -42,6 +42,8 @@ paths: description: The protocols supported by the homeserver. schema: $ref: ../application-service/definitions/protocol_metadata.yaml + tags: + - Third Party Lookup "/thirdparty/protocol/{protocol}": get: summary: Retrieve metadata about a specific protocol that the homeserver supports. @@ -71,6 +73,8 @@ paths: } schema: $ref: definitions/errors/error.yaml + tags: + - Third Party Lookup "/thirdparty/location/{protocol}": get: summary: Retrieve Matrix-side portals rooms leading to a third party location. @@ -112,6 +116,8 @@ paths: } schema: $ref: definitions/errors/error.yaml + tags: + - Third Party Lookup "/thirdparty/user/{protocol}": get: summary: Retrieve the Matrix User ID of a corresponding third party user. @@ -147,6 +153,8 @@ paths: } schema: $ref: definitions/errors/error.yaml + tags: + - Third Party Lookup "/thirdparty/location": get: summary: Reverse-lookup third party locations given a Matrix room alias. @@ -177,6 +185,8 @@ paths: } schema: $ref: definitions/errors/error.yaml + tags: + - Third Party Lookup "/thirdparty/user": get: summary: Reverse-lookup third party users given a Matrix User ID. @@ -206,3 +216,5 @@ paths: } schema: $ref: definitions/errors/error.yaml + tags: + - Third Party Lookup diff --git a/data/api/client-server/users.yaml b/data/api/client-server/users.yaml index 255c538b1..ae015e7a5 100644 --- a/data/api/client-server/users.yaml +++ b/data/api/client-server/users.yaml @@ -47,6 +47,7 @@ paths: parameters: - in: body name: body + required: true schema: type: object properties: @@ -95,6 +96,7 @@ paths: description: The display name of the user, if one exists. avatar_url: type: string + format: uri example: "mxc://bar.com/foo" description: The avatar url, as an MXC, if one exists. limited: @@ -105,4 +107,4 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - User directory diff --git a/data/api/client-server/whoami.yaml b/data/api/client-server/whoami.yaml index 3458c4d0d..54d9cde90 100644 --- a/data/api/client-server/whoami.yaml +++ b/data/api/client-server/whoami.yaml @@ -89,4 +89,4 @@ paths: schema: "$ref": "definitions/errors/rate_limited.yaml" tags: - - User data + - Session management diff --git a/data/api/server-server/user_devices.yaml b/data/api/server-server/user_devices.yaml index 0c2348dab..9fb15777f 100644 --- a/data/api/server-server/user_devices.yaml +++ b/data/api/server-server/user_devices.yaml @@ -96,7 +96,7 @@ paths: "ed25519:base64+master+public+key": "base64+master+public+key", } } - self_signing_keys: + self_signing_key: type: object description: |- The user\'s self-signing key. diff --git a/data/event-schemas/schema/m.room.member.yaml b/data/event-schemas/schema/m.room.member.yaml index 928e1528f..37975cbe1 100644 --- a/data/event-schemas/schema/m.room.member.yaml +++ b/data/event-schemas/schema/m.room.member.yaml @@ -45,6 +45,7 @@ properties: avatar_url: description: 'The avatar URL for this user, if any.' type: string + format: uri displayname: description: 'The display name for this user, if any.' type: diff --git a/data/event-schemas/schema/m.room.tombstone.yaml b/data/event-schemas/schema/m.room.tombstone.yaml index 0fd8ba452..1c590e1fd 100644 --- a/data/event-schemas/schema/m.room.tombstone.yaml +++ b/data/event-schemas/schema/m.room.tombstone.yaml @@ -10,7 +10,7 @@ properties: description: A server-defined message. replacement_room: type: string - description: The new room the client should be visiting. + description: The room ID of the new room the client should be visiting. required: - replacement_room - body diff --git a/layouts/partials/navbar.html b/layouts/partials/navbar.html index 8a7364401..e78ee9c41 100644 --- a/layouts/partials/navbar.html +++ b/layouts/partials/navbar.html @@ -45,8 +45,10 @@ {{ $status := .Site.Params.version.status }} {{ if ne $status "unstable"}} - {{ $ret = .Site.Params.version.number }} - {{ $ret = delimit (slice "version" $ret) " " }} + {{ $path := path.Join "changelogs" }} + + {{/* produces a string similar to "version v1.5" */}} + {{ $ret = delimit (slice "version v" .Site.Params.version.major "." .Site.Params.version.minor) "" }} {{ end }} {{ return $ret }} diff --git a/layouts/shortcodes/changelog/changelog-changes.html b/layouts/shortcodes/changelog/changelog-changes.html index a1e277283..11a598580 100644 --- a/layouts/shortcodes/changelog/changelog-changes.html +++ b/layouts/shortcodes/changelog/changelog-changes.html @@ -7,22 +7,26 @@ it expects to find newsfragments describing changes to that API. If the `version.status` setting in config.toml is anything other than - "unstable", then it also expects to find a "release.yaml" file in /changelogs, - which contains: - - `tag`: Git tag for this release - - `date`: date of this release - It then renders this info a table, before the list of changes. + "unstable", then it also expects to find additional settings under + `version` in config.toml: + - `major`: the major version number of the release + - `minor`: the minor version number of the release + - `release_date`: the date of the release + + The release tag is calculated as `v.`; for example `v1.5`. + + It then renders this into a table displayed before the list of changes. */}} {{ $path := path.Join "changelogs" }} {{ $status := .Site.Params.version.status }} +{{ $release_tag := delimit (slice "v" .Site.Params.version.major "." .Site.Params.version.minor) "" }} {{ if ne $status "unstable" }} -{{ $release_info := readFile (path.Join $path "release.yaml") | transform.Unmarshal }} - - + +
Git commithttps://github.com/matrix-org/matrix-doc/tree/{{ $release_info.tag }}
Release date{{ $release_info.date }}
Git commithttps://github.com/matrix-org/matrix-doc/tree/{{ $release_tag }}
Release date{{ .Site.Params.version.release_date }}
{{ end }} diff --git a/layouts/shortcodes/changelog/changelog-description.html b/layouts/shortcodes/changelog/changelog-description.html index 738ff675b..3c7197252 100644 --- a/layouts/shortcodes/changelog/changelog-description.html +++ b/layouts/shortcodes/changelog/changelog-description.html @@ -8,8 +8,12 @@ {{ $status := .Site.Params.version.status }} {{ if eq $status "unstable"}} +

This is the unstable version of the Matrix specification.

This changelog lists changes made since the last release of the specification.

+ {{ else }} -

This is version {{ .Site.Params.version.number }} of the Matrix specification.

+ +

This is version v{{ .Site.Params.version.major }}.{{ .Site.Params.version.minor }} of the Matrix specification.

+ {{ end }} diff --git a/meta/documentation_style.rst b/meta/documentation_style.rst index cfec5e3ba..aea495bd3 100644 --- a/meta/documentation_style.rst +++ b/meta/documentation_style.rst @@ -8,7 +8,7 @@ in. Format ------ -Documentation is written in github-flavored markdown. +Documentation is written in Commonmark markdown. Sections -------- @@ -66,6 +66,12 @@ Lists should: * Be used where they provide clarity. * Contain entries which start with a capital and end with a full stop. +When talking about properties in JSON objects, prefer the word "property" to "field", +"member", or various other alternatives. For example: "this property will be set to +X if ...". Also avoid the term "key" unless you are specifically talking about the +*name* of a property - and be mindful of the scope for confusion with cryptographic +keys. + OpenAPI ~~~~~~~ diff --git a/package-lock.json b/package-lock.json index 5dce70c7d..73994715f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -97,22 +97,10 @@ "postcss-value-parser": "^4.1.0" }, "dependencies": { - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -135,15 +123,48 @@ } }, "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001230", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz", + "integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==", + "dev": true + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.739", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz", + "integrity": "sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "node-releases": { + "version": "1.1.72", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", + "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "dev": true + } } }, "caller-callsite": { @@ -274,12 +295,6 @@ "path-type": "^4.0.0" } }, - "electron-to-chromium": { - "version": "1.3.534", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.534.tgz", - "integrity": "sha512-7x2S3yUrspNHQOoPk+Eo+iHViSiJiEGPI6BpmLy1eT2KRNGCkBt/NUYqjfXLd1DpDCQp7n3+LfA1RkbG+LqTZQ==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -295,12 +310,6 @@ "is-arrayish": "^0.2.1" } }, - "escalade": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", - "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", - "dev": true - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -387,9 +396,9 @@ "dev": true }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -418,8 +427,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "ignore": { "version": "5.1.8", @@ -575,12 +583,6 @@ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", "dev": true }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -658,9 +660,9 @@ "dev": true }, "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", "dev": true, "requires": { "chalk": "^2.4.2", diff --git a/proposals/1772-groups-as-rooms.md b/proposals/1772-groups-as-rooms.md index b6f60b388..1d431f841 100644 --- a/proposals/1772-groups-as-rooms.md +++ b/proposals/1772-groups-as-rooms.md @@ -126,7 +126,7 @@ relationship can be expressed in one of two ways: `origin_server_ts` of their `m.room.create` events, or ascending lexicographic order of their `room_id`s in case of equal `origin_server_ts`. `order`s which are not strings, or do not consist - solely of ascii characters in the range `\x20` (space) to `\x7F` (`~`), or + solely of ascii characters in the range `\x20` (space) to `\x7E` (`~`), or consist of more than 50 characters, are forbidden and the field should be ignored if received.) diff --git a/proposals/2265-email-lowercase.md b/proposals/2265-email-lowercase.md index 5a1db6825..e4fe53139 100644 --- a/proposals/2265-email-lowercase.md +++ b/proposals/2265-email-lowercase.md @@ -23,8 +23,8 @@ Sydent. This proposal suggests changing the specification of the e-mail 3PID type in [the Matrix spec appendices](https://matrix.org/docs/spec/appendices#pid-types) to mandate that, before any processing, e-mail addresses must go through a full -case folding based on [the unicode mapping -file](https://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt), on top of +case folding as described under "Caseless Matching" in +[chapter 5 of the unicode standard](https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf#G21790), on top of having their domain lowercased. This means that `Strauß@Example.com` must be considered as being the same e-mail diff --git a/proposals/2732-olm-fallback-keys.md b/proposals/2732-olm-fallback-keys.md new file mode 100644 index 000000000..5ab90117c --- /dev/null +++ b/proposals/2732-olm-fallback-keys.md @@ -0,0 +1,97 @@ +# MSC2732: Olm fallback keys + +Olm uses a set of one-time keys when initializing a session between two +devices: Alice uploads one-time keys to her homeserver, and Bob claims one of +them to perform a Diffie-Hellman to generate a shared key. As implied by the +name, a one-time key is only to be used once. However, if all of Alice's +one-time keys are claimed, Bob will not be able to create a session with Alice. + +This can be addressed by Alice uploading a fallback key that is used in place +of a one-time key when no one-time keys are available. + +## Proposal + +A new request parameter, `fallback_keys`, is added to the body of the +[`/keys/upload` client-server API](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload), which is in the same format as the +`one_time_keys` parameter with the exception that there must be at most one key +per key algorithm. If the user had previously uploaded a fallback key for a +given algorithm, it is replaced -- the server will only keep one fallback key +per algorithm for each user. + +When uploading fallback keys for algorithms whose key format is a signed JSON +object, client should include a property named `fallback` with a value of +`true`. + +Example: + +`POST /keys/upload` + +```json +{ + "fallback_keys": { + "signed_curve25519:AAAAAA": { + "key": "base64+public+key", + "fallback": true, + "signatures": { + "@alice:example.org": { + "ed25519:DEVICEID": "base64+signature" + } + } + } + } +} +``` + +When Bob calls `/keys/claim` to claim one of Alice's one-time keys, but Alice +has no one-time keys left, the homeserver will return the fallback key instead, +if Alice had previously uploaded one. Unlike with one-time keys, fallback keys +are not deleted when they are returned by `/keys/claim`. However, the server +marks that they have been used. + +A new response parameter, `device_unused_fallback_key_types`, is added to +`/sync`. This is an array listing the key algorithms for which the server has +an unused fallback key for the device. If the client wants the server to have a +fallback key for a given key algorithm, but that algorithm is not listed in +`device_unused_fallback_key_types`, the client will upload a new key as above. + +The `device_unused_fallback_key_types` parameter must be present if the server +supports fallback keys. Clients can thus treat this field as an indication +that the server supports fallback keys, and so only upload fallback keys to +servers that support them. + +Example: + +`GET /sync` + +Response: + +```jsonc +{ + // other fields... + "device_unused_fallback_key_types": ["signed_curve25519"] +} +``` + +## Security considerations + +Using a fallback key rather than a one-time key has security implications. An +attacker can replay a message that was originally sent with a fallback key, and +the receiving client will accept it as a new message if the fallback key is +still active. Also, an attacker that compromises a client may be able to +retrieve the private part of the fallback key to decrypt past messages if the +client has still retained the private part of the fallback key. + +For this reason, clients should not store the private part of the fallback key +indefinitely. For example, client should only store at most two fallback keys: +the current fallback key (that it has not yet received any messages for) and +the previous fallback key, and should remove the previous fallback key once it +is reasonably certain that it has received all the messages that use it (for +example, one hour after receiving the first message that used it). + +For addressing replay attacks, clients can also keep track of inbound sessions +to detect replays. + +## Unstable prefix + +The `fallback_keys` request parameter and the `device_unused_fallback_key_types` +response parameter will be prefixed by `org.matrix.msc2732.`. diff --git a/proposals/2778-appservice-login.md b/proposals/2778-appservice-login.md new file mode 100644 index 000000000..fd509ab89 --- /dev/null +++ b/proposals/2778-appservice-login.md @@ -0,0 +1,135 @@ +# MSC2778: Providing authentication method for appservice users + +Appservices within Matrix are increasingly attempting to support End-to-End Encryption. As such, they +need a way to generate devices for their users so that they can participate in E2E rooms. In order to +do so, this proposal suggests implementing an appservice extension to the +[`POST /login` endpoint](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-login). + +Appservice users do not usually need to log in as they do not need their own access token, and do not +traditionally need a "device". However, E2E encryption demands that at least one user in a room has a +Matrix device which means bridge users need to be able to generate a device on demand. In the past, +bridge developers have used the bridge bot's device for all bridge users in the room, but this causes +problems should the bridge wish to only join ghosts to a room (e.g. for DMs). + +Another advantage this provides is that an appservice can now be used to generate access tokens for +any user in its namespace without having to set a password for that user, which may be useful where +maintaining password(s) in the configuration is undesirable. + +## Proposal + +A new `type` is to be added to `POST /login`: `m.login.application_service` + +The `/login` endpoint may now take an `access_token` in the same way that other +authenticated endpoints do. No additional parameters should be specified in the request body. + +Example request + +```json +{ + "type": "m.login.application_service", + "identifier": { + "type": "m.id.user", + "user": "_bridge_alice" + } +} +``` + +Note: Implementations MUST use the `identifier.type`=`m.id.user` method of specifying the +localpart. The deprecated top-level `user` field **cannot** use this login flow type. This +is deliberate so as to coax developers into using the new identifier format when implementing +new flows. + +The response body should be unchanged from the existing `/login` specification. + +If one of the following conditions are true: + +- The access token is not provided +- The access token does not correspond to an appservice +- Or the user has not previously been registered + +Then the servers MUST reject with HTTP 403, with an `errcode` of `"M_FORBIDDEN"`. + +If the access token DOES correspond to an appservice but the user is not inside its namespace, +then the `errcode` must be `"M_EXCLUSIVE"`. + +Homeservers should ignore the `access_token` parameter if a type other than +`m.login.application_service` has been provided. + +Appservices creating **new** users can still use the `/register` endpoint to generate an `access_token` / `device_id` +but for existing users, the `/login` endpoint can be used instead. + +## Potential issues + +This proposal means that there will be more calls to make when setting up a appservice user, when +using encryption. While this could be done during the registration step, this would prohibit creating +new devices should the appservice intentionally or inadvertently have lost the client-side device data. + +## Alternatives + +### 1. Include the token in the `/login` request body + +One minor tweak to the current proposal could be to include the token as part of the auth data, rather than +being part of the header/params to the request. An argument could be made for either, but since the specification +expects the appservice to pass the token this way in all requests, including `/register`, it seems wise to keep +it that way. + +### 2. Use implementation specific "shared secret" authentication + +Some community members have used homeserver implementation details such as a "shared secret" authentication method to +log into the accounts without having to use the /login process at all. Synapse provides such a function, +but also means the appservice can now authenticate as any user on the homeserver. This is undesirable from a +security standpoint. + +### 3. Keep using `/register` solely + +A third option could be to create a new endpoint that simply creates a new device for an appservice user on demand. +Given the rest of the matrix eco-system does this with /login, and /login is already extensible with `type`, it would +create more work for all parties involved for little benefit. + +Finally, `POST /register` does already return a `device_id` and `access_token` so appservices +could store this information rather than calling `POST /login` at all. This does however present a few problems: + +- Quite a few appservices which only support unencrypted messaging do not use/store the `device_id`/`access_token` from a register call. + In the event that an appservice eventually gains the ability to support encryption, they would be unable to fetch a new `device_id`/ + `access_token` for any existing users (as `/register` would fail for an existing user). +- If user tokens were lost or exposed, there is no way to programattically create new access tokens for these users. +- Finally, if a user was registered externally and the appservice would like to masquerade as it, it would be unable to fetch + an access token for that user. + +While `POST /register` does work, it is impactical as the sole method of fetching an access token. + +## Security considerations + +Appservices could use this new functionality to generate devices for any userId that are within its namespace e.g. setting the +user namespace regex to `@.*:example.com` would allow appservice to control anyone on the homeserver. While this sounds scary, in practice +this is not a problem because: + +- Appservice namespaces are maintained by the homeserver admin. If the namespace were to change, then it's reasonable + to assume that the server admin is aware. There is no defense mechanism to stop a malicious server admin from creating new + devices for a given user's account as they could also do so by simply modifying the database. + +- While an appservice *could* try to masquerade as a user maliciously without the server admin expecting it, it would still + be bound by the restrictions of the namespace. Server admins are expected to be aware of the implications of adding new + appservices to their server so the burden of responsibility lies with the server admin. + +- Appservices already can /sync as any user using the `as_token` and send any messages as any user in the namespace, the only + difference is that without a dedicated access token they are unable to receive device messages. While in theory this + does make them unable to see encrypted messages, this is not designed to be a security mechanism. + +In conclusion this MSC only automates the creation of new devices for users inside an AS namespace, which is something +a server admin could already do. Appservices should always be treated with care and so with these facts in mind the MSC should +be considered secure. + +## Unstable prefix + +Implementations should use `uk.half-shot.msc2778.login.application_service` for `type` given in the +`POST /login` until this lands in a released version of the specification. + +## Implementations + +The proposal has been implemented by a homeserver, a bridge SDK and two bridges: + +- [synapse](https://github.com/matrix-org/synapse/pull/8320) +- [mautrix-python](https://github.com/tulir/mautrix-python/commit/12d7c48ca7c15fd3ff61608369af1cf69e289aeb) +- [mautrix-whatsapp](https://github.com/tulir/mautrix-whatsapp/commit/ead8a869c84d07fadc7cfcf3d522452c99faaa36) +- [matrix-appservice-bridge](https://github.com/matrix-org/matrix-appservice-bridge/pull/231/files#diff-5e93f1b51d50a44fcf0ca46ea1793c1cR851-R864) diff --git a/proposals/3083-restricted-rooms.md b/proposals/3083-restricted-rooms.md new file mode 100644 index 000000000..1caa9f970 --- /dev/null +++ b/proposals/3083-restricted-rooms.md @@ -0,0 +1,291 @@ +# Restricting room membership based on membership in other rooms + +A desirable feature is to give room admins the power to restrict membership of +their room based on the membership of one or more rooms. + +Potential usecases include: + +* Private spaces (allowing any member of a [MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772) + space to join child rooms in that space), for example: + + > members of the #doglovers:example.com space can join this room without an invitation[1](#f1) +* Room upgrades for private rooms (instead of issuing invites to each user). +* Allowing all users in a private room to be able to join a private breakout room. + +This does not preclude members from being directly invited to the room, which is +still a useful discovery feature. + +## Proposal + +In a future room version a new `join_rule` (`restricted`) will be used to reflect +a cross between `invite` and `public` join rules. The content of the join rules +would include the rooms to trust for membership. For example: + +```json +{ + "type": "m.room.join_rules", + "state_key": "", + "content": { + "join_rule": "restricted", + "allow": [ + { + "type": "m.room_membership", + "room_id": "!mods:example.org" + }, + { + "type": "m.room_membership", + "room_id": "!users:example.org" + } + ] + } +} +``` + +This means that a user must be a member of the `!mods:example.org` room or +`!users:example.org` room in order to join without an invite[2](#f2). +Membership in a single allowed room is enough. + +If the `allow` key is an empty list (or not a list at all), then no users are +allowed to join without an invite. Each entry is expected to be an object with the +following keys: + +* `type`: `"m.room_membership"` to describe that we are allowing access via room + membership. Future MSCs may define other types. +* `room_id`: The room ID to check the membership of. + +Any entries in the list which do not match the expected format are ignored. Thus, +if all entries are invalid, the list behaves as if empty and all users without +an invite are rejected. + +The `allow` key is to be protected when redacting an event. + +When a homeserver receives a `/join` request from a client or a `/make_join` / +`/send_join` request from another homeserver, the request should only be permitted +if the user is invited to this room, or is joined to one of the listed rooms. If +the user is not a member of at least one of the rooms, the homeserver should return +an error response with HTTP status code of 403 and an `errcode` of `M_FORBIDDEN`. + +It is possible for a resident homeserver (one which receives a `/make_join` / +`/send_join` request) to not know if the user is in some of the allowed rooms (due +to not participating in them). If the user is not in any of the allowed rooms that +are known to the homeserver, and the homeserver is not participating in all listed +rooms, then it should return an error response with HTTP status code of 400 with an `errcode` of `M_UNABLE_TO_AUTHORISE_JOIN`. The joining server should +attempt to join via another resident homeserver. If the resident homeserver knows +that the user is not in *any* of the allowed rooms it should return an error response +with HTTP status code of 403 and an `errcode` of `M_FORBIDDEN`. Note that it is a +configuration error if there are allowed rooms with no participating authorised +servers. + +A chosen resident homeserver might also be unable to issue invites (which, as below, +is a pre-requisite for generating a correctly-signed join event). In this case +it should return an error response with HTTP status code of 400 and an `errcode` +of `M_UNABLE_TO_GRANT_JOIN`. The joining server should attempt to join via another +resident homeserver. + +From the perspective of the [auth rules](https://spec.matrix.org/unstable/rooms/v1/#authorization-rules), +the `restricted` join rule has the same behavior as `public`, with the additional +caveat that servers must ensure that, for `m.room.member` events with a `membership` of `join`: + +* The user's previous membership was `invite` or `join`, or +* The join event has a valid signature from a homeserver whose users have the + power to issue invites. + + When generating a join event for `/join` or `/make_join`, the server should + include the MXID of a local user who could issue an invite in the content with + the key `join_authorised_via_users_server`. The actual user chosen is arbitrary. + +The changes to the auth rules imply that: + +* A join event issued via `/send_join` is signed by not just the requesting + server, but also the resident server.[3](#f3) + + In order for the joining server to receive the proper signatures the join + event will be returned via `/send_join` in the `event` field. +* The auth chain of the join event needs to include events which prove + the homeserver can be issuing the join. This can be done by including: + + * The `m.room.power_levels` event. + * The join event of the user specified in `join_authorised_via_users_server`. + + It should be confirmed that the authorising user is in the room. (This + prevents situations where any homeserver could process the join, even if + they weren't in the room, under certain power level conditions.) + +The above creates a new restriction on the relationship between the resident +servers used for `/make_join` and `/send_join` -- they must now both go to +the same server (since the `join_authorised_via_users_server` is added in +the call to `/make_join`, while the final signature is added during +the call to `/send_join`). If a request to `/send_join` is received that includes +an event from a different resident server it should return an error response with +HTTP status code of 400. + +Note that the homeservers whose users can issue invites are trusted to confirm +that the `allow` rules were properly checked (since this cannot easily be +enforced over federation by event authorisation).[4](#f4) + +To better cope with joining via aliases, homeservers should use the list of +authorised servers (not the list of candidate servers) when a user attempts to +join a room. + +## Summary of the behaviour of join rules + +See the [join rules](https://matrix.org/docs/spec/client_server/r0.6.1#m-room-join-rules) +specification for full details; the summary below is meant to highlight the differences +between `public`, `invite`, and `restricted` from a user perspective. Note that +all join rules are subject to `ban` and `server_acls`. + +* `public`: anyone can join, as today. +* `invite`: only people with membership `invite` can join, as today. +* `knock`: the same as `invite`, except anyone can knock. See + [MSC2403](https://github.com/matrix-org/matrix-doc/pull/2403). +* `private`: This is reserved, but unspecified. +* `restricted`: the same as `invite`, except users may also join if they are a + member of a room listed in the `allow` rules. + +## Security considerations + +Increased trust to enforce the join rules during calls to `/join`, `/make_join`, +and `/send_join` is placed in the homeservers whose users can issue invites. +Although it is possible for those homeservers to issue a join event in bad faith, +there is no real-world benefit to doing this as those homeservers could easily +side-step the restriction by issuing an invite first anyway. + +## Unstable prefix + +The `restricted` join rule will be included in a future room version to allow +servers and clients to opt-into the new functionality. + +During development, an unstable room version of `org.matrix.msc3083.v2` will be used. +Since the room version namespaces the behaviour, the `allow` key and value, as well +as the `restricted` join rule value do not need unstable prefixes. + +An unstable key of `org.matrix.msc3083.v2.event` will be used in the response +from `/send_join` in place of `event` during development. + +## Alternatives + +It may seem that just having the `allow` key with `public` join rules is enough +(as originally suggested in [MSC2962](https://github.com/matrix-org/matrix-doc/pull/2962)), +but there are concerns that changing the behaviour of a pre-existing `public` +join rule may cause security issues in older implementations (that do not yet +understand the new behaviour). This could be solved by introducing a new room +version, thus it seems clearer to introduce a new join rule -- `restricted`. + +Using an `allow` key with the `invite` join rules to broaden who can join was rejected +as an option since it requires weakening the [auth rules](https://spec.matrix.org/unstable/rooms/v1/#authorization-rules). +From the perspective of the auth rules, the `restricted` join rule is identical +to `public` with additional checks on the signature of the event. + +## Future extensions + +### Checking room membership over federation + +If a homeserver is not in an allowed room (and thus doesn't know the +membership of it) then the server cannot enforce the membership checks while +generating a join event. Peeking over federation, as described in +[MSC2444](https://github.com/matrix-org/matrix-doc/pull/2444), +could be used to establish if the user is in any of the proper rooms. + +This would then delegate power out to a (potentially) untrusted server, giving that +peek server significant power. For example, a poorly chosen peek +server could lie about the room membership and add an `@evil_user:example.org` +to an allowed room to gain membership to a room. + +As iterated above, this MSC recommends rejecting the join, potentially allowing +the requesting homeserver to retry via another homeserver. + +### Kicking users out when they leave the allowed room + +In the above example, suppose `@bob:server.example` leaves `!users:example.org`: +should they be removed from the room? Likely not, by analogy with what happens +when you switch the join rules from `public` to `invite`. Join rules currently govern +joins, not existing room membership. + +It is left to a future MSC to consider this, but some potential thoughts are +given below. + +If you assume that a user *should* be removed in this case, one option is to +leave the departure up to Bob's server `server.example`, but this places a +relatively high level of trust in that server. Additionally, if `server.example` +were offline, other users in the room would still see Bob in the room (and their +servers would attempt to send message traffic to it). + +Another consideration is that users may have joined via a direct invite, not via +access through a room. + +Fixing this is thorny. Some sort of annotation on the membership events might +help, but it's unclear what the desired semantics are: + +* Assuming that users in an allowed room are *not* kicked when that room is + removed from `allow`, are those users then given a pass to remain + in the room indefinitely? What happens if the room is added back to + `allow` and *then* the user leaves it? +* Suppose a user joins a room via an allowed room (RoomA). Later, RoomB is added + to the `allow` list and RoomA is removed. What should happen when the + user leaves RoomB? Are they exempt from the kick? + +It is possible that completely different state should be kept, or a different +`m.room.member` state could be used in a more reasonable way to track this. + +### Inheriting join rules + +If an allowed room is a space and you make a parent space invite-only, should that +(optionally?) cascade into child rooms? This would have some of the same problems +as inheriting power levels, as discussed in [MSC2962](https://github.com/matrix-org/matrix-doc/pull/2962). + +### Additional allow types + +Future MSCs may wish to define additional values for the `type` argument, potentially +restricting access via: + +* MXIDs or servers. +* A shared secret (room password). + +These are just examples and are not fully thought through for this MSC, but it should +be possible to add these behaviors in the future. + +### Client considerations + +[MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772) defines a `via` +key in the content of `m.space.child` events: + +> the content must contain a via `key` which gives a list of candidate servers +> that can be used to join the room. + +It is possible for the list of candidate servers and the list of authorised +servers to diverge. It may not be possible for a user to join a room if there's +no overlap between these lists. + +If there is some overlap between the lists of servers the join request should +complete successfully. + +Clients should also consider the authorised servers when generating candidate +servers to embed in links to the room, e.g. via matrix.to. + +A future MSC may define a way to override or update the `via` key in a coherent +manner. + +## Footnotes + +[1]: The converse restriction, "anybody can join, provided they are not members +of the #catlovers:example.com space" is less useful since: + +1. Users in the banned room could simply leave it at any time +2. This functionality is already partially provided by + [Moderation policy lists](https://matrix.org/docs/spec/client_server/r0.6.1#moderation-policy-lists). [↩](#a1) + +[2]: Note that there is nothing stopping users sending and +receiving invites in `public` rooms today, and they work as you might expect. +The only difference is that you are not *required* to hold an invite when +joining the room. [↩](#a2) + +[3]: This seems like an improvement regardless since the resident server +is accepting the event on behalf of the joining server and ideally this should be +verifiable after the fact, even for current room versions. Requiring all events +to be signed and verified in this way is left to a future MSC. [↩](#a3) + +[4]: This has the downside of increased centralisation, as some +homeservers that are already in the room may not issue a join event for another +user on that server. (It must go through the `/make_join` / `/send_join` flow of +a server whose users may issue invites.) This is considered a reasonable +trade-off. [↩](#a4) diff --git a/proposals/3173-expose-stripped-state-events.md b/proposals/3173-expose-stripped-state-events.md new file mode 100644 index 000000000..830a9388a --- /dev/null +++ b/proposals/3173-expose-stripped-state-events.md @@ -0,0 +1,195 @@ +# MSC3173: Expose stripped state events to any potential joiner + +It can be useful to view the partial state of a room before joining to allow a user +to know *what* they're joining. For example, it improves the user experience to +show the user the room name and avatar before joining. + +It is already allowed to partially view the room state without being joined to +the room in some situations: + +* If the room has `history_visibility: world_readable`, then anyone can inspect + it (by calling `/state` on it). +* Rooms in the [room directory](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-publicrooms) + expose some of their state publicly. +* [Invited users](https://matrix.org/docs/spec/server_server/r0.1.4#put-matrix-federation-v2-invite-roomid-eventid) + and [knocking users](https://github.com/matrix-org/matrix-doc/pull/2403) + receive stripped state events to display metadata to users. + +This MSC proposes formalizing that the stripped state that is currently available +to invited and knocking users is available to any user who could potentially join +a room. It also defines "stripped state" and consolidates the recommendation on +which events to include in the stripped state. + +## Background + +When creating an invite it is [currently recommended](https://matrix.org/docs/spec/server_server/r0.1.4#put-matrix-federation-v2-invite-roomid-eventid) +to include stripped state events which are useful for displaying the invite to a user: + +> An optional list of simplified events to help the receiver of the invite identify +> the room. The recommended events to include are the join rules, canonical alias, +> avatar, and name of the room. + +The invited user receives these [stripped state events](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) +as part of the `/sync` response: + +> The state of a room that the user has been invited to. These state events may +> only have the `sender`, `type`, `state_key` and `content` keys present. These +> events do not replace any state that the client already has for the room, for +> example if the client has archived the room. + +These are sent as part of the [`unsigned` content of the `m.room.member` event](https://spec.matrix.org/unstable/client-server-api/#mroommember) +containing the invite. + +[MSC2403: Add "knock" feature](https://github.com/matrix-org/matrix-doc/pull/2403) +extends this concept to also include the stripped state events in the `/sync` response +for knocking users: + +> It is proposed to add a fourth possible key to rooms, called `knock`. Its value +> is a mapping from room ID to room information. The room information is a mapping +> from a key `knock_state` to another mapping with key events being a list of +> `StrippedStateEvent`. + +It is also provides an extended rationale of why this is useful: + +> These stripped state events contain information about the room, most notably the +> room's name and avatar. A client will need this information to show a nice +> representation of pending knocked rooms. The recommended events to include are the +> join rules, canonical alias, avatar, name and encryption state of the room, rather +> than all room state. This behaviour matches the information sent to remote +> homeservers when remote users are invited to a room. + +[MSC1772: Spaces](https://github.com/matrix-org/matrix-doc/pull/1772) additionally +recommends including the `m.room.create` event as one of the stripped state events: + +> Join rules, invites and 3PID invites work as for a normal room, with the exception +> that `invite_state` sent along with invites should be amended to include the +> `m.room.create` event, to allow clients to discern whether an invite is to a +> space-room or not. + +## Proposal + +The specification does not currently define what "stripped state" is or formally +describe who can access it, instead it is specified that certain situations (e.g. +an invite or knock) provide a potential joiner with the stripped state of a room. + +This MSC clarifies what "stripped state" is and formalizes who can access the +stripped state of a room in future cases. + +Potential ways that a user might be able to join a room include, but are not +limited to, the following mechanisms: + +* A room that has `join_rules` set to `public` or `knock`. +* A room that the user is in possession of an invite to (regardless of the `join_rules`). + +This MSC proposes a formal definition for the stripped state of a room[1](#f1): + +> The stripped state of a room is a list of simplified state events to help a +> potential joiner identify the room. These state events may only have the +> `sender`, `type`, `state_key` and `content` keys present. + +### Client behavior + +These events do not replace any state that the client already has for the room, +for example if the client has archived the room. Instead the client should keep +two separate copies of the state: the one from the stripped state and one from the +archived state. If the client joins the room then the current state will be given +as a delta against the archived state not the stripped state. + +### Server behavior + +It is recommended (although not required[2](#f2)) that +homeserver implementations include the following events as part of the stripped +state of a room: + +* Create event (`m.room.create`)[3](#f3) +* Join rules (`m.room.join_rules`) +* Canonical alias (`m.room.canonical_alias`) +* Room avatar (`m.room.avatar`) +* Room name (`m.room.name`) +* Encryption information (`m.room.encryption`)[4](#f4) +* Room topic (`m.room.topic`)[5](#f5) + +## Potential issues + +This is a formalization of current behavior and should not introduce new issues. + +## Alternatives + +A different approach would be to continue with what is done today for invites, +knocking, the room directory: separately specify that a user is allowed to see +the stripped state (and what events the stripped state should contain). + +## Security considerations + +This would allow for invisibly accessing the stripped state of a room with `public` +or `knock` join rules. + +In the case of a public room, if the room has `history_visibility` set to `world_readable` +then this is no change. Additionally, this information is already provided by the +room directory (if the room is listed there). Otherwise, it is trivial to access +the state of the room by joining, but currently users in the room would know +that the join occurred. + +Similarly, in the case of knocking, a user is able to trivially access the +stripped state of the room by knocking, but users in the room would know that +the knock occurred. + +This does not seem to weaken the security expectations of either join rule. + +## Future extensions + +### Revisions to the room directory + +A future MSC could include additional information from the stripped state events +in the [room directory](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-publicrooms). +The main missing piece seems to be the encryption information, but there may also +be other pieces of information to include. + +### Additional ways to access the stripped state + +[MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946) proposes including +the stripped state in the spaces summary. Not needing to rationalize what state +can be included for a potential joiner would simplify this (and future) MSCs. + +### Additional ways to join a room + +[MSC3083](https://github.com/matrix-org/matrix-doc/pull/3083) proposes a new +join rule due to membership in a space. This MSC would clarify that the stripped +state of a room is available to those joiners. + +### Dedicated API for accessing the stripped state + +Dedicated client-server and server-server APIs could be added to request the +stripped state events, but that is considered out-of-scope for the current +proposal. + +This API would allow any potential joiner to query for the stripped state. If +the server does not know the room's state it would need to query other servers +for it. + +## Unstable prefix + +N/A + +## Footnotes + +[1]: No changes are proposed to +[the definition of `history_visibility`](https://matrix.org/docs/spec/client_server/latest#room-history-visibility). +The state of a room which is `world_readable` is available to anyone. This somewhat +implies that the stripped state is also available to anyone, regardless of the join +rules, but having a `world_readable`, `invite` room does not seem valuable. [↩](#a1) + +[2]: Privacy conscious deployments may wish to limit the metadata +available to users who are not in a room as the trade-off against user experience. +There seems to be no reason to not allow this. [↩](#a2) + +[3]: As updated in [MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772). [↩](#a3) + +[4]: The encryption information (`m.room.encryption`) is already sent +from Synapse and generally seems useful for a user to know before joining a room. +[↩](#a4) + +[5]: The room topic (`m.room.topic`) is included as part of the +[room directory](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-publicrooms) +response for public rooms. It is also planned to be included as part of [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946) +in the spaces summary response. [↩](#a5) diff --git a/proposals/3289-rooms-v8.md b/proposals/3289-rooms-v8.md new file mode 100644 index 000000000..7212e0a8c --- /dev/null +++ b/proposals/3289-rooms-v8.md @@ -0,0 +1,15 @@ +# MSC3289: Room Version 8 + +A new room version, `8`, is proposed using [room version 7](https://spec.matrix.org/unstable/rooms/v7/) +as a base and incorporating the following MSCs: + +* [MSC3083](https://github.com/matrix-org/matrix-doc/pull/3083) - Restricting room + membership based on membership in other rooms + +Though other MSCs are capable of being included in this version, they do not have +sufficient implementation to be considered for this room version. A future room +version may include them. + +Room version `8` upon being added to the specification shall be considered stable. +No other room versions are affected by this MSC. Before room version `8` can enter +the specification, MSC3083 needs to complete its final comment period.