Merge branch 'main' into travis/ref-rel

This commit is contained in:
Travis Ralston 2022-09-26 14:40:55 -06:00
commit b65ad68361
29 changed files with 540 additions and 123 deletions

View file

@ -0,0 +1 @@
Add `m.replace` relations (event edits), as per [MSC2676](https://github.com/matrix-org/matrix-spec-proposals/pull/2676).

View file

@ -0,0 +1 @@
Fix various typos throughout the specification.

View file

@ -0,0 +1 @@
Add `m.read.private` receipts, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285).

View file

@ -0,0 +1 @@
Make `m.fully_read` optional on `/read_markers`, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285).

View file

@ -0,0 +1 @@
Allow `m.fully_read` markers to be set from `/receipts`, as per [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285).

View file

@ -0,0 +1 @@
Reinforce the relationship of refreshed access tokens to transaction IDs.

View file

@ -0,0 +1 @@
Fix various typos throughout the specification.

View file

@ -0,0 +1 @@
Clarify enum values by separating possible values with commas.

View file

@ -0,0 +1 @@
Fix various typos throughout the specification.

View file

@ -0,0 +1 @@
Fix the spacing of mapping types generated from the OpenAPI spec.

View file

@ -213,12 +213,19 @@ See the [Server Notices](#server-notices) module for more information.
The client-server API typically uses `HTTP PUT` to submit requests with
a client-generated transaction identifier. This means that these
requests are idempotent. The scope of a transaction identifier is a
particular access token. It **only** serves to identify new requests
requests are idempotent. It **only** serves to identify new requests
from retransmits. After the request has finished, the `{txnId}` value
should be changed (how is not specified; a monotonically increasing
integer is recommended).
The scope of a transaction ID is a "client session", where that session
is identified by a particular access token. When [refreshing](#refreshing-access-tokens)
an access token, the transaction ID's scope is retained. This means that
if a client with token `A` uses `TXN1` as their transaction ID, refreshes
the token to `B`, and uses `TXN1` again it'll be assumed to be a duplicate
request and ignored. If the client logs out and back in between the `A` and
`B` tokens, `TXN1` could be used once for each.
Some API endpoints may allow or require the use of `POST` requests
without a transaction ID. Where this is optional, the use of a `PUT`
request is strongly recommended.
@ -1955,16 +1962,6 @@ rooms, or the relationship missing properties required by the schema below. Clie
handling such invalid relationships should show the events independently of each
other, optionally with an error message.
{{% boxes/note %}}
While this specification describes an `m.relates_to` object containing a `rel_type`, there
is not currently any relationship type which uses this structure. Replies, described below,
form their relationship outside of the `rel_type` as a legacy type of relationship. Future
versions of the specification might change replies to better match the relationship structures.
Custom `rel_type`s can, and should, still use the schema described above for relevant
behaviour.
{{% /boxes/note %}}
`m.relates_to` is defined as follows:
{{% definition path="api/client-server/definitions/m.relates_to" %}}
@ -1974,6 +1971,7 @@ behaviour.
This specification describes the following relationship types:
* [Rich replies](#rich-replies) (**Note**: does not use `rel_type`).
* [Event replacements](#event-replacements).
* [References](#reference-relations)
#### Aggregations
@ -2644,4 +2642,5 @@ systems.
{{< cs-module name="server_notices" >}}
{{< cs-module name="moderation_policies" >}}
{{< cs-module name="spaces" >}}
{{< cs-module name="reference_relations" >}}
{{< cs-module name="event_replacements" >}}
{{< cs-module name="reference_relations" >}}

View file

@ -17,10 +17,10 @@ data with the same `type`.
#### Events
The client receives the account data as events in the `account_data`
sections of a `/sync`.
sections of a [`/sync`](#get_matrixclientv3sync) response.
These events can also be received in a `/events` response or in the
`account_data` section of a room in `/sync`. `m.tag` events appearing in
`account_data` section of a room in a `/sync` response. `m.tag` events appearing in
`/events` will have a `room_id` with the room the tags are for.
#### Client Behaviour

View file

@ -0,0 +1,330 @@
---
type: module
---
### Event replacements
{{% added-in v="1.4" %}}
Event replacements, or "message edit events", are events that use an [event
relationship](#forming-relationships-between-events)
with a `rel_type` of `m.replace`, which indicates that the original event is
intended to be replaced.
An example of a message edit event might look like this:
```json
{
"type": "m.room.message",
"content": {
"body": "* Hello! My name is bar",
"msgtype": "m.text",
"m.new_content": {
"body": "Hello! My name is bar",
"msgtype": "m.text"
},
"m.relates_to": {
"rel_type": "m.replace",
"event_id": "$some_event_id"
}
},
// ... other fields required by events
}
```
The `content` of the replacement must contain a `m.new_content` property which
defines the replacement `content`. The normal `content` properties (`body`,
`msgtype` etc.) provide a fallback for clients which do not understand
replacement events.
`m.new_content` can include any properties that would normally be found in
an event's content property, such as `formatted_body` (see [`m.room.message`
`msgtypes`](#mroommessage-msgtypes)).
#### Validity of replacement events
There are a number of requirements on replacement events, which must be satisfied for the replacement to be considered valid:
* As with all event relationships, the original event and replacement event
must have the same `room_id` (i.e. you cannot send an event in
one room and then an edited version in a different room).
* The original event and replacement event must have the same `sender`
(i.e. you cannot edit someone else's messages).
* The replacement and original events must have the same `type` (i.e. you
cannot change the original event's type).
* The replacement and original events must not have a `state_key` property
(i.e. you cannot edit state events at all).
* The original event must not, itself, have a `rel_type` of `m.replace`
(i.e. you cannot edit an edit — though you can send multiple edits for a
single original event).
* The replacement event (once decrypted, if appropriate) must have an
`m.new_content` property.
If any of these criteria are not satisfied, implementations should ignore the
replacement event (the content of the original should not be replaced, and the
edit should not be included in the server-side aggregation).
Note that the [`msgtype`](#mroommessage-msgtypes) property of replacement
`m.room.message` events does *not* need to be the same as in the original event. For
example, it is legitimate to replace an `m.text` event with an `m.emote`.
#### Editing encrypted events
If the original event was [encrypted](#end-to-end-encryption), the replacement
should be too. In that case, `m.new_content` is placed in the content of the
encrypted payload. As with all event relationships, the `m.relates_to` property
must be sent in the unencrypted (cleartext) part of the event.
For example, a replacement for an encrypted event might look like this:
```json
{
"type": "m.room.encrypted",
"content": {
"m.relates_to": {
"rel_type": "m.replace",
"event_id": "$some_event_id"
},
"algorithm": "m.megolm.v1.aes-sha2",
"sender_key": "<sender_curve25519_key>",
"device_id": "<sender_device_id>",
"session_id": "<outbound_group_session_id>",
"ciphertext": "<encrypted_payload_base_64>"
}
// irrelevant fields not shown
}
```
... and, once decrypted, the payload might look like this:
```json
{
"type": "m.room.<event_type>",
"room_id": "!some_room_id",
"content": {
"body": "* Hello! My name is bar",
"msgtype": "m.text",
"m.new_content": {
"body": "Hello! My name is bar",
"msgtype": "m.text"
}
}
}
```
Note that:
* There is no `m.relates_to` property in the encrypted payload. If there was, it would be ignored.
* There is no `m.new_content` property in the cleartext content of the `m.room.encrypted` event. As above, if there was then it would be ignored.
{{% boxes/note %}}
The payload of an encrypted replacement event must be encrypted as normal, including
ratcheting any [Megolm](#mmegolmv1aes-sha2) session as normal. The original Megolm
ratchet entry should **not** be re-used.
{{% /boxes/note %}}
#### Applying `m.new_content`
When applying a replacement, the `content` of the original event is treated as
being overwritten entirely by `m.new_content`, with the exception of `m.relates_to`,
which is left *unchanged*. Any `m.relates_to` property within `m.new_content`
is ignored.
{{% boxes/note %}}
Note that server implementations must not *actually* overwrite
the original event's `content`: instead the server presents it as being overwritten
when it is served over the client-server API. See [Server-side replacement of content](#server-side-replacement-of-content)
below.
{{% /boxes/note %}}
For example, given a pair of events:
```json
{
"event_id": "$original_event",
"type": "m.room.message",
"content": {
"body": "I really like cake",
"msgtype": "m.text",
"formatted_body": "I really like cake",
}
}
```
```json
{
"event_id": "$edit_event",
"type": "m.room.message",
"content": {
"body": "* I really like *chocolate* cake",
"msgtype": "m.text",
"m.new_content": {
"body": "I really like *chocolate* cake",
"msgtype": "m.text",
"com.example.extension_property": "chocolate"
},
"m.relates_to": {
"rel_type": "m.replace",
"event_id": "$original_event_id"
}
}
}
```
... then the end result is an event as shown below:
```json
{
"event_id": "$original_event",
"type": "m.room.message",
"content": {
"body": "I really like *chocolate* cake",
"msgtype": "m.text",
"com.example.extension_property": "chocolate"
}
}
```
Note that `formatted_body` is now absent, because it was absent in the
replacement event.
#### Server behaviour
##### Server-side aggregation of `m.replace` relationships
Note that there can be multiple events with an `m.replace` relationship to a
given event (for example, if an event is edited multiple times). These should
be [aggregated](#aggregations) by the homeserver.
The aggregation format of `m.replace` relationships gives the `event_id`,
`origin_server_ts`, and `sender` of the **most recent** replacement event. The
most recent event is determined by comparing `origin_server_ts`; if two or more
replacement events have identical `origin_server_ts`, the event with the
lexicographically largest `event_id` is treated as more recent.
This aggregation is bundled under the `unsigned` property as `m.relations` for any
event that is the target of an `m.replace` relationship. For example:
```json
{
"event_id": "$original_event_id",
// irrelevant fields not shown
"unsigned": {
"m.relations": {
"m.replace": {
"event_id": "$latest_edit_event_id",
"origin_server_ts": 1649772304313,
"sender": "@editing_user:localhost"
}
}
}
}
```
If the original event is
[redacted](#redactions), any
`m.replace` relationship should **not** be bundled with it (whether or not any
subsequent replacements are themselves redacted). Note that this behaviour is
specific to the `m.replace` relationship. See also [redactions of edited
events](#redactions-of-edited-events) below.
##### Server-side replacement of content
Whenever an `m.replace` is to be bundled with an event as above, the server
should also modify the content of the original event according to the
`m.new_content` of the most recent replacement event (determined as above).
An exception applies to [`GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}`](#get_matrixclientv3roomsroomideventeventid),
which should return the unmodified event (though the relationship should still
be bundled, as described above).
#### Client behaviour
Clients can often ignore `m.replace` events, because any events returned
by the server to the client will be updated by the server to account for
subsequent edits.
However, clients should apply the replacement themselves when the server is
unable to do so. This happens in the following situations:
* The client has already received and stored the original event before the
message edit event arrives.
* The original event (and hence its replacement) are encrypted.
Client authors are reminded to take note of the requirements for [Validity of
message edit events](#validity-of-message-edit-events), and to ignore any
invalid edit events that are received.
##### Permalinks
When creating [links](/appendices/#uris) to events (also known as permalinks),
clients build links which reference the event that the creator of the permalink
is viewing at that point (which might be a message edit event).
The client viewing the permalink should resolve this reference to the original
event, and then display the most recent version of that event.
#### Redactions of edited events
When an event using a `rel_type` of `m.replace` is [redacted](#redactions), it
removes that edit revision. This has little effect if there were subsequent
edits. However, if it was the most recent edit, the event is in effect
reverted to its content before the redacted edit.
Redacting the *original* message in effect removes the message, including all
subsequent edits, from the visible timeline. In this situation, homeservers
will return an empty `content` for the original event as with any other
redacted event, and as
[above](#server-side-aggregation-of-mreplace-relationships) the replacement
events will not be bundled with the original event. Note that the subsequent edits are
not actually redacted themselves: they simply serve no purpose within the visible timeline.
#### Edits of replies
Some particular constraints apply to events which replace a
[reply](#rich-replies). In particular:
* In contrast to the original reply, there should be no `m.in_reply_to`
property in the the `m.relates_to` object, since it would be redundant (see
[Applying `m.new_content`](#applying-mnew_content) above, which notes that
the original event's `m.relates_to` is preserved), as well as being contrary
to the spirit of the event relationships mechanism which expects only one
"parent" per event.
* `m.new_content` should **not** contain any [reply
fallback](#fallbacks-for-rich-replies),
since it is assumed that any client which can handle edits can also display
replies natively. However, the `content` of the replacement event should provide
fallback content for clients which support neither rich replies nor edits.
An example of an edit to a reply is as follows:
```json
{
"type": "m.room.message",
// irrelevant fields not shown
"content": {
"body": "> <@alice:example.org> question\n\n* reply",
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"formatted_body": "<mx-reply><blockquote><a href=\"https://matrix.to/#/!somewhere:example.org/$event:example.org\">In reply to</a> <a href=\"https://matrix.to/#/@alice:example.org\">@alice:example.org</a><br />question</blockquote></mx-reply>* reply",
"m.new_content": {
"body": "reply",
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"formatted_body": "reply"
},
"m.relates_to": {
"rel_type": "m.replace",
"event_id": "$original_reply_event"
}
}
}
```

View file

@ -107,7 +107,19 @@ determined by the push rules which apply to an event.
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
be marked as read.
be marked as read. 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
the receipt which is more recent/ahead must be used to determine where
the user has read up to. For example, given an oldest-first set of events A,
B, C, and D the `m.read` receipt could be at event C and `m.read.private`
at event A - the user is considered to have read up to event C. If the
`m.read.private` receipt is then updated to point to B or C, the user's
notification state doesn't change (the `m.read` receipt is still more
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
behind the `m.read.private` receipt).
##### Push Rules
@ -768,7 +780,7 @@ per-device using the APIs below.
##### Push Rules: Events
When a user changes their push rules a `m.push_rules` event is sent to
all clients in the `account_data` section of their next `/sync` request.
all clients in the `account_data` section of their next [`/sync`](#get_matrixclientv3sync) request.
The content of the event is the current push rules for the user.
{{% event event="m.push_rules" %}}

View file

@ -31,12 +31,16 @@ The client cannot update fully read markers by directly modifying the
`m.fully_read` account data event. Instead, the client must make use of
the read markers API to change the values.
{{< changed-in v="1.4" >}} `m.read.private` receipts can now be sent from
`/read_markers`.
The read markers API can additionally update the user's read receipt
(`m.read`) location in the same operation as setting the fully read
marker location. This is because read receipts and read markers are
commonly updated at the same time, and therefore the client might wish
to save an extra HTTP call. Providing an `m.read` location performs the
same task as a request to `/receipt/m.read/$event:example.org`.
(`m.read` or `m.read.private`) location in the same operation as setting
the fully read marker location. This is because read receipts and read
markers are commonly updated at the same time, and therefore the client
might wish to save an extra HTTP call. Providing `m.read` and/or
`m.read.private` performs the same task as a request to
[`/receipt/{receiptType}/{eventId}`](#post_matrixclientv3roomsroomidreceiptreceipttypeeventid).
{{% http-api spec="client-server" api="read_markers" %}}
@ -44,8 +48,9 @@ same task as a request to `/receipt/m.read/$event:example.org`.
The server MUST prevent clients from setting `m.fully_read` directly in
room account data. The server must additionally ensure that it treats
the presence of `m.read` in the `/read_markers` request the same as how
it would for a request to `/receipt/m.read/$event:example.org`.
the presence of `m.read` and `m.read.private` in the `/read_markers`
request the same as how it would for a request to
[`/receipt/{receiptType}/{eventId}`](#post_matrixclientv3roomsroomidreceiptreceipttypeeventid).
Upon updating the `m.fully_read` event due to a request to
`/read_markers`, the server MUST send the updated account data event

View file

@ -4,10 +4,14 @@ type: module
### Receipts
{{< changed-in v="1.4" >}} Added private read receipts.
This module adds in support for receipts. These receipts are a form of
acknowledgement of an event. This module defines a single
acknowledgement: `m.read` which indicates that the user has read up to a
given event.
acknowledgement of an event. This module defines the `m.read` receipt
for indicating that the user has read up to a given event, and `m.read.private`
to achieve the same purpose without any other user being aware. Primarily,
`m.read.private` is intended to clear [notifications](#receiving-notifications)
without advertising read-up-to status to others.
Sending a receipt for each event can result in sending large amounts of
traffic to a homeserver. To prevent this from becoming a problem,
@ -59,12 +63,36 @@ following HTTP APIs.
{{% http-api spec="client-server" api="receipts" %}}
##### Private read receipts
{{% added-in v="1.4" %}}
Some users would like to mark a room as read, clearing their [notification counts](#receiving-notifications),
but not give away the fact that they've read a particular message yet. To
achieve this, clients can send `m.read.private` receipts instead of `m.read`
to do exactly that: clear notifications and not broadcast the receipt to
other users.
Servers MUST NOT send the `m.read.private` receipt to any other user than the
one which originally sent it.
Between `m.read` and `m.read.private`, the receipt which is more "ahead" or
"recent" is used when determining the highest read-up-to mark. See the
[notifications](#receiving-notifications) section for more information on
how this affects notification counts.
If a client sends an `m.read` receipt which is "behind" the `m.read.private`
receipt, other users will see that change happen but the sending user will
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
several messages behind the `m.read.private` receipt, for example.
#### Server behaviour
For efficiency, receipts SHOULD be batched into one event per room
before delivering them to clients.
Receipts are sent across federation as EDUs with type `m.receipt`. The
Some receipts are sent across federation as EDUs with type `m.receipt`. The
format of the EDUs are:
```
@ -80,7 +108,8 @@ format of the EDUs are:
```
These are always sent as deltas to previously sent receipts. Currently
only a single `<receipt_type>` should be used: `m.read`.
only a single `<receipt_type>` should be used: `m.read`. `m.read.private`
MUST NOT appear in this federated `m.receipt` EDU.
#### Security considerations

View file

@ -30,7 +30,7 @@ clients can access, depending on what keys are given to them.
##### Key storage
Each key has an ID, and the description of the key is stored in the
user's account\_data using the event type
user's account data using the event type
`m.secret_storage.key.[key ID]`. The contents of the account data for
the key will include an `algorithm` property, which indicates the
encryption algorithm used, as well as a `name` property, which is a
@ -51,7 +51,7 @@ Other properties depend on the encryption algorithm, and are described
below.
A key can be marked as the "default" key by setting the user's
account\_data with event type `m.secret_storage.default_key` to an
account data with event type `m.secret_storage.default_key` to an
object that has the ID of the key as its `key` property. The default key
will be used to encrypt all secrets that the user would expect to be
available on all their clients. Unless the user specifies otherwise,
@ -71,8 +71,8 @@ default key.
##### Secret storage
Encrypted data is stored in the user's account\_data using the event
type defined by the feature that uses the data. The account\_data will
Encrypted data is stored in the user's account data using the event
type defined by the feature that uses the data. The account data will
have an `encrypted` property that is a map from key ID to an object. The
algorithm from the `m.secret_storage.key.[key ID]` data for the given
key defines how the other properties are interpreted, though it's

View file

@ -29,11 +29,12 @@ securityDefinitions:
paths:
"/user/{userId}/account_data/{type}":
put:
summary: Set some account_data for the user.
summary: Set some account data for the user.
description: |-
Set some account_data for the client. This config is only visible to the user
that set the account_data. The config will be synced to clients in the
top-level `account_data`.
Set some account data for the client. This config is only visible to the user
that set the account data. The config will be available to clients through the
top-level `account_data` field in the homeserver response to
[/sync](#get_matrixclientv3sync).
operationId: setAccountData
security:
- accessToken: []
@ -43,7 +44,7 @@ paths:
name: userId
required: true
description: |-
The ID of the user to set account_data for. The access token must be
The ID of the user to set account data for. The access token must be
authorized to make requests for this user ID.
x-example: "@alice:example.com"
- in: path
@ -51,14 +52,14 @@ paths:
name: type
required: true
description: |-
The event type of the account_data to set. Custom types should be
The event type of the account data to set. Custom types should be
namespaced to avoid clashes.
x-example: "org.example.custom.config"
- in: body
name: content
required: true
description: |-
The content of the account_data
The content of the account data.
schema:
type: object
example: {
@ -66,7 +67,7 @@ paths:
responses:
200:
description:
The account_data was successfully added.
The account data was successfully added.
examples:
application/json: {}
schema:
@ -107,10 +108,10 @@ paths:
tags:
- User data
get:
summary: Get some account_data for the user.
summary: Get some account data for the user.
description: |-
Get some account_data for the client. This config is only visible to the user
that set the account_data.
Get some account data for the client. This config is only visible to the user
that set the account data.
operationId: getAccountData
security:
- accessToken: []
@ -120,7 +121,7 @@ paths:
name: userId
required: true
description: |-
The ID of the user to get account_data for. The access token must be
The ID of the user to get account data for. The access token must be
authorized to make requests for this user ID.
x-example: "@alice:example.com"
- in: path
@ -128,7 +129,7 @@ paths:
name: type
required: true
description: |-
The event type of the account_data to get. Custom types should be
The event type of the account data to get. Custom types should be
namespaced to avoid clashes.
x-example: "org.example.custom.config"
responses:
@ -157,7 +158,7 @@ paths:
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "Room account data not found."
"error": "Account data not found."
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
@ -165,11 +166,11 @@ paths:
- User data
"/user/{userId}/rooms/{roomId}/account_data/{type}":
put:
summary: Set some account_data for the user that is specific to a room.
summary: Set some account data for the user that is specific to a room.
description: |-
Set some account_data for the client on a given room. This config is only
visible to the user that set the account_data. The config will be synced to
clients in the per-room `account_data`.
Set some account data for the client on a given room. This config is only
visible to the user that set the account data. The config will be delivered to
clients in the per-room entries via [/sync](#get_matrixclientv3sync).
operationId: setAccountDataPerRoom
security:
- accessToken: []
@ -179,7 +180,7 @@ paths:
name: userId
required: true
description: |-
The ID of the user to set account_data for. The access token must be
The ID of the user to set account data for. The access token must be
authorized to make requests for this user ID.
x-example: "@alice:example.com"
- in: path
@ -187,21 +188,21 @@ paths:
name: roomId
required: true
description: |-
The ID of the room to set account_data on.
The ID of the room to set account data on.
x-example: "!726s6s6q:example.com"
- in: path
type: string
name: type
required: true
description: |-
The event type of the account_data to set. Custom types should be
The event type of the account data to set. Custom types should be
namespaced to avoid clashes.
x-example: "org.example.custom.room.config"
- in: body
name: content
required: true
description: |-
The content of the account_data
The content of the account data.
schema:
type: object
example: {
@ -209,7 +210,7 @@ paths:
responses:
200:
description:
The account_data was successfully added.
The account data was successfully added.
examples:
application/json: {}
schema:
@ -251,10 +252,10 @@ paths:
tags:
- User data
get:
summary: Get some account_data for the user that is specific to a room.
summary: Get some account data for the user that is specific to a room.
description: |-
Get some account_data for the client on a given room. This config is only
visible to the user that set the account_data.
Get some account data for the client on a given room. This config is only
visible to the user that set the account data.
operationId: getAccountDataPerRoom
security:
- accessToken: []
@ -264,7 +265,7 @@ paths:
name: userId
required: true
description: |-
The ID of the user to set account_data for. The access token must be
The ID of the user to get account data for. The access token must be
authorized to make requests for this user ID.
x-example: "@alice:example.com"
- in: path
@ -272,14 +273,14 @@ paths:
name: roomId
required: true
description: |-
The ID of the room to get account_data for.
The ID of the room to get account data for.
x-example: "!726s6s6q:example.com"
- in: path
type: string
name: type
required: true
description: |-
The event type of the account_data to get. Custom types should be
The event type of the account data to get. Custom types should be
namespaced to avoid clashes.
x-example: "org.example.custom.room.config"
responses:

View file

@ -94,7 +94,7 @@ properties:
}
transaction_id:
description: |
The client-supplied transaction ID, for example, provided via
The client-supplied [transaction ID](/client-server-api/#transaction-identifiers), for example, provided via
`PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`,
if the client being given the event is the same one which sent it.
type: string

View file

@ -111,7 +111,7 @@ paths:
post:
summary: Start the requesting user participating in a particular room.
description: |-
*Note that this API takes either a room ID or alias, unlike* `/room/{roomId}/join`.
*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.
This API starts a user participating in a particular room, if that user
is allowed to participate in that room. After this call, the client is

View file

@ -195,7 +195,7 @@ paths:
x-example: "@alice:example.com"
responses:
200:
description: The avatar URL for this user.
description: The profile information for this user.
examples:
application/json: {
"avatar_url": "mxc://matrix.org/SDGdghriugerRg",

View file

@ -1,4 +1,5 @@
# Copyright 2018 New Vector Ltd
# Copyright 2022 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -56,6 +57,9 @@ paths:
The event ID the read marker should be located at. The
event MUST belong to the room.
example: "$somewhere:example.org"
x-changedInMatrixVersion:
1.4: |
This property is no longer required.
"m.read":
type: string
description: |-
@ -63,11 +67,18 @@ paths:
equivalent to calling `/receipt/m.read/$elsewhere:example.org`
and is provided here to save that extra call.
example: "$elsewhere:example.org"
required: ['m.fully_read']
"m.read.private":
x-addedInMatrixVersion: "1.4"
type: string
description: |-
The event ID to set the *private* read receipt location at. This
equivalent to calling `/receipt/m.read.private/$elsewhere:example.org`
and is provided here to save that extra call.
example: "$elsewhere:example.org"
responses:
200:
description: |-
The read marker, and read receipt if provided, have been updated.
The read marker, and read receipt(s) if provided, have been updated.
schema:
type: object
properties: {}

View file

@ -1,4 +1,5 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2022 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -46,10 +47,19 @@ paths:
- in: path
type: string
name: receiptType
description: The type of receipt to send.
description: |-
The type of receipt to send. This can also be `m.fully_read` as an
alternative to [`/read_makers`](/client-server-api/#post_matrixclientv3roomsroomidread_markers).
Note that `m.fully_read` does not appear under `m.receipt`: this endpoint
effectively calls `/read_markers` internally when presented with a receipt
type of `m.fully_read`.
required: true
x-example: "m.read"
enum: ["m.read"]
x-changedInMatrixVersion:
1.4: |
Allow `m.read.private` receipts and `m.fully_read` markers to be set.
enum: ["m.read", "m.read.private", "m.fully_read"]
- in: path
type: string
name: eventId

View file

@ -62,7 +62,7 @@ paths:
name: txnId
type: string
description: |-
The transaction ID for this event. Clients should generate a
The [transaction ID](/client-server-api/#transaction-identifiers) for this event. Clients should generate a
unique ID; it will be used by the server to ensure idempotency of requests.
required: true
x-example: "37"

View file

@ -58,7 +58,7 @@ paths:
name: txnId
type: string
description: |-
The transaction ID for this event. Clients should generate an
The [transaction ID](/client-server-api/#transaction-identifiers) for this event. Clients should generate an
ID unique across requests with the same access token; it will be
used by the server to ensure idempotency of requests.
required: true

View file

@ -48,7 +48,7 @@ paths:
name: txnId
type: string
description: |-
The transaction ID for this event. Clients should generate an
The [transaction ID](/client-server-api/#transaction-identifiers) for this event. Clients should generate an
ID unique across requests with the same access token; it will be
used by the server to ensure idempotency of requests.
required: true

View file

@ -7,6 +7,11 @@
"@rikj:jki.re": {
"ts": 1436451550453
}
},
"m.read.private": {
"@self:example.org": {
"ts": 1661384801651
}
}
}
}

View file

@ -1,49 +1,54 @@
{
"type": "object",
"title": "Receipt Event",
"description": "Informs the client of new receipts.",
"allOf": [{
"$ref": "core-event-schema/event.yaml"
}],
"properties": {
"content": {
"type": "object",
"patternProperties": {
"^\\$": {
"type": "object",
"x-pattern": "$EVENT_ID",
"title": "Receipts",
"description": "The mapping of event ID to a collection of receipts for this event ID. The event ID is the ID of the event being acknowledged and *not* an ID for the receipt itself.",
"properties": {
"m.read": {
"type": "object",
"title": "Users",
"description": "A collection of users who have sent `m.read` receipts for this event.",
"patternProperties": {
"^@": {
"type": "object",
"title": "Receipt",
"description": "The mapping of user ID to receipt. The user ID is the entity who sent this receipt.",
"x-pattern": "$USER_ID",
"properties": {
"ts": {
"type": "integer",
"format": "int64",
"description": "The timestamp the receipt was sent at."
}
}
}
}
}
}
}
},
"additionalProperties": false
},
"type": {
"type": "string",
"enum": ["m.receipt"]
}
},
"required": ["type", "content"]
}
type: object
title: Receipt Event
description: Informs the client of new receipts.
x-changedInMatrixVersion:
1.4: |
Added `m.read.private` receipts to the event's `content`.
allOf:
- $ref: "core-event-schema/event.yaml"
properties:
content:
type: object
patternProperties:
"^\\$":
type: object
x-pattern: "$EVENT_ID"
title: Receipts
description: |-
The mapping of event ID to a collection of receipts for this
event ID. The event ID is the ID of the event being acknowledged
and *not* an ID for the receipt itself.
properties:
"m.read":
type: object
title: Users
description: |-
A collection of users who have sent `m.read` receipts for
this event.
patternProperties:
"^@": &receiptUserMap
type: object
title: Receipt
description: |-
The mapping of user ID to receipt. The user ID is the
entity who sent this receipt.
x-pattern: "$USER_ID"
properties:
ts:
type: integer
format: int64
description: The timestamp the receipt was sent at.
"m.read.private":
type: object
title: Own User
description: |-
Similar to `m.read`, the users who have sent `m.read.private`
receipts for this event. Due to the nature of private read
receipts, this should only ever have the current user's ID.
patternProperties:
"^@": *receiptUserMap
additionalProperties: false
type:
type: string
enum: ["m.receipt", "m.receipt.private"]
required: ["type", "content"]

View file

@ -73,7 +73,7 @@
*/}}
{{ if reflect.IsMap $property.additionalProperties }}
{{ if $property.additionalProperties.title }}
{{ $type = delimit (slice "{ string: " $property.additionalProperties.title "}" ) "" }}
{{ $type = delimit (slice "{string: " $property.additionalProperties.title "}" ) "" }}
{{ end }}
{{ end }}
@ -89,7 +89,7 @@
<td>
{{ if $required }}<strong>Required: </strong>{{end -}}
{{ $property.description | markdownify -}}
{{ if eq $type "enum"}}<p>One of: <code>{{ $property.enum }}</code>.</p>{{ end -}}
{{ if eq $type "enum"}}<p>One of: <code>[{{ delimit $property.enum ", " }}]</code>.</p>{{ end -}}
{{ if (index $property "x-addedInMatrixVersion") }}{{ partial "added-in" (dict "v" (index $property "x-addedInMatrixVersion")) }}{{ end -}}
{{ if (index $property "x-changedInMatrixVersion") }}{{ partial "changed-in" (dict "changes_dict" (index $property "x-changedInMatrixVersion")) }}{{ end -}}
</td>