Compare commits

...

6 commits

Author SHA1 Message Date
Johannes Marbach cdcc2b9a03
Merge 7b3083885b into fca171427f 2025-04-22 17:33:14 +01:00
Kévin Commaille fca171427f
Clarifications around third-party invites (#2083)
Some checks failed
Spec / 🔎 Validate OpenAPI specifications (push) Has been cancelled
Spec / 🔎 Check Event schema examples (push) Has been cancelled
Spec / 🔎 Check OpenAPI definitions examples (push) Has been cancelled
Spec / 🔎 Check JSON Schemas inline examples (push) Has been cancelled
Spec / ⚙️ Calculate baseURL for later jobs (push) Has been cancelled
Spec / 📢 Run towncrier for changelog (push) Has been cancelled
Spell Check / Spell Check with Typos (push) Has been cancelled
Spec / 🐍 Build OpenAPI definitions (push) Has been cancelled
Spec / 📖 Build the spec (push) Has been cancelled
Spec / 🔎 Validate generated HTML (push) Has been cancelled
Spec / 📖 Build the historical backup spec (push) Has been cancelled
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-04-22 15:48:50 +01:00
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
20 changed files with 446 additions and 217 deletions

View file

@ -0,0 +1,2 @@
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

@ -0,0 +1 @@
Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266).

View file

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

View file

@ -0,0 +1,2 @@
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

@ -0,0 +1 @@
Extend `/_matrix/federation/v1/hierarchy/{roomId}` with the new optional properties `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266).

View file

@ -2835,6 +2835,10 @@ re-invited.
{{% http-api spec="client-server" api="list_public_rooms" %}}
### Room Summaries
{{% http-api spec="client-server" api="room_summary" %}}
## User Data
### User Directory

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
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
not. Either way, the client calls [`/invite`](#post_matrixclientv3roomsroomidinvite) with the details of the
third-party identifier.
not. Either way, the client calls [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite)
with the details of the third-party identifier.
The homeserver asks the identity server whether a Matrix user ID is
known for that identifier:
@ -37,10 +37,12 @@ A client asks a server to invite a user by their third-party identifier.
#### Server behaviour
Upon receipt of an [`/invite`](#post_matrixclientv3roomsroomidinvite), the server is expected to look up the
third-party identifier with the provided identity server. If the lookup
yields a result for a Matrix User ID then the normal invite process can
be initiated. This process ends up looking like this:
Upon receipt of an [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite),
the server is expected to look up the third-party identifier with the provided
identity server by making a call to [`/_matrix/identity/v2/lookup`](/identity-service-api/#post_matrixidentityv2lookup).
If the lookup yields a result for a Matrix User ID then the normal [invite
process](/server-server-api/#inviting-to-a-room) can be initiated. This process
ends up looking like this:
```
+---------+ +-------------+ +-----------------+
@ -66,10 +68,11 @@ be initiated. This process ends up looking like this:
| | |
```
However, if the lookup does not yield a bound User ID, the homeserver
must store the invite on the identity server and emit a valid
`m.room.third_party_invite` event to the room. This process ends up
looking like this:
However, if the lookup does not yield a bound User ID, the homeserver must store
the invite on the identity server with a call to
[`/_matrix/identity/v2/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
and emit a valid [`m.room.third_party_invite`](#mroomthird_party_invite) event
to the room. This process ends up looking like this:
```
+---------+ +-------------+ +-----------------+
@ -101,15 +104,18 @@ looking like this:
| | |
```
All homeservers MUST verify the signature in the event's
`content.third_party_invite.signed` object.
The third-party user will then need to verify their identity, which results in a
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).
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.
All homeservers MUST verify the signature in the `m.room.member` event's
`content.third_party_invite.signed` object.
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
@ -193,8 +199,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
correct as well as the `key_validity_url` as still being valid. This is
done by making a request to the [identity server
/isvalid](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
done by making a request to the identity server's
[`/pubkey/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
endpoint, using the provided URL rather than constructing a new one. The
query string and response for the provided URL must match the Identity
Service Specification.

View file

@ -970,9 +970,8 @@ the event to other servers in the room.
## Third-party invites
{{% boxes/note %}}
More information about third-party invites is available in the
[Client-Server API](/client-server-api) under
the Third-party Invites module.
More information about third-party invites is available in the Client-Server API
under the [Third-party invites](/client-server-api/#third-party-invites) module.
{{% /boxes/note %}}
When a user wants to invite another user in a room but doesn't know the
@ -985,38 +984,41 @@ API](/identity-service-api).
### Cases where an association exists for a third-party identifier
If the third-party identifier is already bound to a Matrix ID, a lookup
request on the identity server will return it. The invite is then
processed by the inviting homeserver as a standard `m.room.member`
invite event. This is the simplest case.
If the third-party identifier is already bound to a Matrix ID, a [lookup
request](/identity-service-api/#post_matrixidentityv2lookup) on the identity
server will return it. The invite is then processed by the inviting homeserver
as a [standard `m.room.member` invite event](#inviting-to-a-room). This is the
simplest case.
### 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
homeserver will request the identity server to store an invite for this
identifier and to deliver it to whoever binds it to its Matrix ID. It
will also send an `m.room.third_party_invite` event in the room to
specify a display name, a token and public keys the identity server
provided as a response to the invite storage request.
homeserver will request the identity server to [store an invite](/identity-service-api/#invitation-storage)
for this 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)
event in the room to specify a display name, a token and public keys the
identity server provided as a response to the invite storage request.
When a third-party identifier with pending invites gets bound to a
Matrix ID, the identity server will send a POST request to the ID's
homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage)
section of the Identity Service API.
When a third-party identifier with pending invites gets bound to a Matrix ID,
the identity server will send a request to the [`/3pid/onbind`](#put_matrixfederationv13pidonbind)
endpoint of the the ID's homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage) section of the Identity
Service API.
The following process applies for each invite sent by the identity
server:
The invited homeserver will create an `m.room.member` invite event
containing a special `third_party_invite` section containing the token
and a signed object, both provided by the identity server.
The invited homeserver will create an [`m.room.member`](/client-server-api/#mroommember)
invite event containing a special `third_party_invite` section containing the
token and a `signed` object, both provided by the identity server.
If the invited homeserver is in the room the invite came from, it can
auth the event and send it.
However, if the invited homeserver isn't in the room the invite came
from, it will need to request the room's homeserver to auth the event.
from, it will need to request the inviting 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" %}}

View file

@ -0,0 +1,48 @@
# 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: RoomSummary
allOf:
- $ref: public_rooms_chunk.yaml
- type: object
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
allowed_room_ids:
type: array
items:
type: string
description: |-
If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which
are specified by the join rules. Empty or omitted otherwise.
encryption:
type: string
enum:
- "m.megolm.v1.aes-sha2"
description: |-
The encryption algorithm to be used to encrypt messages sent in the
room.
room_version:
description: The version of the room.
type: string
required:
- room_id
- num_joined_members
- world_readable
- guest_can_join

View file

@ -0,0 +1,138 @@
# 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.
openapi: 3.1.0
info:
title: Matrix Client-Server Room Summary API
version: 1.0.0
paths:
"/room_summary/{roomIdOrAlias}":
get:
x-addedInMatrixVersion: "1.15"
summary: Retrieves a summary for a room.
description: |-
Retrieves a summary for a room.
Clients should note that requests for rooms where the user's membership
is `invite` or `knock` might yield outdated, partial or even no data
since the server may not have access to the current state of the room.
Servers MAY allow unauthenticated access to this API if at least one of
the following conditions holds true:
- The room has a [join rule](#mroomjoin_rules) of `public`, `knock` or
`knock_restricted`.
- The room has a `world_readable` [history visibility](#room-history-visibility).
Servers should consider rate limiting federation requests more heavily,
if the client is unauthenticated.
operationId: getRoomSummary
security:
- signedRequest: []
parameters:
- in: path
name: roomIdOrAlias
description: The room identifier or alias to summarise.
required: true
example: "#monkeys:matrix.org"
schema:
type: string
- in: query
name: via
description: |-
The servers to attempt to request the summary from when
the local server cannot generate it (for instance, because
it has no local user in the room).
example:
- matrix.org
- elsewhere.ca
schema:
type: array
items:
type: string
responses:
"200":
description: A summary of the room.
content:
application/json:
schema:
description: A summary of the room.
allOf:
- $ref: ../client-server/definitions/room_summary.yaml
- type: object
properties:
room_type:
x-addedInMatrixVersion: # Overrides room_summary.yaml
membership:
description: |-
The membership state of the user if the user is joined to the room. Absent
if the API was called unauthenticated.
enum:
- invite
- join
- knock
- leave
- ban
type: string
required:
- guest_can_join
- num_joined_members
- room_id
- world_readable
examples:
response:
value: {
room_id: "!ol19s:bleecker.street",
avatar_url: "mxc://bleecker.street/CHEDDARandBRIE",
guest_can_join: false,
name: "CHEESE",
num_joined_members: 37,
topic: "Tasty tasty cheese",
world_readable: true,
join_rule: "public",
room_type: "m.space",
membership: "invite",
encryption: "m.megolm.v1.aes-sha2",
room_version: "9001",
}
"404":
description: |-
The room could not be found.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_NOT_FOUND",
"error": "Room not found."
}
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
protocol:
enum:
- http
- https
default: https
hostname:
default: localhost:8008
basePath:
default: /_matrix/client/v1
components:
securitySchemes:
accessTokenQuery:
$ref: definitions/security.yaml#/accessTokenQuery
accessTokenBearer:
$ref: definitions/security.yaml#/accessTokenBearer

View file

@ -102,15 +102,10 @@ paths:
* The room's [`m.room.history_visibility`](#room-history-visibility) is set to `world_readable`.
items:
allOf:
- $ref: definitions/public_rooms_chunk.yaml
- $ref: definitions/room_summary.yaml
- type: object
title: SpaceHierarchyRoomsChunk
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
children_state:
type: array
description: |-
@ -130,6 +125,12 @@ paths:
description: The `origin_server_ts` for the event.
required:
- origin_server_ts
allowed_room_ids:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
encryption:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
room_version:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
required:
- children_state
next_batch:

View file

@ -57,9 +57,6 @@ paths:
- A signature of the token, signed with the identity server's private key
- 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
security:
- accessTokenQuery: []
@ -72,6 +69,8 @@ paths:
example: "!d41d8cd:matrix.org"
schema:
type: string
format: mx-room-id
pattern: "^!"
requestBody:
content:
application/json:
@ -90,7 +89,9 @@ paths:
value: {}
"403":
description: |-
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:
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:
- The invitee has been banned from the room.
- The invitee is already a member of the room.

View file

@ -43,7 +43,8 @@ paths:
properties:
public_key:
type: string
description: Unpadded Base64 encoded public key.
description: |-
[Unpadded Base64](/appendices/#unpadded-base64)-encoded public key.
required:
- public_key
examples:
@ -74,7 +75,8 @@ paths:
- in: query
name: public_key
required: true
description: The unpadded base64-encoded public key to check.
description: |-
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public key to check.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema:
type: string
@ -105,7 +107,14 @@ paths:
- in: query
name: public_key
required: true
description: The unpadded base64-encoded public key to check.
description: |-
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
schema:
type: string

View file

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

View file

@ -61,22 +61,10 @@ paths:
room:
description: A summary of the room requested.
allOf:
- $ref: ../client-server/definitions/public_rooms_chunk.yaml
- $ref: ../client-server/definitions/room_summary.yaml
- type: object
title: SpaceHierarchyParentRoom
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
allowed_room_ids:
type: array
items:
type: string
description: |-
If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which
are specified by the join rules. Empty or omitted otherwise.
children_state:
type: array
description: |-
@ -96,6 +84,10 @@ paths:
description: The `origin_server_ts` for the event.
required:
- origin_server_ts
encryption:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
room_version:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
required:
- children_state
children:
@ -105,22 +97,14 @@ paths:
be excluded.
items:
allOf:
- $ref: ../client-server/definitions/public_rooms_chunk.yaml
- $ref: ../client-server/definitions/room_summary.yaml
- type: object
title: SpaceHierarchyChildRoomsChunk
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
allowed_room_ids:
type: array
items:
type: string
description: |-
If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which
are specified by the join rules. Empty or omitted otherwise.
encryption:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
room_version:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
inaccessible_children:
type: array
items:

View file

@ -35,6 +35,8 @@ paths:
example: "!abc123:matrix.org"
schema:
type: string
format: mx-room-id
pattern: "^!"
requestBody:
content:
application/json:
@ -50,16 +52,22 @@ paths:
description: |-
The room ID the event is for. Must match the ID given in
the path.
format: mx-room-id
pattern: "^!"
example: "!abc123:matrix.org"
sender:
type: string
description: |-
The user ID of the user who sent the original `m.room.third_party_invite`
event.
format: mx-user-id
pattern: "^@"
example: "@joe:matrix.org"
state_key:
type: string
description: The user ID of the invited user
format: mx-user-id
pattern: "^@"
example: "@someone:example.org"
content:
type: object
@ -82,45 +90,7 @@ paths:
third-party identifier.
example: alice
signed:
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
$ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml
required:
- display_name
- signed
@ -215,6 +185,8 @@ paths:
mxid:
type: string
description: The user that is now bound to the third-party identifier.
format: mx-user-id
pattern: "^@"
example: "@alice:matrix.org"
invites:
type: array
@ -237,59 +209,23 @@ paths:
mxid:
type: string
description: The now-bound user ID that received the invite.
format: mx-user-id
pattern: "^@"
example: "@alice:matrix.org"
room_id:
type: string
description: The room ID the invite is valid for.
format: mx-room-id
pattern: "^!"
example: "!somewhere:example.org"
sender:
type: string
description: The user ID that sent the invite.
format: mx-user-id
pattern: "^@"
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:
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
$ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml
required:
- medium
- address

View file

@ -0,0 +1,45 @@
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,17 +2,27 @@
allOf:
- $ref: core-event-schema/state_event.yaml
description: |-
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.
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.
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 participate in the room until they join.
- `join` - The user has joined the room (possibly after accepting an invite), and may participate in it.
- `leave` - The user was once joined to the room, but has since left (possibly by choice, or 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.
- `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.
- `join` - The user has joined the room (possibly after accepting an invite), and may participate
in it.
- `leave` - The user was once joined to the room, but has since left (possibly by choice, or
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 successor of an `m.room.third_party_invite` event, and absent otherwise.
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`](/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.
If present, this contains an array of [stripped state events](/client-server-api/#stripped-state)
@ -57,63 +67,54 @@ properties:
- ban
type: string
is_direct:
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).
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).
type: boolean
join_authorised_via_users_server:
x-addedInMatrixVersion: "1.2"
type: string
description: |-
Usually found on `join` events, this field is used to denote which homeserver (through representation of a user with sufficient power level)
authorised the user's join. More information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms).
Usually found on `join` events, this field is used to denote which homeserver (through
representation of a user with sufficient power level) authorised the user's join. More
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) of including this
field in further events: in particular, the event must be signed by the server which
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 copy, as otherwise the event might fail event authorization.
Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules)
of including this field in further events: in particular, the event must be signed by the
server which 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
copy, as otherwise the event might fail event authorization.
reason:
x-addedInMatrixVersion: "1.1"
type: string
description: |-
Optional user-supplied text for why their membership has changed. For kicks and bans, this is typically the reason for the kick or ban.
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
as in a case where Bob rejects an invite from Alice about an upcoming concert, but can't make it that day.
Optional user-supplied text for why their membership has changed. For kicks and bans,
this is typically the reason for the kick or ban. 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 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 the potential for spam and abuse. Hiding the
reason behind a button or other component is recommended.
Clients are not recommended to show this reason to users when receiving an invite due to
the potential for spam and abuse. Hiding the reason behind a button or other component is
recommended.
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:
display_name:
description: A name which can be displayed to represent the user instead of their third-party identifier
description: |-
A name which can be displayed to represent the user instead of their
third-party identifier
type: string
signed:
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
$ref: components/signed_third_party_invite.yaml
required:
- display_name
- signed
title: Invite
type: object
required:
- membership
title: EventContent

View file

@ -1,28 +1,56 @@
---
allOf:
- $ref: core-event-schema/state_event.yaml
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."
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.
properties:
content:
properties:
display_name:
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."
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.
type: string
key_validity_url:
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'."
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'.
type: string
format: uri
public_key:
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.
description: |-
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
public_keys:
description: Keys with which the token may be signed.
items:
properties:
key_validity_url:
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."
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.
type: string
public_key:
description: A base-64 encoded ed25519 key with which token may be signed.
description: |-
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
required:
- public_key
@ -35,11 +63,15 @@ properties:
- public_key
type: object
state_key:
description: 'The token, of which a signature must be produced in order to join the room.'
description: |-
The token, of which a signature must be produced in order to join the
room.
type: string
type:
enum:
- m.room.third_party_invite
type: string
title: 'An invitation to a room issued to a third-party identifier, rather than a matrix user ID.'
title: |-
An invitation to a room issued to a third-party identifier, rather than a
matrix user ID.
type: object

View file

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