mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-03-28 05:54:09 +01:00
Merge branch 'main' into travis/ref-rel
This commit is contained in:
commit
0add77dea9
|
|
@ -1 +0,0 @@
|
||||||
Add HTML anchors for object definitions in the formatted specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Replace homeserver authorization approach with an `Authorization` header instead of `access_token` when talking to the application service, as per [MSC2832](https://github.com/matrix-org/matrix-spec-proposals/pull/2832).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Mention that the `/rooms/{roomId}/invite` endpoint will return a 200 response if the user is already invited to the room.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Describe return codes for account data endpoints, and clarify that per-room data does not inherit from the global data.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix various typos throughout the specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix various typos throughout the specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Clarify that policy rule globs work like ACL globs. Contributed by Nico.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Clarify the format of some structures in the End-to-end encryption module.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix various typos throughout the specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add HTML anchors for object definitions in the formatted specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Tweak the styling of `<code>` snippets in tables rendered from OpenAPI definitions.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix various typos throughout the specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Update "API Standards" section to clarify how JSON is used.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add a `.m.rule.room.server_acl` push rule to match `m.room.server_acl` events, as per [MSC3786](https://github.com/matrix-org/matrix-spec-proposals/pull/3786).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Remove unused policy room sharing mechanism, as per [MSC3844](https://github.com/matrix-org/matrix-spec-proposals/pull/3844).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add `Cross-Origin-Resource-Policy` (CORP) headers to media repository, as per [MSC3828](https://github.com/matrix-org/matrix-spec-proposals/pull/3828).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Copy a room's `type` when upgrading it, as per [MSC3818](https://github.com/matrix-org/matrix-spec-proposals/pull/3818).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add `room_types` filter and `room_type` response to `/publicRooms`, as per [MSC3827](https://github.com/matrix-org/matrix-spec-proposals/pull/3827).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add a `.m.rule.room.server_acl` push rule to match `m.room.server_acl` events, as per [MSC3786](https://github.com/matrix-org/matrix-spec-proposals/pull/3786).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Clarify that the "device_id", "user_id" and "access_token" fields are required in the response body of `POST /_matrix/client/v3/login`.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add `m.replace` relations (event edits), as per [MSC2676](https://github.com/matrix-org/matrix-spec-proposals/pull/2676).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix various typos throughout the specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add `m.read.private` receipts, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Make `m.fully_read` optional on `/read_markers`, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Allow `m.fully_read` markers to be set from `/receipts`, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Reinforce the relationship of refreshed access tokens to transaction IDs.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix various typos throughout the specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Clarify enum values by separating possible values with commas.
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix naming of `device_one_time_keys_count` in `/sync`.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix various typos throughout the specification.
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add HTML anchors for object definitions in the formatted specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Update "API Standards" section to clarify how JSON is used.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Render HTML anchors for object definition tables.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add internal changes changelog section.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Give rendered-data sections a background and some padding.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix rendering of shortcodes within the client-server API.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix the spacing of mapping types generated from the OpenAPI spec.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add HTML anchors for object definitions in the formatted specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
For room versions 1 through 10, clarify that events with rejected `auth_events` must be rejected.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
For room versions 2–10: correct a mistaken clarification to the state resolution algorithm.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
For room versions 7 through 10: Clarify that `invite->knock` is actually a legal transition.
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Reword the event auth rules to clarify that users cannot demote other users with the same power level.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Various clarifications to the text on event authorisation rules.
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add HTML anchors for object definitions in the formatted specification.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Tweak the styling of `<code>` snippets in tables rendered from OpenAPI definitions.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Update "API Standards" section to clarify how JSON is used.
|
|
||||||
|
|
@ -49,9 +49,9 @@ status = "unstable"
|
||||||
current_version_url = "https://spec.matrix.org/latest"
|
current_version_url = "https://spec.matrix.org/latest"
|
||||||
# The following is used when status = "stable", and is displayed in various UI elements on a released version
|
# 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.
|
# of the spec. CI will set these values here automatically when a release git tag (i.e `v1.5`) is created.
|
||||||
#major = "1"
|
# major = "1"
|
||||||
#minor = "3"
|
# minor = "4"
|
||||||
#release_date = "June 16, 2022"
|
# release_date = "September 29, 2022"
|
||||||
|
|
||||||
# User interface configuration
|
# User interface configuration
|
||||||
[params.ui]
|
[params.ui]
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ underlying homeserver implementation.
|
||||||
|
|
||||||
## Application Services
|
## Application Services
|
||||||
|
|
||||||
Application services are passive and can only observe events from
|
Application services are passive and can only observe events from the
|
||||||
homeserver. They can inject events into rooms they are participating in.
|
homeserver. They can inject events into rooms they are participating in.
|
||||||
They cannot prevent events from being sent, nor can they modify the
|
They cannot prevent events from being sent, nor can they modify the
|
||||||
content of the event being sent. In order to observe events from a
|
content of the event being sent. In order to observe events from a
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ weight: 1000
|
||||||
{{% changelog/changelog-changes %}}
|
{{% changelog/changelog-changes %}}
|
||||||
|
|
||||||
<!-- DO NOT REMOVE OR CHANGE - Release script puts next release here -->
|
<!-- DO NOT REMOVE OR CHANGE - Release script puts next release here -->
|
||||||
|
{{% changelog/changelog-rendered p="changelogs/v1.4.md" %}}
|
||||||
{{% changelog/changelog-rendered p="changelogs/v1.3.md" %}}
|
{{% changelog/changelog-rendered p="changelogs/v1.3.md" %}}
|
||||||
{{% changelog/changelog-rendered p="changelogs/v1.2.md" %}}
|
{{% changelog/changelog-rendered p="changelogs/v1.2.md" %}}
|
||||||
{{% changelog/changelog-rendered p="changelogs/v1.1.md" %}}
|
{{% changelog/changelog-rendered p="changelogs/v1.1.md" %}}
|
||||||
|
|
|
||||||
|
|
@ -1972,6 +1972,7 @@ This specification describes the following relationship types:
|
||||||
|
|
||||||
* [Rich replies](#rich-replies) (**Note**: does not use `rel_type`).
|
* [Rich replies](#rich-replies) (**Note**: does not use `rel_type`).
|
||||||
* [Event replacements](#event-replacements).
|
* [Event replacements](#event-replacements).
|
||||||
|
* [Threads](#threading).
|
||||||
* [References](#reference-relations)
|
* [References](#reference-relations)
|
||||||
|
|
||||||
#### Aggregations
|
#### Aggregations
|
||||||
|
|
@ -1988,11 +1989,6 @@ of times that `key` was used by child events.
|
||||||
|
|
||||||
The actual aggregation format depends on the `rel_type`.
|
The actual aggregation format depends on the `rel_type`.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
|
||||||
This specification does not currently describe any `rel_type`s which require
|
|
||||||
aggregation. This functionality forms a framework for future extensions.
|
|
||||||
{{% /boxes/note %}}
|
|
||||||
|
|
||||||
Aggregations are sometimes automatically included by a server alongside the parent
|
Aggregations are sometimes automatically included by a server alongside the parent
|
||||||
event. This is known as a "bundled aggregation" or "bundle" for simplicity. The
|
event. This is known as a "bundled aggregation" or "bundle" for simplicity. The
|
||||||
act of doing this is "bundling".
|
act of doing this is "bundling".
|
||||||
|
|
@ -2057,6 +2053,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)
|
||||||
|
|
||||||
{{% 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
|
||||||
|
|
@ -2643,4 +2640,5 @@ systems.
|
||||||
{{< cs-module name="moderation_policies" >}}
|
{{< cs-module name="moderation_policies" >}}
|
||||||
{{< cs-module name="spaces" >}}
|
{{< cs-module name="spaces" >}}
|
||||||
{{< cs-module name="event_replacements" >}}
|
{{< cs-module name="event_replacements" >}}
|
||||||
|
{{< cs-module name="threading" >}}
|
||||||
{{< cs-module name="reference_relations" >}}
|
{{< cs-module name="reference_relations" >}}
|
||||||
|
|
@ -1622,7 +1622,7 @@ specified). The client is expected to use [`/keys/query`](/client-server-api/#po
|
||||||
sync, as documented in [Tracking the device list for a
|
sync, as documented in [Tracking the device list for a
|
||||||
user](#tracking-the-device-list-for-a-user).
|
user](#tracking-the-device-list-for-a-user).
|
||||||
|
|
||||||
It also adds a `one_time_keys_count` property. Note the spelling
|
It also adds a `device_one_time_keys_count` property. Note the spelling
|
||||||
difference with the `one_time_key_counts` property in the
|
difference with the `one_time_key_counts` property in the
|
||||||
[`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) response.
|
[`/keys/upload`](/client-server-api/#post_matrixclientv3keysupload) response.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,9 @@ Not all attributes on those tags should be permitted as they may be
|
||||||
avenues for other disruption attempts, such as adding `onclick` handlers
|
avenues for other disruption attempts, such as adding `onclick` handlers
|
||||||
or excessively large text. Clients should only permit the attributes
|
or excessively large text. Clients should only permit the attributes
|
||||||
listed for the tags below. Where `data-mx-bg-color` and `data-mx-color`
|
listed for the tags below. Where `data-mx-bg-color` and `data-mx-color`
|
||||||
are listed, clients should translate the value (a 6-character hex color
|
are listed, clients should translate the value (a `#` character followed
|
||||||
code) to the appropriate CSS/attributes for the tag.
|
by a 6-character hex color code) to the appropriate CSS/attributes for
|
||||||
|
the tag.
|
||||||
|
|
||||||
`font`
|
`font`
|
||||||
`data-mx-bg-color`, `data-mx-color`, `color`
|
`data-mx-bg-color`, `data-mx-color`, `color`
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,10 @@ determined by the push rules which apply to an event.
|
||||||
|
|
||||||
When the user updates their read receipt (either by using the API or by
|
When the user updates their read receipt (either by using the API or by
|
||||||
sending an event), notifications prior to and including that event MUST
|
sending an event), notifications prior to and including that event MUST
|
||||||
be marked as read. Note that users can send both an `m.read` and
|
be marked as read. Which specific events are affected can vary depending
|
||||||
`m.read.private` receipt, both of which are capable of clearing notifications.
|
on whether a [threaded read receipt](#threaded-read-receipts) was used.
|
||||||
|
Note that users can send both an `m.read` and `m.read.private` receipt,
|
||||||
|
both of which are capable of clearing notifications.
|
||||||
|
|
||||||
If the user has both `m.read` and `m.read.private` set in the room then
|
If the user has both `m.read` and `m.read.private` set in the room then
|
||||||
the receipt which is more recent/ahead must be used to determine where
|
the receipt which is more recent/ahead must be used to determine where
|
||||||
|
|
@ -121,6 +123,17 @@ 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 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 the [event relationship](#forming-relationships-between-events)
|
||||||
|
until it finds a thread root (as specified by the [threading module](#threading)),
|
||||||
|
however it is not recommended that the server traverse infinitely. Instead,
|
||||||
|
implementations are encouraged to do a maximum of 3 hops to find a thread
|
||||||
|
before deciding that the event does not belong to a thread. This is primarily
|
||||||
|
to ensure that future events, like `m.reaction`, are correctly considered
|
||||||
|
"part of" a given thread.
|
||||||
|
|
||||||
##### Push Rules
|
##### Push Rules
|
||||||
|
|
||||||
A push rule is a single rule that states under what *conditions* an
|
A push rule is a single rule that states under what *conditions* an
|
||||||
|
|
|
||||||
|
|
@ -22,33 +22,68 @@ 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:
|
||||||
|
* Unthreaded: Denotes a read-up-to receipt regardless of threads. This is how
|
||||||
|
pre-threading read receipts worked.
|
||||||
|
* Threaded, main timeline: Denotes a read-up-to receipt for events not in a
|
||||||
|
particular thread. Identified by the thread ID `main`.
|
||||||
|
* Threaded, in a thread: Denotes a read-up-to receipt within a particular
|
||||||
|
thread. Identified by the event ID of the thread root.
|
||||||
|
|
||||||
|
Threaded read receipts are discussed in further detail [below](#threaded-read-receipts).
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
Each `user_id`, `receipt_type` pair must be associated with only a
|
{{< changed-in v="1.4" >}} Each `user_id`, `receipt_type`, and categorisation
|
||||||
single `event_id`.
|
(unthreaded, or `thread_id`) tuple must be associated with only a single
|
||||||
|
`event_id`.
|
||||||
|
|
||||||
{{% event event="m.receipt" %}}
|
{{% event event="m.receipt" %}}
|
||||||
|
|
||||||
#### Client behaviour
|
#### Client behaviour
|
||||||
|
|
||||||
|
{{< 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
|
||||||
deltas which update existing mappings. Clients should replace older
|
deltas which update existing mappings. Clients should replace older
|
||||||
receipt acknowledgements based on `user_id` and `receipt_type` pairs.
|
receipt acknowledgements based on `user_id`, `receipt_type`, and the
|
||||||
|
`thread_id` (if present).
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
Client receives m.receipt:
|
Client receives m.receipt:
|
||||||
user = @alice:example.com
|
user = @alice:example.com
|
||||||
receipt_type = m.read
|
receipt_type = m.read
|
||||||
event_id = $aaa:example.com
|
event_id = $aaa:example.com
|
||||||
|
thread_id = undefined
|
||||||
|
|
||||||
Client receives another m.receipt:
|
Client receives another m.receipt:
|
||||||
user = @alice:example.com
|
user = @alice:example.com
|
||||||
receipt_type = m.read
|
receipt_type = m.read
|
||||||
event_id = $bbb:example.com
|
event_id = $bbb:example.com
|
||||||
|
thread_id = main
|
||||||
|
|
||||||
The client should replace the older acknowledgement for $aaa:example.com with
|
The client does not replace any acknowledgements, yet.
|
||||||
this one for $bbb:example.com
|
|
||||||
|
Client receives yet another m.receipt:
|
||||||
|
user = @alice:example.com
|
||||||
|
receipt_type = m.read
|
||||||
|
event_id = $ccc:example.com
|
||||||
|
thread_id = undefined
|
||||||
|
|
||||||
|
The client replaces the older acknowledgement for $aaa:example.com
|
||||||
|
with this new one for $ccc:example.com, but does not replace the
|
||||||
|
acknowledgement for $bbb:example.com because it belongs to a thread.
|
||||||
|
|
||||||
|
Client receives yet another m.receipt:
|
||||||
|
user = @alice:example.com
|
||||||
|
receipt_type = m.read
|
||||||
|
event_id = $ddd:example.com
|
||||||
|
thread_id = main
|
||||||
|
|
||||||
|
Now the client replaces the older $bbb:example.com acknowledgement with
|
||||||
|
this new $ddd:example.com acknowledgement. The client does NOT replace the
|
||||||
|
older acknowledgement for $ccc:example.com as it is unthreaded.
|
||||||
|
|
||||||
Clients should send read receipts when there is some certainty that the
|
Clients should send read receipts when there is some certainty that the
|
||||||
event in question has been **displayed** to the user. Simply receiving
|
event in question has been **displayed** to the user. Simply receiving
|
||||||
|
|
@ -58,6 +93,12 @@ room that the event was sent to or dismissing a notification in order
|
||||||
for the event to count as "read". Clients SHOULD NOT send read receipts
|
for the event to count as "read". Clients SHOULD NOT send read receipts
|
||||||
for events sent by their own user.
|
for events sent by their own user.
|
||||||
|
|
||||||
|
Similar to the rules for sending receipts, threaded receipts should appear
|
||||||
|
in the context of the thread. If a thread is rendered behind a disclosure,
|
||||||
|
the client hasn't yet shown the event (or any applicable read receipts)
|
||||||
|
to the user. Once they expand the thread though, a threaded read receipt
|
||||||
|
would be sent and per-thread receipts from other users shown.
|
||||||
|
|
||||||
A client can update the markers for its user by interacting with the
|
A client can update the markers for its user by interacting with the
|
||||||
following HTTP APIs.
|
following HTTP APIs.
|
||||||
|
|
||||||
|
|
@ -87,6 +128,89 @@ not have their notification counts rewound to that point in time. While
|
||||||
uncommon, it is considered valid to have an `m.read` (public) receipt lag
|
uncommon, it is considered valid to have an `m.read` (public) receipt lag
|
||||||
several messages behind the `m.read.private` receipt, for example.
|
several messages behind the `m.read.private` receipt, for example.
|
||||||
|
|
||||||
|
##### Threaded read receipts
|
||||||
|
|
||||||
|
{{% added-in v="1.4" %}}
|
||||||
|
|
||||||
|
If a client does not use [threading](#threading), then they will simply only
|
||||||
|
send "unthreaded" read receipts which affect the whole room regardless of threads.
|
||||||
|
|
||||||
|
A threaded read receipt is simply one which has a `thread_id` on it, targeting
|
||||||
|
either a thread root's event ID or `main` for the main timeline.
|
||||||
|
|
||||||
|
Threading introduces a concept of multiple conversations being held in the same
|
||||||
|
room and thus deserve their own read receipts and notification counts. An event is
|
||||||
|
considered to be "in a thread" if it meets any of the following criteria:
|
||||||
|
* It has a `rel_type` of `m.thread`.
|
||||||
|
* It has child events with a `rel_type` of `m.thread` (in which case it'd be the
|
||||||
|
thread root).
|
||||||
|
* Following the event relationships, it has a parent event which qualifies for
|
||||||
|
one of the above. Implementations should not recurse infinitely, though: a
|
||||||
|
maximum of 3 hops is recommended to cover indirect relationships.
|
||||||
|
|
||||||
|
Events not in a thread but still in the room are considered to be part of the
|
||||||
|
"main timeline", or a special thread with an ID of `main`.
|
||||||
|
|
||||||
|
The following is an example DAG for a room, with dotted lines showing event
|
||||||
|
relationships and solid lines showing topological ordering.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
`m.reaction` relationships are not currently specified, but are shown here for
|
||||||
|
their conceptual place in a threaded DAG. They are currently proposed as
|
||||||
|
[MSC2677](https://github.com/matrix-org/matrix-spec-proposals/pull/2677).
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
This DAG can be represented as 3 threaded timelines, with `A` and `B` being thread
|
||||||
|
roots:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
With this, we can demonstrate that:
|
||||||
|
* A threaded read receipt on `I` would mark `A`, `B`, and `I` as read.
|
||||||
|
* A threaded read receipt on `E` would mark `C` and `E` as read.
|
||||||
|
* An unthreaded read receipt on `D` would mark `A`, `B`, `C`, and `D` as read.
|
||||||
|
|
||||||
|
Note that marking `A` as read with a threaded read receipt would not mean
|
||||||
|
that `C`, `E`, `G`, or `H` get marked as read: Thread A's timeline would need
|
||||||
|
its own threaded read receipt at `H` to accomplish that.
|
||||||
|
|
||||||
|
The read receipts for the above 3 examples would be:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$I": {
|
||||||
|
"m.read": {
|
||||||
|
"@user:example.org": {
|
||||||
|
"ts": 1661384801651,
|
||||||
|
"thread_id": "main" // because `I` is not in a thread, but is a threaded receipt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$E": {
|
||||||
|
"m.read": {
|
||||||
|
"@user:example.org": {
|
||||||
|
"ts": 1661384801651,
|
||||||
|
"thread_id": "$A" // because `E` is in Thread `A`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$D": {
|
||||||
|
"m.read": {
|
||||||
|
"@user:example.org": {
|
||||||
|
"ts": 1661384801651
|
||||||
|
// no `thread_id` because the receipt is *unthreaded*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Conditions on sending read receipts apply similarly to threaded and unthreaded read
|
||||||
|
receipts. For example, a client might send a private read receipt for a threaded
|
||||||
|
event when the user expands that thread.
|
||||||
|
|
||||||
#### Server behaviour
|
#### Server behaviour
|
||||||
|
|
||||||
For efficiency, receipts SHOULD be batched into one event per room
|
For efficiency, receipts SHOULD be batched into one event per room
|
||||||
|
|
@ -99,7 +223,7 @@ format of the EDUs are:
|
||||||
{
|
{
|
||||||
<room_id>: {
|
<room_id>: {
|
||||||
<receipt_type>: {
|
<receipt_type>: {
|
||||||
<user_id>: { <content> }
|
<user_id>: { <content (ts & thread_id, currently)> }
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
|
|
|
||||||
201
content/client-server-api/modules/threading.md
Normal file
201
content/client-server-api/modules/threading.md
Normal file
|
|
@ -0,0 +1,201 @@
|
||||||
|
---
|
||||||
|
type: module
|
||||||
|
---
|
||||||
|
|
||||||
|
### Threading
|
||||||
|
|
||||||
|
{{% added-in v="1.4" %}}
|
||||||
|
|
||||||
|
Threads allow users to visually branch their conversations in a room. Typically mostly used
|
||||||
|
when a room is discussing multiple topics, threads provide more organisation of communication
|
||||||
|
that traditional [rich replies](#rich-replies) can't always offer.
|
||||||
|
|
||||||
|
Clients SHOULD render threads differently to regular messages or replies in the timeline, such
|
||||||
|
as by providing some context to what is going on in the thread but keeping the full conversation
|
||||||
|
history behind a disclosure.
|
||||||
|
|
||||||
|
Threads are established using a `rel_type` of `m.thread` and reference the *thread root* (the
|
||||||
|
first event in a thread). It is not possible to create a thread from an event with a `rel_type`,
|
||||||
|
which includes not being able to nest threads. All conversation in a thread reference the thread
|
||||||
|
root instead of the most recent message, unlike rich reply chains.
|
||||||
|
|
||||||
|
As a worked example, the following represents a thread and how it'd be formed:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
// irrelevant fields excluded
|
||||||
|
"type": "m.room.message",
|
||||||
|
"event_id": "$alice_hello",
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"content": {
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "Hello world! How are you?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
// irrelevant fields excluded
|
||||||
|
"type": "m.room.message",
|
||||||
|
"event_id": "$bob_hello",
|
||||||
|
"sender": "@bob:example.org",
|
||||||
|
"content": {
|
||||||
|
"m.relates_to": {
|
||||||
|
"rel_type": "m.thread",
|
||||||
|
"event_id": "$alice_hello"
|
||||||
|
},
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "I'm doing okay, thank you! How about yourself?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
// irrelevant fields excluded
|
||||||
|
"type": "m.room.message",
|
||||||
|
"event_id": "$alice_reply",
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"content": {
|
||||||
|
"m.relates_to": {
|
||||||
|
"rel_type": "m.thread",
|
||||||
|
"event_id": "$alice_hello" // note: always references the *thread root*
|
||||||
|
},
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "I'm doing great! Thanks for asking."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As shown, any event without a `rel_type` can become a thread root by simply referencing it
|
||||||
|
using an `m.thread` relationship.
|
||||||
|
|
||||||
|
#### Fallback for unthreaded clients
|
||||||
|
|
||||||
|
Clients which understand how to work with threads should simply do so, however clients which
|
||||||
|
might not be aware of threads (due to age or scope) might not be able to helpfully represent
|
||||||
|
the conversation history to its users.
|
||||||
|
|
||||||
|
To work around this, events sent by clients which understand threads include [rich reply](#rich-replies)
|
||||||
|
metadata to attempt to form a reply chain representation of the conversation. This representation
|
||||||
|
is not ideal for heavily threaded rooms, but allows for users to have context as to what is
|
||||||
|
being discussed with respect to other messages in the room.
|
||||||
|
|
||||||
|
This representation is achieved by merging the two relationships and setting a new `is_falling_back`
|
||||||
|
flag to `true`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
// within an event's content...
|
||||||
|
"m.relates_to": {
|
||||||
|
// The m.thread relationship structure
|
||||||
|
"rel_type": "m.thread",
|
||||||
|
"event_id": "$root",
|
||||||
|
|
||||||
|
// The rich reply structure
|
||||||
|
"m.in_reply_to": {
|
||||||
|
// The most recent message known to the client in the thread.
|
||||||
|
// This should be something with a high chance of being rendered by the other client,
|
||||||
|
// such as an `m.room.message` event.
|
||||||
|
"event_id": "$target"
|
||||||
|
},
|
||||||
|
|
||||||
|
// A flag to denote that this is a thread with reply fallback
|
||||||
|
"is_falling_back": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For `m.room.message` events represented this way, no [reply fallback](#fallbacks-for-rich-replies)
|
||||||
|
is specified. This allows thread-aware clients to discard the `m.in_reply_to` object entirely
|
||||||
|
when `is_falling_back` is `true`.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
Clients which are acutely aware of threads (they do not render threads, but are otherwise
|
||||||
|
aware of the feature existing in the spec) can treat rich replies to an event with a `rel_type`
|
||||||
|
of `m.thread` as a threaded reply, for conversation continuity on the threaded client's side.
|
||||||
|
|
||||||
|
To do this, copy the `event_id` (thread root) from the event being replied to, add the
|
||||||
|
`m.in_reply_to` metadata, and add `is_falling_back: true` to `m.relates_to`.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
#### Replies within threads
|
||||||
|
|
||||||
|
In the [fallback for unthreaded clients](#fallback-for-unthreaded-clients) section, a new
|
||||||
|
`is_falling_back` flag is added to `m.relates_to`. This flag defaults to `false` when not
|
||||||
|
provided, which also allows a threaded message to contain a reply itself.
|
||||||
|
|
||||||
|
Aside from `is_falling_back` being `false` (or not specified), the fallback for unthreaded
|
||||||
|
clients is used to create a reply within a thread: clients should render the event accordingly.
|
||||||
|
|
||||||
|
#### Server behaviour
|
||||||
|
|
||||||
|
##### Validation of `m.thread` relationships
|
||||||
|
|
||||||
|
Servers SHOULD reject client requests which attempt to start a thread off an event with a
|
||||||
|
`rel_type`. If the client attempts to target an event which already has an `m.thread`,
|
||||||
|
`m.reference`, or any other `rel_type` then it should receive a HTTP 400 error response
|
||||||
|
with appropriate error message, as per the [standard error response](#standard-error-response)
|
||||||
|
structure.
|
||||||
|
|
||||||
|
{{% boxes/note %}}
|
||||||
|
A specific error code is not currently available for this case: servers should use `M_UNKNOWN`
|
||||||
|
alongside the HTTP 400 status code.
|
||||||
|
{{% /boxes/note %}}
|
||||||
|
|
||||||
|
##### Server-side aggregation of `m.thread` relationships
|
||||||
|
|
||||||
|
Given threads always reference the thread root, an event can have multiple "child" events which
|
||||||
|
then form the thread itself. These events should be [aggregated](#aggregations) by the server.
|
||||||
|
|
||||||
|
The aggregation for threads includes some information about the user's participation in the thread,
|
||||||
|
the approximate number of events in the thread (as known to the server), and the most recent event
|
||||||
|
in the thread (topologically). This is then bundled into the event as `m.thread`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"event_id": "$root_event",
|
||||||
|
// irrelevant fields not shown
|
||||||
|
"unsigned": {
|
||||||
|
"m.relations": {
|
||||||
|
"m.thread": {
|
||||||
|
"latest_event": {
|
||||||
|
// A serialized copy of the latest event in the thread.
|
||||||
|
// Some fields are not shown here for brevity.
|
||||||
|
"event_id": "$message",
|
||||||
|
"sender": "@alice:example.org",
|
||||||
|
"room_id": "!room:example.org",
|
||||||
|
"type": "m.room.message",
|
||||||
|
"content": {
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "Woo! Threads!"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"count": 7,
|
||||||
|
"current_user_participated": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`latest_event` is the most recent event (topologically to the server) in the thread sent by an
|
||||||
|
un-[ignored user](#ignoring-users).
|
||||||
|
|
||||||
|
Note that any bundled aggregations on `latest_event` should also be present. The server should be
|
||||||
|
careful to avoid loops, though loops are not currently possible due to `m.thread` not being possible
|
||||||
|
to target an event with a `rel_type` already.
|
||||||
|
|
||||||
|
`count` is simply the number of events using `m.thread` as a `rel_type` pointing to the target event.
|
||||||
|
It does not include events sent by [ignored users](#ignoring-users).
|
||||||
|
|
||||||
|
`current_user_participated` is `true` when the authenticated user is either:
|
||||||
|
1. The `sender` of the event receiving the bundle (they sent the thread root).
|
||||||
|
2. The `sender` of an event which references the thread root with a `rel_type` of `m.thread`.
|
||||||
|
|
||||||
|
#### Querying threads in a room
|
||||||
|
|
||||||
|
Clients looking to get all the events in a thread can use
|
||||||
|
[`GET /relations/{threadRootId}/m.thread`](#get_matrixclientv1roomsroomidrelationseventidreltype),
|
||||||
|
however getting all threads in a room is done through a dedicated API:
|
||||||
|
|
||||||
|
{{% http-api spec="client-server" api="threads_list" %}}
|
||||||
|
|
@ -6,8 +6,9 @@ type: module
|
||||||
|
|
||||||
Users may wish to be informed when another user is typing in a room.
|
Users may wish to be informed when another user is typing in a room.
|
||||||
This can be achieved using typing notifications. These are ephemeral
|
This can be achieved using typing notifications. These are ephemeral
|
||||||
events scoped to a `room_id`. This means they do not form part of the
|
events, so they do not form part of the
|
||||||
[Event Graph](index.html#event-graphs) but still have a `room_id` key.
|
[Event Graph](index.html#event-graphs). Typing notifications are scoped
|
||||||
|
to a room.
|
||||||
|
|
||||||
#### Events
|
#### Events
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@ the default power level for users in the room.
|
||||||
The rules are as follows:
|
The rules are as follows:
|
||||||
|
|
||||||
1. If type is `m.room.create`:
|
1. If type is `m.room.create`:
|
||||||
1. If it has any previous 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
|
||||||
`sender`, reject.
|
`sender`, reject.
|
||||||
3. If `content.room_version` is present and is not a recognised
|
3. If `content.room_version` is present and is not a recognised
|
||||||
version, reject.
|
version, reject.
|
||||||
4. If `content` has no `creator` field, reject.
|
4. If `content` has no `creator` property, reject.
|
||||||
5. Otherwise, allow.
|
5. Otherwise, allow.
|
||||||
2. Considering the event's `auth_events`:
|
2. Considering the event's `auth_events`:
|
||||||
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
||||||
|
|
@ -45,7 +45,8 @@ The rules are as follows:
|
||||||
2. If sender's domain doesn't matches `state_key`, reject.
|
2. If sender's domain doesn't matches `state_key`, reject.
|
||||||
3. Otherwise, allow.
|
3. Otherwise, allow.
|
||||||
5. If type is `m.room.member`:
|
5. If type is `m.room.member`:
|
||||||
1. If no `state_key` key or `membership` key in `content`, reject.
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
|
`content`, reject.
|
||||||
2. If `membership` is `join`:
|
2. If `membership` is `join`:
|
||||||
1. If the only previous event is an `m.room.create` and the
|
1. If the only previous event is an `m.room.create` and the
|
||||||
`state_key` is the creator, allow.
|
`state_key` is the creator, allow.
|
||||||
|
|
@ -56,11 +57,11 @@ The rules are as follows:
|
||||||
5. If the `join_rule` is `public`, allow.
|
5. If the `join_rule` is `public`, allow.
|
||||||
6. Otherwise, reject.
|
6. Otherwise, reject.
|
||||||
3. If `membership` is `invite`:
|
3. If `membership` is `invite`:
|
||||||
1. If `content` has `third_party_invite` key:
|
1. If `content` has a `third_party_invite` property:
|
||||||
1. If *target user* is banned, reject.
|
1. If *target user* is banned, reject.
|
||||||
2. If `content.third_party_invite` does not have a `signed`
|
2. If `content.third_party_invite` does not have a `signed`
|
||||||
key, reject.
|
property, reject.
|
||||||
3. If `signed` does not have `mxid` and `token` keys,
|
3. If `signed` does not have `mxid` and `token` properties,
|
||||||
reject.
|
reject.
|
||||||
4. If `mxid` does not match `state_key`, reject.
|
4. If `mxid` does not match `state_key`, reject.
|
||||||
5. If there is no `m.room.third_party_invite` event in the
|
5. If there is no `m.room.third_party_invite` event in the
|
||||||
|
|
@ -71,8 +72,8 @@ The rules are as follows:
|
||||||
7. If any signature in `signed` matches any public key in
|
7. If any signature in `signed` matches any public key in
|
||||||
the `m.room.third_party_invite` event, allow. The public
|
the `m.room.third_party_invite` event, allow. The public
|
||||||
keys are in `content` of `m.room.third_party_invite` as:
|
keys are in `content` of `m.room.third_party_invite` as:
|
||||||
1. A single public key in the `public_key` field.
|
1. A single public key in the `public_key` property.
|
||||||
2. A list of public keys in the `public_keys` field.
|
2. A list of public keys in the `public_keys` property.
|
||||||
8. Otherwise, reject.
|
8. Otherwise, reject.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
reject.
|
reject.
|
||||||
|
|
@ -110,29 +111,32 @@ The rules are as follows:
|
||||||
9. If the event has a `state_key` that starts with an `@` and does not
|
9. If the event has a `state_key` that starts with an `@` and does not
|
||||||
match the `sender`, reject.
|
match the `sender`, reject.
|
||||||
10. If type is `m.room.power_levels`:
|
10. If type is `m.room.power_levels`:
|
||||||
1. If `users` key in `content` is not a dictionary with keys that
|
1. If the `users` property in `content` is not an object with keys that
|
||||||
are valid user IDs with values that are integers (or a string
|
are valid user IDs with values that are integers (or a string
|
||||||
that is an integer), reject.
|
that is an integer), reject.
|
||||||
2. If there is no previous `m.room.power_levels` event in the room,
|
2. If there is no previous `m.room.power_levels` event in the room,
|
||||||
allow.
|
allow.
|
||||||
3. For the keys `users_default`, `events_default`, `state_default`,
|
3. For the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, `invite` check if they were added,
|
`ban`, `redact`, `kick`, `invite` check if they were added,
|
||||||
changed or removed. For each found alteration:
|
changed or removed. For each found alteration:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is greater than the `sender`'s current
|
||||||
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 greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
4. For each entry being added, changed or removed in both the
|
4. For each entry being changed in, or removed from, the `events` property:
|
||||||
`events` and `users` keys:
|
1. If the current value is greater than the `sender`'s current
|
||||||
1. If the current value is higher than the `sender`'s current
|
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
5. For each entry being added to, or changed in, the `events` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
5. For each entry being changed under the `users` key, other than
|
6. For each entry being changed in, or removed from, the `users` property,
|
||||||
the `sender`'s own entry:
|
other than the `sender`'s own entry:
|
||||||
1. If the current value is equal to the `sender`'s current
|
1. If the current value is greater than or equal to the `sender`'s
|
||||||
power level, reject.
|
current power level, reject.
|
||||||
6. Otherwise, allow.
|
7. For each entry being added to, or changed in, the `users` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
level, reject.
|
||||||
|
8. Otherwise, allow.
|
||||||
11. If type is `m.room.redaction`:
|
11. If type is `m.room.redaction`:
|
||||||
1. If the `sender`'s power level is greater than or equal to the
|
1. If the `sender`'s power level is greater than or equal to the
|
||||||
*redact level*, allow.
|
*redact level*, allow.
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
toc_hide: true
|
toc_hide: true
|
||||||
---
|
---
|
||||||
|
|
||||||
{{% added-in this=true %}} In room versions 1 and 2, events need a
|
{{< added-in this=true >}} 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.
|
||||||
The event must still be signed by the server denoted by the `sender`,
|
The event must still be signed by the server denoted by the `sender` property,
|
||||||
however.
|
however.
|
||||||
|
|
||||||
The types of state events that affect authorization are:
|
The types of state events that affect authorization are:
|
||||||
|
|
@ -26,12 +26,12 @@ the default power level for users in the room.
|
||||||
The complete list of rules, as of room version 3, is as follows:
|
The complete list of rules, as of room version 3, is as follows:
|
||||||
|
|
||||||
1. If type is `m.room.create`:
|
1. If type is `m.room.create`:
|
||||||
1. If it has any previous 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
|
||||||
`sender`, reject.
|
`sender`, reject.
|
||||||
3. If `content.room_version` is present and is not a recognised
|
3. If `content.room_version` is present and is not a recognised
|
||||||
version, reject.
|
version, reject.
|
||||||
4. If `content` has no `creator` field, reject.
|
4. If `content` has no `creator` property, reject.
|
||||||
5. Otherwise, allow.
|
5. Otherwise, allow.
|
||||||
2. Considering the event's `auth_events`:
|
2. Considering the event's `auth_events`:
|
||||||
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
||||||
|
|
@ -52,7 +52,8 @@ The complete list of rules, as of room version 3, is as follows:
|
||||||
2. If sender's domain doesn't matches `state_key`, reject.
|
2. If sender's domain doesn't matches `state_key`, reject.
|
||||||
3. Otherwise, allow.
|
3. Otherwise, allow.
|
||||||
5. If type is `m.room.member`:
|
5. If type is `m.room.member`:
|
||||||
1. If no `state_key` key or `membership` key in `content`, reject.
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
|
`content`, reject.
|
||||||
2. If `membership` is `join`:
|
2. If `membership` is `join`:
|
||||||
1. If the only previous event is an `m.room.create` and the
|
1. If the only previous event is an `m.room.create` and the
|
||||||
`state_key` is the creator, allow.
|
`state_key` is the creator, allow.
|
||||||
|
|
@ -63,11 +64,11 @@ The complete list of rules, as of room version 3, is as follows:
|
||||||
5. If the `join_rule` is `public`, allow.
|
5. If the `join_rule` is `public`, allow.
|
||||||
6. Otherwise, reject.
|
6. Otherwise, reject.
|
||||||
3. If `membership` is `invite`:
|
3. If `membership` is `invite`:
|
||||||
1. If `content` has `third_party_invite` key:
|
1. If `content` has a `third_party_invite` property:
|
||||||
1. If *target user* is banned, reject.
|
1. If *target user* is banned, reject.
|
||||||
2. If `content.third_party_invite` does not have a `signed`
|
2. If `content.third_party_invite` does not have a `signed`
|
||||||
key, reject.
|
property, reject.
|
||||||
3. If `signed` does not have `mxid` and `token` keys,
|
3. If `signed` does not have `mxid` and `token` properties,
|
||||||
reject.
|
reject.
|
||||||
4. If `mxid` does not match `state_key`, reject.
|
4. If `mxid` does not match `state_key`, reject.
|
||||||
5. If there is no `m.room.third_party_invite` event in the
|
5. If there is no `m.room.third_party_invite` event in the
|
||||||
|
|
@ -78,8 +79,8 @@ The complete list of rules, as of room version 3, is as follows:
|
||||||
7. If any signature in `signed` matches any public key in
|
7. If any signature in `signed` matches any public key in
|
||||||
the `m.room.third_party_invite` event, allow. The public
|
the `m.room.third_party_invite` event, allow. The public
|
||||||
keys are in `content` of `m.room.third_party_invite` as:
|
keys are in `content` of `m.room.third_party_invite` as:
|
||||||
1. A single public key in the `public_key` field.
|
1. A single public key in the `public_key` property.
|
||||||
2. A list of public keys in the `public_keys` field.
|
2. A list of public keys in the `public_keys` property.
|
||||||
8. Otherwise, reject.
|
8. Otherwise, reject.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
reject.
|
reject.
|
||||||
|
|
@ -117,29 +118,32 @@ The complete list of rules, as of room version 3, is as follows:
|
||||||
9. If the event has a `state_key` that starts with an `@` and does not
|
9. If the event has a `state_key` that starts with an `@` and does not
|
||||||
match the `sender`, reject.
|
match the `sender`, reject.
|
||||||
10. If type is `m.room.power_levels`:
|
10. If type is `m.room.power_levels`:
|
||||||
1. If `users` key in `content` is not a dictionary with keys that
|
1. If `users` property in `content` is not an object with keys that
|
||||||
are valid user IDs with values that are integers (or a string
|
are valid user IDs with values that are integers (or a string
|
||||||
that is an integer), reject.
|
that is an integer), reject.
|
||||||
2. If there is no previous `m.room.power_levels` event in the room,
|
2. If there is no previous `m.room.power_levels` event in the room,
|
||||||
allow.
|
allow.
|
||||||
3. For the keys `users_default`, `events_default`, `state_default`,
|
3. For the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, `invite` check if they were added,
|
`ban`, `redact`, `kick`, `invite` check if they were added,
|
||||||
changed or removed. For each found alteration:
|
changed or removed. For each found alteration:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is greater than the `sender`'s current
|
||||||
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 greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
4. For each entry being added, changed or removed in both the
|
4. For each entry being changed in, or removed from, the `events` property:
|
||||||
`events` and `users` keys:
|
1. If the current value is greater than the `sender`'s current
|
||||||
1. If the current value is higher than the `sender`'s current
|
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
5. For each entry being added to, or changed in, the `events` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
5. For each entry being changed under the `users` key, other than
|
6. For each entry being changed in, or removed from, the `users` property,
|
||||||
the `sender`'s own entry:
|
other than the `sender`'s own entry:
|
||||||
1. If the current value is equal to the `sender`'s current
|
1. If the current value is greater than or equal to the `sender`'s
|
||||||
power level, reject.
|
current power level, reject.
|
||||||
6. Otherwise, allow.
|
7. For each entry being added to, or changed in, the `users` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
level, reject.
|
||||||
|
8. Otherwise, allow.
|
||||||
11. Otherwise, allow.
|
11. Otherwise, allow.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
toc_hide: true
|
toc_hide: true
|
||||||
---
|
---
|
||||||
|
|
||||||
Events must be signed by the server denoted by the `sender` key.
|
Events must be signed by the server denoted by the `sender` property.
|
||||||
|
|
||||||
`m.room.redaction` events are not explicitly part of the auth rules.
|
`m.room.redaction` events are not explicitly part of the auth rules.
|
||||||
They are still subject to the minimum power level rules, but should always
|
They are still subject to the minimum power level rules, but should always
|
||||||
|
|
@ -27,12 +27,12 @@ the default power level for users in the room.
|
||||||
The rules are as follows:
|
The rules are as follows:
|
||||||
|
|
||||||
1. If type is `m.room.create`:
|
1. If type is `m.room.create`:
|
||||||
1. If it has any previous 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
|
||||||
`sender`, reject.
|
`sender`, reject.
|
||||||
3. If `content.room_version` is present and is not a recognised
|
3. If `content.room_version` is present and is not a recognised
|
||||||
version, reject.
|
version, reject.
|
||||||
4. If `content` has no `creator` field, reject.
|
4. If `content` has no `creator` property, reject.
|
||||||
5. Otherwise, allow.
|
5. Otherwise, allow.
|
||||||
2. Considering the event's `auth_events`:
|
2. Considering the event's `auth_events`:
|
||||||
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
||||||
|
|
@ -49,9 +49,10 @@ The rules are as follows:
|
||||||
property `m.federate` set to `false`, and the `sender` domain of the event
|
property `m.federate` set to `false`, and the `sender` domain of the event
|
||||||
does not match the `sender` domain of the create event, reject.
|
does not match the `sender` domain of the create event, reject.
|
||||||
4. If type is `m.room.member`:
|
4. If type is `m.room.member`:
|
||||||
1. If no `state_key` key or `membership` key in `content`, reject.
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
2. If `content` has a `join_authorised_via_users_server`
|
`content`, reject.
|
||||||
key:
|
2. {{< added-in this=true >}}
|
||||||
|
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.
|
||||||
3. If `membership` is `join`:
|
3. If `membership` is `join`:
|
||||||
|
|
@ -61,7 +62,8 @@ 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. If the `join_rule` is `restricted`:
|
5. {{< added-in this=true >}}
|
||||||
|
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`
|
||||||
is not a user with sufficient permission to invite other
|
is not a user with sufficient permission to invite other
|
||||||
|
|
@ -70,11 +72,11 @@ The rules are as follows:
|
||||||
6. If the `join_rule` is `public`, allow.
|
6. If the `join_rule` is `public`, allow.
|
||||||
7. Otherwise, reject.
|
7. Otherwise, reject.
|
||||||
4. If `membership` is `invite`:
|
4. If `membership` is `invite`:
|
||||||
1. If `content` has `third_party_invite` key:
|
1. If `content` has a `third_party_invite` property:
|
||||||
1. If *target user* is banned, reject.
|
1. If *target user* is banned, reject.
|
||||||
2. If `content.third_party_invite` does not have a `signed`
|
2. If `content.third_party_invite` does not have a `signed`
|
||||||
key, reject.
|
property, reject.
|
||||||
3. If `signed` does not have `mxid` and `token` keys,
|
3. If `signed` does not have `mxid` and `token` properties,
|
||||||
reject.
|
reject.
|
||||||
4. If `mxid` does not match `state_key`, reject.
|
4. If `mxid` does not match `state_key`, reject.
|
||||||
5. If there is no `m.room.third_party_invite` event in the
|
5. If there is no `m.room.third_party_invite` event in the
|
||||||
|
|
@ -85,8 +87,8 @@ The rules are as follows:
|
||||||
7. If any signature in `signed` matches any public key in
|
7. If any signature in `signed` matches any public key in
|
||||||
the `m.room.third_party_invite` event, allow. The public
|
the `m.room.third_party_invite` event, allow. The public
|
||||||
keys are in `content` of `m.room.third_party_invite` as:
|
keys are in `content` of `m.room.third_party_invite` as:
|
||||||
1. A single public key in the `public_key` field.
|
1. A single public key in the `public_key` property.
|
||||||
2. A list of public keys in the `public_keys` field.
|
2. A list of public keys in the `public_keys` property.
|
||||||
8. Otherwise, reject.
|
8. Otherwise, reject.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
reject.
|
reject.
|
||||||
|
|
@ -130,29 +132,34 @@ 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. If `users` key in `content` is not a dictionary with keys that
|
1. If the `users` property in `content` is not an object with keys that
|
||||||
are valid user IDs with values that are integers (or a string
|
are valid user IDs with values that are integers (or a string
|
||||||
that is an integer), reject.
|
that is an integer), reject.
|
||||||
2. If there is no previous `m.room.power_levels` event in the room,
|
2. If there is no previous `m.room.power_levels` event in the room,
|
||||||
allow.
|
allow.
|
||||||
3. For the keys `users_default`, `events_default`, `state_default`,
|
3. For the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, `invite` check if they were added,
|
`ban`, `redact`, `kick`, `invite` check if they were added,
|
||||||
changed or removed. For each found alteration:
|
changed or removed. For each found alteration:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is higher than the `sender`'s current
|
||||||
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. For each entry being added, changed or removed in both the
|
4. For each entry being changed in, or removed from, the `events` or
|
||||||
`events`, `users`, and `notifications` keys:
|
`notifications` properties:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is greater than the `sender`'s current
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
5. For each entry being added to, or changed in the `events` or
|
||||||
|
`notifications` properties:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
5. For each entry being changed under the `users` key, other than
|
6. For each entry being changed in, or removed from, the `users` property,
|
||||||
the `sender`'s own entry:
|
other than the `sender`'s own entry:
|
||||||
1. If the current value is equal to the `sender`'s current
|
1. If the current value is greater than or equal to the `sender`'s
|
||||||
power level, reject.
|
current power level, reject.
|
||||||
6. Otherwise, allow.
|
7. For each entry being added to, or changed in, the `users` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
level, reject.
|
||||||
|
8. Otherwise, allow.
|
||||||
10. Otherwise, allow.
|
10. Otherwise, allow.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ correctly structured are rejected under the authorization rules below.
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
Events must be signed by the server denoted by the `sender` key.
|
Events must be signed by the server denoted by the `sender` property.
|
||||||
|
|
||||||
`m.room.redaction` events are not explicitly part of the auth rules.
|
`m.room.redaction` events are not explicitly part of the auth rules.
|
||||||
They are still subject to the minimum power level rules, but should always
|
They are still subject to the minimum power level rules, but should always
|
||||||
|
|
@ -99,12 +99,12 @@ the default power level for users in the room.
|
||||||
The rules are as follows:
|
The rules are as follows:
|
||||||
|
|
||||||
1. If type is `m.room.create`:
|
1. If type is `m.room.create`:
|
||||||
1. If it has any previous 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
|
||||||
`sender`, reject.
|
`sender`, reject.
|
||||||
3. If `content.room_version` is present and is not a recognised
|
3. If `content.room_version` is present and is not a recognised
|
||||||
version, reject.
|
version, reject.
|
||||||
4. If `content` has no `creator` field, reject.
|
4. If `content` has no `creator` property, reject.
|
||||||
5. Otherwise, allow.
|
5. Otherwise, allow.
|
||||||
2. Considering the event's `auth_events`:
|
2. Considering the event's `auth_events`:
|
||||||
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
1. If there are duplicate entries for a given `type` and `state_key` pair,
|
||||||
|
|
@ -121,7 +121,8 @@ The rules are as follows:
|
||||||
property `m.federate` set to `false`, and the `sender` domain of the event
|
property `m.federate` set to `false`, and the `sender` domain of the event
|
||||||
does not match the `sender` domain of the create event, reject.
|
does not match the `sender` domain of the create event, reject.
|
||||||
4. If type is `m.room.member`:
|
4. If type is `m.room.member`:
|
||||||
1. If no `state_key` key or `membership` key in `content`, reject.
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
|
`content`, reject.
|
||||||
2. If `content` has a `join_authorised_via_users_server`
|
2. If `content` has a `join_authorised_via_users_server`
|
||||||
key:
|
key:
|
||||||
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
|
||||||
|
|
@ -143,11 +144,11 @@ The rules are as follows:
|
||||||
6. If the `join_rule` is `public`, allow.
|
6. If the `join_rule` is `public`, allow.
|
||||||
7. Otherwise, reject.
|
7. Otherwise, reject.
|
||||||
4. If `membership` is `invite`:
|
4. If `membership` is `invite`:
|
||||||
1. If `content` has `third_party_invite` key:
|
1. If `content` has a `third_party_invite` property:
|
||||||
1. If *target user* is banned, reject.
|
1. If *target user* is banned, reject.
|
||||||
2. If `content.third_party_invite` does not have a `signed`
|
2. If `content.third_party_invite` does not have a `signed`
|
||||||
key, reject.
|
property, reject.
|
||||||
3. If `signed` does not have `mxid` and `token` keys,
|
3. If `signed` does not have `mxid` and `token` properties,
|
||||||
reject.
|
reject.
|
||||||
4. If `mxid` does not match `state_key`, reject.
|
4. If `mxid` does not match `state_key`, reject.
|
||||||
5. If there is no `m.room.third_party_invite` event in the
|
5. If there is no `m.room.third_party_invite` event in the
|
||||||
|
|
@ -158,8 +159,8 @@ The rules are as follows:
|
||||||
7. If any signature in `signed` matches any public key in
|
7. If any signature in `signed` matches any public key in
|
||||||
the `m.room.third_party_invite` event, allow. The public
|
the `m.room.third_party_invite` event, allow. The public
|
||||||
keys are in `content` of `m.room.third_party_invite` as:
|
keys are in `content` of `m.room.third_party_invite` as:
|
||||||
1. A single public key in the `public_key` field.
|
1. A single public key in the `public_key` property.
|
||||||
2. A list of public keys in the `public_keys` field.
|
2. A list of public keys in the `public_keys` property.
|
||||||
8. Otherwise, reject.
|
8. Otherwise, reject.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
reject.
|
reject.
|
||||||
|
|
@ -206,35 +207,40 @@ The rules are as follows:
|
||||||
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 this="true" >}}
|
1. {{< added-in this="true" >}}
|
||||||
If any of the keys `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 this="true" >}}
|
2. {{< added-in this="true" >}}
|
||||||
If either of the keys `events` or `notifications` in `content`
|
If either of the properties `events` or `notifications` in `content`
|
||||||
are present and not a dictionary with values that are integers,
|
are present and not an object with values that are integers,
|
||||||
reject.
|
reject.
|
||||||
3. If `users` key in `content` is not a dictionary with keys that
|
3. If the `users` property in `content` is not an obiect with keys that
|
||||||
are valid user IDs with values that are integers, reject.
|
are valid user IDs with values that are integers, reject.
|
||||||
2. If there is no previous `m.room.power_levels` event in the room,
|
4. If there is no previous `m.room.power_levels` event in the room,
|
||||||
allow.
|
allow.
|
||||||
3. For the keys `users_default`, `events_default`, `state_default`,
|
5. For the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, `invite` check if they were added,
|
`ban`, `redact`, `kick`, `invite` check if they were added,
|
||||||
changed or removed. For each found alteration:
|
changed or removed. For each found alteration:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is higher than the `sender`'s current
|
||||||
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. For each entry being added, changed or removed in both the
|
6. For each entry being changed in, or removed from, the `events` or
|
||||||
`events`, `users`, and `notifications` keys:
|
`notifications` properties:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is greater than the `sender`'s current
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
7. For each entry being added to, or changed in, the `events` or
|
||||||
|
`notifications` properties:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
5. For each entry being changed under the `users` key, other than
|
8. For each entry being changed in, or removed from, the `users` property,
|
||||||
the `sender`'s own entry:
|
other than the `sender`'s own entry:
|
||||||
1. If the current value is equal to the `sender`'s current
|
1. If the current value is greater than or equal to the `sender`'s
|
||||||
power level, reject.
|
current power level, reject.
|
||||||
6. Otherwise, allow.
|
9. For each entry being added to, or changed in, the `users` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
level, reject.
|
||||||
|
10. Otherwise, allow.
|
||||||
10. Otherwise, allow.
|
10. Otherwise, allow.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ The complete structure of a event in a v3 room is shown below.
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{% added-in this=true %}} `m.room.redaction` events are no longer
|
{{< added-in this=true >}} `m.room.redaction` events are no longer
|
||||||
explicitly part of the auth rules. They are still subject to the
|
explicitly part of the auth rules. They are still subject to the
|
||||||
minimum power level rules, but should always fall into "11. Otherwise,
|
minimum power level rules, but should always fall into "11. Otherwise,
|
||||||
allow". Instead of being authorized at the time of receipt, they are
|
allow". Instead of being authorized at the time of receipt, they are
|
||||||
|
|
@ -97,7 +97,7 @@ authorized at a later stage: see the [Handling Redactions](#handling-redactions)
|
||||||
section below for more information.
|
section below for more information.
|
||||||
|
|
||||||
<!-- set withVersioning=true so we get all the "new in this version" stuff -->
|
<!-- set withVersioning=true so we get all the "new in this version" stuff -->
|
||||||
{{% rver-fragment name="v3-auth-rules" withVersioning=true %}}
|
{{< rver-fragment name="v3-auth-rules" withVersioning=true >}}
|
||||||
|
|
||||||
## Unchanged from v2
|
## Unchanged from v2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,16 +46,16 @@ fall into "10. Otherwise, allow". Instead of being authorized at the time
|
||||||
of receipt, they are authorized at a later stage: see the
|
of receipt, they are authorized at a later stage: see the
|
||||||
[Handling Redactions](#handling-redactions) section below for more information.
|
[Handling Redactions](#handling-redactions) section below for more information.
|
||||||
|
|
||||||
{{% added-in this=true %}} Rule 4, which related specifically to events
|
{{< added-in this=true >}} 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 this=true %}} Additionally, the authorization rules for events
|
{{< added-in this=true >}} Additionally, the authorization rules for events of
|
||||||
of type `m.room.power_levels` now include the content key `notifications`.
|
type `m.room.power_levels` now include a `notifications` property under
|
||||||
This new rule takes the place of rule 10.4, which checked the `events` and
|
`content`. This updates rules 10.4 and 10.5 (now 9.4 and 9.5), which checked
|
||||||
`users` keys.
|
the `events` property.
|
||||||
|
|
||||||
Events must be signed by the server denoted by the `sender` key.
|
Events must be signed by the server denoted by the `sender` property.
|
||||||
|
|
||||||
The types of state events that affect authorization are:
|
The types of state events that affect authorization are:
|
||||||
|
|
||||||
|
|
@ -74,12 +74,12 @@ the default power level for users in the room.
|
||||||
The rules are as follows:
|
The rules are as follows:
|
||||||
|
|
||||||
1. If type is `m.room.create`:
|
1. If type is `m.room.create`:
|
||||||
1. If it has any previous 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
|
||||||
`sender`, reject.
|
`sender`, reject.
|
||||||
3. If `content.room_version` is present and is not a recognised
|
3. If `content.room_version` is present and is not a recognised
|
||||||
version, reject.
|
version, reject.
|
||||||
4. If `content` has no `creator` field, reject.
|
4. If `content` has no `creator` property, reject.
|
||||||
5. Otherwise, allow.
|
5. Otherwise, allow.
|
||||||
2. Reject if event has `auth_events` that:
|
2. Reject if event has `auth_events` that:
|
||||||
1. have duplicate entries for a given `type` and `state_key` pair
|
1. have duplicate entries for a given `type` and `state_key` pair
|
||||||
|
|
@ -90,7 +90,8 @@ The rules are as follows:
|
||||||
3. If event does not have a `m.room.create` in its `auth_events`,
|
3. If event does not have a `m.room.create` in its `auth_events`,
|
||||||
reject.
|
reject.
|
||||||
4. If type is `m.room.member`:
|
4. If type is `m.room.member`:
|
||||||
1. If no `state_key` key or `membership` key in `content`, reject.
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
|
`content`, reject.
|
||||||
2. If `membership` is `join`:
|
2. If `membership` is `join`:
|
||||||
1. If the only previous event is an `m.room.create` and the
|
1. If the only previous event is an `m.room.create` and the
|
||||||
`state_key` is the creator, allow.
|
`state_key` is the creator, allow.
|
||||||
|
|
@ -101,11 +102,11 @@ The rules are as follows:
|
||||||
5. If the `join_rule` is `public`, allow.
|
5. If the `join_rule` is `public`, allow.
|
||||||
6. Otherwise, reject.
|
6. Otherwise, reject.
|
||||||
3. If `membership` is `invite`:
|
3. If `membership` is `invite`:
|
||||||
1. If `content` has `third_party_invite` key:
|
1. If `content` has a `third_party_invite` property:
|
||||||
1. If *target user* is banned, reject.
|
1. If *target user* is banned, reject.
|
||||||
2. If `content.third_party_invite` does not have a `signed`
|
2. If `content.third_party_invite` does not have a `signed`
|
||||||
key, reject.
|
property, reject.
|
||||||
3. If `signed` does not have `mxid` and `token` keys,
|
3. If `signed` does not have `mxid` and `token` properties,
|
||||||
reject.
|
reject.
|
||||||
4. If `mxid` does not match `state_key`, reject.
|
4. If `mxid` does not match `state_key`, reject.
|
||||||
5. If there is no `m.room.third_party_invite` event in the
|
5. If there is no `m.room.third_party_invite` event in the
|
||||||
|
|
@ -116,8 +117,8 @@ The rules are as follows:
|
||||||
7. If any signature in `signed` matches any public key in
|
7. If any signature in `signed` matches any public key in
|
||||||
the `m.room.third_party_invite` event, allow. The public
|
the `m.room.third_party_invite` event, allow. The public
|
||||||
keys are in `content` of `m.room.third_party_invite` as:
|
keys are in `content` of `m.room.third_party_invite` as:
|
||||||
1. A single public key in the `public_key` field.
|
1. A single public key in the `public_key` property.
|
||||||
2. A list of public keys in the `public_keys` field.
|
2. A list of public keys in the `public_keys` property.
|
||||||
8. Otherwise, reject.
|
8. Otherwise, reject.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
reject.
|
reject.
|
||||||
|
|
@ -155,29 +156,36 @@ 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. If `users` key in `content` is not a dictionary with keys that
|
1. If the `users` property in `content` is not an object with keys that
|
||||||
are valid user IDs with values that are integers (or a string
|
are valid user IDs with values that are integers (or a string
|
||||||
that is an integer), reject.
|
that is an integer), reject.
|
||||||
2. If there is no previous `m.room.power_levels` event in the room,
|
2. If there is no previous `m.room.power_levels` event in the room,
|
||||||
allow.
|
allow.
|
||||||
3. For the keys `users_default`, `events_default`, `state_default`,
|
3. For the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, `invite` check if they were added,
|
`ban`, `redact`, `kick`, `invite` check if they were added,
|
||||||
changed or removed. For each found alteration:
|
changed or removed. For each found alteration:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is higher than the `sender`'s current
|
||||||
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. For each entry being added, changed or removed in both the
|
4. {{< changed-in this="true" >}}
|
||||||
`events`, `users`, and `notifications` keys:
|
For each entry being changed in, or removed from, the `events` or
|
||||||
1. If the current value is higher than the `sender`'s current
|
`notifications` properties:
|
||||||
|
1. If the current value is greater than the `sender`'s current
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
5. {{< changed-in this="true" >}}
|
||||||
|
For each entry being added to, or changed in, the `events` or
|
||||||
|
`notifications` properties:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
5. For each entry being changed under the `users` key, other than
|
6. For each entry being changed in, or removed from, the `users` property,
|
||||||
the `sender`'s own entry:
|
other than the `sender`'s own entry:
|
||||||
1. If the current value is equal to the `sender`'s current
|
1. If the current value is greater than or equal to the `sender`'s
|
||||||
power level, reject.
|
current power level, reject.
|
||||||
6. Otherwise, allow.
|
7. For each entry being added to, or changed in, the `users` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
level, reject.
|
||||||
|
8. Otherwise, allow.
|
||||||
10. Otherwise, allow.
|
10. Otherwise, allow.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ as do the versions v6 is based upon.
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{% added-in this=true %}} For checks performed upon `m.room.member` events, a
|
{{< added-in this=true >}} 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` key.
|
Events must be signed by the server denoted by the `sender` property.
|
||||||
|
|
||||||
`m.room.redaction` events are not explicitly part of the auth rules.
|
`m.room.redaction` events are not explicitly part of the auth rules.
|
||||||
They are still subject to the minimum power level rules, but should always
|
They are still subject to the minimum power level rules, but should always
|
||||||
|
|
@ -60,12 +60,12 @@ the default power level for users in the room.
|
||||||
The rules are as follows:
|
The rules are as follows:
|
||||||
|
|
||||||
1. If type is `m.room.create`:
|
1. If type is `m.room.create`:
|
||||||
1. If it has any previous 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
|
||||||
`sender`, reject.
|
`sender`, reject.
|
||||||
3. If `content.room_version` is present and is not a recognised
|
3. If `content.room_version` is present and is not a recognised
|
||||||
version, reject.
|
version, reject.
|
||||||
4. If `content` has no `creator` field, reject.
|
4. If `content` has no `creator` property, reject.
|
||||||
5. Otherwise, allow.
|
5. Otherwise, allow.
|
||||||
2. Reject if event has `auth_events` that:
|
2. Reject if event has `auth_events` that:
|
||||||
1. have duplicate entries for a given `type` and `state_key` pair
|
1. have duplicate entries for a given `type` and `state_key` pair
|
||||||
|
|
@ -76,22 +76,24 @@ The rules are as follows:
|
||||||
3. If event does not have a `m.room.create` in its `auth_events`,
|
3. If event does not have a `m.room.create` in its `auth_events`,
|
||||||
reject.
|
reject.
|
||||||
4. If type is `m.room.member`:
|
4. If type is `m.room.member`:
|
||||||
1. If no `state_key` key or `membership` key in `content`, reject.
|
1. If there is no `state_key` property, or no `membership` property in
|
||||||
|
`content`, reject.
|
||||||
2. If `membership` is `join`:
|
2. If `membership` is `join`:
|
||||||
1. If the only previous event is an `m.room.create` and the
|
1. If the only previous event is an `m.room.create` and the
|
||||||
`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. If the `join_rule` is `invite` or `knock` then allow if
|
4. {{< changed-in this=true >}}
|
||||||
|
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.
|
||||||
6. Otherwise, reject.
|
6. Otherwise, reject.
|
||||||
3. If `membership` is `invite`:
|
3. If `membership` is `invite`:
|
||||||
1. If `content` has `third_party_invite` key:
|
1. If `content` has `third_party_invite` property:
|
||||||
1. If *target user* is banned, reject.
|
1. If *target user* is banned, reject.
|
||||||
2. If `content.third_party_invite` does not have a `signed`
|
2. If `content.third_party_invite` does not have a `signed`
|
||||||
key, reject.
|
property, reject.
|
||||||
3. If `signed` does not have `mxid` and `token` keys,
|
3. If `signed` does not have `mxid` and `token` properties,
|
||||||
reject.
|
reject.
|
||||||
4. If `mxid` does not match `state_key`, reject.
|
4. If `mxid` does not match `state_key`, reject.
|
||||||
5. If there is no `m.room.third_party_invite` event in the
|
5. If there is no `m.room.third_party_invite` event in the
|
||||||
|
|
@ -102,8 +104,8 @@ The rules are as follows:
|
||||||
7. If any signature in `signed` matches any public key in
|
7. If any signature in `signed` matches any public key in
|
||||||
the `m.room.third_party_invite` event, allow. The public
|
the `m.room.third_party_invite` event, allow. The public
|
||||||
keys are in `content` of `m.room.third_party_invite` as:
|
keys are in `content` of `m.room.third_party_invite` as:
|
||||||
1. A single public key in the `public_key` field.
|
1. A single public key in the `public_key` property.
|
||||||
2. A list of public keys in the `public_keys` field.
|
2. A list of public keys in the `public_keys` property.
|
||||||
8. Otherwise, reject.
|
8. Otherwise, reject.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
reject.
|
reject.
|
||||||
|
|
@ -113,7 +115,8 @@ 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. If the `sender` matches `state_key`, allow if and only if
|
1. {{< changed-in this=true >}}
|
||||||
|
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`.
|
||||||
2. If the `sender`'s current membership state is not `join`,
|
2. If the `sender`'s current membership state is not `join`,
|
||||||
|
|
@ -132,7 +135,8 @@ 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. If `membership` is `knock`:
|
6. {{< added-in this=true >}}
|
||||||
|
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.
|
||||||
3. If the `sender`'s current membership is not `ban` or `join`, allow.
|
3. If the `sender`'s current membership is not `ban` or `join`, allow.
|
||||||
|
|
@ -147,29 +151,34 @@ 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. If `users` key in `content` is not a dictionary with keys that
|
1. If the `users` property in `content` is not an object with keys that
|
||||||
are valid user IDs with values that are integers (or a string
|
are valid user IDs with values that are integers (or a string
|
||||||
that is an integer), reject.
|
that is an integer), reject.
|
||||||
2. If there is no previous `m.room.power_levels` event in the room,
|
2. If there is no previous `m.room.power_levels` event in the room,
|
||||||
allow.
|
allow.
|
||||||
3. For the keys `users_default`, `events_default`, `state_default`,
|
3. For the properties `users_default`, `events_default`, `state_default`,
|
||||||
`ban`, `redact`, `kick`, `invite` check if they were added,
|
`ban`, `redact`, `kick`, `invite` check if they were added,
|
||||||
changed or removed. For each found alteration:
|
changed or removed. For each found alteration:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is higher than the `sender`'s current
|
||||||
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. For each entry being added, changed or removed in both the
|
4. For each entry being changed in, or removed from, the `events` or
|
||||||
`events`, `users`, and `notifications` keys:
|
`notifications` properties:
|
||||||
1. If the current value is higher than the `sender`'s current
|
1. If the current value is greater than the `sender`'s current
|
||||||
power level, reject.
|
power level, reject.
|
||||||
2. If the new value is higher than the `sender`'s current power
|
5. For each entry being added to, or changed in, the `events` or
|
||||||
|
`notifications` properties:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
level, reject.
|
level, reject.
|
||||||
5. For each entry being changed under the `users` key, other than
|
6. For each entry being changed in, or removed from, the `users` property,
|
||||||
the `sender`'s own entry:
|
other than the `sender`'s own entry:
|
||||||
1. If the current value is equal to the `sender`'s current
|
1. If the current value is greater than or equal to the `sender`'s
|
||||||
power level, reject.
|
current power level, reject.
|
||||||
6. Otherwise, allow.
|
7. For each entry being added to, or changed in, the `users` property:
|
||||||
|
1. If the new value is greater than the `sender`'s current power
|
||||||
|
level, reject.
|
||||||
|
8. Otherwise, allow..
|
||||||
10. Otherwise, allow.
|
10. Otherwise, allow.
|
||||||
|
|
||||||
{{% boxes/note %}}
|
{{% boxes/note %}}
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,11 @@ room without invite. Otherwise, the room version inherits all properties of
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{% added-in this=true %}} For checks performed upon `m.room.member` events, new
|
{{< added-in this=true >}} 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).
|
||||||
|
|
||||||
{{% rver-fragment name="v8-auth-rules" %}}
|
{{< rver-fragment name="v8-auth-rules" withVersioning=true >}}
|
||||||
|
|
||||||
### Redactions
|
### Redactions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ completeness.
|
||||||
|
|
||||||
### Authorization rules
|
### Authorization rules
|
||||||
|
|
||||||
{{% rver-fragment name="v8-auth-rules" %}}
|
{{< rver-fragment name="v8-auth-rules" >}}
|
||||||
|
|
||||||
### State resolution
|
### State resolution
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ properties:
|
||||||
|
|
||||||
The relationship type determines how clients should perceive the event, and in what
|
The relationship type determines how clients should perceive the event, and in what
|
||||||
context. Some relationship types are processed server-side for "bundling", though not
|
context. Some relationship types are processed server-side for "bundling", though not
|
||||||
all relationships require such behaviour. For example, an `m.thread` relationship type
|
all relationships require such behaviour. For example, an [`m.thread` relationship type](/client-server-api/#threading)
|
||||||
might denote that the event is part of a "thread" of messages and should be rendered as
|
denotes that the event is part of a "thread" of messages and should be rendered as
|
||||||
such.
|
such.
|
||||||
event_id:
|
event_id:
|
||||||
type: string
|
type: string
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
# Copyright 2016 OpenMarket Ltd
|
# Copyright 2016 OpenMarket Ltd
|
||||||
|
# Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +17,12 @@ allOf:
|
||||||
- type: object
|
- type: object
|
||||||
title: RoomEventFilter
|
title: RoomEventFilter
|
||||||
properties:
|
properties:
|
||||||
|
unread_thread_notifications:
|
||||||
|
type: boolean
|
||||||
|
description: |-
|
||||||
|
If `true`, enables per-[thread](/client-server-api/#threading) notification
|
||||||
|
counts. Only applies to the `/sync` endpoint. Defaults to `false`.
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
lazy_load_members:
|
lazy_load_members:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |-
|
description: |-
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,18 @@ paths:
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
properties:
|
||||||
|
thread_id:
|
||||||
|
type: string
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
description: |-
|
||||||
|
The root thread event's ID (or `main`) for which
|
||||||
|
thread this receipt is intended to be under. If
|
||||||
|
not specified, the read receipt is *unthreaded*
|
||||||
|
(default).
|
||||||
example: {
|
example: {
|
||||||
}
|
"thread_id": "main"
|
||||||
|
}
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: The receipt was sent.
|
description: The receipt was sent.
|
||||||
|
|
@ -88,5 +98,19 @@ paths:
|
||||||
description: This request was rate-limited.
|
description: This request was rate-limited.
|
||||||
schema:
|
schema:
|
||||||
"$ref": "definitions/errors/rate_limited.yaml"
|
"$ref": "definitions/errors/rate_limited.yaml"
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
The `thread_id` is invalid in some way. For example:
|
||||||
|
* It is not a string.
|
||||||
|
* It is empty.
|
||||||
|
* It is provided for an incompatible receipt type.
|
||||||
|
* The `event_id` is not related to the `thread_id`.
|
||||||
|
schema:
|
||||||
|
$ref: "definitions/errors/error.yaml"
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_INVALID_PARAM",
|
||||||
|
"error": "thread_id field must be a non-empty string"
|
||||||
|
}
|
||||||
tags:
|
tags:
|
||||||
- Room participation
|
- Room participation
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ paths:
|
||||||
The pagination token to start returning results from. If not supplied, results
|
The pagination token to start returning results from. If not supplied, results
|
||||||
start at the most recent topological event known to the server.
|
start at the most recent topological event known to the server.
|
||||||
|
|
||||||
Can be a `next_batch` token from a previous call, or a returned
|
Can be a `next_batch` or `prev_batch` token from a previous call, or a returned
|
||||||
`start` token from [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages),
|
`start` token from [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages),
|
||||||
or a `next_batch` token from [`/sync`](/client-server-api/#get_matrixclientv3sync).
|
or a `next_batch` token from [`/sync`](/client-server-api/#get_matrixclientv3sync).
|
||||||
required: false
|
required: false
|
||||||
|
|
@ -89,6 +89,16 @@ paths:
|
||||||
Similarly, the server should apply a default value when not supplied.
|
Similarly, the server should apply a default value when not supplied.
|
||||||
required: false
|
required: false
|
||||||
x-example: 20
|
x-example: 20
|
||||||
|
- in: query
|
||||||
|
type: string
|
||||||
|
enum: ["b", "f"]
|
||||||
|
name: dir
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
description: |-
|
||||||
|
Optional (default `b`) direction to return events from. If this is set to `f`, events
|
||||||
|
will be returned in chronological order starting at `from`. If it
|
||||||
|
is set to `b`, events will be returned in *reverse* chronological
|
||||||
|
order, again starting at `from`.
|
||||||
responses:
|
responses:
|
||||||
# note: this endpoint deliberately does not support rate limiting, therefore a
|
# note: this endpoint deliberately does not support rate limiting, therefore a
|
||||||
# 429 error response is not included.
|
# 429 error response is not included.
|
||||||
|
|
@ -193,7 +203,7 @@ paths:
|
||||||
The pagination token to start returning results from. If not supplied, results
|
The pagination token to start returning results from. If not supplied, results
|
||||||
start at the most recent topological event known to the server.
|
start at the most recent topological event known to the server.
|
||||||
|
|
||||||
Can be a `next_batch` token from a previous call, or a returned
|
Can be a `next_batch` or `prev_batch` token from a previous call, or a returned
|
||||||
`start` token from [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages),
|
`start` token from [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages),
|
||||||
or a `next_batch` token from [`/sync`](/client-server-api/#get_matrixclientv3sync).
|
or a `next_batch` token from [`/sync`](/client-server-api/#get_matrixclientv3sync).
|
||||||
required: false
|
required: false
|
||||||
|
|
@ -219,6 +229,16 @@ paths:
|
||||||
Similarly, the server should apply a default value when not supplied.
|
Similarly, the server should apply a default value when not supplied.
|
||||||
required: false
|
required: false
|
||||||
x-example: 20
|
x-example: 20
|
||||||
|
- in: query
|
||||||
|
type: string
|
||||||
|
enum: ["b", "f"]
|
||||||
|
name: dir
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
description: |-
|
||||||
|
Optional (default `b`) direction to return events from. If this is set to `f`, events
|
||||||
|
will be returned in chronological order starting at `from`. If it
|
||||||
|
is set to `b`, events will be returned in *reverse* chronological
|
||||||
|
order, again starting at `from`.
|
||||||
responses:
|
responses:
|
||||||
# note: this endpoint deliberately does not support rate limiting, therefore a
|
# note: this endpoint deliberately does not support rate limiting, therefore a
|
||||||
# 429 error response is not included.
|
# 429 error response is not included.
|
||||||
|
|
@ -335,7 +355,7 @@ paths:
|
||||||
The pagination token to start returning results from. If not supplied, results
|
The pagination token to start returning results from. If not supplied, results
|
||||||
start at the most recent topological event known to the server.
|
start at the most recent topological event known to the server.
|
||||||
|
|
||||||
Can be a `next_batch` token from a previous call, or a returned
|
Can be a `next_batch` or `prev_batch` token from a previous call, or a returned
|
||||||
`start` token from [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages),
|
`start` token from [`/messages`](/client-server-api/#get_matrixclientv3roomsroomidmessages),
|
||||||
or a `next_batch` token from [`/sync`](/client-server-api/#get_matrixclientv3sync).
|
or a `next_batch` token from [`/sync`](/client-server-api/#get_matrixclientv3sync).
|
||||||
required: false
|
required: false
|
||||||
|
|
@ -361,6 +381,16 @@ paths:
|
||||||
Similarly, the server should apply a default value when not supplied.
|
Similarly, the server should apply a default value when not supplied.
|
||||||
required: false
|
required: false
|
||||||
x-example: 20
|
x-example: 20
|
||||||
|
- in: query
|
||||||
|
type: string
|
||||||
|
enum: ["b", "f"]
|
||||||
|
name: dir
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
description: |-
|
||||||
|
Optional (default `b`) direction to return events from. If this is set to `f`, events
|
||||||
|
will be returned in chronological order starting at `from`. If it
|
||||||
|
is set to `b`, events will be returned in *reverse* chronological
|
||||||
|
order, again starting at `from`.
|
||||||
responses:
|
responses:
|
||||||
# note: this endpoint deliberately does not support rate limiting, therefore a
|
# note: this endpoint deliberately does not support rate limiting, therefore a
|
||||||
# 429 error response is not included.
|
# 429 error response is not included.
|
||||||
|
|
|
||||||
|
|
@ -239,17 +239,50 @@ paths:
|
||||||
Counts of unread notifications for this room. See the
|
Counts of unread notifications for this room. See the
|
||||||
[Receiving notifications](/client-server-api/#receiving-notifications) section
|
[Receiving notifications](/client-server-api/#receiving-notifications) section
|
||||||
for more information on how these are calculated.
|
for more information on how these are calculated.
|
||||||
|
|
||||||
|
If `unread_thread_notifications` was specified as `true` on the `RoomEventFilter`,
|
||||||
|
these counts will only be for the main timeline rather than all events in the room.
|
||||||
|
See the [threading module](#threading) for more information.
|
||||||
|
x-changedInMatrixVersion:
|
||||||
|
1.4: |
|
||||||
|
Updated to reflect behaviour of having `unread_thread_notifications` as `true` in
|
||||||
|
the `RoomEventFilter` for `/sync`.
|
||||||
properties:
|
properties:
|
||||||
highlight_count:
|
highlight_count:
|
||||||
title: Highlighted notification count
|
title: Highlighted notification count
|
||||||
type: integer
|
type: integer
|
||||||
description: The number of unread notifications
|
description: The number of unread notifications
|
||||||
for this room with the highlight flag set
|
for this room with the highlight flag set.
|
||||||
notification_count:
|
notification_count:
|
||||||
title: Total notification count
|
title: Total notification count
|
||||||
type: integer
|
type: integer
|
||||||
description: The total number of unread notifications
|
description: The total number of unread notifications
|
||||||
for this room
|
for this room.
|
||||||
|
unread_thread_notifications:
|
||||||
|
title: Unread Thread Notification Counts
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
If `unread_thread_notifications` was specified as `true` on the `RoomEventFilter`,
|
||||||
|
the notification counts for each [thread](#threading) in this room. The object is
|
||||||
|
keyed by thread root ID, with values matching `unread_notifications`.
|
||||||
|
|
||||||
|
If a thread does not have any notifications it can be omitted from this object. If
|
||||||
|
no threads have notification counts, this whole object can be omitted.
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
additionalProperties:
|
||||||
|
title: ThreadNotificationCounts
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
highlight_count:
|
||||||
|
title: ThreadedHighlightNotificationCount
|
||||||
|
type: integer
|
||||||
|
description: |-
|
||||||
|
The number of unread notifications for this *thread* with the highlight flag set.
|
||||||
|
notification_count:
|
||||||
|
title: ThreadedTotalNotificationCount
|
||||||
|
type: integer
|
||||||
|
description: |-
|
||||||
|
The total number of unread notifications for this *thread*.
|
||||||
invite:
|
invite:
|
||||||
title: Invited Rooms
|
title: Invited Rooms
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -424,6 +457,16 @@ paths:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"unread_notifications": {
|
||||||
|
"highlight_count": 1,
|
||||||
|
"notification_count": 5
|
||||||
|
},
|
||||||
|
"unread_thread_notifications": {
|
||||||
|
"$threadroot": {
|
||||||
|
"highlight_count": 3,
|
||||||
|
"notification_count": 6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
135
data/api/client-server/threads_list.yaml
Normal file
135
data/api/client-server/threads_list.yaml
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
# Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Client-Server Threads List API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8008
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
- http
|
||||||
|
basePath: /_matrix/client/v1
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/rooms/{roomId}/threads":
|
||||||
|
get:
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
summary: Retrieve a list of threads in a room, with optional filters.
|
||||||
|
description: |-
|
||||||
|
Paginates over the thread roots in a room, ordered by the `latest_event` of each thread root
|
||||||
|
in its bundle.
|
||||||
|
operationId: getThreadRoots
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: roomId
|
||||||
|
description: The room ID where the thread roots are located.
|
||||||
|
required: true
|
||||||
|
x-example: "!room:example.org"
|
||||||
|
- in: query
|
||||||
|
type: string
|
||||||
|
name: include
|
||||||
|
enum: [all, participated]
|
||||||
|
description: |-
|
||||||
|
Optional (default `all`) flag to denote which thread roots are of interest to the caller.
|
||||||
|
When `all`, all thread roots found in the room are returned. When `participated`, only
|
||||||
|
thread roots for threads the user has [participated in](/client-server-api/#server-side-aggreagtion-of-mthread-relationships)
|
||||||
|
will be returned.
|
||||||
|
x-example: "all"
|
||||||
|
- in: query
|
||||||
|
type: integer
|
||||||
|
name: limit
|
||||||
|
description: |-
|
||||||
|
Optional limit for the maximum number of thread roots to include per response. Must be an integer
|
||||||
|
greater than zero.
|
||||||
|
|
||||||
|
Servers should apply a default value, and impose a maximum value to avoid resource exhaustion.
|
||||||
|
x-example: 20
|
||||||
|
- in: query
|
||||||
|
type: string
|
||||||
|
name: from
|
||||||
|
description: |-
|
||||||
|
A pagination token from a previous result. When not provided, the server starts paginating from
|
||||||
|
the most recent event visible to the user (as per history visibility rules; topologically).
|
||||||
|
x-example: "next_batch_token"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: |-
|
||||||
|
A portion of the available thread roots in the room, based on the filter criteria.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"chunk": [{ "$ref": "../../event-schemas/examples/m.room.message$m.text.yaml" }],
|
||||||
|
"next_batch": "next_batch_token"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
chunk:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The thread roots, ordered by the `latest_event` in each event's aggregation bundle. All events
|
||||||
|
returned include bundled [aggregations](/client-server-api/#aggregations).
|
||||||
|
|
||||||
|
If the thread root event was sent by an [ignored user](/client-server-api/#ignoring-users), the
|
||||||
|
event is returned redacted to the caller. This is to simulate the same behaviour of a client doing
|
||||||
|
aggregation locally on the thread.
|
||||||
|
items:
|
||||||
|
$ref: "definitions/client_event.yaml"
|
||||||
|
next_batch:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
A token to supply to `from` to keep paginating the responses. Not present when there are
|
||||||
|
no further results.
|
||||||
|
required: [chunk]
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The user cannot view or peek on the room. A meaningful `errcode`
|
||||||
|
and description error text will be returned. Example reasons for rejection are:
|
||||||
|
|
||||||
|
- The room is not set up for peeking.
|
||||||
|
- The user has been banned from the room.
|
||||||
|
- The room does not exist.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You are not allowed to view this room."
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
The request was invalid in some way. A meaningful `errcode`
|
||||||
|
and description error text will be returned. Example reasons for rejection are:
|
||||||
|
|
||||||
|
- The `from` token is unknown to the server.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_INVALID_PARAM",
|
||||||
|
"error": "Unknown pagination token"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
|
429:
|
||||||
|
description: This request was rate-limited.
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/rate_limited.yaml"
|
||||||
|
tags:
|
||||||
|
- Threads
|
||||||
|
|
@ -65,6 +65,15 @@ allOf:
|
||||||
A POSIX timestamp in milliseconds for when the user read
|
A POSIX timestamp in milliseconds for when the user read
|
||||||
the event specified in the read receipt.
|
the event specified in the read receipt.
|
||||||
example: 1533358089009
|
example: 1533358089009
|
||||||
|
thread_id:
|
||||||
|
type: string
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
description: |-
|
||||||
|
The root thread event's ID (or `main`) for which
|
||||||
|
thread this receipt is intended to be under. If
|
||||||
|
not specified, the read receipt is *unthreaded*
|
||||||
|
(default).
|
||||||
|
example: "$threadroot"
|
||||||
required: ['ts']
|
required: ['ts']
|
||||||
required: ['event_ids', 'data']
|
required: ['event_ids', 'data']
|
||||||
required: ['m.read']
|
required: ['m.read']
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,7 @@ paths:
|
||||||
items:
|
items:
|
||||||
$ref: "../../event-schemas/schema/core-event-schema/stripped_state.yaml"
|
$ref: "../../event-schemas/schema/core-event-schema/stripped_state.yaml"
|
||||||
description: |-
|
description: |-
|
||||||
An optional list of [stripped state events](/client-server-api/#stripped-state)
|
A list of [stripped state events](/client-server-api/#stripped-state)
|
||||||
to help the initiator of the knock identify the room.
|
to help the initiator of the knock identify the room.
|
||||||
example:
|
example:
|
||||||
$ref: "../../event-schemas/examples/knock_room_state.json"
|
$ref: "../../event-schemas/examples/knock_room_state.json"
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,14 @@ properties:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
description: The timestamp the receipt was sent at.
|
description: The timestamp the receipt was sent at.
|
||||||
|
thread_id:
|
||||||
|
type: string
|
||||||
|
x-addedInMatrixVersion: "1.4"
|
||||||
|
description: |-
|
||||||
|
The root thread event's ID (or `main`) for which
|
||||||
|
thread this receipt is intended to be under. If
|
||||||
|
not specified, the read receipt is *unthreaded*
|
||||||
|
(default).
|
||||||
"m.read.private":
|
"m.read.private":
|
||||||
type: object
|
type: object
|
||||||
title: Own User
|
title: Own User
|
||||||
|
|
|
||||||
141
layouts/partials/changelogs/v1.4.md
Normal file
141
layouts/partials/changelogs/v1.4.md
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
<!--
|
||||||
|
This is a header file for the generated changelog.
|
||||||
|
|
||||||
|
Variables:
|
||||||
|
v1.4 = Replaced by the version number (eg: v1.2)
|
||||||
|
September 29, 2022 = Replaced by the date (eg: April 01, 2021)
|
||||||
|
-->
|
||||||
|
|
||||||
|
## v1.4
|
||||||
|
|
||||||
|
<table class="release-info">
|
||||||
|
<tr><th>Git commit</th><td><a href="https://github.com/matrix-org/matrix-spec/tree/v1.4">https://github.com/matrix-org/matrix-spec/tree/v1.4</a></td>
|
||||||
|
<tr><th>Release date</th><td>September 29, 2022</td>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Intentionally blank line to ensure headers work in the concatenated changelog -->
|
||||||
|
### Client-Server API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Removed Endpoints</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Remove unused policy room sharing mechanism, as per [MSC3844](https://github.com/matrix-org/matrix-spec-proposals/pull/3844). ([#1196](https://github.com/matrix-org/matrix-spec/issues/1196))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add a `.m.rule.room.server_acl` push rule to match `m.room.server_acl` events, as per [MSC3786](https://github.com/matrix-org/matrix-spec-proposals/pull/3786). ([#1190](https://github.com/matrix-org/matrix-spec/issues/1190), [#1201](https://github.com/matrix-org/matrix-spec/issues/1201))
|
||||||
|
- Add `Cross-Origin-Resource-Policy` (CORP) headers to media repository, as per [MSC3828](https://github.com/matrix-org/matrix-spec-proposals/pull/3828). ([#1197](https://github.com/matrix-org/matrix-spec/issues/1197))
|
||||||
|
- Copy a room's `type` when upgrading it, as per [MSC3818](https://github.com/matrix-org/matrix-spec-proposals/pull/3818). ([#1198](https://github.com/matrix-org/matrix-spec/issues/1198))
|
||||||
|
- Add `room_types` filter and `room_type` response to `/publicRooms`, as per [MSC3827](https://github.com/matrix-org/matrix-spec-proposals/pull/3827). ([#1199](https://github.com/matrix-org/matrix-spec/issues/1199))
|
||||||
|
- Add `m.replace` relations (event edits), as per [MSC2676](https://github.com/matrix-org/matrix-spec-proposals/pull/2676). ([#1211](https://github.com/matrix-org/matrix-spec/issues/1211))
|
||||||
|
- Add `m.read.private` receipts, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285). ([#1216](https://github.com/matrix-org/matrix-spec/issues/1216))
|
||||||
|
- Make `m.fully_read` optional on `/read_markers`, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285). ([#1216](https://github.com/matrix-org/matrix-spec/issues/1216))
|
||||||
|
- Allow `m.fully_read` markers to be set from `/receipts`, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285). ([#1216](https://github.com/matrix-org/matrix-spec/issues/1216))
|
||||||
|
- Add threading via `m.thread` relations, as per [MSC3440](https://github.com/matrix-org/matrix-spec-proposals/pull/3440), [MSC3816](https://github.com/matrix-org/matrix-spec-proposals/pull/3816), [MSC3856](https://github.com/matrix-org/matrix-spec-proposals/pull/3856), and [MSC3715](https://github.com/matrix-org/matrix-spec-proposals/pull/3715). ([#1254](https://github.com/matrix-org/matrix-spec/issues/1254))
|
||||||
|
- Add per-thread notifications and read receipts, as per [MSC3771](https://github.com/matrix-org/matrix-spec-proposals/pull/3771) and [MSC3773](https://github.com/matrix-org/matrix-spec-proposals/pull/3773). ([#1255](https://github.com/matrix-org/matrix-spec/issues/1255))
|
||||||
|
- Add `thread_id` to the `/receipt` endpoint, as per [MSC3771](https://github.com/matrix-org/matrix-spec-proposals/pull/3771). ([#1261](https://github.com/matrix-org/matrix-spec/issues/1261))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Mention that the `/rooms/{roomId}/invite` endpoint will return a 200 response if the user is already invited to the room. ([#1084](https://github.com/matrix-org/matrix-spec/issues/1084))
|
||||||
|
- Fix various typos throughout the specification. ([#1135](https://github.com/matrix-org/matrix-spec/issues/1135), [#1161](https://github.com/matrix-org/matrix-spec/issues/1161), [#1164](https://github.com/matrix-org/matrix-spec/issues/1164), [#1170](https://github.com/matrix-org/matrix-spec/issues/1170), [#1180](https://github.com/matrix-org/matrix-spec/issues/1180), [#1215](https://github.com/matrix-org/matrix-spec/issues/1215), [#1238](https://github.com/matrix-org/matrix-spec/issues/1238), [#1243](https://github.com/matrix-org/matrix-spec/issues/1243), [#1263](https://github.com/matrix-org/matrix-spec/issues/1263))
|
||||||
|
- Describe return codes for account data endpoints, and clarify that per-room data does not inherit from the global data. ([#1155](https://github.com/matrix-org/matrix-spec/issues/1155))
|
||||||
|
- Clarify that policy rule globs work like ACL globs. Contributed by Nico. ([#1165](https://github.com/matrix-org/matrix-spec/issues/1165))
|
||||||
|
- Clarify the format of some structures in the End-to-end encryption module. ([#1166](https://github.com/matrix-org/matrix-spec/issues/1166))
|
||||||
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
- Tweak the styling of `<code>` snippets in tables rendered from OpenAPI definitions. ([#1179](https://github.com/matrix-org/matrix-spec/issues/1179))
|
||||||
|
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
||||||
|
- Clarify that the "device_id", "user_id" and "access_token" fields are required in the response body of `POST /_matrix/client/v3/login`. ([#1210](https://github.com/matrix-org/matrix-spec/issues/1210))
|
||||||
|
- Reinforce the relationship of refreshed access tokens to transaction IDs. ([#1236](https://github.com/matrix-org/matrix-spec/issues/1236))
|
||||||
|
- Clarify enum values by separating possible values with commas. ([#1240](https://github.com/matrix-org/matrix-spec/issues/1240))
|
||||||
|
|
||||||
|
|
||||||
|
### Server-Server API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add per-thread notifications and read receipts, as per [MSC3771](https://github.com/matrix-org/matrix-spec-proposals/pull/3771) and [MSC3773](https://github.com/matrix-org/matrix-spec-proposals/pull/3773). ([#1255](https://github.com/matrix-org/matrix-spec/issues/1255))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
- Tweak the styling of `<code>` snippets in tables rendered from OpenAPI definitions. ([#1179](https://github.com/matrix-org/matrix-spec/issues/1179))
|
||||||
|
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
||||||
|
|
||||||
|
|
||||||
|
### Application Service API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Breaking Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Replace homeserver authorization approach with an `Authorization` header instead of `access_token` when talking to the application service, as per [MSC2832](https://github.com/matrix-org/matrix-spec-proposals/pull/2832). ([#1200](https://github.com/matrix-org/matrix-spec/issues/1200))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
|
||||||
|
|
||||||
|
### Identity Service API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
- Update "API Standards" section to clarify how JSON is used. ([#1185](https://github.com/matrix-org/matrix-spec/issues/1185))
|
||||||
|
|
||||||
|
|
||||||
|
### Push Gateway API
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add HTML anchors for object definitions in the formatted specification. ([#1174](https://github.com/matrix-org/matrix-spec/issues/1174))
|
||||||
|
|
||||||
|
|
||||||
|
### Room Versions
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- For room versions 1 through 10, clarify that events with rejected `auth_events` must be rejected. ([#1137](https://github.com/matrix-org/matrix-spec/issues/1137))
|
||||||
|
- For room versions 2–10: correct a mistaken clarification to the state resolution algorithm. ([#1158](https://github.com/matrix-org/matrix-spec/issues/1158))
|
||||||
|
- For room versions 7 through 10: Clarify that `invite->knock` is actually a legal transition. ([#1175](https://github.com/matrix-org/matrix-spec/issues/1175))
|
||||||
|
|
||||||
|
|
||||||
|
### Appendices
|
||||||
|
|
||||||
|
|
||||||
|
No significant changes.
|
||||||
|
|
||||||
|
|
||||||
|
### Internal Changes/Tooling
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Backwards Compatible Changes</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Add internal changes changelog section. ([#1194](https://github.com/matrix-org/matrix-spec/issues/1194))
|
||||||
|
|
||||||
|
|
||||||
|
<strong>Spec Clarifications</strong>
|
||||||
|
|
||||||
|
|
||||||
|
- Render HTML anchors for object definition tables. ([#1191](https://github.com/matrix-org/matrix-spec/issues/1191))
|
||||||
|
- Give rendered-data sections a background and some padding. ([#1195](https://github.com/matrix-org/matrix-spec/issues/1195))
|
||||||
|
- Fix rendering of shortcodes within the client-server API. ([#1205](https://github.com/matrix-org/matrix-spec/issues/1205))
|
||||||
|
- Fix the spacing of mapping types generated from the OpenAPI spec. ([#1230](https://github.com/matrix-org/matrix-spec/issues/1230))
|
||||||
|
|
@ -21,5 +21,6 @@
|
||||||
{{ $content := $page.Content }}
|
{{ $content := $page.Content }}
|
||||||
{{ if not $withVersioning }}
|
{{ if not $withVersioning }}
|
||||||
{{ $content = (replace $content "[New in this version]" "") }}
|
{{ $content = (replace $content "[New in this version]" "") }}
|
||||||
|
{{ $content = (replace $content "[Changed in this version]" "") }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $content | safeHTML }}
|
{{ $content | safeHTML }}
|
||||||
|
|
|
||||||
|
|
@ -83,3 +83,5 @@ is typically best reserved for the next release cycle.
|
||||||
4. Wait for the GitHub Actions build to complete on the tag.
|
4. Wait for the GitHub Actions build to complete on the tag.
|
||||||
5. Update the assets on the GitHub release to those generated by the latest Actions build.
|
5. Update the assets on the GitHub release to those generated by the latest Actions build.
|
||||||
6. Deploy the release on the webserver. See internal wiki.
|
6. Deploy the release on the webserver. See internal wiki.
|
||||||
|
7. Remove the changelog entries from `main`, if the changes landed on `main`.
|
||||||
|
8. Update the github release changelog and changelog on `main`, likely by hand.
|
||||||
|
|
|
||||||
1
static/diagrams/threaded-dag-threads.drawio
Normal file
1
static/diagrams/threaded-dag-threads.drawio
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<mxfile host="app.diagrams.net" modified="2022-09-27T03:26:23.216Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" etag="YZcXq9Sm_7Lqw5o2RvSU" version="14.6.7" type="device"><diagram id="_rQ0dgHO1UnHExDn0l7E" name="Page-1">7ZpdU+IwFIZ/DZc6bdNWuJQCujPquOvOrl452TbQaNowIXztr9+EJv0goLCirYwyo81JGpL3PQ8nU2mBIFlcMDiOr2mESMuxokUL9FqO41i+I/7IyDKL2JbvZZERw5GKFYE7/BfpgSo6xRGaVAZySgnH42owpGmKQl6JQcbovDpsSEn1XcdwhIzAXQiJGf2NIx5n0bZzVsQvER7F+p1tv5P1JFAPVjuZxDCi81II9FsgYJTy7CpZBIhI9bQu2X2DLb35whhK+S43/PIf6YMfPSfXNzfx1WP3ez/2ToDaxwySqdrxz5ghGInYudQaJ4jgFKkt8KXWhdFpGiE5td0C3XmMObobw1D2zkUqiFjME6K6hzTlA5hgIrPgEpEZ4jiEsgMTElBC2WpS0O/Jl4jPEJMjyDnBo1T0cTpW09ypJajty4FosVURO9dZZCiiCeJsKYbo9NTWqOT0dHteOO2c+acqY+Oyz201FKr8GuWzFxaIC+XCPo742x3pHrsjAFQdcS3TEdu3Nvhhv5sfruHHNcTpsTuRq7zUHJhO5G59jBO2YcS5If0rYsPJOCsSQ7yQBq2LHAR9byDW2D2Egp2qgsDeoOAGAcG76dc25EKRKHaqSRmP6YimkPSLaLeay8WYKyrTbhV8QpwvVeWGU06rkqMF5vfi2lLXD/JafKRmrd6i1NVb6kYq9nuvJ5CN0l2yWdy2aun7Kiz9FHhOxHZv0Fz8/kETmObGyn2/bKuQiU5ZiF7QUx1tOGQjxF/LWzNNGCKQ41l1HQc33TGg6TYZGsdvGDQueDM0T9NkrMenNEU1cFRC56GM1RaOCPyDSBeGz6PVTkpeDwL5eqlsHRAw8BkAAwZgwZsBOwRIbn5u1afbjlczSs4XSnWh5O6IklMnSuZJu9cElMBaTXLdumuSewwg7Xm2awhI3o4ggTpB8gyQ+o0AyW5eTbINYb5Q+iCU/B1RcutEyXwaN2gCSu76g7K6axLoGEIlpwzBkGOaHgNje577IjiJ8+XLxi3kHLF0FXEstzkYnr2toqmEPLFObfFTSUpbfbjvTKqa/ZZisYliCB0OJ2Jp6ymaL+L/s9b878dFE+g2C6Xv1lwoQXsD3yjC/BjY3rN+fh62Ozuy7dVZYs3KcdkECF3QvNOqZQhz/LQ1BCX9ILrZj1D0KkswfWsETO6HPdcXzeJLFdlBofhuCuj/Aw==</diagram></mxfile>
|
||||||
BIN
static/diagrams/threaded-dag-threads.png
Normal file
BIN
static/diagrams/threaded-dag-threads.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
1
static/diagrams/threaded-dag.drawio
Normal file
1
static/diagrams/threaded-dag.drawio
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<mxfile host="app.diagrams.net" modified="2022-09-27T03:11:43.523Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" etag="L_ujIRop4Jndk67DcTE9" version="14.6.7" type="device"><diagram id="_rQ0dgHO1UnHExDn0l7E" name="Page-1">7VpbU+IwFP41PMqkTS/wKDfdGXXcdWdXn5wsDTTaNkwIAvvrN6UJbYlCF1gbXcYZTU5P0ub0u6S1DdiNFxcMTcJrGuCoYYNg0YC9hm3bwLPFnzSyzCIW8NwsMmYkkLE8cEd+Y5UoozMS4GkpkVMacTIpB4c0SfCQl2KIMTovp41oVD7rBI2xFrgbokiP/iQBD7Noy/bz+CUm41Cd2fLa2ZEYqWS5kmmIAjovhGC/AbuMUp614kUXR2n1VF2ycYM3jq4vjOGEVxnww3ukD17wHF/f3IRXj52v/dA9k7O8oGgmF3wur5YvVQnmIeH4boKGaX8u7nMDdkIeR6JniSaaTrLCj8gCi3N15JSYcbx481qtdQUEdjCNMWdLkaIGQFk0BRtH9uf5PVApYaH8KobkXR+vZ84LIxqyNn9Tp5ZWFhwIoMguZTykY5qgqJ9HO4zOkiAtyapOec4VpRMZfMKcLyXq0YzTcmnxgvB70Qay/ZC2m67s9RaFQ72l6iRivfdqgrRTGJV282Grnho3ogkfoJhEaeA7iQXpbHCD5+L3NxqjZH1j03Vvv62iTHTGhnhLPaUscMTGmO/Cpw4ThiPEyUv5Oo5+022NHB0TyGED08jhn8hxTHLAiuSwayWHr7EjbvKQYRQcjIanWTxR+QlN8IEAadpuASNWNYSApu8WQWLtgEiApuF6AWnnFnGOWbKK2MAR0Qj9wlEHDZ/Hq+V2aUTZqkBw0E1/NoF2iaMXzMkQ1QOvWrUXaujqGqG9vmna2z5p7zHJ4VQkB6xVe52Po71F6QXVALIpvWAHQj6O9FZFV63OroOrZ4L0Qsc06XVP0ntMcrgVyeHUKr3ux5He/ba99ifd9laF13YVOgNNB/pSIitDbjXdOWNoWUiYUJLwaeFst2kgP5WjZpSCp577B2/kW7C1LV80sivYGK0uh45GU1GYTYKsS7A/Z3TK9E0wFMeCTdcwS3FOlnJMznsVOe/Wain6e0ZjLWWv3bz9SXfzVdF16G5+L/dwwYa27XAPG7S25Zfd41jO4GnIHxjhDG3THjXgyReOyVy/InO9Wn1BZ0fcFK4w5IQmRjvDf/+KvSq+Dn2LuJ8ztMrOoH04sOkMbbgt/984g/7fpQsTnME17v2/fZASgJMzlOvZrshcv1ZnAK84Aw4If7ddwrvq/puKXcEQpkIeSDL+vloMyAOi54LXbbCA8wp2UgP2an1abWvQuzRBmD3XNGG2tLKchPkAcqgPQneyo10nOyxdmb+YQA///T6oFN38o9ZsO5h/Gwz7fwA=</diagram></mxfile>
|
||||||
BIN
static/diagrams/threaded-dag.png
Normal file
BIN
static/diagrams/threaded-dag.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Loading…
Reference in a new issue