mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-03-23 03:34:08 +01:00
Merge branch 'main' into login-formats
This commit is contained in:
commit
094680f3d1
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
|
@ -255,7 +255,7 @@ jobs:
|
||||||
- name: "Run htmltest"
|
- name: "Run htmltest"
|
||||||
uses: wjdp/htmltest-action@master
|
uses: wjdp/htmltest-action@master
|
||||||
with:
|
with:
|
||||||
config: .htmltest.yaml
|
config: .htmltest.yml
|
||||||
|
|
||||||
build-historical-spec:
|
build-historical-spec:
|
||||||
name: "📖 Build the historical backup spec"
|
name: "📖 Build the historical backup spec"
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,6 @@ Custom SCSS for the Matrix spec
|
||||||
*/
|
*/
|
||||||
@import "syntax.scss";
|
@import "syntax.scss";
|
||||||
|
|
||||||
/* Workaround for https://github.com/google/docsy/issues/1116:
|
|
||||||
* fix scroll-anchoring */
|
|
||||||
.td-outer {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overrides for the navbar */
|
/* Overrides for the navbar */
|
||||||
.td-navbar {
|
.td-navbar {
|
||||||
box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25);
|
box-shadow: 0px 0px 8px rgba(179, 179, 179, 0.25);
|
||||||
|
|
@ -387,6 +381,11 @@ footer {
|
||||||
border-top: 1px $table-border-color solid;
|
border-top: 1px $table-border-color solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td > p:last-child {
|
||||||
|
// Avoid unnecessary space at the bottom of the cells.
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&.object-table, &.response-table, &.content-type-table {
|
&.object-table, &.response-table, &.content-type-table {
|
||||||
border: 1px $table-border-color solid;
|
border: 1px $table-border-color solid;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Sort VoIP events semantically.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify that servers must forward custom keys in `PusherData` when sending notifications to the push gateway.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify formats of string types.
|
||||||
1
changelogs/internal/newsfragments/1967.clarification
Normal file
1
changelogs/internal/newsfragments/1967.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add `x-weight` property for sorting events rendered with the `event-group` shortcode.
|
||||||
1
changelogs/internal/newsfragments/1969.clarification
Normal file
1
changelogs/internal/newsfragments/1969.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Enforce consistent vertical spacing between paragraphs in endpoint definitions.
|
||||||
1
changelogs/internal/newsfragments/1975.clarification
Normal file
1
changelogs/internal/newsfragments/1975.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Fix formatting of `added-in` and `changed-in` shortcodes by using `%` delimiter.
|
||||||
1
changelogs/internal/newsfragments/1976.clarification
Normal file
1
changelogs/internal/newsfragments/1976.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Remove CSS workaround for scroll-anchoring.
|
||||||
1
changelogs/internal/newsfragments/1977.clarification
Normal file
1
changelogs/internal/newsfragments/1977.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Rename `custom-formats.yaml` to `string-formats.yaml` and update its docs.
|
||||||
1
changelogs/internal/newsfragments/1985.clarification
Normal file
1
changelogs/internal/newsfragments/1985.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Rename `.htmltest.yaml` to `.htmltest.yml`.
|
||||||
1
changelogs/push_gateway/newsfragments/1968.clarification
Normal file
1
changelogs/push_gateway/newsfragments/1968.clarification
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Document the schema of `PusherData`.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Add 403 error response to `/_matrix/federation/v1/state_ids/{roomId}`.
|
||||||
|
|
@ -761,7 +761,7 @@ wish to consider handling them as `u`, `r`, and `e` respectively.
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
{{< changed-in v="1.11" >}}
|
{{% changed-in v="1.11" %}}
|
||||||
Referencing event IDs within a room identified by room alias (`r`) rather than room ID
|
Referencing event IDs within a room identified by room alias (`r`) rather than room ID
|
||||||
(`roomid`) is now deprecated. We are not aware of these ever having been used in
|
(`roomid`) is now deprecated. We are not aware of these ever having been used in
|
||||||
practice, and are nonsensical given room aliases are mutable.
|
practice, and are nonsensical given room aliases are mutable.
|
||||||
|
|
@ -858,7 +858,7 @@ Examples of matrix.to URIs are:
|
||||||
* Link to `@alice:example.org`: `https://matrix.to/#/%40alice%3Aexample.org`
|
* Link to `@alice:example.org`: `https://matrix.to/#/%40alice%3Aexample.org`
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
{{< changed-in v="1.11" >}}
|
{{% changed-in v="1.11" %}}
|
||||||
Referencing event IDs within a room identified by room alias rather than room ID
|
Referencing event IDs within a room identified by room alias rather than room ID
|
||||||
is now deprecated. We are not aware of these ever having been used in
|
is now deprecated. We are not aware of these ever having been used in
|
||||||
practice, and are nonsensical given room aliases are mutable.
|
practice, and are nonsensical given room aliases are mutable.
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,8 @@ The `retry_after_ms` property MAY be included to tell the client how long
|
||||||
they have to wait in milliseconds before they can try again. This property is
|
they have to wait in milliseconds before they can try again. This property is
|
||||||
deprecated, in favour of the `Retry-After` header.
|
deprecated, in favour of the `Retry-After` header.
|
||||||
|
|
||||||
{{< changed-in v="1.10" >}}: `retry_after_ms` property deprecated in favour of `Retry-After` header.
|
{{% changed-in v="1.10" %}}: `retry_after_ms` property deprecated in favour of `Retry-After` header.
|
||||||
|
|
||||||
### Transaction identifiers
|
### Transaction identifiers
|
||||||
|
|
||||||
The client-server API typically uses `HTTP PUT` to submit requests with
|
The client-server API typically uses `HTTP PUT` to submit requests with
|
||||||
|
|
@ -436,7 +437,7 @@ could mean one of four things:
|
||||||
1. the access token was never valid.
|
1. the access token was never valid.
|
||||||
2. the access token has been logged out.
|
2. the access token has been logged out.
|
||||||
3. the access token has been [soft logged out](#soft-logout).
|
3. the access token has been [soft logged out](#soft-logout).
|
||||||
4. {{< added-in v="1.3" >}} the access token [needs to be refreshed](#refreshing-access-tokens).
|
4. {{% added-in v="1.3" %}} the access token [needs to be refreshed](#refreshing-access-tokens).
|
||||||
|
|
||||||
When a client receives an error code of `M_UNKNOWN_TOKEN`, it should:
|
When a client receives an error code of `M_UNKNOWN_TOKEN`, it should:
|
||||||
|
|
||||||
|
|
@ -1350,7 +1351,7 @@ client supports it, the client should redirect the user to the
|
||||||
is complete, the client will need to submit a `/login` request matching
|
is complete, the client will need to submit a `/login` request matching
|
||||||
`m.login.token`.
|
`m.login.token`.
|
||||||
|
|
||||||
{{< added-in v="1.7" >}} Already-authenticated clients can additionally generate
|
{{% added-in v="1.7" %}} Already-authenticated clients can additionally generate
|
||||||
a token for their user ID if supported by the homeserver using
|
a token for their user ID if supported by the homeserver using
|
||||||
[`POST /login/get_token`](/client-server-api/#post_matrixclientv1loginget_token).
|
[`POST /login/get_token`](/client-server-api/#post_matrixclientv1loginget_token).
|
||||||
|
|
||||||
|
|
@ -2342,7 +2343,7 @@ The endpoints where the server *should* include bundled aggregations are:
|
||||||
* [`GET /sync`](#get_matrixclientv3sync) when the relevant section has a `limited` value
|
* [`GET /sync`](#get_matrixclientv3sync) when the relevant section has a `limited` value
|
||||||
of `true`.
|
of `true`.
|
||||||
* [`POST /search`](#post_matrixclientv3search) for any matching events under `room_events`.
|
* [`POST /search`](#post_matrixclientv3search) for any matching events under `room_events`.
|
||||||
* {{< added-in v="1.4" >}} [`GET /rooms/{roomId}/threads`](#get_matrixclientv1roomsroomidthreads)
|
* {{% added-in v="1.4" %}} [`GET /rooms/{roomId}/threads`](#get_matrixclientv1roomsroomidthreads)
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
The server is **not** required to return bundled aggregations on deprecated endpoints
|
The server is **not** required to return bundled aggregations on deprecated endpoints
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ When serving content, the server SHOULD provide a
|
||||||
`Content-Security-Policy` header. The recommended policy is
|
`Content-Security-Policy` header. The recommended policy is
|
||||||
`sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';`.
|
`sandbox; default-src 'none'; script-src 'none'; plugin-types application/pdf; style-src 'unsafe-inline'; object-src 'self';`.
|
||||||
|
|
||||||
{{< added-in v="1.4" >}} The server SHOULD additionally provide
|
{{% added-in v="1.4" %}} The server SHOULD additionally provide
|
||||||
`Cross-Origin-Resource-Policy: cross-origin` when serving content to allow
|
`Cross-Origin-Resource-Policy: cross-origin` when serving content to allow
|
||||||
(web) clients to access restricted APIs such as `SharedArrayBuffer` when
|
(web) clients to access restricted APIs such as `SharedArrayBuffer` when
|
||||||
interacting with the media repository.
|
interacting with the media repository.
|
||||||
|
|
||||||
{{< changed-in v="1.11" >}} The unauthenticated download endpoints have been
|
{{% changed-in v="1.11" %}} The unauthenticated download endpoints have been
|
||||||
deprecated in favour of newer, authenticated, ones. This change includes updating
|
deprecated in favour of newer, authenticated, ones. This change includes updating
|
||||||
the paths of all media endpoints from `/_matrix/media/*` to `/_matrix/client/{version}/media/*`,
|
the paths of all media endpoints from `/_matrix/media/*` to `/_matrix/client/{version}/media/*`,
|
||||||
with the exception of the `/upload` and `/create` endpoints. The upload/create
|
with the exception of the `/upload` and `/create` endpoints. The upload/create
|
||||||
|
|
@ -44,7 +44,7 @@ mxc://<server-name>/<media-id>
|
||||||
|
|
||||||
Clients can access the content repository using the following endpoints.
|
Clients can access the content repository using the following endpoints.
|
||||||
|
|
||||||
{{< changed-in v="1.11" >}} A number of endpoints under the /_matrix/media hierarchy
|
{{% changed-in v="1.11" %}} A number of endpoints under the /_matrix/media hierarchy
|
||||||
have been deprecated and replaced with new endpoints which require authentication.
|
have been deprecated and replaced with new endpoints which require authentication.
|
||||||
The deprecated endpoints are marked in the section below.
|
The deprecated endpoints are marked in the section below.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ replacement event.
|
||||||
|
|
||||||
##### Server-side aggregation of `m.replace` relationships
|
##### Server-side aggregation of `m.replace` relationships
|
||||||
|
|
||||||
{{< changed-in v="1.7" >}}
|
{{% changed-in v="1.7" %}}
|
||||||
|
|
||||||
Note that there can be multiple events with an `m.replace` relationship to a
|
Note that there can be multiple events with an `m.replace` relationship to a
|
||||||
given event (for example, if an event is edited multiple times). These should
|
given event (for example, if an event is edited multiple times). These should
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,13 @@ for retrieving events and associated media:
|
||||||
* [GET /rooms/{roomId}/event/{eventId}](#get_matrixclientv3roomsroomideventeventid)
|
* [GET /rooms/{roomId}/event/{eventId}](#get_matrixclientv3roomsroomideventeventid)
|
||||||
* [GET /rooms/{roomId}/state/{eventType}/{stateKey}](#get_matrixclientv3roomsroomidstateeventtypestatekey)
|
* [GET /rooms/{roomId}/state/{eventType}/{stateKey}](#get_matrixclientv3roomsroomidstateeventtypestatekey)
|
||||||
* [GET /rooms/{roomId}/messages](#get_matrixclientv3roomsroomidmessages)
|
* [GET /rooms/{roomId}/messages](#get_matrixclientv3roomsroomidmessages)
|
||||||
* {{< added-in v="1.1" >}} [GET /rooms/{roomId}/members](#get_matrixclientv3roomsroomidmembers)
|
* {{% added-in v="1.1" %}} [GET /rooms/{roomId}/members](#get_matrixclientv3roomsroomidmembers)
|
||||||
* [GET /rooms/{roomId}/initialSync](#get_matrixclientv3roomsroomidinitialsync)
|
* [GET /rooms/{roomId}/initialSync](#get_matrixclientv3roomsroomidinitialsync)
|
||||||
* [GET /sync](#get_matrixclientv3sync)
|
* [GET /sync](#get_matrixclientv3sync)
|
||||||
* [GET /events](#get_matrixclientv3events) as used for room previews.
|
* [GET /events](#get_matrixclientv3events) as used for room previews.
|
||||||
* {{< added-in v="1.12" >}} [GET /media/download/{serverName}/{mediaId}](#get_matrixclientv1mediadownloadservernamemediaid)
|
* {{% added-in v="1.12" %}} [GET /media/download/{serverName}/{mediaId}](#get_matrixclientv1mediadownloadservernamemediaid)
|
||||||
* {{< added-in v="1.12" >}} [GET /media/download/{serverName}/{mediaId}/{fileName}](#get_matrixclientv1mediadownloadservernamemediaidfilename)
|
* {{% added-in v="1.12" %}} [GET /media/download/{serverName}/{mediaId}/{fileName}](#get_matrixclientv1mediadownloadservernamemediaidfilename)
|
||||||
* {{< added-in v="1.12" >}} [GET /media/thumbnail/{serverName}/{mediaId}](#get_matrixclientv1mediathumbnailservernamemediaid)
|
* {{% added-in v="1.12" %}} [GET /media/thumbnail/{serverName}/{mediaId}](#get_matrixclientv1mediathumbnailservernamemediaid)
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
for sending events:
|
for sending events:
|
||||||
|
|
@ -55,9 +55,9 @@ for sending events:
|
||||||
* [POST /rooms/{roomId}/leave](#post_matrixclientv3roomsroomidleave)
|
* [POST /rooms/{roomId}/leave](#post_matrixclientv3roomsroomidleave)
|
||||||
* [PUT /rooms/{roomId}/send/{eventType}/{txnId}](#put_matrixclientv3roomsroomidsendeventtypetxnid)
|
* [PUT /rooms/{roomId}/send/{eventType}/{txnId}](#put_matrixclientv3roomsroomidsendeventtypetxnid)
|
||||||
|
|
||||||
* {{< changed-in v="1.2" >}} Guests can now send *any* event type rather than just `m.room.message` events.
|
* {{% changed-in v="1.2" %}} Guests can now send *any* event type rather than just `m.room.message` events.
|
||||||
|
|
||||||
* {{< added-in v="1.2" >}} [PUT /rooms/{roomId}/state/{eventType}/{stateKey}](#put_matrixclientv3roomsroomidstateeventtypestatekey)
|
* {{% added-in v="1.2" %}} [PUT /rooms/{roomId}/state/{eventType}/{stateKey}](#put_matrixclientv3roomsroomidstateeventtypestatekey)
|
||||||
* [PUT /sendToDevice/{eventType}/{txnId}](#put_matrixclientv3sendtodeviceeventtypetxnid)
|
* [PUT /sendToDevice/{eventType}/{txnId}](#put_matrixclientv3sendtodeviceeventtypetxnid)
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
|
|
@ -67,7 +67,7 @@ for their own account maintenance:
|
||||||
* [GET /devices](#get_matrixclientv3devices)
|
* [GET /devices](#get_matrixclientv3devices)
|
||||||
* [GET /devices/{deviceId}](#get_matrixclientv3devicesdeviceid)
|
* [GET /devices/{deviceId}](#get_matrixclientv3devicesdeviceid)
|
||||||
* [PUT /devices/{deviceId}](#put_matrixclientv3devicesdeviceid)
|
* [PUT /devices/{deviceId}](#put_matrixclientv3devicesdeviceid)
|
||||||
* {{< added-in v="1.2" >}} [GET /account/whoami](#get_matrixclientv3accountwhoami)
|
* {{% added-in v="1.2" %}} [GET /account/whoami](#get_matrixclientv3accountwhoami)
|
||||||
|
|
||||||
The following API endpoints are allowed to be accessed by guest accounts
|
The following API endpoints are allowed to be accessed by guest accounts
|
||||||
for end-to-end encryption:
|
for end-to-end encryption:
|
||||||
|
|
|
||||||
|
|
@ -525,7 +525,7 @@ Definition:
|
||||||
|
|
||||||
<a id="_m_rule_is_user_mention"></a> **`.m.rule.is_user_mention`**
|
<a id="_m_rule_is_user_mention"></a> **`.m.rule.is_user_mention`**
|
||||||
|
|
||||||
{{< added-in v="1.7" >}}
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
Matches any message which contains the user's Matrix ID in the list of `user_ids`
|
Matches any message which contains the user's Matrix ID in the list of `user_ids`
|
||||||
under the `m.mentions` property.
|
under the `m.mentions` property.
|
||||||
|
|
@ -594,7 +594,7 @@ Definition:
|
||||||
|
|
||||||
<a id="_m_rule_is_room_mention"></a> **`.m.rule.is_room_mention`**
|
<a id="_m_rule_is_room_mention"></a> **`.m.rule.is_room_mention`**
|
||||||
|
|
||||||
{{< added-in v="1.7" >}}
|
{{% added-in v="1.7" %}}
|
||||||
|
|
||||||
Matches any message from a sender with the proper power level with the `room`
|
Matches any message from a sender with the proper power level with the `room`
|
||||||
property of the `m.mentions` property set to `true`.
|
property of the `m.mentions` property set to `true`.
|
||||||
|
|
@ -1072,7 +1072,7 @@ ahead), however if the `m.read.private` receipt were to be updated to
|
||||||
event D then the user has read up to D (the `m.read` receipt is now
|
event D then the user has read up to D (the `m.read` receipt is now
|
||||||
behind the `m.read.private` receipt).
|
behind the `m.read.private` receipt).
|
||||||
|
|
||||||
{{< added-in v="1.4" >}} When handling threaded read receipts, the server is to
|
{{% added-in v="1.4" %}} When handling threaded read receipts, the server is to
|
||||||
partition the notification count to each thread (with the main timeline being
|
partition the notification count to each thread (with the main timeline being
|
||||||
its own thread). To determine if an event is part of a thread the server follows
|
its own thread). To determine if an event is part of a thread the server follows
|
||||||
the [event relationship](#forming-relationships-between-events) until it finds a
|
the [event relationship](#forming-relationships-between-events) until it finds a
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ The client cannot update fully read markers by directly modifying the
|
||||||
`m.fully_read` account data event. Instead, the client must make use of
|
`m.fully_read` account data event. Instead, the client must make use of
|
||||||
the read markers API to change the values.
|
the read markers API to change the values.
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} `m.read.private` receipts can now be sent from
|
{{% changed-in v="1.4" %}} `m.read.private` receipts can now be sent from
|
||||||
`/read_markers`.
|
`/read_markers`.
|
||||||
|
|
||||||
The read markers API can additionally update the user's read receipt
|
The read markers API can additionally update the user's read receipt
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
### Receipts
|
### Receipts
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} Added private read receipts.
|
{{% changed-in v="1.4" %}} Added private read receipts.
|
||||||
|
|
||||||
This module adds in support for receipts. These receipts are a form of
|
This module adds in support for receipts. These receipts are a form of
|
||||||
acknowledgement of an event. This module defines the `m.read` receipt
|
acknowledgement of an event. This module defines the `m.read` receipt
|
||||||
|
|
@ -19,7 +19,7 @@ that the user had read all events *up to* the referenced event. See the
|
||||||
[Receiving notifications](#receiving-notifications) section for more
|
[Receiving notifications](#receiving-notifications) section for more
|
||||||
information on how read receipts affect notification counts.
|
information on how read receipts affect notification counts.
|
||||||
|
|
||||||
{{< added-in v="1.4" >}} Read receipts exist in three major forms:
|
{{% added-in v="1.4" %}} Read receipts exist in three major forms:
|
||||||
* Unthreaded: Denotes a read-up-to receipt regardless of threads. This is how
|
* Unthreaded: Denotes a read-up-to receipt regardless of threads. This is how
|
||||||
pre-threading read receipts worked.
|
pre-threading read receipts worked.
|
||||||
* Threaded, main timeline: Denotes a read-up-to receipt for events not in a
|
* Threaded, main timeline: Denotes a read-up-to receipt for events not in a
|
||||||
|
|
@ -31,7 +31,7 @@ Threaded read receipts are discussed in further detail [below](#threaded-read-re
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} Each `user_id`, `receipt_type`, and categorisation
|
{{% changed-in v="1.4" %}} Each `user_id`, `receipt_type`, and categorisation
|
||||||
(unthreaded, or `thread_id`) tuple must be associated with only a single
|
(unthreaded, or `thread_id`) tuple must be associated with only a single
|
||||||
`event_id`.
|
`event_id`.
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ Threaded read receipts are discussed in further detail [below](#threaded-read-re
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
{{< changed-in v="1.4" >}} Altered to support threaded read receipts.
|
{{% changed-in v="1.4" %}} Altered to support threaded read receipts.
|
||||||
|
|
||||||
In `/sync`, receipts are listed under the `ephemeral` array of events
|
In `/sync`, receipts are listed under the `ephemeral` array of events
|
||||||
for a given room. New receipts that come down the event streams are
|
for a given room. New receipts that come down the event streams are
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ rooms instead of individual events. Server administrators and safety teams
|
||||||
should, therefore, be cautious not to shut down rooms that might otherwise
|
should, therefore, be cautious not to shut down rooms that might otherwise
|
||||||
be legitimate.
|
be legitimate.
|
||||||
|
|
||||||
{{< changed-in v="1.8" >}} When processing event reports, servers MUST
|
{{% changed-in v="1.8" %}} When processing event reports, servers MUST
|
||||||
verify that the reporting user is currently joined to the room the event
|
verify that the reporting user is currently joined to the room the event
|
||||||
is in before accepting a report.
|
is in before accepting a report.
|
||||||
|
|
||||||
{{< added-in v="1.12" >}} Contrarily, servers MUST NOT restrict room reports
|
{{% added-in v="1.12" %}} Contrarily, servers MUST NOT restrict room reports
|
||||||
based on whether or not the reporting user is joined to the room. This is
|
based on whether or not the reporting user is joined to the room. This is
|
||||||
because users can be exposed to harmful content without being joined to a
|
because users can be exposed to harmful content without being joined to a
|
||||||
room. For instance, through room directories or invites.
|
room. For instance, through room directories or invites.
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ server:
|
||||||
1. Checks that the user has permission to send `m.room.tombstone`
|
1. Checks that the user has permission to send `m.room.tombstone`
|
||||||
events in the room.
|
events in the room.
|
||||||
|
|
||||||
2. {{< changed-in v="1.4" >}} Creates a replacement room with a `m.room.create` event containing a
|
2. {{% changed-in v="1.4" %}} Creates a replacement room with a `m.room.create` event containing a
|
||||||
`predecessor` field, the applicable `room_version`, and a `type` field
|
`predecessor` field, the applicable `room_version`, and a `type` field
|
||||||
which is copied from the `predecessor` room. If no `type` is set on the
|
which is copied from the `predecessor` room. If no `type` is set on the
|
||||||
previous room, no `type` is specified on the new room's create event
|
previous room, no `type` is specified on the new room's create event
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
---
|
---
|
||||||
{{< added-in v=3 >}} In room versions 1 and 2, events need a
|
{{% added-in v=3 %}} In room versions 1 and 2, events need a
|
||||||
signature from the domain of the `event_id` in order to be considered
|
signature from the domain of the `event_id` in order to be considered
|
||||||
valid. This room version does not include an `event_id` over federation
|
valid. This room version does not include an `event_id` over federation
|
||||||
in the same respect, so does not need a signature from that server.
|
in the same respect, so does not need a signature from that server.
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ The rules are as follows:
|
||||||
4. If type is `m.room.member`:
|
4. If type is `m.room.member`:
|
||||||
1. If there is no `state_key` property, or no `membership` property in
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
`content`, reject.
|
`content`, reject.
|
||||||
2. {{< added-in v=8 >}}
|
2. {{% added-in v=8 %}}
|
||||||
If `content` has a `join_authorised_via_users_server` property:
|
If `content` has a `join_authorised_via_users_server` property:
|
||||||
1. If the event is not validly signed by the homeserver of the user ID denoted
|
1. If the event is not validly signed by the homeserver of the user ID denoted
|
||||||
by the key, reject.
|
by the key, reject.
|
||||||
|
|
@ -65,7 +65,7 @@ The rules are as follows:
|
||||||
3. If the `sender` is banned, reject.
|
3. If the `sender` is banned, reject.
|
||||||
4. If the `join_rule` is `invite` or `knock` then allow if
|
4. If the `join_rule` is `invite` or `knock` then allow if
|
||||||
membership state is `invite` or `join`.
|
membership state is `invite` or `join`.
|
||||||
5. {{< added-in v=8 >}}
|
5. {{% added-in v=8 %}}
|
||||||
If the `join_rule` is `restricted`:
|
If the `join_rule` is `restricted`:
|
||||||
1. If membership state is `join` or `invite`, allow.
|
1. If membership state is `join` or `invite`, allow.
|
||||||
2. If the `join_authorised_via_users_server` key in `content`
|
2. If the `join_authorised_via_users_server` key in `content`
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ The rules are as follows:
|
||||||
3. If the `sender` is banned, reject.
|
3. If the `sender` is banned, reject.
|
||||||
4. If the `join_rule` is `invite` or `knock` then allow if
|
4. If the `join_rule` is `invite` or `knock` then allow if
|
||||||
membership state is `invite` or `join`.
|
membership state is `invite` or `join`.
|
||||||
5. {{< changed-in v=10 >}}
|
5. {{% changed-in v=10 %}}
|
||||||
If the `join_rule` is `restricted` or `knock_restricted`:
|
If the `join_rule` is `restricted` or `knock_restricted`:
|
||||||
1. If membership state is `join` or `invite`, allow.
|
1. If membership state is `join` or `invite`, allow.
|
||||||
2. If the `join_authorised_via_users_server` key in `content`
|
2. If the `join_authorised_via_users_server` key in `content`
|
||||||
|
|
@ -197,7 +197,7 @@ The rules are as follows:
|
||||||
than the `sender`'s power level, allow.
|
than the `sender`'s power level, allow.
|
||||||
3. Otherwise, reject.
|
3. Otherwise, reject.
|
||||||
7. If `membership` is `knock`:
|
7. If `membership` is `knock`:
|
||||||
1. {{< changed-in v=10 >}}
|
1. {{% changed-in v=10 %}}
|
||||||
If the `join_rule` is anything other than `knock` or
|
If the `join_rule` is anything other than `knock` or
|
||||||
`knock_restricted`, reject.
|
`knock_restricted`, reject.
|
||||||
2. If `sender` does not match `state_key`, reject.
|
2. If `sender` does not match `state_key`, reject.
|
||||||
|
|
@ -214,11 +214,11 @@ The rules are as follows:
|
||||||
8. If the event has a `state_key` that starts with an `@` and does not
|
8. If the event has a `state_key` that starts with an `@` and does not
|
||||||
match the `sender`, reject.
|
match the `sender`, reject.
|
||||||
9. If type is `m.room.power_levels`:
|
9. If type is `m.room.power_levels`:
|
||||||
1. {{< added-in v=10 >}}
|
1. {{% added-in v=10 %}}
|
||||||
If any of the properties `users_default`, `events_default`, `state_default`,
|
If any of the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, or `invite` in `content` are present and
|
`ban`, `redact`, `kick`, or `invite` in `content` are present and
|
||||||
not an integer, reject.
|
not an integer, reject.
|
||||||
2. {{< added-in v=10 >}}
|
2. {{% added-in v=10 %}}
|
||||||
If either of the properties `events` or `notifications` in `content`
|
If either of the properties `events` or `notifications` in `content`
|
||||||
are present and not an object with values that are integers,
|
are present and not an object with values that are integers,
|
||||||
reject.
|
reject.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ rules.
|
||||||
|
|
||||||
### Redactions
|
### Redactions
|
||||||
|
|
||||||
{{< added-in v=11 >}} The top-level `origin`, `membership`, and `prev_state` properties
|
{{% added-in v=11 %}} The top-level `origin`, `membership`, and `prev_state` properties
|
||||||
are no longer protected from redaction. The [`m.room.create`](/client-server-api#mroomcreate)
|
are no longer protected from redaction. The [`m.room.create`](/client-server-api#mroomcreate)
|
||||||
event now keeps the entire `content` property. The [`m.room.redaction`](/client-server-api#mroomredaction)
|
event now keeps the entire `content` property. The [`m.room.redaction`](/client-server-api#mroomredaction)
|
||||||
event keeps the `redacts` property under `content`. The
|
event keeps the `redacts` property under `content`. The
|
||||||
|
|
@ -112,7 +112,7 @@ the [Handling redactions](#handling-redactions) section.
|
||||||
|
|
||||||
The rules are as follows:
|
The rules are as follows:
|
||||||
|
|
||||||
1. {{< changed-in v=11 >}}
|
1. {{% changed-in v=11 %}}
|
||||||
If type is `m.room.create`:
|
If type is `m.room.create`:
|
||||||
1. If it has any `prev_events`, reject.
|
1. If it has any `prev_events`, reject.
|
||||||
2. If the domain of the `room_id` does not match the domain of the
|
2. If the domain of the `room_id` does not match the domain of the
|
||||||
|
|
@ -142,7 +142,7 @@ The rules are as follows:
|
||||||
1. If the event is not validly signed by the homeserver of the user ID denoted
|
1. If the event is not validly signed by the homeserver of the user ID denoted
|
||||||
by the key, reject.
|
by the key, reject.
|
||||||
3. If `membership` is `join`:
|
3. If `membership` is `join`:
|
||||||
1. {{< changed-in v=11 >}}
|
1. {{% changed-in v=11 %}}
|
||||||
If the only previous event is an `m.room.create` and the
|
If the only previous event is an `m.room.create` and the
|
||||||
`state_key` is the sender, allow.
|
`state_key` is the sender, allow.
|
||||||
2. If the `sender` does not match `state_key`, reject.
|
2. If the `sender` does not match `state_key`, reject.
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ The complete structure of a event in a v3 room is shown below.
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
{{< added-in v=3 >}} `m.room.redaction` events are subject to auth rules in
|
{{% added-in v=3 %}} `m.room.redaction` events are subject to auth rules in
|
||||||
the same way as any other event. In practice, that means they will normally be allowed
|
the same way as any other event. In practice, that means they will normally be allowed
|
||||||
by the auth rules, unless the `m.room.power_levels` event sets a power level requirement
|
by the auth rules, unless the `m.room.power_levels` event sets a power level requirement
|
||||||
for `m.room.redaction`events via the `events` or `events_default` properties. In
|
for `m.room.redaction`events via the `events` or `events_default` properties. In
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ which implement the redaction algorithm locally should refer to the
|
||||||
|
|
||||||
### Redactions
|
### Redactions
|
||||||
|
|
||||||
{{< added-in v=6 >}} All significant meaning for `m.room.aliases`
|
{{% added-in v=6 %}} All significant meaning for `m.room.aliases`
|
||||||
has been removed from the redaction algorithm. The remaining rules are
|
has been removed from the redaction algorithm. The remaining rules are
|
||||||
the same as past room versions.
|
the same as past room versions.
|
||||||
|
|
||||||
|
|
@ -41,11 +41,11 @@ in [room version 5](/rooms/v5).
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{< added-in v=6 >}} Rule 4, which related specifically to events
|
{{% added-in v=6 %}} Rule 4, which related specifically to events
|
||||||
of type `m.room.aliases`, is removed. `m.room.aliases` events must still pass
|
of type `m.room.aliases`, is removed. `m.room.aliases` events must still pass
|
||||||
authorization checks relating to state events.
|
authorization checks relating to state events.
|
||||||
|
|
||||||
{{< added-in v=6 >}} Additionally, the authorization rules for events of
|
{{% added-in v=6 %}} Additionally, the authorization rules for events of
|
||||||
type `m.room.power_levels` now include a `notifications` property under
|
type `m.room.power_levels` now include a `notifications` property under
|
||||||
`content`. This updates rules 10.4 and 10.5 (now 9.4 and 9.5), which checked
|
`content`. This updates rules 10.4 and 10.5 (now 9.4 and 9.5), which checked
|
||||||
the `events` property.
|
the `events` property.
|
||||||
|
|
@ -175,12 +175,12 @@ The rules are as follows:
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
2. If the new value is higher than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
4. {{< changed-in v=6 >}}
|
4. {{% changed-in v=6 %}}
|
||||||
For each entry being changed in, or removed from, the `events` or
|
For each entry being changed in, or removed from, the `events` or
|
||||||
`notifications` properties:
|
`notifications` properties:
|
||||||
1. If the current value is greater than the `sender`'s current
|
1. If the current value is greater than the `sender`'s current
|
||||||
power level, reject.
|
power level, reject.
|
||||||
5. {{< changed-in v=6 >}}
|
5. {{% changed-in v=6 %}}
|
||||||
For each entry being added to, or changed in, the `events` or
|
For each entry being added to, or changed in, the `events` or
|
||||||
`notifications` properties:
|
`notifications` properties:
|
||||||
1. If the new value is greater than the `sender`'s current power
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ as do the versions v6 is based upon.
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{< added-in v=7 >}} For checks performed upon `m.room.member` events, a
|
{{% added-in v=7 %}} For checks performed upon `m.room.member` events, a
|
||||||
new point for `membership=knock` is added.
|
new point for `membership=knock` is added.
|
||||||
|
|
||||||
Events must be signed by the server denoted by the `sender` property.
|
Events must be signed by the server denoted by the `sender` property.
|
||||||
|
|
@ -90,7 +90,7 @@ The rules are as follows:
|
||||||
`state_key` is the creator, allow.
|
`state_key` is the creator, allow.
|
||||||
2. If the `sender` does not match `state_key`, reject.
|
2. If the `sender` does not match `state_key`, reject.
|
||||||
3. If the `sender` is banned, reject.
|
3. If the `sender` is banned, reject.
|
||||||
4. {{< changed-in v=7 >}}
|
4. {{% changed-in v=7 %}}
|
||||||
If the `join_rule` is `invite` or `knock` then allow if
|
If the `join_rule` is `invite` or `knock` then allow if
|
||||||
membership state is `invite` or `join`.
|
membership state is `invite` or `join`.
|
||||||
5. If the `join_rule` is `public`, allow.
|
5. If the `join_rule` is `public`, allow.
|
||||||
|
|
@ -122,7 +122,7 @@ The rules are as follows:
|
||||||
the *invite level*, allow.
|
the *invite level*, allow.
|
||||||
5. Otherwise, reject.
|
5. Otherwise, reject.
|
||||||
4. If `membership` is `leave`:
|
4. If `membership` is `leave`:
|
||||||
1. {{< changed-in v=7 >}}
|
1. {{% changed-in v=7 %}}
|
||||||
If the `sender` matches `state_key`, allow if and only if
|
If the `sender` matches `state_key`, allow if and only if
|
||||||
that user's current membership state is `invite`, `join`,
|
that user's current membership state is `invite`, `join`,
|
||||||
or `knock`.
|
or `knock`.
|
||||||
|
|
@ -142,7 +142,7 @@ The rules are as follows:
|
||||||
the *ban level*, and the *target user*'s power level is less
|
the *ban level*, and the *target user*'s power level is less
|
||||||
than the `sender`'s power level, allow.
|
than the `sender`'s power level, allow.
|
||||||
3. Otherwise, reject.
|
3. Otherwise, reject.
|
||||||
6. {{< added-in v=7 >}}
|
6. {{% added-in v=7 %}}
|
||||||
If `membership` is `knock`:
|
If `membership` is `knock`:
|
||||||
1. If the `join_rule` is anything other than `knock`, reject.
|
1. If the `join_rule` is anything other than `knock`, reject.
|
||||||
2. If `sender` does not match `state_key`, reject.
|
2. If `sender` does not match `state_key`, reject.
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ room without invite. Otherwise, the room version inherits all properties of
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{< added-in v=8 >}} For checks performed upon `m.room.member` events, new
|
{{% added-in v=8 %}} For checks performed upon `m.room.member` events, new
|
||||||
points for handling `content.join_authorised_via_users_server` are added (Rule 4.2
|
points for handling `content.join_authorised_via_users_server` are added (Rule 4.2
|
||||||
and 4.3.5).
|
and 4.3.5).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Clients which implement the redaction algorithm locally should refer to the
|
||||||
|
|
||||||
### Redactions
|
### Redactions
|
||||||
|
|
||||||
{{< added-in v=9 >}} [`m.room.member`](/client-server-api#mroommember) events
|
{{% added-in v=9 %}} [`m.room.member`](/client-server-api#mroommember) events
|
||||||
now keep `join_authorised_via_users_server` in addition to other keys in `content`
|
now keep `join_authorised_via_users_server` in addition to other keys in `content`
|
||||||
when being redacted.
|
when being redacted.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ to send. The process overall is as follows:
|
||||||
Requests must be made with a `Host` header of
|
Requests must be made with a `Host` header of
|
||||||
`<delegated_hostname>:<delegated_port>`. The target server must
|
`<delegated_hostname>:<delegated_port>`. The target server must
|
||||||
present a valid certificate for `<delegated_hostname>`.
|
present a valid certificate for `<delegated_hostname>`.
|
||||||
3. {{< added-in v="1.8" >}} If `<delegated_hostname>` is not an IP literal and no
|
3. {{% added-in v="1.8" %}} If `<delegated_hostname>` is not an IP literal and no
|
||||||
`<delegated_port>` is present, an SRV record is looked up for
|
`<delegated_port>` is present, an SRV record is looked up for
|
||||||
`_matrix-fed._tcp.<delegated_hostname>`. This may result in another
|
`_matrix-fed._tcp.<delegated_hostname>`. This may result in another
|
||||||
hostname (to be resolved using AAAA or A records) and port.
|
hostname (to be resolved using AAAA or A records) and port.
|
||||||
|
|
@ -171,7 +171,7 @@ to send. The process overall is as follows:
|
||||||
`<delegated_hostname>`. The target server must present a valid
|
`<delegated_hostname>`. The target server must present a valid
|
||||||
certificate for `<delegated_hostname>`.
|
certificate for `<delegated_hostname>`.
|
||||||
|
|
||||||
4. {{< added-in v="1.8" >}} If the `/.well-known` request resulted in an error response, a server is
|
4. {{% added-in v="1.8" %}} If the `/.well-known` request resulted in an error response, a server is
|
||||||
found by resolving an SRV record for `_matrix-fed._tcp.<hostname>`. This may
|
found by resolving an SRV record for `_matrix-fed._tcp.<hostname>`. This may
|
||||||
result in a hostname (to be resolved using AAAA or A records) and
|
result in a hostname (to be resolved using AAAA or A records) and
|
||||||
port. Requests are made to the resolved IP address and port, with a `Host`
|
port. Requests are made to the resolved IP address and port, with a `Host`
|
||||||
|
|
@ -375,7 +375,7 @@ The authorization parameters to include are:
|
||||||
|
|
||||||
- `origin`: the server name of the sending server. This is the same as the
|
- `origin`: the server name of the sending server. This is the same as the
|
||||||
`origin` field from JSON described in step 1.
|
`origin` field from JSON described in step 1.
|
||||||
- `destination`: {{< added-in v="1.3" >}} the server name of the receiving
|
- `destination`: {{% added-in v="1.3" %}} the server name of the receiving
|
||||||
server. This is the same as the `destination` field from the JSON described
|
server. This is the same as the `destination` field from the JSON described
|
||||||
in step 1. For compatibility with older servers, recipients should accept
|
in step 1. For compatibility with older servers, recipients should accept
|
||||||
requests without this parameter, but MUST always send it. If this property
|
requests without this parameter, but MUST always send it. If this property
|
||||||
|
|
@ -389,7 +389,7 @@ The authorization parameters to include are:
|
||||||
Unknown parameters are ignored.
|
Unknown parameters are ignored.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
{{< changed-in v="1.11" >}}
|
{{% changed-in v="1.11" %}}
|
||||||
This section used to reference [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-2.1)
|
This section used to reference [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-2.1)
|
||||||
and [RFC 7230](https://datatracker.ietf.org/doc/html/rfc9110#section-5.6.2), that
|
and [RFC 7230](https://datatracker.ietf.org/doc/html/rfc9110#section-5.6.2), that
|
||||||
were obsoleted by RFC 9110 without changes to the sections of interest here.
|
were obsoleted by RFC 9110 without changes to the sections of interest here.
|
||||||
|
|
@ -1204,7 +1204,7 @@ Servers MUST use the server described in the [Matrix Content URI](/client-server
|
||||||
Formatted as `mxc://{ServerName}/{MediaID}`, servers MUST download the media from
|
Formatted as `mxc://{ServerName}/{MediaID}`, servers MUST download the media from
|
||||||
`ServerName` using the below endpoints.
|
`ServerName` using the below endpoints.
|
||||||
|
|
||||||
{{< changed-in v="1.11" >}} Servers were previously advised to use the `/_matrix/media/*`
|
{{% changed-in v="1.11" %}} Servers were previously advised to use the `/_matrix/media/*`
|
||||||
endpoints described by the [Content Repository module in the Client-Server API](/client-server-api/#content-repository),
|
endpoints described by the [Content Repository module in the Client-Server API](/client-server-api/#content-repository),
|
||||||
however, those endpoints have been deprecated. New endpoints are introduced which
|
however, those endpoints have been deprecated. New endpoints are introduced which
|
||||||
require authentication. Naturally, as a server is not a user, they cannot provide
|
require authentication. Naturally, as a server is not a user, they cannot provide
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ paths:
|
||||||
{{% /boxes/note %}}
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
{{% boxes/warning %}}
|
{{% boxes/warning %}}
|
||||||
{{< changed-in v="1.11" >}} This endpoint MAY return `404 M_NOT_FOUND`
|
{{% changed-in v="1.11" %}} This endpoint MAY return `404 M_NOT_FOUND`
|
||||||
for media which exists, but is after the server froze unauthenticated
|
for media which exists, but is after the server froze unauthenticated
|
||||||
media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more
|
media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more
|
||||||
information.
|
information.
|
||||||
|
|
@ -303,7 +303,7 @@ paths:
|
||||||
provided by the caller.
|
provided by the caller.
|
||||||
|
|
||||||
{{% boxes/warning %}}
|
{{% boxes/warning %}}
|
||||||
{{< changed-in v="1.11" >}} This endpoint MAY return `404 M_NOT_FOUND`
|
{{% changed-in v="1.11" %}} This endpoint MAY return `404 M_NOT_FOUND`
|
||||||
for media which exists, but is after the server froze unauthenticated
|
for media which exists, but is after the server froze unauthenticated
|
||||||
media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more
|
media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more
|
||||||
information.
|
information.
|
||||||
|
|
@ -375,7 +375,7 @@ paths:
|
||||||
See the [Thumbnails](/client-server-api/#thumbnails) section for more information.
|
See the [Thumbnails](/client-server-api/#thumbnails) section for more information.
|
||||||
|
|
||||||
{{% boxes/warning %}}
|
{{% boxes/warning %}}
|
||||||
{{< changed-in v="1.11" >}} This endpoint MAY return `404 M_NOT_FOUND`
|
{{% changed-in v="1.11" %}} This endpoint MAY return `404 M_NOT_FOUND`
|
||||||
for media which exists, but is after the server froze unauthenticated
|
for media which exists, but is after the server froze unauthenticated
|
||||||
media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more
|
media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more
|
||||||
information.
|
information.
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ properties:
|
||||||
arbitrary string with no specified maximum length.
|
arbitrary string with no specified maximum length.
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
|
format: uri
|
||||||
description: |
|
description: |
|
||||||
A link to the text of this document, in the appropriate
|
A link to the text of this document, in the appropriate
|
||||||
language. MUST be a valid URI with scheme `https://` or
|
language. MUST be a valid URI with scheme `https://` or
|
||||||
|
|
|
||||||
|
|
@ -210,17 +210,21 @@ paths:
|
||||||
type: object
|
type: object
|
||||||
description: |-
|
description: |-
|
||||||
Required if `kind` is not `null`. A dictionary of information
|
Required if `kind` is not `null`. A dictionary of information
|
||||||
for the pusher implementation itself. If `kind` is `http`,
|
for the pusher implementation itself.
|
||||||
this should contain `url` which is the URL to use to send
|
|
||||||
notifications to.
|
If `kind` is `http`, this MUST contain `url` which is the URL
|
||||||
|
to use for sending notifications. Clients MAY use this object
|
||||||
|
to pass custom data to their push gateway. Servers MUST forward
|
||||||
|
the entire content including `format` and any custom keys but excluding `url`
|
||||||
|
when calling [`/_matrix/push/v1/notify`](/push-gateway-api/#post_matrixpushv1notify).
|
||||||
title: PusherData
|
title: PusherData
|
||||||
properties:
|
properties:
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
description: |-
|
description: |-
|
||||||
Required if `kind` is `http`. The URL to use to send
|
Required if `kind` is `http`. The URL to use for sending
|
||||||
notifications to. MUST be an HTTPS URL with a path of
|
notifications. MUST be an HTTPS URL with a path of
|
||||||
`/_matrix/push/v1/notify`.
|
`/_matrix/push/v1/notify`.
|
||||||
example: https://push-gateway.location.here/_matrix/push/v1/notify
|
example: https://push-gateway.location.here/_matrix/push/v1/notify
|
||||||
format:
|
format:
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,15 @@ paths:
|
||||||
type: object
|
type: object
|
||||||
title: PusherData
|
title: PusherData
|
||||||
description: |-
|
description: |-
|
||||||
A dictionary of additional pusher-specific data. For
|
A dictionary of additional pusher-specific data. This
|
||||||
'http' pushers, this is the data dictionary passed in at
|
is the `data` dictionary passed in at
|
||||||
pusher creation minus the `url` key.
|
[pusher creation](/client-server-api/#post_matrixclientv3pushersset)
|
||||||
|
minus the `url` key.
|
||||||
|
properties:
|
||||||
|
format:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The format to use for sending notifications.
|
||||||
tweaks:
|
tweaks:
|
||||||
type: object
|
type: object
|
||||||
title: Tweaks
|
title: Tweaks
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,19 @@ paths:
|
||||||
required:
|
required:
|
||||||
- auth_chain_ids
|
- auth_chain_ids
|
||||||
- pdu_ids
|
- pdu_ids
|
||||||
|
"403":
|
||||||
|
description: |-
|
||||||
|
The requesting host is not in the room, or is excluded from the room via `m.room.server_acl`.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
|
examples:
|
||||||
|
response:
|
||||||
|
value: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You do not have permission to access the state at the requested event."
|
||||||
|
}
|
||||||
"404":
|
"404":
|
||||||
description: |-
|
description: |-
|
||||||
The given `event_id` was not found or the server doesn't know about the state at
|
The given `event_id` was not found or the server doesn't know about the state at
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "This event is sent by the callee when they wish to answer the call.",
|
"description": "This event is sent by the callee when they wish to answer the call.",
|
||||||
|
"x-weight": 40,
|
||||||
"allOf": [{
|
"allOf": [{
|
||||||
"$ref": "core-event-schema/room_event.yaml"
|
"$ref": "core-event-schema/room_event.yaml"
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ description: |-
|
||||||
This event is sent by callers after sending an invite and by the callee after
|
This event is sent by callers after sending an invite and by the callee after
|
||||||
answering. Its purpose is to give the other party additional ICE candidates to
|
answering. Its purpose is to give the other party additional ICE candidates to
|
||||||
try using to communicate.
|
try using to communicate.
|
||||||
|
x-weight: 20
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: core-event-schema/room_event.yaml
|
- $ref: core-event-schema/room_event.yaml
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ description: |
|
||||||
the new call unless the user had specifically chosen to do so.
|
the new call unless the user had specifically chosen to do so.
|
||||||
* `unknown_error`: Some other failure occurred that meant the client was unable to continue the call
|
* `unknown_error`: Some other failure occurred that meant the client was unable to continue the call
|
||||||
rather than the user choosing to end it.
|
rather than the user choosing to end it.
|
||||||
|
x-weight: 80
|
||||||
allOf:
|
allOf:
|
||||||
- "$ref": core-event-schema/room_event.yaml
|
- "$ref": core-event-schema/room_event.yaml
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "This event is sent by the caller when they wish to establish a call.",
|
"description": "This event is sent by the caller when they wish to establish a call.",
|
||||||
|
"x-weight": 10,
|
||||||
"allOf": [{
|
"allOf": [{
|
||||||
"$ref": "core-event-schema/room_event.yaml"
|
"$ref": "core-event-schema/room_event.yaml"
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ description: |
|
||||||
attempt to validate the `type` field, but simply pass the object into the
|
attempt to validate the `type` field, but simply pass the object into the
|
||||||
WebRTC API.
|
WebRTC API.
|
||||||
x-addedInMatrixVersion: "1.7"
|
x-addedInMatrixVersion: "1.7"
|
||||||
|
x-weight: 60
|
||||||
allOf:
|
allOf:
|
||||||
- "$ref": core-event-schema/room_event.yaml
|
- "$ref": core-event-schema/room_event.yaml
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ description: |
|
||||||
Note that, unlike `m.call.hangup`, this event has no `reason` field: the rejection of
|
Note that, unlike `m.call.hangup`, this event has no `reason` field: the rejection of
|
||||||
a call is always implicitly because the user chose not to answer it.
|
a call is always implicitly because the user chose not to answer it.
|
||||||
x-addedInMatrixVersion: "1.7"
|
x-addedInMatrixVersion: "1.7"
|
||||||
|
x-weight: 30
|
||||||
allOf:
|
allOf:
|
||||||
- "$ref": core-event-schema/room_event.yaml
|
- "$ref": core-event-schema/room_event.yaml
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
type: object
|
type: object
|
||||||
x-addedInMatrixVersion: "1.11"
|
x-addedInMatrixVersion: "1.11"
|
||||||
|
x-weight: 70
|
||||||
description: |-
|
description: |-
|
||||||
This event is sent by callers when they wish to update a stream's metadata
|
This event is sent by callers when they wish to update a stream's metadata
|
||||||
but no negotiation is required.
|
but no negotiation is required.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "This event is sent by the caller's client once it has decided which other client to talk to, by selecting one of multiple possible incoming `m.call.answer` events. Its `selected_party_id` field indicates the answer it's chosen. The `call_id` and `party_id` of the caller is also included. If the callee's client sees a `select_answer` for an answer with party ID other than the one it sent, it ends the call and informs the user the call was answered elsewhere. It does not send any events. Media can start flowing before this event is seen or even sent. Clients that implement previous versions of this specification will ignore this event and behave as they did before.",
|
"description": "This event is sent by the caller's client once it has decided which other client to talk to, by selecting one of multiple possible incoming `m.call.answer` events. Its `selected_party_id` field indicates the answer it's chosen. The `call_id` and `party_id` of the caller is also included. If the callee's client sees a `select_answer` for an answer with party ID other than the one it sent, it ends the call and informs the user the call was answered elsewhere. It does not send any events. Media can start flowing before this event is seen or even sent. Clients that implement previous versions of this specification will ignore this event and behave as they did before.",
|
||||||
"x-addedInMatrixVersion": "1.7",
|
"x-addedInMatrixVersion": "1.7",
|
||||||
|
"x-weight": 50,
|
||||||
"allOf": [{
|
"allOf": [{
|
||||||
"$ref": "core-event-schema/room_event.yaml"
|
"$ref": "core-event-schema/room_event.yaml"
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,29 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# This file contains the list of custom formats supported for the `format` key
|
# This file contains the list of string formats supported for the `format` key
|
||||||
# and the `x-pattern-format` extension (see `openapi_extensions.md` for more
|
# and the `x-pattern-format` extension within JSON Schema objects in the
|
||||||
# details).
|
# OpenAPI documents within the Matrix Specification. See
|
||||||
|
# `openapi_extensions.md` [1] for more details.
|
||||||
#
|
#
|
||||||
# Each entry must use the `mx-` prefix and have the form:
|
# [1]: https://github.com/matrix-org/matrix-spec/blob/main/openapi_extensions.md#custom-x-pattern-format-key-and-custom-formats
|
||||||
#
|
#
|
||||||
# mx-custom-key:
|
# Custom formats defined in the Matrix specification should always use the `mx-`
|
||||||
|
# prefix. They should link to the section containing the definition of the
|
||||||
|
# format in the spec.
|
||||||
|
#
|
||||||
|
# Formats that are already supported in the JSON Schema specification should
|
||||||
|
# link to the RFC where they are defined, and should not use a regex to allow
|
||||||
|
# tools that recognize the format to validate it properly.
|
||||||
|
# See <https://json-schema.org/understanding-json-schema/reference/string#built-in-formats>.
|
||||||
|
#
|
||||||
|
# All entries have the form:
|
||||||
|
#
|
||||||
|
# key:
|
||||||
# title: The title rendered in the specification
|
# title: The title rendered in the specification
|
||||||
# url: /url/to#definition
|
# url: /url/to#definition
|
||||||
|
# # regex: A regex that can be used to validate the custom format if possible.
|
||||||
|
# It should be used as the `pattern` of the string.
|
||||||
|
|
||||||
mx-user-id:
|
mx-user-id:
|
||||||
title: User ID
|
title: User ID
|
||||||
|
|
@ -49,5 +63,4 @@ mx-mxc-uri:
|
||||||
|
|
||||||
uri:
|
uri:
|
||||||
title: URI
|
title: URI
|
||||||
url: http://tools.ietf.org/html/rfc3986
|
url: https://datatracker.ietf.org/doc/html/rfc3986
|
||||||
# no regex
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
{{ $ver := .v }}
|
{{ $ver := .v -}}
|
||||||
{{ $this := .this }}
|
{{ $this := .this -}}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
This differs from the shortcode added-in by wanting to be a block instead of inline
|
This differs from the shortcode added-in by wanting to be a block instead of inline
|
||||||
and by slightly altering the rendered text as a result.
|
and by slightly altering the rendered text as a result.
|
||||||
*/}}
|
*/}}
|
||||||
|
|
||||||
{{ if $this }}
|
{{ if $this -}}
|
||||||
**New in this version.**
|
<p><strong>New in this version.</strong></p>
|
||||||
{{ else }}
|
{{ else -}}
|
||||||
**Added in `v{{ $ver }}`**
|
<p><strong>Added in <code>v{{ $ver }}</code></strong></p>
|
||||||
{{ end }}
|
{{ end -}}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,10 @@
|
||||||
version -> details pairs.
|
version -> details pairs.
|
||||||
*/ -}}
|
*/ -}}
|
||||||
{{ range $ver, $details := .changes_dict -}}
|
{{ range $ver, $details := .changes_dict -}}
|
||||||
<br><br>
|
<p>
|
||||||
<strong>
|
<strong>
|
||||||
Changed in <code>v{{ $ver }}</code>:
|
Changed in <code>v{{ $ver }}</code>:
|
||||||
</strong>
|
</strong>
|
||||||
{{ $details | markdownify }}
|
{{ $details | markdownify }}
|
||||||
{{ end }}
|
</p>
|
||||||
|
{{ end -}}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,12 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>{{ $mime }}</code></td>
|
<td><code>{{ $mime }}</code></td>
|
||||||
<td>
|
<td>
|
||||||
{{ $body.schema.description | markdownify -}}
|
{{/*
|
||||||
|
Force the rendering as a block so the description is always inside a
|
||||||
|
paragraph. This allows to always keep the same spacing between paragraphs
|
||||||
|
when adding added-in and changed-in paragraphs.
|
||||||
|
*/}}
|
||||||
|
{{ $body.schema.description | page.RenderString (dict "display" "block") -}}
|
||||||
{{ if (index $body.schema "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index $body.schema "x-addedInMatrixVersion")) }}{{ end -}}
|
{{ if (index $body.schema "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index $body.schema "x-addedInMatrixVersion")) }}{{ end -}}
|
||||||
{{ if (index $body.schema "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index $body.schema "x-changedInMatrixVersion")) }}{{ end -}}
|
{{ if (index $body.schema "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index $body.schema "x-changedInMatrixVersion")) }}{{ end -}}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ resolve-additional-types.)
|
||||||
|
|
||||||
{{/* If the string uses a known format, use it. */}}
|
{{/* If the string uses a known format, use it. */}}
|
||||||
{{ with .format }}
|
{{ with .format }}
|
||||||
{{ with partial "custom-format" . }}
|
{{ with partial "string-format" . }}
|
||||||
{{ $type = . }}
|
{{ $type = . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -264,7 +264,7 @@ resolve-additional-types.)
|
||||||
{{ range $formatId, $formatType := $formatMap.Values }}
|
{{ range $formatId, $formatType := $formatMap.Values }}
|
||||||
{{ $formatKey := "string" }}
|
{{ $formatKey := "string" }}
|
||||||
{{ if ne $formatId "string" }}
|
{{ if ne $formatId "string" }}
|
||||||
{{ with partial "custom-format" $formatId }}
|
{{ with partial "string-format" $formatId }}
|
||||||
{{ $formatKey = . }}
|
{{ $formatKey = . }}
|
||||||
{{ else }}
|
{{ else }}
|
||||||
{{ errorf "Unsupported value for `x-pattern-format`: %s" $formatId }}
|
{{ errorf "Unsupported value for `x-pattern-format`: %s" $formatId }}
|
||||||
|
|
@ -306,9 +306,21 @@ resolve-additional-types.)
|
||||||
* `x-changedInMatrixVersion`: optional string indicating in which Matrix
|
* `x-changedInMatrixVersion`: optional string indicating in which Matrix
|
||||||
spec version this property was last changed.
|
spec version this property was last changed.
|
||||||
*/}}
|
*/}}
|
||||||
{{ define "partials/property-description" }}
|
{{ define "partials/property-description" -}}
|
||||||
{{ if .required }}<strong>Required: </strong>{{end -}}
|
{{ $description := .property.description -}}
|
||||||
{{ .property.description | markdownify -}}
|
{{ if .required -}}
|
||||||
|
{{/*
|
||||||
|
Prepend "Required:" to make it part of the first paragraph of the
|
||||||
|
description.
|
||||||
|
*/}}
|
||||||
|
{{- $description = printf "<strong>Required: </strong>%s" $description -}}
|
||||||
|
{{ end -}}
|
||||||
|
{{/*
|
||||||
|
Force the rendering as a block so the description is always inside a
|
||||||
|
paragraph. This allows to always keep the same spacing between paragraphs
|
||||||
|
when adding added-in and changed-in paragraphs.
|
||||||
|
*/}}
|
||||||
|
{{ $description | page.RenderString (dict "display" "block") -}}
|
||||||
{{ if .property.enum }}<p>One of: <code>[{{ delimit .property.enum ", " }}]</code>.</p>{{ end -}}
|
{{ if .property.enum }}<p>One of: <code>[{{ delimit .property.enum ", " }}]</code>.</p>{{ end -}}
|
||||||
{{ if (index .property "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index .property "x-addedInMatrixVersion")) }}{{ end -}}
|
{{ if (index .property "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index .property "x-addedInMatrixVersion")) }}{{ end -}}
|
||||||
{{ if (index .property "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index .property "x-changedInMatrixVersion")) }}{{ end -}}
|
{{ if (index .property "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index .property "x-changedInMatrixVersion")) }}{{ end -}}
|
||||||
|
|
@ -319,12 +331,12 @@ resolve-additional-types.)
|
||||||
Computes the type to display for a string format, given the identifier of
|
Computes the type to display for a string format, given the identifier of
|
||||||
the format as a string.
|
the format as a string.
|
||||||
*/}}
|
*/}}
|
||||||
{{ define "partials/custom-format" }}
|
{{ define "partials/string-format" }}
|
||||||
{{ $customFormat := "" }}
|
{{ $stringFormat := "" }}
|
||||||
|
|
||||||
{{ with index site.Data "custom-formats" . }}
|
{{ with index site.Data "string-formats" . }}
|
||||||
{{ $customFormat = printf "<a href=\"%s\">%s</a>" (htmlEscape .url) (htmlEscape .title) }}
|
{{ $stringFormat = printf "<a href=\"%s\">%s</a>" (htmlEscape .url) (htmlEscape .title) }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ return $customFormat }}
|
{{ return $stringFormat }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,24 @@
|
||||||
|
|
||||||
{{ $base_path := "event-schemas/schema" }}
|
{{ $base_path := "event-schemas/schema" }}
|
||||||
|
|
||||||
{{ $events := index .Site.Data "event-schemas" "schema" }}
|
|
||||||
{{ $group_name := .Params.group_name }}
|
{{ $group_name := .Params.group_name }}
|
||||||
|
|
||||||
{{ range $event_name, $event_data := $events }}
|
{{/* Filter events and prepare them for sorting */}}
|
||||||
|
{{ $events := slice }}
|
||||||
|
{{ range $event_name, $event_data := index .Site.Data "event-schemas" "schema" }}
|
||||||
{{ $prefix := substr $event_name 0 (len $group_name) }}
|
{{ $prefix := substr $event_name 0 (len $group_name) }}
|
||||||
{{ if eq $prefix $group_name }}
|
{{ if eq $prefix $group_name }}
|
||||||
|
{{ $events = $events | append (dict "event_name" $event_name "event_data" $event_data) }}
|
||||||
{{ $path := delimit (slice $base_path $event_name) "/" }}
|
|
||||||
{{ $event_data = partial "json-schema/resolve-refs" (dict "schema" $event_data "path" $path) }}
|
|
||||||
{{ $event_data := partial "json-schema/resolve-allof" $event_data }}
|
|
||||||
|
|
||||||
{{ partial "events/render-event" (dict "event_name" $event_name "event_data" $event_data)}}
|
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{/* Render the events sorted by x-weight */}}
|
||||||
|
{{ range sort $events "event_data.x-weight" }}
|
||||||
|
|
||||||
|
{{ $path := delimit (slice $base_path .event_name) "/" }}
|
||||||
|
{{ $event_data := partial "json-schema/resolve-refs" (dict "schema" .event_data "path" $path) }}
|
||||||
|
{{ $event_data := partial "json-schema/resolve-allof" $event_data }}
|
||||||
|
|
||||||
|
{{ partial "events/render-event" (dict "event_name" .event_name "event_data" $event_data)}}
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,6 @@ current version is `v1.1` then annotate your changes with `v1.2`.
|
||||||
* `{{% added-in v="1.2" %}}` or `{{% changed-in v="1.2" %}}` within Markdown documents.
|
* `{{% added-in v="1.2" %}}` or `{{% changed-in v="1.2" %}}` within Markdown documents.
|
||||||
* `x-addedInMatrixVersion` and `x-changedInMatrixVersion` within OpenAPI.
|
* `x-addedInMatrixVersion` and `x-changedInMatrixVersion` within OpenAPI.
|
||||||
|
|
||||||
**Tip**: If you're trying to inline the Markdown version and getting unexpected results,
|
|
||||||
try replacing the `%` symbols with `<` and `>`, changing how Hugo renders the shortcode.
|
|
||||||
|
|
||||||
OpenAPI
|
OpenAPI
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,5 +39,10 @@ is a property to convey semantic information about a schema. We define
|
||||||
`x-pattern-format` as a key on the schemas under `patternProperties` with the
|
`x-pattern-format` as a key on the schemas under `patternProperties` with the
|
||||||
same use as `format`, but that applies to the pattern of the property. We also
|
same use as `format`, but that applies to the pattern of the property. We also
|
||||||
define custom values for formats with the `mx-` prefix in
|
define custom values for formats with the `mx-` prefix in
|
||||||
`data/custom-formats.yaml`. Those values are recognized in the rendered
|
`data/string-formats.yaml`. The values in this file are recognized in the
|
||||||
specification and link to the definition of the format.
|
rendered specification and link to the definition of the format.
|
||||||
|
|
||||||
|
## Custom `x-weight` key
|
||||||
|
|
||||||
|
This property allows controlling the display order of events rendered with the
|
||||||
|
`event-group` shortcode.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue