Compare commits

..

4 commits

Author SHA1 Message Date
Johannes Marbach 7b3083885b Fix example 2025-03-31 14:27:09 +02:00
Johannes Marbach a96aeb5882 Fix indentation 2025-03-31 14:25:45 +02:00
Johannes Marbach 54842585db Add changelog 2025-03-31 14:22:49 +02:00
Johannes Marbach cbcbde8f3c Spec for MSC3266: Room Summary API
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
2025-03-31 14:13:08 +02:00
74 changed files with 431 additions and 870 deletions

View file

@ -2,7 +2,6 @@ name: "Spec"
env: env:
HUGO_VERSION: 0.139.0 HUGO_VERSION: 0.139.0
PYTHON_VERSION: 3.13
on: on:
push: push:
@ -41,7 +40,7 @@ jobs:
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: '3.9'
cache: 'pip' cache: 'pip'
cache-dependency-path: scripts/requirements.txt cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies" - name: " Install dependencies"
@ -60,7 +59,7 @@ jobs:
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: '3.9'
cache: 'pip' cache: 'pip'
cache-dependency-path: scripts/requirements.txt cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies" - name: " Install dependencies"
@ -79,7 +78,7 @@ jobs:
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: '3.9'
cache: 'pip' cache: 'pip'
cache-dependency-path: scripts/requirements.txt cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies" - name: " Install dependencies"
@ -121,7 +120,7 @@ jobs:
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: '3.9'
cache: 'pip' cache: 'pip'
cache-dependency-path: scripts/requirements.txt cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies" - name: " Install dependencies"
@ -173,7 +172,7 @@ jobs:
- name: " Setup Python" - name: " Setup Python"
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: '3.9'
- name: " Install towncrier" - name: " Install towncrier"
run: "pip install 'towncrier'" run: "pip install 'towncrier'"
- name: "Generate changelog" - name: "Generate changelog"
@ -284,11 +283,10 @@ jobs:
npm i npm i
npm run get-proposals npm run get-proposals
- name: "⚙️ hugo" - name: "⚙️ hugo"
env:
HUGO_PARAMS_VERSION_STATUS: "historical"
# Create a baseURL like `/v1.2` out of the `v1.2` tag # Create a baseURL like `/v1.2` out of the `v1.2` tag
run: | run: |
hugo --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec" echo -e '[params.version]\nstatus="historical"' > historical.toml
hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec"
- name: "📥 Spec definition download" - name: "📥 Spec definition download"
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4

View file

@ -316,19 +316,13 @@ Custom SCSS for the Matrix spec
h2 { h2 {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
font-size: 1.3rem; font-size: 1.3rem;
margin: 1.5rem 0 1rem 0; margin: 3rem 0 .5rem 0;
} }
h3 { h3 {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
font-size: 1.1rem; font-size: 1.1rem;
margin: 1.5rem 0 1rem 0; margin: 1.5rem 0 .75rem 0;
}
/* Reduce top margin of h3 if previous sibling is a h2 */
h2 + h3 {
margin-top: 1rem;
} }
hr { hr {
@ -373,6 +367,11 @@ Custom SCSS for the Matrix spec
} }
} }
// add some space between two tables when they are right next to each other
& + table {
margin-top: 4rem;
}
caption { caption {
caption-side: top; caption-side: top;
color: $dark; color: $dark;
@ -444,17 +443,6 @@ Custom SCSS for the Matrix spec
} }
} }
/* Have consistent spacing around tables and examples */
table, .highlight {
margin-top: 0;
margin-bottom: 2rem;
/* We don't need the margin on the last child of the .rendered-data block */
&:last-child {
margin-bottom: 0;
}
}
pre { pre {
border: 0; border: 0;
border-left: solid 5px $secondary; border-left: solid 5px $secondary;

View file

@ -1 +0,0 @@
Correct null value handling for the AS Registration's `url` property.

View file

@ -1 +0,0 @@
Clarify behaviour when the `topic` key of a `m.room.topic` event is absent, null, or empty.

View file

@ -1 +0,0 @@
Fix the example of the `GET /sync` endpoint and the `m.room.member` example used in several places.

View file

@ -1,2 +0,0 @@
Clarify the format of third-party invites, including the fact that identity
server public keys can be encoded using standard or URL-safe base64.

View file

@ -1 +0,0 @@
Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765).

View file

@ -1 +0,0 @@
"Public" rooms in profile look-ups are defined through their join rule and history visibility.

View file

@ -1 +0,0 @@
"Public" rooms in user directory queries are defined through their join rule and history visibility.

View file

@ -1 +0,0 @@
Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility.

View file

@ -1 +0,0 @@
"Public" rooms with respect to call invites are defined through their join rule.

View file

@ -1 +0,0 @@
"Public" rooms have no specific meaning with respect to moderation policy lists.

View file

@ -1 +0,0 @@
"Public" rooms with respect to presence are defined through their join rule.

View file

@ -1 +0,0 @@
Spaces are subject to the same access mechanisms as rooms.

View file

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

View file

@ -1 +0,0 @@
Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147).

View file

@ -1 +0,0 @@
Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks.

View file

@ -1 +0,0 @@
Fix typo: as->has.

View file

@ -1 +0,0 @@
Clarify that public keys can be encoded using standard or URL-safe base64.

View file

@ -1 +0,0 @@
Adjust margins in rendered endpoints.

View file

@ -1 +0,0 @@
Replace Hugo shortcodes in OpenAPI output.

View file

@ -1 +0,0 @@
Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks.

View file

@ -1 +0,0 @@
Fix the historical info box when generating the historical spec in CI.

View file

@ -1 +0,0 @@
Update the header navigation menu with links to modern matrix.org. Contributed by @HarHarLinks.

View file

@ -1 +0,0 @@
Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room.

View file

@ -1,2 +0,0 @@
Clarify the format of third-party invites, including the fact that identity
server public keys can be encoded using standard or URL-safe base64.

View file

@ -1 +0,0 @@
Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765).

View file

@ -1 +0,0 @@
Clarify that auth event of `content.join_authorised_via_users_server` is only necessary for `m.room.member` with a `membership` of `join`.

View file

@ -1 +0,0 @@
Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility.

View file

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

View file

@ -1 +0,0 @@
Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks.

View file

@ -23,15 +23,15 @@ description = "Home of the Matrix specification for decentralised communication"
[menus] [menus]
[[menus.main]] [[menus.main]]
name = 'Foundation' name = 'Foundation'
url = 'https://matrix.org/foundation/about/' url = 'https://matrix.org/foundation/'
weight = 10 weight = 10
[[menus.main]] [[menus.main]]
name = 'User Docs' name = 'FAQs'
url = 'https://matrix.org/docs/' url = 'https://matrix.org/faq'
weight = 20 weight = 20
[[menus.main]] [[menus.main]]
name = 'Blog' name = 'Blog'
url = 'https://matrix.org/blog/' url = 'https://matrix.org/blog/posts'
weight = 30 weight = 30
[markup] [markup]

View file

@ -492,10 +492,10 @@ via the query string). It is expected that the application service use
the transactions pushed to it to handle events rather than syncing with the transactions pushed to it to handle events rather than syncing with
the user implied by `sender_localpart`. the user implied by `sender_localpart`.
#### Published room directories #### Application service room directories
Application services can maintain their own published room directories for Application services can maintain their own room directories for their
their defined third-party protocols. These directories may be accessed by defined third-party protocols. These room directories may be accessed by
clients through additional parameters on the `/publicRooms` clients through additional parameters on the `/publicRooms`
client-server endpoint. client-server endpoint.

View file

@ -371,23 +371,15 @@ valid data was obtained, but no server is available to serve the client.
No further guess should be attempted and the user should make a No further guess should be attempted and the user should make a
conscientious decision what to do next. conscientious decision what to do next.
### Well-known URIs ### Well-known URI
Matrix facilitates automatic discovery for the Client-Server API base URL and more via the
[RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615) "Well-Known URI" method.
This method uses JSON files at a predetermined location on the root path `/.well-known/` to
specify parameter values.
{{% boxes/note %}} {{% boxes/note %}}
Diverging from the rest of the endpoints in the Client-Server spec, these files can not be provided
on the base URL that the Client-Server API is reachable on, as it is yet to be discovered.
Instead, they can be reached via HTTPS on the [server name](/appendices/#server-name)'s hostname as domain.
Servers hosting the `.well-known` JSON file SHOULD offer CORS headers, Servers hosting the `.well-known` JSON file SHOULD offer CORS headers,
as per the [CORS](#web-browser-clients) section in this specification. as per the [CORS](#web-browser-clients) section in this specification.
{{% /boxes/note %}} {{% /boxes/note %}}
The flow for auto-discovery is as follows: The `.well-known` method uses a JSON file at a predetermined location to
specify parameter values. The flow for this method is as follows:
1. Extract the [server name](/appendices/#server-name) from the user's Matrix ID by splitting the 1. Extract the [server name](/appendices/#server-name) from the user's Matrix ID by splitting the
Matrix ID at the first colon. Matrix ID at the first colon.
@ -423,17 +415,10 @@ The flow for auto-discovery is as follows:
{{% http-api spec="client-server" api="wellknown" %}} {{% http-api spec="client-server" api="wellknown" %}}
{{% http-api spec="client-server" api="support" %}}
### API Versions
Upon connecting, the Matrix client and server need to negotiate which version of the specification
they commonly support, as the API evolves over time. The server advertises its supported versions
and optionally unstable features to the client, which can then go on to make requests to the
endpoints it supports.
{{% http-api spec="client-server" api="versions" %}} {{% http-api spec="client-server" api="versions" %}}
{{% http-api spec="client-server" api="support" %}}
## Client Authentication ## Client Authentication
Most API endpoints require the user to identify themselves by presenting Most API endpoints require the user to identify themselves by presenting
@ -2846,35 +2831,7 @@ re-invited.
{{% http-api spec="client-server" api="banning" %}} {{% http-api spec="client-server" api="banning" %}}
### Published room directory ### Listing rooms
Homeservers MAY publish a room directory to allow users to discover rooms. A room
can have one of two visibility settings in the directory:
- `public`: The room will be shown in the published room directory.
- `private`: The room will be hidden from the published room directory.
Clients can define a room's initial visibility in the directory via the `visibility`
parameter in [`/createRoom`](#post_matrixclientv3createroom). Irrespective of room
creation, clients can query and change a room's visibility in the directory through
the endpoints listed below, provided that the server permits this.
{{% boxes/warning %}}
The visibility setting merely defines whether a room is included in the published
room directory or not. It doesn't make any guarantees about the room's
[join rule](#mroomjoin_rules) or [history visibility](#room-history-visibility).
In particular, a visibility setting of `public` should not be confused with a `public`
join rule. Rooms with a join rule of `knock`, for instance, could reasonably be published
in the directory, too.
Similarly, a visibility setting of `public` does not necessarily imply a `world_readable`
history visibility.
To increase performance or by preference, servers MAY apply additional filters when listing the
directory, for instance, by automatically excluding rooms with `invite` join rules
that are not `world_readable` regardless of their visibility.
{{% /boxes/warning %}}
{{% http-api spec="client-server" api="list_public_rooms" %}} {{% http-api spec="client-server" api="list_public_rooms" %}}
@ -2894,15 +2851,10 @@ that are not `world_readable` regardless of their visibility.
#### Server behaviour #### Server behaviour
Homeservers MUST at a minimum allow profile look-up for users who are Homeservers MUST at a minimum allow profile look-up for:
visible to the requester based on their membership in rooms known to the
homeserver. This means:
- users that share a room with the requesting user - users that share a room with the requesting user
- users who are joined to rooms known to the homeserver that have a - users that reside in public rooms known to the homeserver
`public` [join rule](#mroomjoin_rules)
- users who are joined to rooms known to the homeserver that have a
`world_readable` [history visibility](#room-history-visibility)
In all other cases, homeservers MAY deny profile look-up by responding with In all other cases, homeservers MAY deny profile look-up by responding with
403 and an error code of `M_FORBIDDEN`. 403 and an error code of `M_FORBIDDEN`.

View file

@ -528,7 +528,7 @@ messages, Alice only sends one request event (an event with type
`m.room.message` with `msgtype: m.key.verification.request`, rather than an `m.room.message` with `msgtype: m.key.verification.request`, rather than an
event with type `m.key.verification.request`), to the room. In addition, Alice event with type `m.key.verification.request`), to the room. In addition, Alice
does not send an `m.key.verification.cancel` event to tell Bob's other devices does not send an `m.key.verification.cancel` event to tell Bob's other devices
that the request has already been accepted; instead, when Bob's other devices that the request as already been accepted; instead, when Bob's other devices
see his `m.key.verification.ready` event, they will know that the request has see his `m.key.verification.ready` event, they will know that the request has
already been accepted, and that they should ignore the request. already been accepted, and that they should ignore the request.
@ -1512,11 +1512,40 @@ message.
The plaintext payload is of the form: The plaintext payload is of the form:
{{% definition path="api/client-server/definitions/olm_payload" %}} ```json
{
"type": "<type of the plaintext event>",
"content": "<content for the plaintext event>",
"sender": "<sender_user_id>",
"recipient": "<recipient_user_id>",
"recipient_keys": {
"ed25519": "<our_ed25519_key>"
},
"keys": {
"ed25519": "<sender_ed25519_key>"
}
}
```
The type and content of the plaintext message event are given in the The type and content of the plaintext message event are given in the
payload. payload.
Other properties are included in order to prevent an attacker from
publishing someone else's curve25519 keys as their own and subsequently
claiming to have sent messages which they didn't. `sender` must
correspond to the user who sent the event, `recipient` to the local
user, and `recipient_keys` to the local ed25519 key.
Clients must confirm that the `sender_key` property in the cleartext
`m.room.encrypted` event body, and the `keys.ed25519` property in the
decrypted plaintext, match the keys returned by
[`/keys/query`](#post_matrixclientv3keysquery) for
the given user. Clients must also verify the signature of the keys from the
`/keys/query` response. Without this check, a client cannot be sure that
the sender device owns the private part of the ed25519 key it claims to
have in the Olm payload. This is crucial when the ed25519 key corresponds
to a verified device.
If a client has multiple sessions established with another device, it If a client has multiple sessions established with another device, it
should use the session from which it last received and successfully should use the session from which it last received and successfully
decrypted a message. For these purposes, a session that has not received decrypted a message. For these purposes, a session that has not received
@ -1526,68 +1555,6 @@ maximum number of olm sessions that it will maintain for each device,
and expiring sessions on a Least Recently Used basis. The maximum number and expiring sessions on a Least Recently Used basis. The maximum number
of olm sessions maintained per device should be at least 4. of olm sessions maintained per device should be at least 4.
###### Validation of incoming decrypted events
{{% changed-in v="1.15" %}} Existing checks made more explicit, and checks for `sender_device_keys` added.
After decrypting an incoming encrypted event, clients MUST apply the
following checks:
1. The `sender` property in the decrypted content must match the
`sender` of the event.
2. The `keys.ed25519` property in the decrypted content must match
the `sender_key` property in the cleartext `m.room.encrypted`
event body.
3. The `recipient` property in the decrypted content must match
the user ID of the local user.
4. The `recipient_keys.ed25519` property in the decrypted content
must match the client device's [Ed25519 signing key](#device-keys).
5. Where `sender_device_keys` is present in the decrypted content:
1. `sender_device_keys.user_id` must also match the `sender`
of the event.
2. `sender_device_keys.keys.ed25519:<device_id>` must also match
the `sender_key` property in the cleartext `m.room.encrypted`
event body.
3. `sender_device_keys.keys.curve25519:<device_id>` must match
the Curve25519 key used to establish the Olm session.
4. The `sender_device_keys` structure must have a valid signature
from the key with ID `ed25519:<device_id>` (i.e., the sending
device's Ed25519 key).
Any event that does not comply with these checks MUST be discarded.
###### Verification of the sending user for incoming events
{{% added-in v="1.15" %}}
In addition, for each Olm session, clients MUST verify that the
Curve25519 key used to establish the Olm session does indeed belong
to the claimed `sender`. This requires a signed "device keys" structure
for that Curve25519 key, which can be obtained in one of two ways:
1. An Olm message may be received with a `sender_device_keys` property
in the decrypted content.
2. The keys are returned via a [`/keys/query`](#post_matrixclientv3keysquery)
request. Note that both the Curve25519 key **and** the Ed25519 key in
the returned device keys structure must match those used in an
Olm-encrypted event as above. (In particular, the Ed25519 key must
be present in the **encrypted** content of an Olm-encrypted event
to prevent an attacker from claiming another user's Curve25519 key
as their own.)
Ownership of the Curve25519 key is then established in one of two ways:
1. Via [cross-signing](#cross-signing). For this to be sufficient, the
device keys structure must be signed by the sender's self-signing key,
and that self-signing key must itself have been validated (either via
[explicit verification](#device-verification) or a "trust on first use" (TOFU) mechanism).
2. Via explicit verification of the device's Ed25519 signing key, as
contained in the device keys structure. This is no longer recommended.
A failure to complete these verifications does not necessarily mean that
the session is bogus; however it is the case that there is no proof that
the claimed sender is accurate, and the user should be warned accordingly.
###### Recovering from undecryptable messages ###### Recovering from undecryptable messages
Occasionally messages may be undecryptable by clients due to a variety Occasionally messages may be undecryptable by clients due to a variety

View file

@ -18,9 +18,8 @@ the entity making the decisions on filtering is best positioned to
interpret the rules how it sees fit. interpret the rules how it sees fit.
Moderation policy lists are stored as room state events. There are no Moderation policy lists are stored as room state events. There are no
restrictions on how the rooms can be configured in terms of restrictions on how the rooms can be configured (they could be public,
[join rules](#mroomjoin_rules), [history visibility](#room-history-visibility), private, encrypted, etc).
encryption, etc.
There are currently 3 kinds of entities which can be affected by rules: There are currently 3 kinds of entities which can be affected by rules:
`user`, `server`, and `room`. All 3 are described with `user`, `server`, and `room`. All 3 are described with

View file

@ -68,7 +68,5 @@ will cause the server to automatically set their presence to `online`.
#### Security considerations #### Security considerations
Presence information is published to all users who share a room with the Presence information is shared with all users who share a room with the
target user. If the target user is a member of a room with a `public` target user. In large public rooms this could be undesirable.
[join rule](#mroomjoin_rules), any other user in the federation is
able to gain access to the target user's presence. This could be undesirable.

View file

@ -26,10 +26,9 @@ on certain keys of certain event types.
The supported keys to search over are: The supported keys to search over are:
- `content.body` in [`m.room.message`](/client-server-api/#mroommessage) - `content.body` in `m.room.message`
- `content.name` in [`m.room.name`](/client-server-api/#mroomname) - `content.name` in `m.room.name`
- In [`m.room.topic`](/client-server-api/#mroomtopic), `content.topic` - `content.topic` in `m.room.topic`
as well as the `body` of the `text/plain` representation in `content['m.topic']`.
The search will *not* include rooms that are end to end encrypted. The search will *not* include rooms that are end to end encrypted.

View file

@ -58,7 +58,7 @@ available on all their clients. Unless the user specifies otherwise,
clients will try to use the default key to decrypt secrets. clients will try to use the default key to decrypt secrets.
Clients that want to present a simplified interface to users by not supporting Clients that want to present a simplified interface to users by not supporting
multiple keys should use the default key if one is specified. If no default multiple keys should use the default key if one is specified. If not default
key is specified, the client may behave as if there is no key is present at key is specified, the client may behave as if there is no key is present at
all. When such a client creates a key, it should mark that key as being the all. When such a client creates a key, it should mark that key as being the
default key. default key.

View file

@ -2,8 +2,8 @@
{{% added-in v="1.2" %}} {{% added-in v="1.2" %}}
Often used to group rooms of similar subject matter (such as an "Official Often used to group rooms of similar subject matter (such as a public "Official
matrix.org rooms" space or a "Work stuff" space), spaces are a way to matrix.org rooms" space or personal "Work stuff" space), spaces are a way to
organise rooms while being represented as rooms themselves. organise rooms while being represented as rooms themselves.
A space is defined by the [`m.space` room type](#types), making it known as a A space is defined by the [`m.space` room type](#types), making it known as a
@ -18,11 +18,11 @@ In the default power level structure, this would be `100`. Clients might wish to
go a step further and explicitly ignore notification counts on space-rooms. go a step further and explicitly ignore notification counts on space-rooms.
Membership of a space is defined and controlled by the existing mechanisms which Membership of a space is defined and controlled by the existing mechanisms which
govern a room: [`m.room.member`](/client-server-api#mroommember), [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility), govern a room: [`m.room.member`](#mroommember), [`m.room.history_visibility`](#mroomhistory_visibility),
and [`m.room.join_rules`](/client-server-api#mroomjoin_rules). Canonical aliases and invites, including and [`m.room.join_rules`](#mroomjoin_rules). Public spaces are encouraged to have
third-party invites, still work just as they do in normal rooms as well. Furthermore, a similar setup to public rooms: `world_readable` history visibility, published
spaces can also be published in the [room directory](/client-server-api#published-room-directory) to make them canonical alias, and suitably public `join_rule`. Invites, including third-party
discoverable. invites, still work just as they do in normal rooms as well.
All other aspects of regular rooms are additionally carried over, such as the All other aspects of regular rooms are additionally carried over, such as the
ability to set arbitrary state events, hold room account data, etc. Spaces are ability to set arbitrary state events, hold room account data, etc. Spaces are
@ -87,9 +87,10 @@ the state of `#space:example.org` would consist of:
} }
``` ```
No state events in the child rooms themselves would be required (though they can also No state events in the child rooms themselves would be required (though they
be present). This allows for users to define spaces without needing explicit permission can also be present). This allows for users
from the room moderators/admins. to define personal/private spaces to organise their own rooms without needing explicit
permission from the room moderators/admins.
Child rooms can be removed from a space by omitting the `via` key of `content` on the Child rooms can be removed from a space by omitting the `via` key of `content` on the
relevant state event, such as through redaction or otherwise clearing the `content`. relevant state event, such as through redaction or otherwise clearing the `content`.

View file

@ -5,8 +5,8 @@ This module adds in support for inviting new members to a room where
their Matrix user ID is not known, instead addressing them by a third-party their Matrix user ID is not known, instead addressing them by a third-party
identifier such as an email address. There are two flows here; one identifier such as an email address. There are two flows here; one
if a Matrix user ID is known for the third-party identifier, and one if if a Matrix user ID is known for the third-party identifier, and one if
not. Either way, the client calls [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite) not. Either way, the client calls [`/invite`](#post_matrixclientv3roomsroomidinvite) with the details of the
with the details of the third-party identifier. third-party identifier.
The homeserver asks the identity server whether a Matrix user ID is The homeserver asks the identity server whether a Matrix user ID is
known for that identifier: known for that identifier:
@ -37,12 +37,10 @@ A client asks a server to invite a user by their third-party identifier.
#### Server behaviour #### Server behaviour
Upon receipt of an [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite), Upon receipt of an [`/invite`](#post_matrixclientv3roomsroomidinvite), the server is expected to look up the
the server is expected to look up the third-party identifier with the provided third-party identifier with the provided identity server. If the lookup
identity server by making a call to [`/_matrix/identity/v2/lookup`](/identity-service-api/#post_matrixidentityv2lookup). yields a result for a Matrix User ID then the normal invite process can
If the lookup yields a result for a Matrix User ID then the normal [invite be initiated. This process ends up looking like this:
process](/server-server-api/#inviting-to-a-room) can be initiated. This process
ends up looking like this:
``` ```
+---------+ +-------------+ +-----------------+ +---------+ +-------------+ +-----------------+
@ -68,11 +66,10 @@ ends up looking like this:
| | | | | |
``` ```
However, if the lookup does not yield a bound User ID, the homeserver must store However, if the lookup does not yield a bound User ID, the homeserver
the invite on the identity server with a call to must store the invite on the identity server and emit a valid
[`/_matrix/identity/v2/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite) `m.room.third_party_invite` event to the room. This process ends up
and emit a valid [`m.room.third_party_invite`](#mroomthird_party_invite) event looking like this:
to the room. This process ends up looking like this:
``` ```
+---------+ +-------------+ +-----------------+ +---------+ +-------------+ +-----------------+
@ -104,19 +101,16 @@ to the room. This process ends up looking like this:
| | | | | |
``` ```
The third-party user will then need to verify their identity, which results in a All homeservers MUST verify the signature in the event's
request to [`/_matrix/federation/v1/3pid/onbind`](/server-server-api/#put_matrixfederationv13pidonbind)
from the identity server to the homeserver that bound the third-party identifier
to a user. The homeserver then exchanges the `m.room.third_party_invite` event
in the room for a complete [`m.room.member`](#mroommember) event with
`content.membership: invite` and a `content.third_party_invite` property for the
user that has bound the third-party identifier. If the invitee is on a different
homeserver than the inviting user, the invitee's homeserver makes a request to
[`/_matrix/federation/v1/exchange_third_party_invite/{roomId}`](/server-server-api/#put_matrixfederationv1exchange_third_party_inviteroomid).
All homeservers MUST verify the signature in the `m.room.member` event's
`content.third_party_invite.signed` object. `content.third_party_invite.signed` object.
The third-party user will then need to verify their identity, which
results in a call from the identity server to the homeserver that bound
the third-party identifier to a user. The homeserver then exchanges the
`m.room.third_party_invite` event in the room for a complete
`m.room.member` event for `membership: invite` for the user that has
bound the third-party identifier.
If a homeserver is joining a room for the first time because of an If a homeserver is joining a room for the first time because of an
`m.room.third_party_invite`, the server which is already participating `m.room.third_party_invite`, the server which is already participating
in the room (which is chosen as per the standard server-server in the room (which is chosen as per the standard server-server
@ -199,8 +193,8 @@ at any time - the completion is not shown in the diagram.
H1 MUST verify the request from H3 to ensure the `signed` property is H1 MUST verify the request from H3 to ensure the `signed` property is
correct as well as the `key_validity_url` as still being valid. This is correct as well as the `key_validity_url` as still being valid. This is
done by making a request to the identity server's done by making a request to the [identity server
[`/pubkey/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyisvalid) /isvalid](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
endpoint, using the provided URL rather than constructing a new one. The endpoint, using the provided URL rather than constructing a new one. The
query string and response for the provided URL must match the Identity query string and response for the provided URL must match the Identity
Service Specification. Service Specification.

View file

@ -202,13 +202,11 @@ specific user, and should be set to the Matrix user ID of that user. Invites
without an `invitee` field are defined to be intended for any member of the without an `invitee` field are defined to be intended for any member of the
room other than the sender of the event. room other than the sender of the event.
Clients should consider an incoming call if they see a non-expired invite event Clients should consider an incoming call if they see a non-expired invite event where the `invitee` field is either
where the `invitee` field is either absent or equal to their user's Matrix ID. absent or equal to their user's Matrix ID, however they should evaluate whether or not to ring based on their
They should, however, evaluate whether or not to ring based on their user's trust user's trust relationship with the callers and/or where the call was placed. As a starting point, it is
relationship with the callers and/or where the call was placed. As a starting suggested that clients ignore call invites from users in public rooms. It is strongly recommended that
point, it is RECOMMENDED that clients ignore call invites in rooms with a when clients do not ring for an incoming call invite, they still display the call invite in the room and
[join rule](#mroomjoin_rules) of `public`. When clients suppress ringing for an
incoming call invite, they SHOULD still display the call invite in the room and
annotate that it was ignored. annotate that it was ignored.
##### Glare ##### Glare

View file

@ -119,8 +119,7 @@ to send. The process overall is as follows:
server must present a valid certificate for the hostname. server must present a valid certificate for the hostname.
3. If the hostname is not an IP literal, a regular HTTPS request is 3. If the hostname is not an IP literal, a regular HTTPS request is
made to `https://<hostname>/.well-known/matrix/server` (according to made to `https://<hostname>/.well-known/matrix/server`, expecting
[RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615)), expecting
the schema defined later in this section. 30x redirects should be the schema defined later in this section. 30x redirects should be
followed, however redirection loops should be avoided. Responses followed, however redirection loops should be avoided. Responses
(successful or otherwise) to the `/.well-known` endpoint should be (successful or otherwise) to the `/.well-known` endpoint should be
@ -544,8 +543,8 @@ the following subset of the room state:
`third_party_invite` property, the current `third_party_invite` property, the current
`m.room.third_party_invite` event with `state_key` matching `m.room.third_party_invite` event with `state_key` matching
`content.third_party_invite.signed.token`, if any. `content.third_party_invite.signed.token`, if any.
- If `membership` is `join`, `content.join_authorised_via_users_server` - If `content.join_authorised_via_users_server` is present,
is present, and the [room version supports restricted rooms](/rooms/#feature-matrix), and the [room version supports restricted rooms](/rooms/#feature-matrix),
then the `m.room.member` event with `state_key` matching then the `m.room.member` event with `state_key` matching
`content.join_authorised_via_users_server`. `content.join_authorised_via_users_server`.
@ -971,8 +970,9 @@ the event to other servers in the room.
## Third-party invites ## Third-party invites
{{% boxes/note %}} {{% boxes/note %}}
More information about third-party invites is available in the Client-Server API More information about third-party invites is available in the
under the [Third-party invites](/client-server-api/#third-party-invites) module. [Client-Server API](/client-server-api) under
the Third-party Invites module.
{{% /boxes/note %}} {{% /boxes/note %}}
When a user wants to invite another user in a room but doesn't know the When a user wants to invite another user in a room but doesn't know the
@ -985,41 +985,38 @@ API](/identity-service-api).
### Cases where an association exists for a third-party identifier ### Cases where an association exists for a third-party identifier
If the third-party identifier is already bound to a Matrix ID, a [lookup If the third-party identifier is already bound to a Matrix ID, a lookup
request](/identity-service-api/#post_matrixidentityv2lookup) on the identity request on the identity server will return it. The invite is then
server will return it. The invite is then processed by the inviting homeserver processed by the inviting homeserver as a standard `m.room.member`
as a [standard `m.room.member` invite event](#inviting-to-a-room). This is the invite event. This is the simplest case.
simplest case.
### Cases where an association doesn't exist for a third-party identifier ### Cases where an association doesn't exist for a third-party identifier
If the third-party identifier isn't bound to any Matrix ID, the inviting If the third-party identifier isn't bound to any Matrix ID, the inviting
homeserver will request the identity server to [store an invite](/identity-service-api/#invitation-storage) homeserver will request the identity server to store an invite for this
for this identifier and to deliver it to whoever binds it to its Matrix ID. It identifier and to deliver it to whoever binds it to its Matrix ID. It
will also send an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) will also send an `m.room.third_party_invite` event in the room to
event in the room to specify a display name, a token and public keys the specify a display name, a token and public keys the identity server
identity server provided as a response to the invite storage request. provided as a response to the invite storage request.
When a third-party identifier with pending invites gets bound to a Matrix ID, When a third-party identifier with pending invites gets bound to a
the identity server will send a request to the [`/3pid/onbind`](#put_matrixfederationv13pidonbind) Matrix ID, the identity server will send a POST request to the ID's
endpoint of the the ID's homeserver as described in the [Invitation homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage) section of the Identity Storage](/identity-service-api#invitation-storage)
Service API. section of the Identity Service API.
The following process applies for each invite sent by the identity The following process applies for each invite sent by the identity
server: server:
The invited homeserver will create an [`m.room.member`](/client-server-api/#mroommember) The invited homeserver will create an `m.room.member` invite event
invite event containing a special `third_party_invite` section containing the containing a special `third_party_invite` section containing the token
token and a `signed` object, both provided by the identity server. and a signed object, both provided by the identity server.
If the invited homeserver is in the room the invite came from, it can If the invited homeserver is in the room the invite came from, it can
auth the event and send it. auth the event and send it.
However, if the invited homeserver isn't in the room the invite came However, if the invited homeserver isn't in the room the invite came
from, it will need to request the inviting homeserver to auth the event from, it will need to request the room's homeserver to auth the event.
at the [`/exchange_third_party_invite`](#put_matrixfederationv1exchange_third_party_inviteroomid)
endpoint.
{{% http-api spec="server-server" api="third_party_invite" %}} {{% http-api spec="server-server" api="third_party_invite" %}}
@ -1048,10 +1045,11 @@ user's Matrix ID and the token delivered when the invite was stored,
this verification will prove that the `m.room.member` invite event comes this verification will prove that the `m.room.member` invite event comes
from the user owning the invited third-party identifier. from the user owning the invited third-party identifier.
## Published Room Directory ## Public Room Directory
To complement the [room directory in the Client-Server API](/client-server-api#published-room-directory), To complement the [Client-Server
homeservers need a way to query the published rooms of another server. API](/client-server-api)'s room directory,
homeservers need a way to query the public rooms for another server.
This can be done by making a request to the `/publicRooms` endpoint for This can be done by making a request to the `/publicRooms` endpoint for
the server the room directory should be retrieved for. the server the room directory should be retrieved for.
@ -1339,7 +1337,7 @@ calculated as follows.
The *content hash* of an event covers the complete event including the The *content hash* of an event covers the complete event including the
*unredacted* contents. It is calculated as follows. *unredacted* contents. It is calculated as follows.
First, any existing `unsigned`, `signatures`, and `hashes` properties are First, any existing `unsigned`, `signature`, and `hashes` members are
removed. The resulting object is then encoded as [Canonical removed. The resulting object is then encoded as [Canonical
JSON](/appendices#canonical-json), and the JSON is hashed using JSON](/appendices#canonical-json), and the JSON is hashed using
SHA-256. SHA-256.

View file

@ -19,7 +19,7 @@ properties:
type: string type: string
description: A unique, user-defined ID of the application service which will never change. description: A unique, user-defined ID of the application service which will never change.
url: url:
type: ["null", "string"] type: string
description: The URL for the application service. May include a path after the domain name. Optionally set to null if no traffic is required. description: The URL for the application service. May include a path after the domain name. Optionally set to null if no traffic is required.
as_token: as_token:
type: string type: string

View file

@ -13,21 +13,18 @@
# limitations under the License. # limitations under the License.
openapi: 3.1.0 openapi: 3.1.0
info: info:
title: Matrix Client-Server Application Service Published Room Directory API title: Matrix Client-Server Application Service Room Directory API
version: 1.0.0 version: 1.0.0
paths: paths:
"/directory/list/appservice/{networkId}/{roomId}": "/directory/list/appservice/{networkId}/{roomId}":
put: put:
summary: |- summary: Updates a room's visibility in the application service's room directory.
Updates a room's visibility in the application service's published room
directory.
description: |- description: |-
Updates the visibility of a given room in the application service's Updates the visibility of a given room on the application service's room
published room directory. directory.
This API is similar to the This API is similar to the room directory visibility API used by clients
[visibility API](/client-server-api#put_matrixclientv3directorylistroomroomid) to update the homeserver's more general room directory.
used by clients to update the homeserver's more general published room directory.
This API requires the use of an application service access token (`as_token`) This API requires the use of an application service access token (`as_token`)
instead of a typical client's access_token. This API cannot be invoked by instead of a typical client's access_token. This API cannot be invoked by

View file

@ -87,9 +87,12 @@ paths:
- public - public
- private - private
description: |- description: |-
The room's visibility in the server's A `public` visibility indicates that the room will be shown
[published room directory](/client-server-api#published-room-directory). in the published room list. A `private` visibility will hide
Defaults to `private`. the room from the published room list. Rooms default to
`private` visibility if this key is not included. NB: This
should not be confused with `join_rules` which also uses the
word `public`.
room_alias_name: room_alias_name:
type: string type: string
description: |- description: |-
@ -106,17 +109,15 @@ paths:
name: name:
type: string type: string
description: |- description: |-
If this is included, an [`m.room.name`](/client-server-api/#mroomname) event If this is included, an `m.room.name` event will be sent
will be sent into the room to indicate the name for the room. into the room to indicate the name of the room. See Room
This overwrites any [`m.room.name`](/client-server-api/#mroomname) Events for more information on `m.room.name`.
event in `initial_state`.
topic: topic:
type: string type: string
description: |- description: |-
If this is included, an [`m.room.topic`](/client-server-api/#mroomtopic) If this is included, an `m.room.topic` event will be sent
event with a `text/plain` mimetype will be sent into the room into the room to indicate the topic for the room. See Room
to indicate the topic for the room. This overwrites any Events for more information on `m.room.topic`.
[`m.room.topic`](/client-server-api/#mroomtopic) event in `initial_state`.
invite: invite:
type: array type: array
description: |- description: |-

View file

@ -1,88 +0,0 @@
# Copyright 2025 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.
type: object
title: OlmPayload
description: |-
The plaintext payload of Olm message events.
properties:
type:
type: string
description: The type of the event.
content:
type: object
description: The event content.
sender:
type: string
description: The user ID of the event sender.
recipient:
type: string
description: The user ID of the intended event recipient.
recipient_keys:
description: The recipient's signing keys of the encrypted event.
$ref: "#/components/schemas/SigningKeys"
keys:
$ref: "#/components/schemas/SigningKeys"
description: The sender's signing keys of the encrypted event.
sender_device_keys:
$ref: device_keys.yaml
description: The sender's device keys.
x-addedInMatrixVersion: "1.15"
required:
- type
- content
- sender
- recipient
- recipient_keys
- keys
components:
schemas:
SigningKeys:
type: object
title: SigningKeys
description: Public keys used for an `m.olm.v1.curve25519-aes-sha2` event.
properties:
ed25519:
type: string
description: The Ed25519 public key encoded using unpadded base64.
required:
- ed25519
example: {
"type": "<type of the plaintext event>",
"content": "<content for the plaintext event>",
"sender": "<sender_user_id>",
"recipient": "<recipient_user_id>",
"recipient_keys": {
"ed25519": "<our_ed25519_key>"
},
"keys": {
"ed25519": "<sender_ed25519_key>"
},
"sender_device_keys": {
"algorithms": ["<supported>", "<algorithms>"],
"user_id": "<user_id>",
"device_id": "<device_id>",
"keys": {
"ed25519:<device_id>": "<sender_ed25519_key>",
"curve25519:<device_id>": "<sender_curve25519_key>"
},
"signatures": {
"<user_id>": {
"ed25519:<device_id>": "<device_signature>",
"ed25519:<ssk_id>": "<ssk_signature>",
}
}
}
}

View file

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
type: object type: object
title: "PublishedRoomsChunk" title: "PublicRoomsChunk"
properties: properties:
canonical_alias: canonical_alias:
type: string type: string
@ -33,9 +33,7 @@ properties:
example: "!abcdefg:example.org" example: "!abcdefg:example.org"
topic: topic:
type: string type: string
description: |- description: The topic of the room, if any.
The plain text topic of the room. Omitted if no `text/plain` mimetype
exists in [`m.room.topic`](/client-server-api/#mroomtopic).
example: "All things general" example: "All things general"
world_readable: world_readable:
type: boolean type: boolean

View file

@ -13,15 +13,28 @@
# limitations under the License. # limitations under the License.
type: object type: object
description: A list of the published rooms on the server. description: A list of the rooms on the server.
required: ["chunk"] required: ["chunk"]
properties: properties:
chunk: chunk:
type: array type: array
description: |- description: |-
A paginated chunk of published rooms. A paginated chunk of public rooms.
items: items:
$ref: "public_rooms_chunk.yaml" allOf:
- $ref: "public_rooms_chunk.yaml"
- type: object
title: PublicRoomsChunk
properties:
# Override description of join_rule
join_rule:
type: string
description: |-
The room's join rule. When not present, the room is assumed to
be `public`. Note that rooms with `invite` join rules are not
expected here, but rooms with `knock` rules are given their
near-public nature.
example: "public"
next_batch: next_batch:
type: string type: string
description: |- description: |-
@ -37,7 +50,7 @@ properties:
total_room_count_estimate: total_room_count_estimate:
type: integer type: integer
description: |- description: |-
An estimate on the total number of published rooms, if the An estimate on the total number of public rooms, if the
server has an estimate. server has an estimate.
example: { example: {
"chunk": [ "chunk": [

View file

@ -23,7 +23,6 @@ allOf:
description: The `type` of room (from description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)), [`m.room.create`](/client-server-api/#mroomcreate)),
if any. if any.
x-addedInMatrixVersion: "1.4"
allowed_room_ids: allowed_room_ids:
type: array type: array
items: items:

View file

@ -13,15 +13,14 @@
# limitations under the License. # limitations under the License.
openapi: 3.1.0 openapi: 3.1.0
info: info:
title: Matrix Client-Server Published Room Directory API title: Matrix Client-Server Room Directory API
version: 1.0.0 version: 1.0.0
paths: paths:
"/directory/list/room/{roomId}": "/directory/list/room/{roomId}":
get: get:
summary: Gets the visibility of a room in the directory summary: Gets the visibility of a room in the directory
description: |- description: Gets the visibility of a given room on the server's public room
Gets the visibility of a given room in the server's directory.
published room directory.
operationId: getRoomVisibilityOnDirectory operationId: getRoomVisibilityOnDirectory
parameters: parameters:
- in: path - in: path
@ -33,7 +32,7 @@ paths:
type: string type: string
responses: responses:
"200": "200":
description: The visibility of the room in the directory. description: The visibility of the room in the directory
content: content:
application/json: application/json:
schema: schema:
@ -51,7 +50,7 @@ paths:
"visibility": "public" "visibility": "public"
} }
"404": "404":
description: The room is not known to the server. description: The room is not known to the server
content: content:
application/json: application/json:
schema: schema:
@ -65,13 +64,14 @@ paths:
tags: tags:
- Room discovery - Room discovery
put: put:
summary: Sets the visibility of a room in the directory summary: Sets the visibility of a room in the room directory
description: |- description: |-
Sets the visibility of a given room in the server's published room directory. Sets the visibility of a given room in the server's public room
directory.
Servers MAY implement additional access control checks, for instance, Servers may choose to implement additional access control checks
to ensure that a room's visibility can only be changed by the room creator here, for instance that room visibility can only be changed by
or a server administrator. the room creator or a server administrator.
operationId: setRoomVisibilityOnDirectory operationId: setRoomVisibilityOnDirectory
security: security:
- accessTokenQuery: [] - accessTokenQuery: []
@ -97,11 +97,11 @@ paths:
- public - public
description: |- description: |-
The new visibility setting for the room. The new visibility setting for the room.
Defaults to `public`. Defaults to 'public'.
example: { example: {
"visibility": "public" "visibility": "public"
} }
description: The new visibility for the room in the published room directory. description: The new visibility for the room on the room directory.
required: true required: true
responses: responses:
"200": "200":
@ -114,7 +114,7 @@ paths:
response: response:
value: {} value: {}
"404": "404":
description: The room is not known to the server. description: The room is not known to the server
content: content:
application/json: application/json:
schema: schema:
@ -129,9 +129,9 @@ paths:
- Room discovery - Room discovery
/publicRooms: /publicRooms:
get: get:
summary: Lists a server's published room directory summary: Lists the public rooms on the server.
description: |- description: |-
Lists a server's published room directory. Lists the public rooms on the server.
This API returns paginated responses. The rooms are ordered by the number This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first. of joined members, with the largest rooms first.
@ -154,13 +154,13 @@ paths:
- in: query - in: query
name: server name: server
description: |- description: |-
The server to fetch the published room directory from. Defaults The server to fetch the public room lists from. Defaults to the
to the local server. Case sensitive. local server. Case sensitive.
schema: schema:
type: string type: string
responses: responses:
"200": "200":
description: A list of the published rooms on the server. description: A list of the rooms on the server.
content: content:
application/json: application/json:
schema: schema:
@ -168,9 +168,9 @@ paths:
tags: tags:
- Room discovery - Room discovery
post: post:
summary: Lists a server's published room directory with an optional filter summary: Lists the public rooms on the server with optional filter.
description: |- description: |-
Lists a server's published room directory with an optional filter. Lists the public rooms on the server, with optional filter.
This API returns paginated responses. The rooms are ordered by the number This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first. of joined members, with the largest rooms first.
@ -182,8 +182,8 @@ paths:
- in: query - in: query
name: server name: server
description: |- description: |-
The server to fetch the published room directory from. Defaults The server to fetch the public room lists from. Defaults to the
to the local server. Case sensitive. local server. Case sensitive.
schema: schema:
type: string type: string
requestBody: requestBody:
@ -253,7 +253,7 @@ paths:
required: true required: true
responses: responses:
"200": "200":
description: A filtered list of the published rooms on the server. description: A list of the rooms on the server.
content: content:
application/json: application/json:
schema: schema:

View file

@ -34,8 +34,8 @@ paths:
`knock_restricted`. `knock_restricted`.
- The room has a `world_readable` [history visibility](#room-history-visibility). - The room has a `world_readable` [history visibility](#room-history-visibility).
Servers should consider rate limiting requests that require a federation Servers should consider rate limiting federation requests more heavily,
request more heavily if the client is unauthenticated. if the client is unauthenticated.
operationId: getRoomSummary operationId: getRoomSummary
security: security:
- signedRequest: [] - signedRequest: []

View file

@ -22,12 +22,9 @@ paths:
description: |- description: |-
Gets server admin contact and support page of the domain. Gets server admin contact and support page of the domain.
{{% boxes/note %}} Like the [well-known discovery URI](/client-server-api/#well-known-uri),
Like the [well-known discovery URI](/client-server-api/#well-known-uris), this should be accessed with the hostname of the homeserver by making a
this endpoint should be accessed with the hostname of the homeserver's
[server name](/appendices/#server-name) by making a
GET request to `https://hostname/.well-known/matrix/support`. GET request to `https://hostname/.well-known/matrix/support`.
{{% /boxes/note %}}
Note that this endpoint is not necessarily handled by the homeserver. Note that this endpoint is not necessarily handled by the homeserver.
It may be served by another webserver, used for discovering support It may be served by another webserver, used for discovering support

View file

@ -441,57 +441,17 @@ paths:
"state": { "state": {
"events": [ "events": [
{ {
"content": { "$ref": "../../event-schemas/examples/m.room.member.yaml"
"avatar_url": "mxc://example.org/SFHyPlCeYUSFFxlgbQYZmoEoe",
"displayname": "Example user",
"membership": "join"
},
"event_id": "$143273976499sgjks:example.org",
"origin_server_ts": 1432735824653,
"sender": "@example:example.org",
"state_key": "@example:example.org",
"type": "m.room.member",
"unsigned": {
"age": 45603,
"membership": "join"
}
} }
] ]
}, },
"timeline": { "timeline": {
"events": [ "events": [
{ {
"content": { "$ref": "../../event-schemas/examples/m.room.member.yaml"
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"sender": "@alice:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234,
"membership": "join"
}
}, },
{ {
"content": { "$ref": "../../event-schemas/examples/m.room.message$m.text.yaml"
"body": "This is an example text message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example text message</b>",
"msgtype": "m.text"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1234,
"membership": "join"
}
} }
], ],
"limited": true, "limited": true,

View file

@ -57,6 +57,9 @@ paths:
- A signature of the token, signed with the identity server's private key - A signature of the token, signed with the identity server's private key
- The matrix user ID who invited them to the room - The matrix user ID who invited them to the room
If a token is requested from the identity server, the homeserver will
append a `m.room.third_party_invite` event to the room.
operationId: inviteBy3PID operationId: inviteBy3PID
security: security:
- accessTokenQuery: [] - accessTokenQuery: []
@ -69,8 +72,6 @@ paths:
example: "!d41d8cd:matrix.org" example: "!d41d8cd:matrix.org"
schema: schema:
type: string type: string
format: mx-room-id
pattern: "^!"
requestBody: requestBody:
content: content:
application/json: application/json:
@ -89,9 +90,7 @@ paths:
value: {} value: {}
"403": "403":
description: |- description: |-
You do not have permission to invite the user to the room. A You do not have permission to invite the user to the room. A meaningful `errcode` and description error text will be returned. Example reasons for rejections are:
meaningful `errcode` and description error text will be returned.
Example reasons for rejections are:
- The invitee has been banned from the room. - The invitee has been banned from the room.
- The invitee is already a member of the room. - The invitee is already a member of the room.

View file

@ -20,17 +20,10 @@ paths:
post: post:
summary: Searches the user directory. summary: Searches the user directory.
description: |- description: |-
Performs a search for users. The homeserver may determine which Performs a search for users. The homeserver may
subset of users are searched. However, the homeserver MUST at a determine which subset of users are searched, however the homeserver
minimum consider users who are visible to the requester based MUST at a minimum consider the users the requesting user shares a
on their membership in rooms known to the homeserver. This means: room with and those who reside in public rooms (known to the homeserver).
- users that share a room with the requesting user
- users who are joined to rooms known to the homeserver that have a
`public` [join rule](#mroomjoin_rules)
- users who are joined to rooms known to the homeserver that have a
`world_readable` [history visibility](#room-history-visibility)
The search MUST consider local users to the homeserver, and SHOULD The search MUST consider local users to the homeserver, and SHOULD
query remote users as part of the search. query remote users as part of the search.

View file

@ -26,12 +26,6 @@ paths:
suitably namespaced for each application and reduces the risk of suitably namespaced for each application and reduces the risk of
clashes. clashes.
{{% boxes/note %}}
This endpoint should be accessed with the hostname of the homeserver's
[server name](/appendices/#server-name) by making a
GET request to `https://hostname/.well-known/matrix/client`.
{{% /boxes/note %}}
Note that this endpoint is not necessarily handled by the homeserver, Note that this endpoint is not necessarily handled by the homeserver,
but by another webserver, to be used for discovering the homeserver URL. but by another webserver, to be used for discovering the homeserver URL.
operationId: getWellknown operationId: getWellknown

View file

@ -43,8 +43,7 @@ paths:
properties: properties:
public_key: public_key:
type: string type: string
description: |- description: Unpadded Base64 encoded public key.
[Unpadded Base64](/appendices/#unpadded-base64)-encoded public key.
required: required:
- public_key - public_key
examples: examples:
@ -75,8 +74,7 @@ paths:
- in: query - in: query
name: public_key name: public_key
required: true required: true
description: |- description: The unpadded base64-encoded public key to check.
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public key to check.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema: schema:
type: string type: string
@ -107,14 +105,7 @@ paths:
- in: query - in: query
name: public_key name: public_key
required: true required: true
description: |- description: The unpadded base64-encoded public key to check.
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public
key to check.
This MUST be the exact same encoded string returned in the response
of the [`/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
endpoint, or found in the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event, so it may use the standard or URL-safe alphabets.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema: schema:
type: string type: string

View file

@ -42,7 +42,7 @@ paths:
(if present) from the request here. (if present) from the request here.
Also, the generated ephemeral public key will be listed as valid on Also, the generated ephemeral public key will be listed as valid on
requests to [`/_matrix/identity/v2/pubkey/ephemeral/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyephemeralisvalid). requests to `/_matrix/identity/v2/pubkey/ephemeral/isvalid`.
Currently, invites may only be issued for 3pids of the `email` medium. Currently, invites may only be issued for 3pids of the `email` medium.
@ -70,14 +70,10 @@ paths:
room_id: room_id:
type: string type: string
description: The Matrix room ID to which the user is invited description: The Matrix room ID to which the user is invited
format: mx-room-id
pattern: "^!"
example: "!something:example.org" example: "!something:example.org"
sender: sender:
type: string type: string
description: The Matrix user ID of the inviting user description: The Matrix user ID of the inviting user
format: mx-user-id
pattern: "^@"
example: "@bob:example.com" example: "@bob:example.com"
room_alias: room_alias:
type: string type: string
@ -85,16 +81,12 @@ paths:
The Matrix room alias for the room to which the user is The Matrix room alias for the room to which the user is
invited. This should be retrieved from the `m.room.canonical_alias` invited. This should be retrieved from the `m.room.canonical_alias`
state event. state event.
format: mx-room-alias
pattern: "^#"
example: "#somewhere:example.org" example: "#somewhere:example.org"
room_avatar_url: room_avatar_url:
type: string type: string
description: |- description: |-
The Content URI for the room to which the user is invited. This should The Content URI for the room to which the user is invited. This should
be retrieved from the `m.room.avatar` state event. be retrieved from the `m.room.avatar` state event.
format: mx-mxc-uri
pattern: "^mxc:\\/\\/"
example: mxc://example.org/s0meM3dia example: mxc://example.org/s0meM3dia
room_join_rules: room_join_rules:
type: string type: string
@ -116,8 +108,6 @@ paths:
type: string type: string
description: The Content URI for the avatar of the user ID initiating the description: The Content URI for the avatar of the user ID initiating the
invite. invite.
format: mx-mxc-uri
pattern: "^mxc:\\/\\/"
example: mxc://example.org/an0th3rM3dia example: mxc://example.org/an0th3rM3dia
room_type: room_type:
type: string type: string
@ -156,7 +146,7 @@ paths:
public_key: public_key:
type: string type: string
description: | description: |
The public key, encoded using standard or URL-safe [unpadded Base64](/appendices/#unpadded-base64). The public key, encoded using [unpadded Base64](/appendices/#unpadded-base64).
key_validity_url: key_validity_url:
type: string type: string
description: | description: |

View file

@ -32,10 +32,6 @@ paths:
[room version specification](/rooms) for precise event formats. **The request and response [room version specification](/rooms) for precise event formats. **The request and response
bodies here describe the common event fields in more detail and may be missing other bodies here describe the common event fields in more detail and may be missing other
required fields for a PDU.** required fields for a PDU.**
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](/server-server-api/#transactions).
operationId: sendInviteV1 operationId: sendInviteV1
security: security:
- signedRequest: [] - signedRequest: []

View file

@ -36,10 +36,6 @@ paths:
[room version specification](/rooms) for precise event formats. **The request and response [room version specification](/rooms) for precise event formats. **The request and response
bodies here describe the common event fields in more detail and may be missing other bodies here describe the common event fields in more detail and may be missing other
required fields for a PDU.** required fields for a PDU.**
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](/server-server-api/#transactions).
operationId: sendInviteV2 operationId: sendInviteV2
security: security:
- signedRequest: [] - signedRequest: []

View file

@ -13,20 +13,16 @@
# limitations under the License. # limitations under the License.
openapi: 3.1.0 openapi: 3.1.0
info: info:
title: Matrix Federation Published Room Directory API title: Matrix Federation Public Rooms API
version: 1.0.0 version: 1.0.0
paths: paths:
/publicRooms: /publicRooms:
get: get:
summary: Lists the server's published room directory summary: Get all the public rooms for a homeserver
description: |- description: |-
Lists the server's published room directory. Gets all the public rooms for the homeserver. This should not return
rooms that are listed on another homeserver's directory, just those
This API returns paginated responses. The rooms are ordered by the number listed on the receiving homeserver's directory.
of joined members, with the largest rooms first.
This SHOULD not return rooms that are listed on another homeserver's directory,
just those listed on the receiving homeserver's directory.
operationId: getPublicRooms operationId: getPublicRooms
security: security:
- signedRequest: [] - signedRequest: []
@ -66,18 +62,21 @@ paths:
type: string type: string
responses: responses:
"200": "200":
description: A list of the published rooms on the server. description: The public room list for the homeserver.
content: content:
application/json: application/json:
schema: schema:
$ref: ../client-server/definitions/public_rooms_response.yaml $ref: ../client-server/definitions/public_rooms_response.yaml
post: post:
summary: Lists the server's published room directory with an optional filter summary: Gets the public rooms on the server with optional filter.
description: |- description: |-
Lists the server's published room directory with an optional filter. Lists the public rooms on the server, with optional filter.
This API returns paginated responses. The rooms are ordered by the number This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first. of joined members, with the largest rooms first.
Note that this endpoint receives and returns the same format that is seen
in the Client-Server API's `POST /publicRooms` endpoint.
operationId: queryPublicRooms operationId: queryPublicRooms
security: security:
- signedRequest: [] - signedRequest: []
@ -148,11 +147,69 @@ paths:
required: true required: true
responses: responses:
"200": "200":
description: A filtered list of the published rooms on the server. description: A list of the rooms on the server.
content: content:
application/json: application/json:
schema: schema:
$ref: ../client-server/definitions/public_rooms_response.yaml type: object
description: A list of the rooms on the server.
required:
- chunk
properties:
chunk:
title: PublicRoomsChunks
type: array
description: A paginated chunk of public rooms.
items:
allOf:
- $ref: ../client-server/definitions/public_rooms_chunk.yaml
- type: object
properties:
# Override description of join_rule
join_rule:
type: string
description: |-
The room's join rule. When not present, the room is assumed to
be `public`. Note that rooms with `invite` join rules are not
expected here, but rooms with `knock` rules are given their
near-public nature.
next_batch:
type: string
description: |-
A pagination token for the response. The absence of this token
means there are no more results to fetch and the client should
stop paginating.
prev_batch:
type: string
description: |-
A pagination token that allows fetching previous results. The
absence of this token means there are no results before this
batch, i.e. this is the first batch.
total_room_count_estimate:
type: integer
description: |-
An estimate on the total number of public rooms, if the
server has an estimate.
examples:
response:
value: {
"chunk": [
{
"avatar_url": "mxc://bleecker.street/CHEDDARandBRIE",
"guest_can_join": false,
"name": "CHEESE",
"num_joined_members": 37,
"room_id": "!ol19s:bleecker.street",
"topic": "Tasty tasty cheese",
"world_readable": true,
"join_rule": "public",
"room_type": "m.space"
}
],
"next_batch": "p190q",
"prev_batch": "p1902",
"total_room_count_estimate": 115
}
servers: servers:
- url: "{protocol}://{hostname}{basePath}" - url: "{protocol}://{hostname}{basePath}"
variables: variables:

View file

@ -35,8 +35,6 @@ paths:
example: "!abc123:matrix.org" example: "!abc123:matrix.org"
schema: schema:
type: string type: string
format: mx-room-id
pattern: "^!"
requestBody: requestBody:
content: content:
application/json: application/json:
@ -52,22 +50,16 @@ paths:
description: |- description: |-
The room ID the event is for. Must match the ID given in The room ID the event is for. Must match the ID given in
the path. the path.
format: mx-room-id
pattern: "^!"
example: "!abc123:matrix.org" example: "!abc123:matrix.org"
sender: sender:
type: string type: string
description: |- description: |-
The user ID of the user who sent the original `m.room.third_party_invite` The user ID of the user who sent the original `m.room.third_party_invite`
event. event.
format: mx-user-id
pattern: "^@"
example: "@joe:matrix.org" example: "@joe:matrix.org"
state_key: state_key:
type: string type: string
description: The user ID of the invited user description: The user ID of the invited user
format: mx-user-id
pattern: "^@"
example: "@someone:example.org" example: "@someone:example.org"
content: content:
type: object type: object
@ -90,7 +82,45 @@ paths:
third-party identifier. third-party identifier.
example: alice example: alice
signed: signed:
$ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml type: object
description: |-
A block of content which has been signed, which servers can use to
verify the event.
title: Invite Signatures
properties:
signatures:
type: object
title: Signatures
additionalProperties:
type: object
additionalProperties:
type: string
description: |-
The server signatures for this event.
The signature is calculated using the process
described at [Signing JSON](/appendices/#signing-json).
example:
magic.forest:
ed25519:3: fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg
mxid:
type: string
description: The invited matrix user ID
example: "@alice:localhost"
token:
type: string
description: The token used to verify the event
example: abc123
required:
- signatures
- mxid
- token
example:
mxid: "@alice:localhost"
token: abc123
signatures:
magic.forest:
ed25519:3: fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg
required: required:
- display_name - display_name
- signed - signed
@ -185,8 +215,6 @@ paths:
mxid: mxid:
type: string type: string
description: The user that is now bound to the third-party identifier. description: The user that is now bound to the third-party identifier.
format: mx-user-id
pattern: "^@"
example: "@alice:matrix.org" example: "@alice:matrix.org"
invites: invites:
type: array type: array
@ -209,23 +237,59 @@ paths:
mxid: mxid:
type: string type: string
description: The now-bound user ID that received the invite. description: The now-bound user ID that received the invite.
format: mx-user-id
pattern: "^@"
example: "@alice:matrix.org" example: "@alice:matrix.org"
room_id: room_id:
type: string type: string
description: The room ID the invite is valid for. description: The room ID the invite is valid for.
format: mx-room-id
pattern: "^!"
example: "!somewhere:example.org" example: "!somewhere:example.org"
sender: sender:
type: string type: string
description: The user ID that sent the invite. description: The user ID that sent the invite.
format: mx-user-id
pattern: "^@"
example: "@bob:matrix.org" example: "@bob:matrix.org"
# TODO (TravisR): Make this reusable when doing IS spec changes
# also make sure it isn't lying about anything, like the key version
signed: signed:
$ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml type: object
title: Identity Server Signatures
description: |-
Signature from the identity server using a long-term private
key.
properties:
mxid:
type: string
description: |-
The user ID that has been bound to the third-party
identifier.
example: "@alice:matrix.org"
token:
type: string
# TODO: What is this actually?
description: A token.
example: Hello World
signatures:
type: object
title: Identity Server Signature
description: |-
The signature from the identity server. The `string` key
is the identity server's domain name, such as vector.im
additionalProperties:
type: object
title: Identity Server Domain Signature
description: The signature for the identity server.
properties:
ed25519:0:
type: string
description: The signature.
example: SomeSignatureGoesHere
required:
- ed25519:0
example:
vector.im:
ed25519:0: SomeSignatureGoesHere
required:
- mxid
- token
- signatures
required: required:
- medium - medium
- address - address

View file

@ -24,12 +24,6 @@ paths:
Gets information about the delegated server for server-server communication Gets information about the delegated server for server-server communication
between Matrix homeservers. Servers should follow 30x redirects, carefully between Matrix homeservers. Servers should follow 30x redirects, carefully
avoiding redirect loops, and use normal X.509 certificate validation. avoiding redirect loops, and use normal X.509 certificate validation.
{{% boxes/note %}}
This endpoint should be accessed with the hostname of the homeserver's
[server name](/appendices/#server-name) by making a
GET request to `https://hostname/.well-known/matrix/server`.
{{% /boxes/note %}}
operationId: getWellKnown operationId: getWellKnown
responses: responses:
"200": "200":

View file

@ -1,7 +1,6 @@
{ {
"$ref": "core/state_event.json", "$ref": "core/state_event.json",
"state_key": "@alice:example.org", "state_key": "@alice:example.org",
"sender": "@alice:example.org",
"type": "m.room.member", "type": "m.room.member",
"content": { "content": {
"membership": "join", "membership": "join",

View file

@ -3,14 +3,6 @@
"type": "m.room.topic", "type": "m.room.topic",
"state_key": "", "state_key": "",
"content": { "content": {
"m.topic": { "topic": "A room topic"
"m.text": [ {
"mimetype": "text/html",
"body": "An <em>interesting</em> room topic"
}, {
"body": "An interesting room topic"
}]
},
"topic": "An interesting room topic"
} }
} }

View file

@ -1,28 +0,0 @@
type: array
description: |-
An ordered array of textual representations in different mimetypes.
Senders SHOULD specify at least one representation and SHOULD always
include a plaintext representation.
Receivers SHOULD use the first representation in the array that
they understand.
title: TextContentBlock
items:
type: object
title: TextualRepresentation
properties:
mimetype:
type: string
description: The mimetype. Defaults to `text/plain` if omitted.
example: "text/html"
body:
type: string
description: |-
The string content.
Clients SHOULD validate and sanitize the content as they do
for rich content associated with [`msgtype`](/client-server-api/#mroommessage-msgtypes)
of [`m.room.message`](/client-server-api/#mroommessage).
required:
- body

View file

@ -1,45 +0,0 @@
title: SignedThirdPartyInvite
description: |-
A block of content which has been signed by the identity server, which
homeservers can use to verify the event. Clients should ignore this.
type: object
properties:
mxid:
description: |-
The user ID that has been bound to the third-party identifier.
type: string
format: mx-user-id
pattern: "^@"
example: "@alice:example.org"
signatures:
title: IdentityServerSignatures
description: |-
The identity server signatures for this block. This is a map of identity
server name to signing key identifier to base64-encoded signature.
The signatures are calculated using the process described at
[Signing JSON](/appendices/#signing-json).
type: object
additionalProperties:
type: object
additionalProperties:
type: string
example: {
"magic.forest": {
"ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
}
}
token:
description: |-
The token generated by the identity server at the
[`/store_invite`](/identity-service-api/#post_matrixidentityv2store-invite)
endpoint.
It matches the `state_key` of the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event.
type: string
example: "abc123"
required:
- mxid
- signatures
- token

View file

@ -2,27 +2,17 @@
allOf: allOf:
- $ref: core-event-schema/state_event.yaml - $ref: core-event-schema/state_event.yaml
description: |- description: |-
Adjusts the membership state for a user in a room. It is preferable to use the membership APIs Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (`/rooms/<room id>/invite` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail.
(`/rooms/<room id>/invite` etc) when performing membership actions rather than adjusting the
state directly as there are a restricted set of valid transformations. For example, user A cannot
force user B to join a room, and trying to force this state change directly will fail.
The following membership states are specified: The following membership states are specified:
- `invite` - The user has been invited to join a room, but has not yet joined it. They may not - `invite` - The user has been invited to join a room, but has not yet joined it. They may not participate in the room until they join.
participate in the room until they join. - `join` - The user has joined the room (possibly after accepting an invite), and may participate in it.
- `join` - The user has joined the room (possibly after accepting an invite), and may participate - `leave` - The user was once joined to the room, but has since left (possibly by choice, or possibly by being kicked).
in it. - `ban` - The user has been banned from the room, and is no longer allowed to join it until they are un-banned from the room (by having their membership state set to a value other than `ban`).
- `leave` - The user was once joined to the room, but has since left (possibly by choice, or - `knock` - The user has knocked on the room, requesting permission to participate. They may not participate in the room until they join.
possibly by being kicked).
- `ban` - The user has been banned from the room, and is no longer allowed to join it until they
are un-banned from the room (by having their membership state set to a value other than `ban`).
- `knock` - The user has knocked on the room, requesting permission to participate. They may not
participate in the room until they join.
The `third_party_invite` property will be set if this invite is an `invite` event and is the The `third_party_invite` property will be set if this invite is an `invite` event and is the successor of an `m.room.third_party_invite` event, and absent otherwise.
successor of an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) event,
and absent otherwise.
This event may also include an `invite_room_state` key inside the event's `unsigned` data. This event may also include an `invite_room_state` key inside the event's `unsigned` data.
If present, this contains an array of [stripped state events](/client-server-api/#stripped-state) If present, this contains an array of [stripped state events](/client-server-api/#stripped-state)
@ -67,54 +57,63 @@ properties:
- ban - ban
type: string type: string
is_direct: is_direct:
description: |- description: Flag indicating if the room containing this event was created with the intention of being a direct chat. See [Direct Messaging](/client-server-api/#direct-messaging).
Flag indicating if the room containing this event was created with the intention of being
a direct chat. See [Direct Messaging](/client-server-api/#direct-messaging).
type: boolean type: boolean
join_authorised_via_users_server: join_authorised_via_users_server:
x-addedInMatrixVersion: "1.2" x-addedInMatrixVersion: "1.2"
type: string type: string
description: |- description: |-
Usually found on `join` events, this field is used to denote which homeserver (through Usually found on `join` events, this field is used to denote which homeserver (through representation of a user with sufficient power level)
representation of a user with sufficient power level) authorised the user's join. More authorised the user's join. More information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms).
information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms).
Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules) Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules) of including this
of including this field in further events: in particular, the event must be signed by the field in further events: in particular, the event must be signed by the server which
server which owns the user ID in the field. When copying the membership event's `content` owns the user ID in the field. When copying the membership event's `content`
(for profile updates and similar) it is therefore encouraged to exclude this field in the (for profile updates and similar) it is therefore encouraged to exclude this
copy, as otherwise the event might fail event authorization. field in the copy, as otherwise the event might fail event authorization.
reason: reason:
x-addedInMatrixVersion: "1.1" x-addedInMatrixVersion: "1.1"
type: string type: string
description: |- description: |-
Optional user-supplied text for why their membership has changed. For kicks and bans, Optional user-supplied text for why their membership has changed. For kicks and bans, this is typically the reason for the kick or ban.
this is typically the reason for the kick or ban. For other membership changes, this is a For other membership changes, this is a way for the user to communicate their intent without having to send a message to the room, such
way for the user to communicate their intent without having to send a message to the as in a case where Bob rejects an invite from Alice about an upcoming concert, but can't make it that day.
room, such as in a case where Bob rejects an invite from Alice about an upcoming concert,
but can't make it that day.
Clients are not recommended to show this reason to users when receiving an invite due to Clients are not recommended to show this reason to users when receiving an invite due to the potential for spam and abuse. Hiding the
the potential for spam and abuse. Hiding the reason behind a button or other component is reason behind a button or other component is recommended.
recommended.
third_party_invite: third_party_invite:
title: ThirdPartyInvite
description: |-
A third-party invite, if this `m.room.member` is the successor to an
[`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event.
type: object
properties: properties:
display_name: display_name:
description: |- description: A name which can be displayed to represent the user instead of their third-party identifier
A name which can be displayed to represent the user instead of their
third-party identifier
type: string type: string
signed: signed:
$ref: components/signed_third_party_invite.yaml description: 'A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.'
properties:
mxid:
description: The invited matrix user ID. Must be equal to the user_id property of the event.
type: string
signatures:
description: 'A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.'
title: Signatures
type: object
additionalProperties:
type: object
additionalProperties:
type: string
token:
description: The token property of the containing third_party_invite object.
type: string
required:
- mxid
- signatures
- token
title: signed
type: object
required: required:
- display_name - display_name
- signed - signed
title: Invite
type: object
required: required:
- membership - membership
title: EventContent title: EventContent

View file

@ -1,56 +1,28 @@
--- ---
allOf: allOf:
- $ref: core-event-schema/state_event.yaml - $ref: core-event-schema/state_event.yaml
description: |- description: "Acts as an `m.room.member` invite event, where there isn't a target user_id to invite. This event contains a token and a public key whose private key must be used to sign the token. Any user who can present that signature may use this invitation to join the target room."
Acts as an `m.room.member` invite event, where there isn't a target user_id to
invite. This event contains a token and a public key whose private key must be
used to sign the token. Any user who can present that signature may use this
invitation to join the target room.
properties: properties:
content: content:
properties: properties:
display_name: display_name:
description: |- description: "A user-readable string which represents the user who has been invited. This should not contain the user's third-party ID, as otherwise when the invite is accepted it would leak the association between the matrix ID and the third-party ID."
A user-readable string which represents the user who has been invited.
This should not contain the user's third-party ID, as otherwise when
the invite is accepted it would leak the association between the
matrix ID and the third-party ID.
type: string type: string
key_validity_url: key_validity_url:
description: |- description: "A URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'."
A URL which can be fetched, with querystring public_key=public_key, to
validate whether the key has been revoked. The URL must return a JSON
object containing a boolean property named 'valid'.
type: string type: string
format: uri
public_key: public_key:
description: |- description: A base64-encoded ed25519 key with which token must be signed (though a signature from any entry in public_keys is also sufficient). This exists for backwards compatibility.
An Ed25519 key with which the token must be signed (though a signature
from any entry in `public_keys` is also sufficient).
The key is encoded using [Unpadded Base64](/appendices/#unpadded-base64),
using the standard or URL-safe alphabets.
This exists for backwards compatibility.
type: string type: string
public_keys: public_keys:
description: Keys with which the token may be signed. description: Keys with which the token may be signed.
items: items:
properties: properties:
key_validity_url: key_validity_url:
description: |- description: "An optional URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'. If this URL is absent, the key must be considered valid indefinitely."
An optional URL which can be fetched, with querystring
`public_key=<public_key>`, to validate whether the key has been
revoked. The URL must return a JSON object containing a boolean
property named `valid`. If this URL is absent, the key must be
considered valid indefinitely.
type: string type: string
public_key: public_key:
description: |- description: A base-64 encoded ed25519 key with which token may be signed.
An Ed25519 key with which the token may be signed.
The key is encoded using [Unpadded Base64](/appendices/#unpadded-base64),
using the standard or URL-safe alphabets.
type: string type: string
required: required:
- public_key - public_key
@ -63,15 +35,11 @@ properties:
- public_key - public_key
type: object type: object
state_key: state_key:
description: |- description: 'The token, of which a signature must be produced in order to join the room.'
The token, of which a signature must be produced in order to join the
room.
type: string type: string
type: type:
enum: enum:
- m.room.third_party_invite - m.room.third_party_invite
type: string type: string
title: |- title: 'An invitation to a room issued to a third-party identifier, rather than a matrix user ID.'
An invitation to a room issued to a third-party identifier, rather than a
matrix user ID.
type: object type: object

View file

@ -1,41 +1,13 @@
--- ---
allOf: allOf:
- $ref: core-event-schema/state_event.yaml - $ref: core-event-schema/state_event.yaml
description: |- description: 'A topic is a short message detailing what is currently being discussed in the room. It can also be used as a way to display extra information about the room, which may not be suitable for the room name. The room topic can also be set when creating a room using `/createRoom` with the `topic` key.'
A topic is a short message detailing what is currently being discussed
in the room. It can also be used as a way to display extra information
about the room, which may not be suitable for the room name. The room
topic can also be set when creating a room using
[`/createRoom`](client-server-api/#post_matrixclientv3createroom), either
with the `topic` key or by specifying a full event in `initial_state`.
If the `topic` property is absent, null, or empty then the topic is unset. In other words,
an empty `topic` property effectively resets the room to having no topic.
In order to prevent formatting abuse in room topics, clients SHOULD
limit the length of topics during both entry and display, for instance,
by capping the number of displayed lines. Additionally, clients SHOULD
ignore things like headings and enumerations (or format them as regular
text).
properties: properties:
content: content:
properties: properties:
topic: topic:
description: |- description: The topic text.
The topic in plain text.
This SHOULD duplicate the content of the `text/plain`
representation in `m.topic` if any exists.
type: string type: string
m.topic:
type: object
title: TopicContentBlock
x-addedInMatrixVersion: "1.15"
description: |-
Textual representation of the room topic in different mimetypes.
properties:
m.text:
$ref: components/m_text_content_block.yaml
required: required:
- topic - topic
type: object type: object

View file

@ -51,11 +51,6 @@ mx-room-id:
url: appendices#room-ids url: appendices#room-ids
# regex: "^!" # regex: "^!"
mx-room-alias:
title: Room Alias
url: appendices#room-aliases
# regex: "^#"
mx-server-name: mx-server-name:
title: Server Name title: Server Name
url: appendices#server-name url: appendices#server-name

View file

@ -32,35 +32,6 @@ import yaml
scripts_dir = os.path.dirname(os.path.abspath(__file__)) scripts_dir = os.path.dirname(os.path.abspath(__file__))
api_dir = os.path.join(os.path.dirname(scripts_dir), "data", "api") api_dir = os.path.join(os.path.dirname(scripts_dir), "data", "api")
# Finds a Hugo shortcode in a string.
#
# A shortcode is defined as (newlines and whitespaces for presentation purpose):
#
# {{%
# <zero or more whitespaces>
# <name of shortcode>
# (optional <one or more whitespaces><list of parameters>)
# <zero or more whitespaces>
# %}}
#
# With:
#
# * <name of shortcode>: any word character and `-` and `/`. `re.ASCII` is used to only match
# ASCII characters in the name.
# * <list of parameters>: any character except `}`, must not start or end with a
# whitespace.
shortcode_regex = re.compile(r"""\{\{\% # {{%
\s* # zero or more whitespaces
(?P<name>[\w/-]+) # name of shortcode
(?:\s+(?P<params>[^\s\}][^\}]+[^\s\}]))? # optional list of parameters
\s* # zero or more whitespaces
\%\}\} # %}}""", re.ASCII | re.VERBOSE)
# Parses the parameters of a Hugo shortcode.
#
# For simplicity, this currently only supports the `key="value"` format.
shortcode_params_regex = re.compile(r"(?P<key>\w+)=\"(?P<value>[^\"]+)\"", re.ASCII)
def prefix_absolute_path_references(text, base_url): def prefix_absolute_path_references(text, base_url):
"""Adds base_url to absolute-path references. """Adds base_url to absolute-path references.
@ -73,90 +44,17 @@ def prefix_absolute_path_references(text, base_url):
""" """
return text.replace("](/", "]({}/".format(base_url)) return text.replace("](/", "]({}/".format(base_url))
def replace_match(match, replacement): def edit_links(node, base_url):
"""Replaces the regex match by the replacement in the text.""" """Finds description nodes and makes any links in them absolute."""
return match.string[:match.start()] + replacement + match.string[match.end():]
def replace_shortcode(shortcode):
"""Replaces the shortcode by a Markdown fallback in the text.
The supported shortcodes are:
* boxes/note, boxes/rationale, boxes/warning
* added-in, changed-in
All closing tags (`{{ /shortcode }}`) are replaced with the empty string.
"""
if shortcode['name'].startswith("/"):
# This is the end of the shortcode, just remove it.
return replace_match(shortcode, "")
# Parse the parameters of the shortcode
params = {}
if shortcode['params']:
for param in shortcode_params_regex.finditer(shortcode['params']):
if param['key']:
params[param['key']] = param['value']
match shortcode['name']:
case "boxes/note":
return replace_match(shortcode, "**NOTE:** ")
case "boxes/rationale":
return replace_match(shortcode, "**RATIONALE:** ")
case "boxes/warning":
return replace_match(shortcode, "**WARNING:** ")
case "added-in":
version = params['v']
if not version:
raise ValueError("Missing parameter `v` for `added-in` shortcode")
return replace_match(shortcode, f"**[Added in `v{version}`]** ")
case "changed-in":
version = params['v']
if not version:
raise ValueError("Missing parameter `v` for `changed-in` shortcode")
return replace_match(shortcode, f"**[Changed in `v{version}`]** ")
case _:
raise ValueError("Unknown shortcode", shortcode['name'])
def find_and_replace_shortcodes(text):
"""Finds Hugo shortcodes and replaces them by a Markdown fallback.
The supported shortcodes are:
* boxes/note, boxes/rationale, boxes/warning
* added-in, changed-in
"""
# We use a `while` loop with `search` instead of a `for` loop with
# `finditer`, because as soon as we start replacing text, the
# indices of the match are invalid.
while shortcode := shortcode_regex.search(text):
text = replace_shortcode(shortcode)
return text
def edit_descriptions(node, base_url):
"""Finds description nodes and apply fixes to them.
The fixes that are applied are:
* Make links absolute
* Replace Hugo shortcodes
"""
if isinstance(node, dict): if isinstance(node, dict):
for key in node: for key in node:
if isinstance(node[key], str): if isinstance(node[key], str):
node[key] = prefix_absolute_path_references(node[key], base_url) node[key] = prefix_absolute_path_references(node[key], base_url)
node[key] = find_and_replace_shortcodes(node[key])
else: else:
edit_descriptions(node[key], base_url) edit_links(node[key], base_url)
elif isinstance(node, list): elif isinstance(node, list):
for item in node: for item in node:
edit_descriptions(item, base_url) edit_links(item, base_url)
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
"dump-openapi.py - assemble the OpenAPI specs into a single JSON file" "dump-openapi.py - assemble the OpenAPI specs into a single JSON file"
@ -266,7 +164,7 @@ for filename in os.listdir(selected_api_dir):
if untagged != 0: if untagged != 0:
print("{} untagged operations, you may want to look into fixing that.".format(untagged)) print("{} untagged operations, you may want to look into fixing that.".format(untagged))
edit_descriptions(output, base_url) edit_links(output, base_url)
print("Generating %s" % output_file) print("Generating %s" % output_file)

View file

@ -1 +0,0 @@
https://matrix.org/funding.json