mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-01-26 00:53:42 +01:00
Merge branch 'master' into matthew/msc1779
This commit is contained in:
commit
efcbf2f807
|
|
@ -98,8 +98,10 @@ the ``newsfragments`` directory. The ``type`` can be one of the following:
|
||||||
|
|
||||||
* ``deprecation`` - Used when deprecating something
|
* ``deprecation`` - Used when deprecating something
|
||||||
|
|
||||||
All news fragments must have a brief summary explaining the change in the contents
|
All news fragments must have a brief summary explaining the change in the
|
||||||
of the file. The summary must end in a full stop to be in line with the style guide.
|
contents of the file. The summary must end in a full stop to be in line with
|
||||||
|
the style guide and and formatting must be done using `Restructured Text
|
||||||
|
<http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_.
|
||||||
|
|
||||||
Changes that do not change the spec, such as changes to the build script, formatting,
|
Changes that do not change the spec, such as changes to the build script, formatting,
|
||||||
CSS, etc should not get a news fragment.
|
CSS, etc should not get a news fragment.
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,12 @@ def check_response(filepath, request, code, response):
|
||||||
filepath, request, code
|
filepath, request, code
|
||||||
))
|
))
|
||||||
check_schema(filepath, example, schema)
|
check_schema(filepath, example, schema)
|
||||||
|
except jsonschema.SchemaError as error:
|
||||||
|
for suberror in sorted(error.context, key=lambda e: e.schema_path):
|
||||||
|
print(list(suberror.schema_path), suberror.message, sep=", ")
|
||||||
|
raise ValueError("Error validating JSON schema for %r %r" % (
|
||||||
|
request, code
|
||||||
|
), e)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError("Error validating JSON schema for %r %r" % (
|
raise ValueError("Error validating JSON schema for %r %r" % (
|
||||||
request, code
|
request, code
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ paths:
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
description: |-
|
description: |-
|
||||||
The id of the user to set account_data for. The access token must be
|
The ID of the user to set account_data for. The access token must be
|
||||||
authorized to make requests for this user id.
|
authorized to make requests for this user ID.
|
||||||
x-example: "@alice:example.com"
|
x-example: "@alice:example.com"
|
||||||
- in: path
|
- in: path
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -69,6 +69,41 @@ paths:
|
||||||
The account_data was successfully added.
|
The account_data was successfully added.
|
||||||
tags:
|
tags:
|
||||||
- User data
|
- User data
|
||||||
|
get:
|
||||||
|
summary: Get some account_data for the user.
|
||||||
|
description: |-
|
||||||
|
Get some account_data for the client. This config is only visible to the user
|
||||||
|
that set the account_data.
|
||||||
|
operationId: getAccountData
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: userId
|
||||||
|
required: true
|
||||||
|
description: |-
|
||||||
|
The ID of the user to get account_data for. The access token must be
|
||||||
|
authorized to make requests for this user ID.
|
||||||
|
x-example: "@alice:example.com"
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: type
|
||||||
|
required: true
|
||||||
|
description: |-
|
||||||
|
The event type of the account_data to get. Custom types should be
|
||||||
|
namespaced to avoid clashes.
|
||||||
|
x-example: "org.example.custom.config"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The account data content for the given type.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
example: {
|
||||||
|
"custom_account_data_key": "custom_config_value"}
|
||||||
|
tags:
|
||||||
|
- User data
|
||||||
"/user/{userId}/rooms/{roomId}/account_data/{type}":
|
"/user/{userId}/rooms/{roomId}/account_data/{type}":
|
||||||
put:
|
put:
|
||||||
summary: Set some account_data for the user.
|
summary: Set some account_data for the user.
|
||||||
|
|
@ -85,15 +120,15 @@ paths:
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
description: |-
|
description: |-
|
||||||
The id of the user to set account_data for. The access token must be
|
The ID of the user to set account_data for. The access token must be
|
||||||
authorized to make requests for this user id.
|
authorized to make requests for this user ID.
|
||||||
x-example: "@alice:example.com"
|
x-example: "@alice:example.com"
|
||||||
- in: path
|
- in: path
|
||||||
type: string
|
type: string
|
||||||
name: roomId
|
name: roomId
|
||||||
required: true
|
required: true
|
||||||
description: |-
|
description: |-
|
||||||
The id of the room to set account_data on.
|
The ID of the room to set account_data on.
|
||||||
x-example: "!726s6s6q:example.com"
|
x-example: "!726s6s6q:example.com"
|
||||||
- in: path
|
- in: path
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -118,3 +153,45 @@ paths:
|
||||||
The account_data was successfully added.
|
The account_data was successfully added.
|
||||||
tags:
|
tags:
|
||||||
- User data
|
- User data
|
||||||
|
get:
|
||||||
|
summary: Get some account_data for the user.
|
||||||
|
description: |-
|
||||||
|
Get some account_data for the client on a given room. This config is only
|
||||||
|
visible to the user that set the account_data.
|
||||||
|
operationId: getAccountDataPerRoom
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: userId
|
||||||
|
required: true
|
||||||
|
description: |-
|
||||||
|
The ID of the user to set account_data for. The access token must be
|
||||||
|
authorized to make requests for this user ID.
|
||||||
|
x-example: "@alice:example.com"
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: roomId
|
||||||
|
required: true
|
||||||
|
description: |-
|
||||||
|
The ID of the room to get account_data for.
|
||||||
|
x-example: "!726s6s6q:example.com"
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: type
|
||||||
|
required: true
|
||||||
|
description: |-
|
||||||
|
The event type of the account_data to get. Custom types should be
|
||||||
|
namespaced to avoid clashes.
|
||||||
|
x-example: "org.example.custom.room.config"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The account data content for the given type.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
example: {
|
||||||
|
"custom_account_data_key": "custom_config_value"}
|
||||||
|
tags:
|
||||||
|
- User data
|
||||||
|
|
|
||||||
112
api/client-server/capabilities.yaml
Normal file
112
api/client-server/capabilities.yaml
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
# Copyright 2019 New Vector Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Client-Server Capabiltiies API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8008
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
- http
|
||||||
|
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/capabilities":
|
||||||
|
get:
|
||||||
|
summary: Gets information about the server's capabilities.
|
||||||
|
description: |-
|
||||||
|
Gets information about the server's supported feature set
|
||||||
|
and other relevant capabilities.
|
||||||
|
operationId: getCapabilities
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The capabilities of the server.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"capabilities": {
|
||||||
|
"m.change_password": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"m.room_versions": {
|
||||||
|
"default": "1",
|
||||||
|
"available": {
|
||||||
|
"1": "stable",
|
||||||
|
"2": "stable",
|
||||||
|
"3": "unstable",
|
||||||
|
"test-version": "unstable"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.example.custom.ratelimit": {
|
||||||
|
"max_requests_per_hour": 600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required: ["capabilities"]
|
||||||
|
properties:
|
||||||
|
capabilities:
|
||||||
|
type: object
|
||||||
|
title: Capabilities
|
||||||
|
description: |-
|
||||||
|
The custom capabilities the server supports, using the
|
||||||
|
Java package naming convention.
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
"m.change_password":
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Capability to indicate if the user can change their password.
|
||||||
|
title: ChangePasswordCapability
|
||||||
|
properties:
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
description: |-
|
||||||
|
True if the user can change their password, false otherwise.
|
||||||
|
example: false
|
||||||
|
required: ['enabled']
|
||||||
|
"m.room_versions":
|
||||||
|
type: object
|
||||||
|
description: The room versions the server supports.
|
||||||
|
title: RoomVersionsCapability
|
||||||
|
properties:
|
||||||
|
default:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The default room version the server is using for new rooms.
|
||||||
|
example: "1"
|
||||||
|
available:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
A detailed description of the room versions the server supports.
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
title: RoomVersionStability
|
||||||
|
enum: [stable, unstable]
|
||||||
|
description: The stability of the room version.
|
||||||
|
required: ['default', 'available']
|
||||||
|
429:
|
||||||
|
description: This request was rate-limited.
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/rate_limited.yaml"
|
||||||
|
tags:
|
||||||
|
- Capabilities
|
||||||
|
|
@ -244,6 +244,12 @@ paths:
|
||||||
invalid: for example, the user's ``power_level`` is set below
|
invalid: for example, the user's ``power_level`` is set below
|
||||||
that necessary to set the room name (``errcode`` set to
|
that necessary to set the room name (``errcode`` set to
|
||||||
``M_INVALID_ROOM_STATE``).
|
``M_INVALID_ROOM_STATE``).
|
||||||
|
|
||||||
|
- The homeserver doesn't support the requested room version, or
|
||||||
|
one or more users being invited to the new room are residents
|
||||||
|
of a homeserver which does not support the requested room version.
|
||||||
|
The ``errcode`` will be ``M_UNSUPPORTED_ROOM_VERSION`` in these
|
||||||
|
cases.
|
||||||
schema:
|
schema:
|
||||||
"$ref": "definitions/errors/error.yaml"
|
"$ref": "definitions/errors/error.yaml"
|
||||||
tags:
|
tags:
|
||||||
|
|
|
||||||
39
api/client-server/definitions/wellknown/full.yaml
Normal file
39
api/client-server/definitions/wellknown/full.yaml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Copyright 2019 New Vector Ltd
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
title: Discovery Information
|
||||||
|
description: |-
|
||||||
|
Used by clients to determine the homeserver, identity server, and other
|
||||||
|
optional components they should be interacting with.
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
"m.homeserver":
|
||||||
|
$ref: "homeserver.yaml"
|
||||||
|
"m.identity_server":
|
||||||
|
$ref: "identity_server.yaml"
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
description: Application-dependent keys using Java package naming convention.
|
||||||
|
required:
|
||||||
|
- m.homeserver
|
||||||
|
example: {
|
||||||
|
"m.homeserver": {
|
||||||
|
"base_url": "https://matrix.example.com"
|
||||||
|
},
|
||||||
|
"m.identity_server": {
|
||||||
|
"base_url": "https://identity.example.com"
|
||||||
|
},
|
||||||
|
"org.example.custom.property": {
|
||||||
|
"app_url": "https://custom.app.example.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -82,6 +82,20 @@ paths:
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
|
||||||
|
The request is invalid. A meaningful ``errcode`` and description
|
||||||
|
error text will be returned. Example reasons for rejection include:
|
||||||
|
|
||||||
|
- The request body is malformed (``errcode`` set to ``M_BAD_JSON``
|
||||||
|
or ``M_NOT_JSON``).
|
||||||
|
|
||||||
|
- One or more users being invited to the room are residents of a
|
||||||
|
homeserver which does not support the requested room version. The
|
||||||
|
``errcode`` will be ``M_UNSUPPORTED_ROOM_VERSION`` in these cases.
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
403:
|
403:
|
||||||
description: |-
|
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:
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,15 @@ paths:
|
||||||
application/json: {
|
application/json: {
|
||||||
"user_id": "@cheeky_monkey:matrix.org",
|
"user_id": "@cheeky_monkey:matrix.org",
|
||||||
"access_token": "abc123",
|
"access_token": "abc123",
|
||||||
"device_id": "GHTYAJCE"
|
"device_id": "GHTYAJCE",
|
||||||
|
"well_known": {
|
||||||
|
"m.homeserver": {
|
||||||
|
"base_url": "https://example.org"
|
||||||
|
},
|
||||||
|
"m.identity_server": {
|
||||||
|
"base_url": "https://id.example.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -166,6 +174,14 @@ paths:
|
||||||
description: |-
|
description: |-
|
||||||
ID of the logged-in device. Will be the same as the
|
ID of the logged-in device. Will be the same as the
|
||||||
corresponding parameter in the request, if one was specified.
|
corresponding parameter in the request, if one was specified.
|
||||||
|
well_known:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Optional client configuration provided by the server. If present,
|
||||||
|
clients SHOULD use the provided object to reconfigure themselves,
|
||||||
|
optionally validating the URLs within. This object takes the same
|
||||||
|
form as the one returned from .well-known autodiscovery.
|
||||||
|
"$ref": "definitions/wellknown/full.yaml"
|
||||||
400:
|
400:
|
||||||
description: |-
|
description: |-
|
||||||
Part of the request was invalid. For example, the login type may not be recognised.
|
Part of the request was invalid. For example, the login type may not be recognised.
|
||||||
|
|
|
||||||
|
|
@ -136,103 +136,3 @@ paths:
|
||||||
"$ref": "definitions/errors/error.yaml"
|
"$ref": "definitions/errors/error.yaml"
|
||||||
tags:
|
tags:
|
||||||
- Presence
|
- Presence
|
||||||
"/presence/list/{userId}":
|
|
||||||
post:
|
|
||||||
summary: Add or remove users from this presence list.
|
|
||||||
description: |-
|
|
||||||
Adds or removes users from this presence list.
|
|
||||||
operationId: modifyPresenceList
|
|
||||||
security:
|
|
||||||
- accessToken: []
|
|
||||||
parameters:
|
|
||||||
- in: path
|
|
||||||
type: string
|
|
||||||
name: userId
|
|
||||||
description: The user whose presence list is being modified.
|
|
||||||
required: true
|
|
||||||
x-example: "@alice:example.com"
|
|
||||||
- in: body
|
|
||||||
name: presence_diff
|
|
||||||
description: The modifications to make to this presence list.
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
example: {
|
|
||||||
"invite": [
|
|
||||||
"@bob:matrix.org"
|
|
||||||
],
|
|
||||||
"drop": [
|
|
||||||
"@alice:matrix.org"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
invite:
|
|
||||||
type: array
|
|
||||||
description: A list of user IDs to add to the list.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: A list of user IDs.
|
|
||||||
drop:
|
|
||||||
type: array
|
|
||||||
description: A list of user IDs to remove from the list.
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: A list of user IDs.
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: The list was updated.
|
|
||||||
examples:
|
|
||||||
application/json: {
|
|
||||||
}
|
|
||||||
schema:
|
|
||||||
type: object # empty json object
|
|
||||||
429:
|
|
||||||
description: This request was rate-limited.
|
|
||||||
schema:
|
|
||||||
"$ref": "definitions/errors/rate_limited.yaml"
|
|
||||||
tags:
|
|
||||||
- Presence
|
|
||||||
get:
|
|
||||||
summary: Get presence events for this presence list.
|
|
||||||
description: |-
|
|
||||||
Retrieve a list of presence events for every user on this list.
|
|
||||||
operationId: getPresenceForList
|
|
||||||
parameters:
|
|
||||||
- in: path
|
|
||||||
type: string
|
|
||||||
name: userId
|
|
||||||
description: The user whose presence list should be retrieved.
|
|
||||||
required: true
|
|
||||||
x-example: "@alice:example.com"
|
|
||||||
responses:
|
|
||||||
200:
|
|
||||||
description: A list of presence events for this list.
|
|
||||||
examples:
|
|
||||||
application/json: [
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"last_active_ago": 395,
|
|
||||||
"presence": "offline",
|
|
||||||
"user_id": "@alice:matrix.org"
|
|
||||||
},
|
|
||||||
"type": "m.presence"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"last_active_ago": 16874,
|
|
||||||
"presence": "online",
|
|
||||||
"user_id": "@marisa:matrix.org",
|
|
||||||
"currently_active": true
|
|
||||||
},
|
|
||||||
"type": "m.presence"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
title: PresenceEvent
|
|
||||||
allOf:
|
|
||||||
- "$ref": "definitions/event-schemas/schema/core-event-schema/event.yaml"
|
|
||||||
tags:
|
|
||||||
- Presence
|
|
||||||
|
|
|
||||||
93
api/client-server/room_upgrades.yaml
Normal file
93
api/client-server/room_upgrades.yaml
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Copyright 2019 New Vector Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Client-Server Room Upgrades API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8008
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
- http
|
||||||
|
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/rooms/{roomId}/upgrade":
|
||||||
|
post:
|
||||||
|
summary: Upgrades a room to a new room version.
|
||||||
|
description: |-
|
||||||
|
Upgrades the given room to a particular room version.
|
||||||
|
operationId: upgradeRoom
|
||||||
|
security:
|
||||||
|
- accessToken: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
type: string
|
||||||
|
name: roomId
|
||||||
|
required: true
|
||||||
|
description: The ID of the room to upgrade.
|
||||||
|
x-example: "!oldroom:example.org"
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
required: true
|
||||||
|
description: The request body
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
new_version:
|
||||||
|
type: string
|
||||||
|
description: The new version for the room.
|
||||||
|
example: {"new_version": "2"}
|
||||||
|
required: [new_version]
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: The room was successfully upgraded.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"replacement_room": "!newroom:example.org"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
replacement_room:
|
||||||
|
type: string
|
||||||
|
description: The ID of the new room.
|
||||||
|
required: [replacement_room]
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
The request was invalid. One way this can happen is if the room version
|
||||||
|
requested is not supported by the homeserver.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_UNSUPPORTED_ROOM_VERSION",
|
||||||
|
"error": "This server does not support that room version"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The user is not permitted to upgrade the room.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You cannot upgrade this room"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
|
tags:
|
||||||
|
- Room ugprades
|
||||||
|
|
@ -33,13 +33,29 @@ paths:
|
||||||
|
|
||||||
Only the latest ``Z`` value will be reported for each supported ``X.Y`` value.
|
Only the latest ``Z`` value will be reported for each supported ``X.Y`` value.
|
||||||
i.e. if the server implements ``r0.0.0``, ``r0.0.1``, and ``r1.2.0``, it will report ``r0.0.1`` and ``r1.2.0``.
|
i.e. if the server implements ``r0.0.0``, ``r0.0.1``, and ``r1.2.0``, it will report ``r0.0.1`` and ``r1.2.0``.
|
||||||
|
|
||||||
|
The server may additionally advertise experimental features it supports
|
||||||
|
through ``unstable_features``. These features should be namespaced and
|
||||||
|
may optionally include version information within their name if desired.
|
||||||
|
Features listed here are not for optionally toggling parts of the Matrix
|
||||||
|
specification and should only be used to advertise support for a feature
|
||||||
|
which has not yet landed in the spec. For example, a feature currently
|
||||||
|
undergoing the proposal process may appear here and eventually be taken
|
||||||
|
off this list once the feature lands in the spec and the server deems it
|
||||||
|
reasonable to do so. Servers may wish to keep advertising features here
|
||||||
|
after they've been released into the spec to give clients a chance to
|
||||||
|
upgrade appropriately. Additionally, clients should avoid using unstable
|
||||||
|
features in their stable releases.
|
||||||
operationId: getVersions
|
operationId: getVersions
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: The versions supported by the server.
|
description: The versions supported by the server.
|
||||||
examples:
|
examples:
|
||||||
application/json: {
|
application/json: {
|
||||||
"versions": ["r0.0.1"]
|
"versions": ["r0.0.1"],
|
||||||
|
"unstable_features": {
|
||||||
|
"org.example.my_feature": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -50,5 +66,15 @@ paths:
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
description: The supported versions
|
description: The supported versions
|
||||||
|
unstable_features:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Experimental features the server supports. Features not listed here,
|
||||||
|
or the lack of this property all together, indicate that a feature is
|
||||||
|
not supported.
|
||||||
|
additionalProperties:
|
||||||
|
type: boolean
|
||||||
|
description: Whether or not the namespaced feature is supported.
|
||||||
|
required: ['versions']
|
||||||
tags:
|
tags:
|
||||||
- Server administration
|
- Server administration
|
||||||
|
|
|
||||||
|
|
@ -38,28 +38,9 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: Server discovery information.
|
description: Server discovery information.
|
||||||
examples:
|
|
||||||
application/json: {
|
|
||||||
"m.homeserver": {
|
|
||||||
"base_url": "https://matrix.example.com"
|
|
||||||
},
|
|
||||||
"m.identity_server": {
|
|
||||||
"base_url": "https://identity.example.com"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
"$ref": "definitions/wellknown/full.yaml"
|
||||||
m.homeserver:
|
|
||||||
description: Information about the homeserver to connect to.
|
|
||||||
"$ref": "definitions/wellknown/homeserver.yaml"
|
|
||||||
m.identity_server:
|
|
||||||
description: Optional. Information about the identity server to connect to.
|
|
||||||
"$ref": "definitions/wellknown/identity_server.yaml"
|
|
||||||
additionalProperties:
|
|
||||||
description: Application-dependent keys using Java package naming convention.
|
|
||||||
required:
|
|
||||||
- m.homeserver
|
|
||||||
404:
|
404:
|
||||||
description: No server discovery information available.
|
description: No server discovery information available.
|
||||||
tags:
|
tags:
|
||||||
|
|
|
||||||
|
|
@ -65,22 +65,6 @@ paths:
|
||||||
event(s), up to the given limit.
|
event(s), up to the given limit.
|
||||||
schema:
|
schema:
|
||||||
$ref: "definitions/transaction.yaml"
|
$ref: "definitions/transaction.yaml"
|
||||||
# Override the example to show the response of the request a bit better
|
|
||||||
examples:
|
|
||||||
application/json: {
|
|
||||||
"$ref": "examples/transaction.json",
|
|
||||||
"pdus": [
|
|
||||||
{
|
|
||||||
"$ref": "pdu.json",
|
|
||||||
"room_id": "!SomeRoom:matrix.org",
|
|
||||||
"event_id": "$abc123:matrix.org"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "pdu.json",
|
|
||||||
"room_id": "!SomeRoom:matrix.org"
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
"/get_missing_events/{roomId}":
|
"/get_missing_events/{roomId}":
|
||||||
post:
|
post:
|
||||||
summary: Retrieves events that the sender is missing
|
summary: Retrieves events that the sender is missing
|
||||||
|
|
@ -114,14 +98,14 @@ paths:
|
||||||
earliest_events:
|
earliest_events:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
The latest events that the sender already has. These are skipped when retrieving
|
The latest event IDs that the sender already has. These are skipped when retrieving
|
||||||
the previous events of ``latest_events``.
|
the previous events of ``latest_events``.
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: ["$missing_event:example.org"]
|
example: ["$missing_event:example.org"]
|
||||||
latest_events:
|
latest_events:
|
||||||
type: array
|
type: array
|
||||||
description: The events to retrieve the previous events for.
|
description: The event IDs to retrieve the previous events for.
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
example: ["$event_that_has_the_missing_event_as_a_previous_event:example.org"]
|
example: ["$event_that_has_the_missing_event_as_a_previous_event:example.org"]
|
||||||
|
|
@ -136,13 +120,16 @@ paths:
|
||||||
properties:
|
properties:
|
||||||
events:
|
events:
|
||||||
type: array
|
type: array
|
||||||
description: The missing events.
|
description: |-
|
||||||
|
The missing events. The event format varies depending on the room version - check
|
||||||
|
the `room version specification`_ for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: definitions/pdu.yaml
|
type: object
|
||||||
|
title: PDU
|
||||||
required: ['events']
|
required: ['events']
|
||||||
examples:
|
examples:
|
||||||
application/json: {
|
application/json: {
|
||||||
"events": [
|
"events": [
|
||||||
{"$ref": "examples/pdu.json"}
|
{"$ref": "examples/minimal_pdu.json"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ description: |-
|
||||||
|
|
||||||
# FIXME: It's very unclear why we have this API surface for synchronising
|
# FIXME: It's very unclear why we have this API surface for synchronising
|
||||||
# device lists, rather than just using a room (which could also be used for
|
# device lists, rather than just using a room (which could also be used for
|
||||||
# presence lists, profile info, etc). But documenting what we have for now...
|
# profile info, etc). But documenting what we have for now...
|
||||||
|
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ../edu.yaml
|
- $ref: ../edu.yaml
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
# Copyright 2018 New Vector Ltd
|
|
||||||
#
|
|
||||||
# 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: m.presence_accept
|
|
||||||
description: |-
|
|
||||||
An EDU representing approval for the observing user to subscribe to the
|
|
||||||
presence of the the observed user.
|
|
||||||
allOf:
|
|
||||||
- $ref: ../edu.yaml
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
edu_type:
|
|
||||||
type: enum
|
|
||||||
enum: ['m.presence_accept']
|
|
||||||
description: The string ``m.presence_accept``
|
|
||||||
example: "m.presence_accept"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
description: The invite information.
|
|
||||||
title: Invite Information
|
|
||||||
properties:
|
|
||||||
observed_user:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The user ID that has approved the ``observer_user`` to
|
|
||||||
subscribe to their presence.
|
|
||||||
example: "@alice:elsewhere.com"
|
|
||||||
observer_user:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The user ID that requested to subscribe to the presence of
|
|
||||||
the ``observed_user``.
|
|
||||||
example: "@john:matrix.org"
|
|
||||||
required: ['observer_user', 'observed_user']
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
# Copyright 2018 New Vector Ltd
|
|
||||||
#
|
|
||||||
# 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: m.presence_deny
|
|
||||||
description: |-
|
|
||||||
An EDU representing a declination or revocation for the observing user
|
|
||||||
to subscribe to the presence of the observed user.
|
|
||||||
example: {
|
|
||||||
"origin": "example.org",
|
|
||||||
"destination": "elsewhere.org",
|
|
||||||
"edu_type": "m.presence_deny",
|
|
||||||
"content": {
|
|
||||||
"observed_user": "@alice:elsewhere.org",
|
|
||||||
"observer_user": "@john:example.org"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allOf:
|
|
||||||
- $ref: ../edu.yaml
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
edu_type:
|
|
||||||
type: enum
|
|
||||||
enum: ['m.presence_deny']
|
|
||||||
description: The string ``m.presence_deny``
|
|
||||||
example: "m.presence_deny"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
description: The invite information.
|
|
||||||
title: Invite Information
|
|
||||||
properties:
|
|
||||||
observed_user:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The user ID that has declined or revoked the ``observer_user`` from
|
|
||||||
subscribing to their presence.
|
|
||||||
example: "@alice:elsewhere.com"
|
|
||||||
observer_user:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The user ID that requested to subscribe to the presence of
|
|
||||||
the ``observed_user``.
|
|
||||||
example: "@john:matrix.org"
|
|
||||||
required: ['observer_user', 'observed_user']
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
# Copyright 2018 New Vector Ltd
|
|
||||||
#
|
|
||||||
# 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: m.presence_invite
|
|
||||||
description: |-
|
|
||||||
An EDU representing a request to subscribe to a user's presence.
|
|
||||||
allOf:
|
|
||||||
- $ref: ../edu.yaml
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
edu_type:
|
|
||||||
type: enum
|
|
||||||
enum: ['m.presence_invite']
|
|
||||||
description: The string ``m.presence_invite``
|
|
||||||
example: "m.presence_invite"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
description: The invite information.
|
|
||||||
title: Invite Information
|
|
||||||
properties:
|
|
||||||
observed_user:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The user ID the ``observer_user`` would like to subscribe
|
|
||||||
to the presence of.
|
|
||||||
example: "@alice:elsewhere.com"
|
|
||||||
observer_user:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
The user ID that is wishing to subscribe to the presence of
|
|
||||||
the ``observed_user``.
|
|
||||||
example: "@john:matrix.org"
|
|
||||||
required: ['observer_user', 'observed_user']
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2018 New Vector Ltd
|
# Copyright 2018-2019 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
|
@ -13,15 +13,14 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
type: object
|
type: object
|
||||||
title: Invite Event
|
title: Invite Event
|
||||||
description: An invite event
|
description: |-
|
||||||
|
An invite event. Note that events have a different format depending on the
|
||||||
|
room version - check the `room version specification`_ for precise event formats.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: "pdu.yaml"
|
|
||||||
- type: object
|
- type: object
|
||||||
properties:
|
properties:
|
||||||
# Note: we override a bunch of parameters to change their descriptions
|
|
||||||
sender:
|
sender:
|
||||||
type: string
|
type: string
|
||||||
# TODO: Verify/clarify this - it doesn't seem right, given this is a 'regular' invite
|
|
||||||
description: |-
|
description: |-
|
||||||
The matrix ID of the user who sent the original ``m.room.third_party_invite``.
|
The matrix ID of the user who sent the original ``m.room.third_party_invite``.
|
||||||
example: "@someone:example.org"
|
example: "@someone:example.org"
|
||||||
|
|
@ -55,33 +54,10 @@ allOf:
|
||||||
description: The value ``invite``.
|
description: The value ``invite``.
|
||||||
example: "invite"
|
example: "invite"
|
||||||
required: ['membership']
|
required: ['membership']
|
||||||
auth_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
An event reference list containing the authorization events that would
|
|
||||||
allow the member to be invited to the room.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
redacts:
|
|
||||||
type: string
|
|
||||||
description: Not used.
|
|
||||||
required:
|
required:
|
||||||
# Every other field is already flagged as required by the $ref
|
|
||||||
- state_key
|
- state_key
|
||||||
|
- sender
|
||||||
|
- origin
|
||||||
|
- origin_server_ts
|
||||||
|
- type
|
||||||
|
- content
|
||||||
|
|
|
||||||
|
|
@ -90,17 +90,6 @@ properties:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
name: Encoded Signature Verification Key
|
name: Encoded Signature Verification Key
|
||||||
tls_fingerprints:
|
|
||||||
type: array
|
|
||||||
description: Hashes of X.509 TLS certificates used by this server.
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
title: TLS Fingerprint
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The `Unpadded Base64`_ encoded fingerprint.
|
|
||||||
example: "VGhpcyBpcyBoYXNoIHdoaWNoIHNob3VsZCBiZSBieXRlcw"
|
|
||||||
valid_until_ts:
|
valid_until_ts:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
type: object
|
type: object
|
||||||
title: Persistent Data Unit
|
title: Persistent Data Unit
|
||||||
description: A persistent data unit (event)
|
description: A persistent data unit (event) for room versions 1 and 2.
|
||||||
example:
|
example:
|
||||||
$ref: "../examples/pdu.json"
|
$ref: "../examples/pdu.json"
|
||||||
allOf:
|
allOf:
|
||||||
|
|
@ -26,13 +26,13 @@ allOf:
|
||||||
description: |-
|
description: |-
|
||||||
Content hashes of the PDU, following the algorithm specified in `Signing Events`_.
|
Content hashes of the PDU, following the algorithm specified in `Signing Events`_.
|
||||||
example: {
|
example: {
|
||||||
"sha256": "thishashcoversallfieldsincasethisisredacted"
|
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||||
}
|
}
|
||||||
properties:
|
properties:
|
||||||
sha256:
|
sha256:
|
||||||
type: string
|
type: string
|
||||||
description: The hash.
|
description: The hash.
|
||||||
example: thishashcoversallfieldsincasthisisredacted
|
example: ThisHashCoversAllFieldsInCaseThisIsRedacted
|
||||||
required: ['sha256']
|
required: ['sha256']
|
||||||
signatures:
|
signatures:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -40,7 +40,7 @@ allOf:
|
||||||
Signatures for the PDU, following the algorithm specified in `Signing Events`_.
|
Signatures for the PDU, following the algorithm specified in `Signing Events`_.
|
||||||
example: {
|
example: {
|
||||||
"example.com": {
|
"example.com": {
|
||||||
"ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus"
|
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
|
|
||||||
73
api/server-server/definitions/pdu_v3.yaml
Normal file
73
api/server-server/definitions/pdu_v3.yaml
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Copyright 2019 New Vector Ltd
|
||||||
|
#
|
||||||
|
# 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: Persistent Data Unit
|
||||||
|
description: A persistent data unit (event) for room version 3 and beyond.
|
||||||
|
example:
|
||||||
|
$ref: "../examples/pdu_v3.json"
|
||||||
|
allOf:
|
||||||
|
- $ref: "unsigned_pdu_base.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
auth_events:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: Event ID.
|
||||||
|
description: |-
|
||||||
|
Event IDs for the authorization events that would
|
||||||
|
allow this event to be in the room.
|
||||||
|
example: ["$base64EncodedHash", "$AnotherEvent"]
|
||||||
|
prev_events:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: Event ID.
|
||||||
|
description: |-
|
||||||
|
Event IDs for the most recent events in the room
|
||||||
|
that the homeserver was aware of when it made this event.
|
||||||
|
example: ["$base64EncodedHash", "$AnotherEvent"]
|
||||||
|
hashes:
|
||||||
|
type: object
|
||||||
|
title: Event Hash
|
||||||
|
description: |-
|
||||||
|
Content hashes of the PDU, following the algorithm specified in `Signing Events`_.
|
||||||
|
example: {
|
||||||
|
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||||
|
}
|
||||||
|
properties:
|
||||||
|
sha256:
|
||||||
|
type: string
|
||||||
|
description: The hash.
|
||||||
|
example: ThisHashCoversAllFieldsInCaseThisIsRedacted
|
||||||
|
required: ['sha256']
|
||||||
|
signatures:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
Signatures for the PDU, following the algorithm specified in `Signing Events`_.
|
||||||
|
example: {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
title: Server Signatures
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- auth_events
|
||||||
|
- prev_events
|
||||||
|
- hashes
|
||||||
|
- signatures
|
||||||
|
|
@ -31,7 +31,17 @@ properties:
|
||||||
example: 1532991320875
|
example: 1532991320875
|
||||||
pdus:
|
pdus:
|
||||||
type: array
|
type: array
|
||||||
description: List of persistent updates to rooms. Must not include more than 50 PDUs.
|
description: |-
|
||||||
|
List of persistent updates to rooms. Must not include more than 50 PDUs. Note that
|
||||||
|
events have a different format depending on the room version - check the
|
||||||
|
`room version specification`_ for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: "pdu.yaml"
|
type: object
|
||||||
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ contained in the transaction. The event format varies depending
|
||||||
|
on the room version - check the `room version specification`_ for precise event formats.
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "../examples/minimal_pdu.json"
|
||||||
required: ['origin', 'origin_server_ts', 'pdus']
|
required: ['origin', 'origin_server_ts', 'pdus']
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2018 New Vector Ltd
|
# Copyright 2018-2019 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,140 +16,13 @@ title: Unsigned Persistent Data Unit
|
||||||
description: An unsigned persistent data unit (event)
|
description: An unsigned persistent data unit (event)
|
||||||
example:
|
example:
|
||||||
$ref: "../examples/unsigned_pdu.json"
|
$ref: "../examples/unsigned_pdu.json"
|
||||||
properties:
|
allOf:
|
||||||
event_id:
|
- $ref: "unsigned_pdu_base.yaml"
|
||||||
type: string
|
- type: object
|
||||||
description: The event ID for the PDU.
|
|
||||||
example: "$a4ecee13e2accdadf56c1025:example.com"
|
|
||||||
room_id:
|
|
||||||
type: string
|
|
||||||
description: Room identifier.
|
|
||||||
example: "!abc123:matrix.org"
|
|
||||||
sender:
|
|
||||||
type: string
|
|
||||||
description: The ID of the user sending the event.
|
|
||||||
example: "@someone:matrix.org"
|
|
||||||
origin:
|
|
||||||
type: string
|
|
||||||
description: The ``server_name`` of the homeserver that created this event.
|
|
||||||
example: "matrix.org"
|
|
||||||
origin_server_ts:
|
|
||||||
type: integer
|
|
||||||
format: int64
|
|
||||||
description: Timestamp in milliseconds on origin homeserver when this event was created.
|
|
||||||
example: 1234567890
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
description: Event type
|
|
||||||
example: "m.room.message"
|
|
||||||
state_key:
|
|
||||||
type: string
|
|
||||||
description: |-
|
|
||||||
If this key is present, the event is a state event, and it will replace previous events
|
|
||||||
with the same ``type`` and ``state_key`` in the room state.
|
|
||||||
example: "my_key"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
description: The content of the event.
|
|
||||||
example: {"key": "value"}
|
|
||||||
prev_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
Event IDs and reference hashes for the most recent events in the room
|
|
||||||
that the homeserver was aware of when it made this event.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
depth:
|
|
||||||
type: integer
|
|
||||||
description: |-
|
|
||||||
The maximum depth of the ``prev_events``, plus one. Must be less than the
|
|
||||||
maximum value for an integer (2^63 - 1). If the room's depth is already at
|
|
||||||
the limit, the depth must be set to the limit.
|
|
||||||
example: 12
|
|
||||||
auth_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
Event IDs and reference hashes for the authorization events that would
|
|
||||||
allow this event to be in the room.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
redacts:
|
|
||||||
type: string
|
|
||||||
description: For redaction events, the ID of the event being redacted.
|
|
||||||
example: "$def456:matrix.org"
|
|
||||||
unsigned:
|
|
||||||
type: object
|
|
||||||
title: Example Unsigned Data
|
|
||||||
description: |-
|
|
||||||
Additional data added by the origin server but not covered by the ``signatures``. More
|
|
||||||
keys than those defined here may be used.
|
|
||||||
example: {"key": "value"}
|
|
||||||
properties:
|
properties:
|
||||||
age:
|
event_id:
|
||||||
type: integer
|
|
||||||
description: The number of milliseconds that have passed since this message was sent.
|
|
||||||
example: 4612
|
|
||||||
replaces_state:
|
|
||||||
type: string
|
type: string
|
||||||
description: The event ID of the state event this event replaces.
|
description: The event ID for the PDU.
|
||||||
example: "$state_event:example.org"
|
example: "$a4ecee13e2accdadf56c1025:example.com"
|
||||||
prev_sender:
|
required:
|
||||||
type: string
|
- event_id
|
||||||
description: The sender of the replaced state event.
|
|
||||||
example: "@someone:example.org"
|
|
||||||
prev_content:
|
|
||||||
type: object
|
|
||||||
description: The content of the replaced state event.
|
|
||||||
example: {
|
|
||||||
"membership": "join",
|
|
||||||
"displayname": "Bob"
|
|
||||||
}
|
|
||||||
redacted_because:
|
|
||||||
type: string
|
|
||||||
description: A reason for why the event was redacted.
|
|
||||||
example: "Inappropriate content"
|
|
||||||
required:
|
|
||||||
- event_id
|
|
||||||
- room_id
|
|
||||||
- sender
|
|
||||||
- origin
|
|
||||||
- origin_server_ts
|
|
||||||
- type
|
|
||||||
- content
|
|
||||||
- prev_events
|
|
||||||
- depth
|
|
||||||
- auth_events
|
|
||||||
|
|
|
||||||
151
api/server-server/definitions/unsigned_pdu_base.yaml
Normal file
151
api/server-server/definitions/unsigned_pdu_base.yaml
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
# Copyright 2018 New Vector Ltd
|
||||||
|
#
|
||||||
|
# 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: Unsigned Persistent Data Unit
|
||||||
|
description: An unsigned persistent data unit (event)
|
||||||
|
example:
|
||||||
|
$ref: "../examples/unsigned_pdu_base.json"
|
||||||
|
properties:
|
||||||
|
room_id:
|
||||||
|
type: string
|
||||||
|
description: Room identifier.
|
||||||
|
example: "!abc123:matrix.org"
|
||||||
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The ID of the user sending the event.
|
||||||
|
example: "@someone:matrix.org"
|
||||||
|
origin:
|
||||||
|
type: string
|
||||||
|
description: The ``server_name`` of the homeserver that created this event.
|
||||||
|
example: "matrix.org"
|
||||||
|
origin_server_ts:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: Timestamp in milliseconds on origin homeserver when this event was created.
|
||||||
|
example: 1234567890
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: Event type
|
||||||
|
example: "m.room.message"
|
||||||
|
state_key:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
If this key is present, the event is a state event, and it will replace previous events
|
||||||
|
with the same ``type`` and ``state_key`` in the room state.
|
||||||
|
example: "my_key"
|
||||||
|
content:
|
||||||
|
type: object
|
||||||
|
description: The content of the event.
|
||||||
|
example: {"key": "value"}
|
||||||
|
prev_events:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
Event IDs and reference hashes for the most recent events in the room
|
||||||
|
that the homeserver was aware of when it made this event.
|
||||||
|
items:
|
||||||
|
type: array
|
||||||
|
maxItems: 2
|
||||||
|
minItems: 2
|
||||||
|
items:
|
||||||
|
- type: string
|
||||||
|
title: Event ID
|
||||||
|
example: "$abc123:matrix.org"
|
||||||
|
- type: object
|
||||||
|
title: Event Hash
|
||||||
|
example: {
|
||||||
|
"sha256": "Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
}
|
||||||
|
properties:
|
||||||
|
sha256:
|
||||||
|
type: string
|
||||||
|
description: The event hash.
|
||||||
|
example: Base64EncodedSha256HashesShouldBe43BytesLong
|
||||||
|
required: ['sha256']
|
||||||
|
depth:
|
||||||
|
type: integer
|
||||||
|
description: |-
|
||||||
|
The maximum depth of the ``prev_events``, plus one. Must be less than the
|
||||||
|
maximum value for an integer (2^63 - 1). If the room's depth is already at
|
||||||
|
the limit, the depth must be set to the limit.
|
||||||
|
example: 12
|
||||||
|
auth_events:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
Event IDs and reference hashes for the authorization events that would
|
||||||
|
allow this event to be in the room.
|
||||||
|
items:
|
||||||
|
type: array
|
||||||
|
maxItems: 2
|
||||||
|
minItems: 2
|
||||||
|
items:
|
||||||
|
- type: string
|
||||||
|
title: Event ID
|
||||||
|
example: "$abc123:matrix.org"
|
||||||
|
- type: object
|
||||||
|
title: Event Hash
|
||||||
|
example: {
|
||||||
|
"sha256": "Base64EncodedSha256HashesShouldBe43BytesLong"
|
||||||
|
}
|
||||||
|
properties:
|
||||||
|
sha256:
|
||||||
|
type: string
|
||||||
|
description: The event hash.
|
||||||
|
example: Base64EncodedSha256HashesShouldBe43BytesLong
|
||||||
|
required: ['sha256']
|
||||||
|
redacts:
|
||||||
|
type: string
|
||||||
|
description: For redaction events, the ID of the event being redacted.
|
||||||
|
example: "$def456:matrix.org"
|
||||||
|
unsigned:
|
||||||
|
type: object
|
||||||
|
title: Example Unsigned Data
|
||||||
|
description: |-
|
||||||
|
Additional data added by the origin server but not covered by the ``signatures``. More
|
||||||
|
keys than those defined here may be used.
|
||||||
|
example: {"key": "value"}
|
||||||
|
properties:
|
||||||
|
age:
|
||||||
|
type: integer
|
||||||
|
description: The number of milliseconds that have passed since this message was sent.
|
||||||
|
example: 4612
|
||||||
|
replaces_state:
|
||||||
|
type: string
|
||||||
|
description: The event ID of the state event this event replaces.
|
||||||
|
example: "$state_event:example.org"
|
||||||
|
prev_sender:
|
||||||
|
type: string
|
||||||
|
description: The sender of the replaced state event.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
prev_content:
|
||||||
|
type: object
|
||||||
|
description: The content of the replaced state event.
|
||||||
|
example: {
|
||||||
|
"membership": "join",
|
||||||
|
"displayname": "Bob"
|
||||||
|
}
|
||||||
|
redacted_because:
|
||||||
|
type: string
|
||||||
|
description: A reason for why the event was redacted.
|
||||||
|
example: "Inappropriate content"
|
||||||
|
required:
|
||||||
|
- event_id
|
||||||
|
- room_id
|
||||||
|
- sender
|
||||||
|
- origin
|
||||||
|
- origin_server_ts
|
||||||
|
- type
|
||||||
|
- content
|
||||||
|
- prev_events
|
||||||
|
- depth
|
||||||
|
- auth_events
|
||||||
|
|
@ -58,10 +58,19 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
The full set of authorization events that make up the state of
|
The full set of authorization events that make up the state of
|
||||||
the room, and their authorization events, recursively.
|
the room, and their authorization events, recursively. Note that
|
||||||
|
events have a different format depending on the room version -
|
||||||
|
check the `room version specification`_ for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
example: [{"$ref": "examples/pdu.json"}]
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ contained in the auth chain. The event format
|
||||||
|
varies depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
required: ['auth_chain']
|
required: ['auth_chain']
|
||||||
"/query_auth/{roomId}/{eventId}":
|
"/query_auth/{roomId}/{eventId}":
|
||||||
post:
|
post:
|
||||||
|
|
@ -98,10 +107,20 @@ paths:
|
||||||
properties:
|
properties:
|
||||||
auth_chain:
|
auth_chain:
|
||||||
type: array
|
type: array
|
||||||
description: The auth chain (the "remote auth").
|
description: |-
|
||||||
|
The auth chain (the "remote auth"). Note that events have a different
|
||||||
|
format depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
example: [{"$ref": "examples/pdu.json"}]
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ contained in the auth chain. The event format
|
||||||
|
varies depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
missing:
|
missing:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
|
|
@ -142,10 +161,19 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
The auth chain the receiver has, and used to determine the auth
|
The auth chain the receiver has, and used to determine the auth
|
||||||
chain differences (the "local auth").
|
chain differences (the "local auth"). Note that events have a different
|
||||||
|
format depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
example: [{"$ref": "examples/pdu.json"}]
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ contained in the auth chain. The event format
|
||||||
|
varies depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
missing:
|
missing:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
|
|
|
||||||
|
|
@ -59,17 +59,35 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
The full set of authorization events that make up the state
|
The full set of authorization events that make up the state
|
||||||
of the room, and their authorization events, recursively.
|
of the room, and their authorization events, recursively. Note that
|
||||||
|
events have a different format depending on the room version -
|
||||||
|
check the `room version specification`_ for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
example: [{"$ref": "examples/pdu.json"}]
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ contained in the auth chain. The event format
|
||||||
|
varies depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
pdus:
|
pdus:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
The fully resolved state of the room at the given event.
|
The fully resolved state of the room at the given event. Note that
|
||||||
|
events have a different format depending on the room version -
|
||||||
|
check the `room version specification`_ for precise event formats.
|
||||||
items:
|
items:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
example: [{"$ref": "examples/pdu.json"}]
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ for the fully resolved state of the room. The event format
|
||||||
|
varies depending on the room version - check the `room version specification`_
|
||||||
|
for precise event formats.
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
required: ['auth_chain', 'pdus']
|
required: ['auth_chain', 'pdus']
|
||||||
"/state_ids/{roomId}":
|
"/state_ids/{roomId}":
|
||||||
get:
|
get:
|
||||||
|
|
|
||||||
7
api/server-server/examples/minimal_pdu.json
Normal file
7
api/server-server/examples/minimal_pdu.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"type": "m.room.minimal_pdu",
|
||||||
|
"room_id": "!somewhere:example.org",
|
||||||
|
"content": {
|
||||||
|
"see_room_version_spec": "The event format changes depending on the room version."
|
||||||
|
}
|
||||||
|
}
|
||||||
19
api/server-server/examples/pdu_v3.json
Normal file
19
api/server-server/examples/pdu_v3.json
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"$ref": "unsigned_pdu_base.json",
|
||||||
|
"hashes": {
|
||||||
|
"sha256": "thishashcoversallfieldsincasethisisredacted"
|
||||||
|
},
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"auth_events": [
|
||||||
|
"$base64encodedeventid",
|
||||||
|
"$adifferenteventid"
|
||||||
|
],
|
||||||
|
"prev_events": [
|
||||||
|
"$base64encodedeventid",
|
||||||
|
"$adifferenteventid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -16,8 +16,5 @@
|
||||||
"ed25519:auto2": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
|
"ed25519:auto2": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tls_fingerprints": [{
|
|
||||||
"sha256": "VGhpcyBpcyBoYXNoIHdoaWNoIHNob3VsZCBiZSBieXRlcw"
|
|
||||||
}],
|
|
||||||
"valid_until_ts": 1652262000000
|
"valid_until_ts": 1652262000000
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
{
|
{
|
||||||
"origin": "matrix.org",
|
"origin": "matrix.org",
|
||||||
"origin_server_ts": 1234567890,
|
"origin_server_ts": 1234567890,
|
||||||
"pdus": [{"$ref": "pdu.json"}]
|
"pdus": [{
|
||||||
|
"$ref": "minimal_pdu.json"
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
|
|
@ -1,27 +1,4 @@
|
||||||
{
|
{
|
||||||
"room_id": "!UcYsUzyxTGDxLBEvLy:example.org",
|
"$ref": "unsigned_pdu_base.json",
|
||||||
"sender": "@alice:example.com",
|
"event_id": "$a4ecee13e2accdadf56c1025:example.com"
|
||||||
"origin": "example.com",
|
|
||||||
"event_id": "$a4ecee13e2accdadf56c1025:example.com",
|
|
||||||
"origin_server_ts": 1404838188000,
|
|
||||||
"depth": 12,
|
|
||||||
"auth_events": [
|
|
||||||
[
|
|
||||||
"$af232176:example.org",
|
|
||||||
{"sha256": "abase64encodedsha256hashshouldbe43byteslong"}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"type": "m.room.message",
|
|
||||||
"prev_events": [
|
|
||||||
[
|
|
||||||
"$af232176:example.org",
|
|
||||||
{"sha256": "abase64encodedsha256hashshouldbe43byteslong"}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"content": {
|
|
||||||
"key": "value"
|
|
||||||
},
|
|
||||||
"unsigned": {
|
|
||||||
"age": 4612
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
26
api/server-server/examples/unsigned_pdu_base.json
Normal file
26
api/server-server/examples/unsigned_pdu_base.json
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"room_id": "!UcYsUzyxTGDxLBEvLy:example.org",
|
||||||
|
"sender": "@alice:example.com",
|
||||||
|
"origin": "example.com",
|
||||||
|
"origin_server_ts": 1404838188000,
|
||||||
|
"depth": 12,
|
||||||
|
"auth_events": [
|
||||||
|
[
|
||||||
|
"$af232176:example.org",
|
||||||
|
{"sha256": "abase64encodedsha256hashshouldbe43byteslong"}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"type": "m.room.message",
|
||||||
|
"prev_events": [
|
||||||
|
[
|
||||||
|
"$af232176:example.org",
|
||||||
|
{"sha256": "abase64encodedsha256hashshouldbe43byteslong"}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"content": {
|
||||||
|
"key": "value"
|
||||||
|
},
|
||||||
|
"unsigned": {
|
||||||
|
"age": 4612
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2018 New Vector Ltd
|
# Copyright 2018-2019 New Vector Ltd
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
|
@ -34,7 +34,16 @@ paths:
|
||||||
Invites a remote user to a room. Once the event has been signed by both the inviting
|
Invites a remote user to a room. Once the event has been signed by both the inviting
|
||||||
homeserver and the invited homeserver, it can be sent to all of the servers in the
|
homeserver and the invited homeserver, it can be sent to all of the servers in the
|
||||||
room by the inviting homeserver.
|
room by the inviting homeserver.
|
||||||
operationId: sendInvite
|
|
||||||
|
Servers should prefer to use the v2 API for invites instead of the v1 API. Servers
|
||||||
|
which receive a v1 invite request must assume that the room version is either ``"1"``
|
||||||
|
or ``"2"``.
|
||||||
|
|
||||||
|
Note that events have a different format depending on the room version - check the
|
||||||
|
`room version specification`_ for precise event formats. **The request and response
|
||||||
|
bodies here describe the common event fields in more detail and may be missing other
|
||||||
|
required fields for a PDU.**
|
||||||
|
operationId: sendInviteV1
|
||||||
security:
|
security:
|
||||||
- signedRequest: []
|
- signedRequest: []
|
||||||
parameters:
|
parameters:
|
||||||
|
|
@ -103,9 +112,12 @@ paths:
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
example: {
|
example: {
|
||||||
"$ref": "examples/pdu.json",
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@joe:elsewhere.com",
|
"state_key": "@joe:elsewhere.com",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"invite_room_state": [
|
"invite_room_state": [
|
||||||
{
|
{
|
||||||
|
|
@ -139,7 +151,8 @@ paths:
|
||||||
200:
|
200:
|
||||||
description: |-
|
description: |-
|
||||||
The event with the invited server's signature added. All other fields of the events
|
The event with the invited server's signature added. All other fields of the events
|
||||||
should remain untouched.
|
should remain untouched. Note that events have a different format depending on the
|
||||||
|
room version - check the `room version specification`_ for precise event formats.
|
||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
minItems: 2
|
minItems: 2
|
||||||
|
|
@ -160,9 +173,12 @@ paths:
|
||||||
200,
|
200,
|
||||||
{
|
{
|
||||||
"event": {
|
"event": {
|
||||||
"$ref": "examples/pdu.json",
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@someone:example.org",
|
"state_key": "@someone:example.org",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"invite_room_state": [
|
"invite_room_state": [
|
||||||
{
|
{
|
||||||
246
api/server-server/invites-v2.yaml
Normal file
246
api/server-server/invites-v2.yaml
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
# Copyright 2018-2019 New Vector Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Federation Invite User To Room API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:8448
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
basePath: /_matrix/federation/v2
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
|
paths:
|
||||||
|
"/invite/{roomId}/{eventId}":
|
||||||
|
put:
|
||||||
|
summary: Invites a remote user to a room
|
||||||
|
description: |-
|
||||||
|
.. Note::
|
||||||
|
This API is nearly identical to the v1 API with the exception of the request
|
||||||
|
body being different, and the response format fixed.
|
||||||
|
|
||||||
|
Invites a remote user to a room. Once the event has been signed by both the inviting
|
||||||
|
homeserver and the invited homeserver, it can be sent to all of the servers in the
|
||||||
|
room by the inviting homeserver.
|
||||||
|
|
||||||
|
This endpoint is preferred over the v1 API as it is more useful for servers. Senders
|
||||||
|
which receive a 400 or 404 response to this endpoint should retry using the v1
|
||||||
|
API as the server may be older, if the room version is "1" or "2".
|
||||||
|
|
||||||
|
Note that events have a different format depending on the room version - check the
|
||||||
|
`room version specification`_ for precise event formats. **The request and response
|
||||||
|
bodies here describe the common event fields in more detail and may be missing other
|
||||||
|
required fields for a PDU.**
|
||||||
|
operationId: sendInviteV2
|
||||||
|
security:
|
||||||
|
- signedRequest: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: roomId
|
||||||
|
type: string
|
||||||
|
description: The room ID that the user is being invited to.
|
||||||
|
required: true
|
||||||
|
x-example: "!abc123:matrix.org"
|
||||||
|
- in: path
|
||||||
|
name: eventId
|
||||||
|
type: string
|
||||||
|
description: The event ID for the invite event, generated by the inviting server.
|
||||||
|
required: true
|
||||||
|
x-example: "$abc123:example.org"
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
type: object
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
room_version:
|
||||||
|
type: string
|
||||||
|
description: The version of the room where the user is being invited to.
|
||||||
|
example: "2"
|
||||||
|
event:
|
||||||
|
$ref: "definitions/invite_event.yaml"
|
||||||
|
invite_room_state:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
An optional list of simplified events to help the receiver of the invite
|
||||||
|
identify the room. The recommended events to include are the join rules,
|
||||||
|
canonical alias, avatar, and name of the room.
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
title: Invite Room State Event
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: The type of event.
|
||||||
|
example: "m.room.join_rules"
|
||||||
|
state_key:
|
||||||
|
type: string
|
||||||
|
description: The state key for the event. May be an empty string.
|
||||||
|
example: ""
|
||||||
|
content:
|
||||||
|
type: object
|
||||||
|
description: The content for the event.
|
||||||
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The sender of the event.
|
||||||
|
example: "@someone:matrix.org"
|
||||||
|
required: ['type', 'state_key', 'content', 'sender']
|
||||||
|
example: [
|
||||||
|
{
|
||||||
|
"type": "m.room.join_rules",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"join_rule": "public"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
required: ['room_version', 'event']
|
||||||
|
example: {
|
||||||
|
"room_version": "2",
|
||||||
|
"event": {
|
||||||
|
"$ref": "examples/minimal_pdu.json",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"state_key": "@joe:elsewhere.com",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
|
"content": {
|
||||||
|
"membership": "invite"
|
||||||
|
},
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version": "SomeSignatureHere"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"invite_room_state": [
|
||||||
|
{
|
||||||
|
"type": "m.room.join_rules",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"join_rule": "public"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"name": "Cool New Room"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: |-
|
||||||
|
The event with the invited server's signature added. All other fields of the events
|
||||||
|
should remain untouched. Note that events have a different format depending on the
|
||||||
|
room version - check the `room version specification`_ for precise event formats.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
description: An object containing the signed invite event.
|
||||||
|
title: Event Container
|
||||||
|
properties:
|
||||||
|
event:
|
||||||
|
$ref: "definitions/invite_event.yaml"
|
||||||
|
required: ['event']
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"event": {
|
||||||
|
"$ref": "examples/minimal_pdu.json",
|
||||||
|
"type": "m.room.member",
|
||||||
|
"state_key": "@someone:example.org",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
|
"unsigned": {
|
||||||
|
"invite_room_state": [
|
||||||
|
{
|
||||||
|
"type": "m.room.join_rules",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"join_rule": "public"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"sender": "@someone:matrix.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"name": "Cool New Room"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"membership": "invite"
|
||||||
|
},
|
||||||
|
"signatures": {
|
||||||
|
"example.com": {
|
||||||
|
"ed25519:key_version": "SomeSignatureHere"
|
||||||
|
},
|
||||||
|
"elsewhere.com": {
|
||||||
|
"ed25519:k3y_versi0n": "SomeOtherSignatureHere"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The invite is not allowed. This could be for a number of reasons, including:
|
||||||
|
|
||||||
|
* The sender is not allowed to send invites to the target user/homeserver.
|
||||||
|
* The homeserver does not permit anyone to invite its users.
|
||||||
|
* The homeserver refuses to participate in the room.
|
||||||
|
schema:
|
||||||
|
$ref: "../client-server/definitions/errors/error.yaml"
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "User cannot invite the target user."
|
||||||
|
}
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
The request is invalid or the room the server is attempting
|
||||||
|
to join has a version that is not listed in the ``ver``
|
||||||
|
parameters.
|
||||||
|
|
||||||
|
The error should be passed through to clients so that they
|
||||||
|
may give better feedback to users.
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: "../client-server/definitions/errors/error.yaml"
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
room_version:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The version of the room. Required if the ``errcode``
|
||||||
|
is ``M_INCOMPATIBLE_ROOM_VERSION``.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_INCOMPATIBLE_ROOM_VERSION",
|
||||||
|
"error": "Your homeserver does not support the features required to join this room",
|
||||||
|
"room_version": "3"
|
||||||
|
}
|
||||||
|
|
@ -61,100 +61,80 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: |-
|
description: |-
|
||||||
A template to be used for the rest of the `Joining Rooms`_ handshake.
|
A template to be used for the rest of the `Joining Rooms`_ handshake. Note that
|
||||||
|
events have a different format depending on the room version - check the
|
||||||
|
`room version specification`_ for precise event formats. **The response body
|
||||||
|
here describes the common event fields in more detail and may be missing other
|
||||||
|
required fields for a PDU.**
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
room_version:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The version of the room where the server is trying to join. If not provided,
|
||||||
|
the room version is assumed to be either "1" or "2".
|
||||||
|
example: "2"
|
||||||
event:
|
event:
|
||||||
allOf:
|
description: |-
|
||||||
- $ref: "definitions/unsigned_pdu.yaml"
|
An unsigned template event. Note that events have a different format
|
||||||
- description: |-
|
depending on the room version - check the `room version specification`_
|
||||||
An unsigned template event.
|
for precise event formats.
|
||||||
|
type: object
|
||||||
|
title: Event Template
|
||||||
|
properties:
|
||||||
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the joining member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
origin:
|
||||||
|
type: string
|
||||||
|
description: The name of the resident homeserver.
|
||||||
|
example: "matrix.org"
|
||||||
|
origin_server_ts:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: A timestamp added by the resident homeserver.
|
||||||
|
example: 1234567890
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: The value ``m.room.member``.
|
||||||
|
example: "m.room.member"
|
||||||
|
state_key:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the joining member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
content:
|
||||||
type: object
|
type: object
|
||||||
|
title: Membership Event Content
|
||||||
|
description: The content of the event.
|
||||||
|
example: {"membership": "join"}
|
||||||
properties:
|
properties:
|
||||||
# Note: we override a bunch of parameters to change their descriptions
|
membership:
|
||||||
sender:
|
|
||||||
type: string
|
type: string
|
||||||
description: The user ID of the joining member.
|
description: The value ``join``.
|
||||||
example: "@someone:example.org"
|
example: "join"
|
||||||
origin:
|
required: ['membership']
|
||||||
type: string
|
required:
|
||||||
description: The name of the resident homeserver.
|
- state_key
|
||||||
example: "matrix.org"
|
- origin
|
||||||
origin_server_ts:
|
- origin_server_ts
|
||||||
type: integer
|
- type
|
||||||
format: int64
|
- content
|
||||||
description: A timestamp added by the resident homeserver.
|
- sender
|
||||||
example: 1234567890
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
description: The value ``m.room.member``.
|
|
||||||
example: "m.room.member"
|
|
||||||
state_key:
|
|
||||||
type: string
|
|
||||||
description: The user ID of the joining member.
|
|
||||||
example: "@someone:example.org"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
title: Membership Event Content
|
|
||||||
description: The content of the event.
|
|
||||||
example: {"membership": "join"}
|
|
||||||
properties:
|
|
||||||
membership:
|
|
||||||
type: string
|
|
||||||
description: The value ``join``.
|
|
||||||
example: "join"
|
|
||||||
required: ['membership']
|
|
||||||
depth:
|
|
||||||
type: integer
|
|
||||||
description: This field must be present but is ignored; it may be 0.
|
|
||||||
example: 12
|
|
||||||
auth_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
An event reference list containing the authorization events that would
|
|
||||||
allow the member to join the room. This should normally be the
|
|
||||||
``m.room.create``, ``m.room.power_levels``, and ``m.room.join_rules``
|
|
||||||
events.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
redacts:
|
|
||||||
type: string
|
|
||||||
description: Not used.
|
|
||||||
required:
|
|
||||||
# Every other field is already flagged as required by the $ref
|
|
||||||
- state_key
|
|
||||||
examples:
|
examples:
|
||||||
application/json: {
|
application/json: {
|
||||||
event: {
|
"room_version": "2",
|
||||||
"$ref": "examples/unsigned_pdu.json",
|
"event": {
|
||||||
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@someone:example.org",
|
"state_key": "@someone:example.org",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
"content": {
|
"content": {
|
||||||
"membership": "join"
|
"membership": "join"
|
||||||
},
|
}
|
||||||
"auth_events": [
|
|
||||||
["$room_cre4te_3vent:matrix.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"}],
|
|
||||||
["$room_j0in_rul3s_3vent:matrix.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"}],
|
|
||||||
["$room_p0wer_l3vels_3vent:matrix.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"}]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
400:
|
400:
|
||||||
|
|
@ -186,7 +166,12 @@ paths:
|
||||||
summary: Submit a signed join event to a resident server
|
summary: Submit a signed join event to a resident server
|
||||||
description: |-
|
description: |-
|
||||||
Submits a signed join event to the resident server for it
|
Submits a signed join event to the resident server for it
|
||||||
to accept it into the room's graph.
|
to accept it into the room's graph. Note that events have
|
||||||
|
a different format depending on the room version - check
|
||||||
|
the `room version specification`_ for precise event formats.
|
||||||
|
**The request and response body here describes the common
|
||||||
|
event fields in more detail and may be missing other required
|
||||||
|
fields for a PDU.**
|
||||||
operationId: sendJoin
|
operationId: sendJoin
|
||||||
security:
|
security:
|
||||||
- signedRequest: []
|
- signedRequest: []
|
||||||
|
|
@ -208,81 +193,54 @@ paths:
|
||||||
type: object
|
type: object
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
allOf:
|
type: object
|
||||||
- $ref: "definitions/pdu.yaml"
|
properties:
|
||||||
- type: object
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the joining member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
origin:
|
||||||
|
type: string
|
||||||
|
description: The name of the joining homeserver.
|
||||||
|
example: "matrix.org"
|
||||||
|
origin_server_ts:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: A timestamp added by the joining homeserver.
|
||||||
|
example: 1234567890
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: The value ``m.room.member``.
|
||||||
|
example: "m.room.member"
|
||||||
|
state_key:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the joining member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
content:
|
||||||
|
type: object
|
||||||
|
title: Membership Event Content
|
||||||
|
description: The content of the event.
|
||||||
|
example: {"membership": "join"}
|
||||||
properties:
|
properties:
|
||||||
# Note: we override a bunch of parameters to change their descriptions
|
membership:
|
||||||
sender:
|
|
||||||
type: string
|
type: string
|
||||||
description: The user ID of the joining member.
|
description: The value ``join``.
|
||||||
example: "@someone:example.org"
|
example: "join"
|
||||||
origin:
|
required: ['membership']
|
||||||
type: string
|
required:
|
||||||
description: The name of the joining homeserver.
|
- state_key
|
||||||
example: "matrix.org"
|
- sender
|
||||||
origin_server_ts:
|
- origin
|
||||||
type: integer
|
- origin_server_ts
|
||||||
format: int64
|
- type
|
||||||
description: A timestamp added by the joining homeserver.
|
- content
|
||||||
example: 1234567890
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
description: The value ``m.room.member``.
|
|
||||||
example: "m.room.member"
|
|
||||||
state_key:
|
|
||||||
type: string
|
|
||||||
description: The user ID of the joining member.
|
|
||||||
example: "@someone:example.org"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
title: Membership Event Content
|
|
||||||
description: The content of the event.
|
|
||||||
example: {"membership": "join"}
|
|
||||||
properties:
|
|
||||||
membership:
|
|
||||||
type: string
|
|
||||||
description: The value ``join``.
|
|
||||||
example: "join"
|
|
||||||
required: ['membership']
|
|
||||||
depth:
|
|
||||||
type: integer
|
|
||||||
description: This field must be present but is ignored; it may be 0.
|
|
||||||
example: 12
|
|
||||||
auth_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
An event reference list containing the authorization events that would
|
|
||||||
allow the member to join the room.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
redacts:
|
|
||||||
type: string
|
|
||||||
description: Not used.
|
|
||||||
required:
|
|
||||||
# Every other field is already flagged as required by the $ref
|
|
||||||
- state_key
|
|
||||||
example: {
|
example: {
|
||||||
"$ref": "examples/pdu.json",
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@someone:example.org",
|
"state_key": "@someone:example.org",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
"content": {
|
"content": {
|
||||||
"membership": "join"
|
"membership": "join"
|
||||||
}
|
}
|
||||||
|
|
@ -308,25 +266,44 @@ paths:
|
||||||
description: The resident server's DNS name.
|
description: The resident server's DNS name.
|
||||||
auth_chain:
|
auth_chain:
|
||||||
type: array
|
type: array
|
||||||
description: The auth chain.
|
description: |-
|
||||||
|
The auth chain. Note that events have a different format depending on
|
||||||
|
the room version - check the `room version specification`_ for precise
|
||||||
|
event formats.
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ that make up the auth chain. The event format varies depending
|
||||||
|
on the room version - check the `room version specification`_ for precise event formats.
|
||||||
schema:
|
schema:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
state:
|
state:
|
||||||
type: array
|
type: array
|
||||||
description: The room state.
|
description: |-
|
||||||
|
The room state. The event format varies depending on the room version -
|
||||||
|
check the `room version specification`_ for precise event formats.
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
|
title: PDU
|
||||||
|
description: |-
|
||||||
|
The `PDUs <#pdus>`_ for the fully resolved state of the room. The event format varies depending
|
||||||
|
on the room version - check the `room version specification`_ for precise event formats.
|
||||||
schema:
|
schema:
|
||||||
$ref: "definitions/pdu.yaml"
|
type: object
|
||||||
|
properties: []
|
||||||
|
example:
|
||||||
|
$ref: "examples/minimal_pdu.json"
|
||||||
required: ["auth_chain", "state", "origin"]
|
required: ["auth_chain", "state", "origin"]
|
||||||
examples:
|
examples:
|
||||||
application/json: [
|
application/json: [
|
||||||
200,
|
200,
|
||||||
{
|
{
|
||||||
"origin": "matrix.org",
|
"origin": "matrix.org",
|
||||||
"auth_chain": [{"$ref": "examples/pdu.json"}],
|
"auth_chain": [{"$ref": "examples/minimal_pdu.json"}],
|
||||||
"state": [{"$ref": "examples/pdu.json"}]
|
"state": [{"$ref": "examples/minimal_pdu.json"}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ paths:
|
||||||
get:
|
get:
|
||||||
summary: Get the homeserver's public key(s)
|
summary: Get the homeserver's public key(s)
|
||||||
description: |-
|
description: |-
|
||||||
Gets the homeserver's published TLS fingerprints and signing keys.
|
Gets the homeserver's published signing keys.
|
||||||
The homeserver may have any number of active keys and may have a
|
The homeserver may have any number of active keys and may have a
|
||||||
number of old keys.
|
number of old keys.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,97 +52,81 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: |-
|
description: |-
|
||||||
A template to be used to call ``/send_leave``.
|
A template to be used to call ``/send_leave``. Note that
|
||||||
|
events have a different format depending on the room version - check the
|
||||||
|
`room version specification`_ for precise event formats. **The response body
|
||||||
|
here describes the common event fields in more detail and may be missing other
|
||||||
|
required fields for a PDU.**
|
||||||
schema:
|
schema:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
room_version:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The version of the room where the server is trying to leave. If not provided,
|
||||||
|
the room version is assumed to be either "1" or "2".
|
||||||
|
example: "2"
|
||||||
event:
|
event:
|
||||||
allOf:
|
description: |-
|
||||||
- $ref: "definitions/unsigned_pdu.yaml"
|
An unsigned template event. Note that events have a different format
|
||||||
- description: |-
|
depending on the room version - check the `room version specification`_
|
||||||
An unsigned template event.
|
for precise event formats.
|
||||||
|
type: object
|
||||||
|
title: Event Template
|
||||||
|
properties:
|
||||||
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the leaving member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
origin:
|
||||||
|
type: string
|
||||||
|
description: The name of the resident homeserver.
|
||||||
|
example: "matrix.org"
|
||||||
|
origin_server_ts:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: A timestamp added by the resident homeserver.
|
||||||
|
example: 1234567890
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: The value ``m.room.member``.
|
||||||
|
example: "m.room.member"
|
||||||
|
state_key:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the leaving member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
content:
|
||||||
type: object
|
type: object
|
||||||
|
title: Membership Event Content
|
||||||
|
description: The content of the event.
|
||||||
|
example: {"membership": "leave"}
|
||||||
properties:
|
properties:
|
||||||
# Note: we override a bunch of parameters to change their descriptions
|
membership:
|
||||||
sender:
|
|
||||||
type: string
|
type: string
|
||||||
description: The user ID of the leaving member.
|
description: The value ``leave``.
|
||||||
example: "@someone:example.org"
|
example: "leave"
|
||||||
origin:
|
required: ['membership']
|
||||||
type: string
|
required:
|
||||||
description: The name of the resident homeserver.
|
- state_key
|
||||||
example: "matrix.org"
|
- sender
|
||||||
origin_server_ts:
|
- origin
|
||||||
type: integer
|
- origin_server_ts
|
||||||
format: int64
|
- type
|
||||||
description: A timestamp added by the resident homeserver.
|
- content
|
||||||
example: 1234567890
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
description: The value ``m.room.member``.
|
|
||||||
example: "m.room.member"
|
|
||||||
state_key:
|
|
||||||
type: string
|
|
||||||
description: The user ID of the leaving member.
|
|
||||||
example: "@someone:example.org"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
title: Membership Event Content
|
|
||||||
description: The content of the event.
|
|
||||||
example: {"membership": "leave"}
|
|
||||||
properties:
|
|
||||||
membership:
|
|
||||||
type: string
|
|
||||||
description: The value ``leave``.
|
|
||||||
example: "leave"
|
|
||||||
required: ['membership']
|
|
||||||
auth_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
An event reference list containing the authorization events that would
|
|
||||||
allow the member to leave the room. This should normally be the
|
|
||||||
``m.room.create``, ``m.room.power_levels``, and ``m.room.join_rules``
|
|
||||||
events.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
redacts:
|
|
||||||
type: string
|
|
||||||
description: Not used.
|
|
||||||
required:
|
|
||||||
# Every other field is already flagged as required by the $ref
|
|
||||||
- state_key
|
|
||||||
examples:
|
examples:
|
||||||
application/json: {
|
application/json: {
|
||||||
|
"room_version": "2",
|
||||||
"event": {
|
"event": {
|
||||||
"$ref": "examples/unsigned_pdu.json",
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@someone:example.org",
|
"state_key": "@someone:example.org",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
"content": {
|
"content": {
|
||||||
"membership": "leave"
|
"membership": "leave"
|
||||||
},
|
}
|
||||||
"auth_events": [
|
|
||||||
["$room_cre4te_3vent:matrix.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"}],
|
|
||||||
["$room_j0in_rul3s_3vent:matrix.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"}],
|
|
||||||
["$room_p0wer_l3vels_3vent:matrix.org", {"sha256": "abase64encodedsha256hashshouldbe43byteslong"}]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
403:
|
403:
|
||||||
|
|
@ -160,7 +144,12 @@ paths:
|
||||||
summary: Submit a signed leave event to a resident server
|
summary: Submit a signed leave event to a resident server
|
||||||
description: |-
|
description: |-
|
||||||
Submits a signed leave event to the resident server for it
|
Submits a signed leave event to the resident server for it
|
||||||
to accept it into the room's graph.
|
to accept it into the room's graph. Note that events have
|
||||||
|
a different format depending on the room version - check
|
||||||
|
the `room version specification`_ for precise event formats.
|
||||||
|
**The request and response body here describes the common
|
||||||
|
event fields in more detail and may be missing other required
|
||||||
|
fields for a PDU.**
|
||||||
operationId: sendLeave
|
operationId: sendLeave
|
||||||
security:
|
security:
|
||||||
- signedRequest: []
|
- signedRequest: []
|
||||||
|
|
@ -182,81 +171,59 @@ paths:
|
||||||
type: object
|
type: object
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
allOf:
|
type: object
|
||||||
- $ref: "definitions/pdu.yaml"
|
properties:
|
||||||
- type: object
|
sender:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the leaving member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
origin:
|
||||||
|
type: string
|
||||||
|
description: The name of the leaving homeserver.
|
||||||
|
example: "matrix.org"
|
||||||
|
origin_server_ts:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: A timestamp added by the leaving homeserver.
|
||||||
|
example: 1234567890
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: The value ``m.room.member``.
|
||||||
|
example: "m.room.member"
|
||||||
|
state_key:
|
||||||
|
type: string
|
||||||
|
description: The user ID of the leaving member.
|
||||||
|
example: "@someone:example.org"
|
||||||
|
content:
|
||||||
|
type: object
|
||||||
|
title: Membership Event Content
|
||||||
|
description: The content of the event.
|
||||||
|
example: {"membership": "leave"}
|
||||||
properties:
|
properties:
|
||||||
# Note: we override a bunch of parameters to change their descriptions
|
membership:
|
||||||
sender:
|
|
||||||
type: string
|
type: string
|
||||||
description: The user ID of the leaving member.
|
description: The value ``leave``.
|
||||||
example: "@someone:example.org"
|
example: "leave"
|
||||||
origin:
|
required: ['membership']
|
||||||
type: string
|
depth:
|
||||||
description: The name of the leaving homeserver.
|
type: integer
|
||||||
example: "matrix.org"
|
description: This field must be present but is ignored; it may be 0.
|
||||||
origin_server_ts:
|
example: 12
|
||||||
type: integer
|
required:
|
||||||
format: int64
|
- state_key
|
||||||
description: A timestamp added by the leaving homeserver.
|
- sender
|
||||||
example: 1234567890
|
- origin
|
||||||
type:
|
- origin_server_ts
|
||||||
type: string
|
- type
|
||||||
description: The value ``m.room.member``.
|
- depth
|
||||||
example: "m.room.member"
|
- content
|
||||||
state_key:
|
|
||||||
type: string
|
|
||||||
description: The user ID of the leaving member.
|
|
||||||
example: "@someone:example.org"
|
|
||||||
content:
|
|
||||||
type: object
|
|
||||||
title: Membership Event Content
|
|
||||||
description: The content of the event.
|
|
||||||
example: {"membership": "leave"}
|
|
||||||
properties:
|
|
||||||
membership:
|
|
||||||
type: string
|
|
||||||
description: The value ``leave``.
|
|
||||||
example: "leave"
|
|
||||||
required: ['membership']
|
|
||||||
depth:
|
|
||||||
type: integer
|
|
||||||
description: This field must be present but is ignored; it may be 0.
|
|
||||||
example: 12
|
|
||||||
auth_events:
|
|
||||||
type: array
|
|
||||||
description: |-
|
|
||||||
An event reference list containing the authorization events that would
|
|
||||||
allow the member to leave the room.
|
|
||||||
items:
|
|
||||||
type: array
|
|
||||||
maxItems: 2
|
|
||||||
minItems: 2
|
|
||||||
items:
|
|
||||||
- type: string
|
|
||||||
title: Event ID
|
|
||||||
example: "$abc123:matrix.org"
|
|
||||||
- type: object
|
|
||||||
title: Event Hash
|
|
||||||
example: {
|
|
||||||
"sha256": "abase64encodedsha256hashshouldbe43byteslong"
|
|
||||||
}
|
|
||||||
properties:
|
|
||||||
sha256:
|
|
||||||
type: string
|
|
||||||
description: The event hash.
|
|
||||||
example: abase64encodedsha256hashshouldbe43byteslong
|
|
||||||
required: ['sha256']
|
|
||||||
redacts:
|
|
||||||
type: string
|
|
||||||
description: Not used.
|
|
||||||
required:
|
|
||||||
# Every other field is already flagged as required by the $ref
|
|
||||||
- state_key
|
|
||||||
example: {
|
example: {
|
||||||
"$ref": "examples/pdu.json",
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"state_key": "@someone:example.org",
|
"state_key": "@someone:example.org",
|
||||||
|
"origin": "example.org",
|
||||||
|
"origin_server_ts": 1549041175876,
|
||||||
|
"sender": "@someone:example.org",
|
||||||
"content": {
|
"content": {
|
||||||
"membership": "leave"
|
"membership": "leave"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ paths:
|
||||||
User ID of the owner.
|
User ID of the owner.
|
||||||
operationId: exchangeOpenIdToken
|
operationId: exchangeOpenIdToken
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: query
|
||||||
name: access_token
|
name: access_token
|
||||||
type: string
|
type: string
|
||||||
description: |-
|
description: |-
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ paths:
|
||||||
third_party_invite:
|
third_party_invite:
|
||||||
type: object
|
type: object
|
||||||
description: The third party invite
|
description: The third party invite
|
||||||
|
title: Third Party Invite
|
||||||
properties:
|
properties:
|
||||||
display_name:
|
display_name:
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -97,6 +98,7 @@ paths:
|
||||||
description: |-
|
description: |-
|
||||||
A block of content which has been signed, which servers can use to
|
A block of content which has been signed, which servers can use to
|
||||||
verify the event.
|
verify the event.
|
||||||
|
title: Invite Signatures
|
||||||
properties:
|
properties:
|
||||||
signatures:
|
signatures:
|
||||||
type: object
|
type: object
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ paths:
|
||||||
|
|
||||||
The sending server must wait and retry for a 200 OK response before sending a
|
The sending server must wait and retry for a 200 OK response before sending a
|
||||||
transaction with a different ``txnId`` to the receiving server.
|
transaction with a different ``txnId`` to the receiving server.
|
||||||
|
|
||||||
|
Note that events have a different format depending on the room version - check
|
||||||
|
the `room version specification`_ for precise event formats.
|
||||||
operationId: sendTransaction
|
operationId: sendTransaction
|
||||||
security:
|
security:
|
||||||
- signedRequest: []
|
- signedRequest: []
|
||||||
|
|
|
||||||
52
api/server-server/wellknown.yaml
Normal file
52
api/server-server/wellknown.yaml
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Copyright 2019 New Vector Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
swagger: '2.0'
|
||||||
|
info:
|
||||||
|
title: "Matrix Federation Server Discovery API"
|
||||||
|
version: "1.0.0"
|
||||||
|
host: localhost:443
|
||||||
|
schemes:
|
||||||
|
- https
|
||||||
|
basePath: /.well-known
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
paths:
|
||||||
|
"/matrix/server":
|
||||||
|
get:
|
||||||
|
summary: Gets information about the delegated server for server-server communication.
|
||||||
|
description: |-
|
||||||
|
Gets information about the delegated server for server-server communication
|
||||||
|
between Matrix homeservers. Servers should follow 30x redirects, carefully
|
||||||
|
avoiding redirect loops, and use normal X.509 certificate validation.
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description:
|
||||||
|
The delegated server information. The ``Content-Type`` for this response SHOULD
|
||||||
|
be ``application/json``, however servers parsing the response should assume that
|
||||||
|
the body is JSON regardless of type. Failures parsing the JSON or invalid data
|
||||||
|
provided in the resulting parsed JSON should not result in discovery failure -
|
||||||
|
consult the server discovery process for information on how to continue.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"m.server": "delegated.example.com:1234"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
"m.server":
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The server name to delegate server-server communciations to, with optional
|
||||||
|
port. The delegated server name uses the same grammar as
|
||||||
|
`server names in the appendices <../appendices.html#server-name>`_.
|
||||||
1
changelogs/client_server/newsfragments/1786.feature
Normal file
1
changelogs/client_server/newsfragments/1786.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add support for advertising experimental features to clients.
|
||||||
1
changelogs/client_server/newsfragments/1790.feature
Normal file
1
changelogs/client_server/newsfragments/1790.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add a mechanism for servers to redirect clients to an alternative homeserver after logging in.
|
||||||
1
changelogs/client_server/newsfragments/1791.feature
Normal file
1
changelogs/client_server/newsfragments/1791.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add room version upgrades.
|
||||||
1
changelogs/client_server/newsfragments/1817.deprecation
Normal file
1
changelogs/client_server/newsfragments/1817.deprecation
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Remove references to presence lists.
|
||||||
1
changelogs/client_server/newsfragments/1829.feature
Normal file
1
changelogs/client_server/newsfragments/1829.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Support optional features by having clients query for capabilities.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix various spelling mistakes throughout the specification.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix various spelling mistakes throughout the specification.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix various spelling mistakes throughout the specification.
|
||||||
1
changelogs/client_server/newsfragments/1873.new
Normal file
1
changelogs/client_server/newsfragments/1873.new
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
``GET /account_data`` routes.
|
||||||
1
changelogs/client_server/newsfragments/1874.feature
Normal file
1
changelogs/client_server/newsfragments/1874.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add ``M_RESOURCE_LIMIT_EXCEEDED`` as an error code for when homeservers exceed limits imposed on them.
|
||||||
1
changelogs/client_server/newsfragments/1875.feature
Normal file
1
changelogs/client_server/newsfragments/1875.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add room version upgrades.
|
||||||
1
changelogs/client_server/newsfragments/1879.feature
Normal file
1
changelogs/client_server/newsfragments/1879.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Support optional features by having clients query for capabilities.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Add the missing `m.push_rules` event schema.
|
||||||
1
changelogs/client_server/newsfragments/1903.feature
Normal file
1
changelogs/client_server/newsfragments/1903.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Emit ``M_UNSUPPORTED_ROOM_VERSION`` error codes where applicable on ``/createRoom`` and ``/invite`` APIs.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix various spelling mistakes throughout the specification.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix various spelling mistakes throughout the specification.
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
r0.1.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Spec Clarifications
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- Remove legacy references to TLS fingerprints. (`#1844 <https://github.com/matrix-org/matrix-doc/issues/1844>`_)
|
||||||
|
- Clarify that servers should not fail to contact servers if ``/.well-known`` fails. (`#1855 <https://github.com/matrix-org/matrix-doc/issues/1855>`_)
|
||||||
|
|
||||||
|
|
||||||
|
r0.1.0
|
||||||
|
======
|
||||||
|
|
||||||
|
This is the first release of the Server Server (Federation) specification.
|
||||||
|
It includes support for homeservers being able to interact with other
|
||||||
|
homeservers in a decentralized and standard way.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Fix the `access_token` parameter in the open_id endpoint.
|
||||||
192
event-schemas/examples/m.push_rules
Normal file
192
event-schemas/examples/m.push_rules
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
{
|
||||||
|
"$ref": "core/event.json",
|
||||||
|
"type": "m.push_rules",
|
||||||
|
"content": {
|
||||||
|
"global": {
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "sound",
|
||||||
|
"value": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"pattern": "alice",
|
||||||
|
"rule_id": ".m.rule.contains_user_name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"override": [
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"dont_notify"
|
||||||
|
],
|
||||||
|
"conditions": [],
|
||||||
|
"default": true,
|
||||||
|
"enabled": false,
|
||||||
|
"rule_id": ".m.rule.master"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"dont_notify"
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"key": "content.msgtype",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "m.notice"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.suppress_notices"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"room": [],
|
||||||
|
"sender": [],
|
||||||
|
"underride": [
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "sound",
|
||||||
|
"value": "ring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"key": "type",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "m.call.invite"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.call"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "sound",
|
||||||
|
"value": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"kind": "contains_display_name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.contains_display_name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "sound",
|
||||||
|
"value": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"is": "2",
|
||||||
|
"kind": "room_member_count"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.room_one_to_one"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "sound",
|
||||||
|
"value": "default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"key": "type",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "m.room.member"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "content.membership",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "invite"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "state_key",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "@alice:example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.invite_for_me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"key": "type",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "m.room.member"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.member_event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
"notify",
|
||||||
|
{
|
||||||
|
"set_tweak": "highlight",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"key": "type",
|
||||||
|
"kind": "event_match",
|
||||||
|
"pattern": "m.room.message"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": true,
|
||||||
|
"enabled": true,
|
||||||
|
"rule_id": ".m.rule.message"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,10 @@
|
||||||
"content": {
|
"content": {
|
||||||
"creator": "@example:example.org",
|
"creator": "@example:example.org",
|
||||||
"room_version": "1",
|
"room_version": "1",
|
||||||
"m.federate": true
|
"m.federate": true,
|
||||||
|
"predecessor": {
|
||||||
|
"event_id": "$something:example.org",
|
||||||
|
"room_id": "!oldroom:example.org"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
event-schemas/examples/m.room.tombstone
Normal file
9
event-schemas/examples/m.room.tombstone
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"$ref": "core/state_event.json",
|
||||||
|
"type": "m.room.tombstone",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"body": "This room has been replaced",
|
||||||
|
"replacement_room": "!newroom:example.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
21
event-schemas/schema/m.push_rules
Normal file
21
event-schemas/schema/m.push_rules
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
description: Describes all push rules for this user.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
global:
|
||||||
|
type: object
|
||||||
|
title: Ruleset
|
||||||
|
description: The global ruleset
|
||||||
|
allOf:
|
||||||
|
- $ref: ../../api/client-server/definitions/push_ruleset.yaml
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.push_rules
|
||||||
|
type: string
|
||||||
|
title: Push rules
|
||||||
|
type: object
|
||||||
|
|
||||||
|
|
@ -14,6 +14,18 @@ properties:
|
||||||
room_version:
|
room_version:
|
||||||
description: The version of the room. Defaults to ``"1"`` if the key does not exist.
|
description: The version of the room. Defaults to ``"1"`` if the key does not exist.
|
||||||
type: string
|
type: string
|
||||||
|
predecessor:
|
||||||
|
description: A reference to the room this room replaces, if the previous room was upgraded.
|
||||||
|
type: object
|
||||||
|
title: Previous Room
|
||||||
|
properties:
|
||||||
|
room_id:
|
||||||
|
type: string
|
||||||
|
description: The ID of the old room.
|
||||||
|
event_id:
|
||||||
|
type: string
|
||||||
|
description: The event ID of the last known event in the old room.
|
||||||
|
required: [room_id, event_id]
|
||||||
required:
|
required:
|
||||||
- creator
|
- creator
|
||||||
type: object
|
type: object
|
||||||
|
|
|
||||||
27
event-schemas/schema/m.room.tombstone
Normal file
27
event-schemas/schema/m.room.tombstone
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/state_event.yaml
|
||||||
|
description: 'A state event signifying that a room has been upgraded to a different room version, and that clients should go there.'
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
body:
|
||||||
|
type: string
|
||||||
|
description: A server-defined message.
|
||||||
|
replacement_room:
|
||||||
|
type: string
|
||||||
|
description: The new room the client should be visiting.
|
||||||
|
required:
|
||||||
|
- replacement_room
|
||||||
|
- body
|
||||||
|
type: object
|
||||||
|
state_key:
|
||||||
|
description: A zero-length string.
|
||||||
|
pattern: '^$'
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.room.tombstone
|
||||||
|
type: string
|
||||||
|
title: Indication that the room has been upgraded.
|
||||||
|
type: object
|
||||||
|
|
@ -18,16 +18,18 @@ The remainder of the process is as follows:
|
||||||
1. Activate your Python 3 virtual environment.
|
1. Activate your Python 3 virtual environment.
|
||||||
1. Having checked out the new release branch, navigate your way over to `./changelogs`.
|
1. Having checked out the new release branch, navigate your way over to `./changelogs`.
|
||||||
1. Follow the release instructions provided in the README.md located there.
|
1. Follow the release instructions provided in the README.md located there.
|
||||||
1. Update the changelog section of the specification you're releasing to make a reference
|
|
||||||
to the new version.
|
|
||||||
1. Update any version/link references across all specifications.
|
1. Update any version/link references across all specifications.
|
||||||
1. Ensure the `targets.yml` file lists the version correctly.
|
1. Generate the specification using `./scripts/gendoc.py`, specifying all the
|
||||||
1. Commit the changes and PR them to master.
|
API versions at the time of generation. For example: `./scripts/gendoc.py -c r0.4.0 -s r0.1.0 -i r0.1.0 #etc`
|
||||||
1. Tag the release with the format `client_server/r0.4.0`.
|
1. PR the changes to the matrix-org/matrix.org repository (for historic tracking).
|
||||||
1. Add the changes to the matrix-org/matrix.org repository (for historic tracking).
|
|
||||||
* This is done by making a PR to the `unstyled_docs/spec` folder for the version and
|
* This is done by making a PR to the `unstyled_docs/spec` folder for the version and
|
||||||
specification you're releasing.
|
specification you're releasing.
|
||||||
* Don't forget to symlink the new release as `latest`.
|
* Don't forget to symlink the new release as `latest`.
|
||||||
|
* For the client-server API, don't forget to generate the swagger JSON by using
|
||||||
|
`./scripts/dump-swagger.py -c r0.4.0`. This will also need symlinking to `latest`.
|
||||||
|
1. Commit the changes and PR them to master. **Wait for review from the spec core team.**
|
||||||
|
* Link to your matrix-org/matrix.org so both can be reviewed at the same time.
|
||||||
|
1. Tag the release with the format `client_server/r0.4.0`.
|
||||||
1. Perform a release on GitHub to tag the release.
|
1. Perform a release on GitHub to tag the release.
|
||||||
1. Yell from the mountaintop to the world about the new release.
|
1. Yell from the mountaintop to the world about the new release.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ When this is called, the server:
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
"room_id": "!QtykxKocfsgujksjgd:matrix.org",
|
"room_id": "!QtykxKocfsgujksjgd:matrix.org",
|
||||||
"content": {
|
"content": {
|
||||||
"version": "2",
|
"room_version": "2",
|
||||||
"predecessor": {
|
"predecessor": {
|
||||||
"room_id": "!cURbaf:matrix.org",
|
"room_id": "!cURbaf:matrix.org",
|
||||||
"event_id": "$1235135aksjgdkg:matrix.org"
|
"event_id": "$1235135aksjgdkg:matrix.org"
|
||||||
|
|
|
||||||
130
proposals/1659-event-id-as-hashes.md
Normal file
130
proposals/1659-event-id-as-hashes.md
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
# Changing Event IDs to be Hashes
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
Having event IDs separate from the hashes leads to issues when a server receives
|
||||||
|
multiple events with the same event ID but different reference hashes. While
|
||||||
|
APIs could be changed to better support dealing with this situation, it is
|
||||||
|
easier and nicer to simply drop the idea of a separate event ID entirely, and
|
||||||
|
instead use the reference hash of an event as its ID.
|
||||||
|
|
||||||
|
## Identifier Format
|
||||||
|
|
||||||
|
Currently hashes in our event format include the hash name, allowing servers to
|
||||||
|
choose which hash functions to use. The idea here was to allow a gradual change
|
||||||
|
between hash functions without the need to globally coordinate shifting from one
|
||||||
|
hash function to another.
|
||||||
|
|
||||||
|
However now that room versions exist, changing hash functions can be achieved by
|
||||||
|
bumping the room version. Using this method would allow using a simple string as
|
||||||
|
the event ID rather than a full structure, significantly easing their usage.
|
||||||
|
|
||||||
|
One side effect of this would be that there would be no indication about which
|
||||||
|
hash function was actually used, and it would need to be inferred from the room
|
||||||
|
version. To aid debuggability it may be worth encoding the hash function into
|
||||||
|
the ID format.
|
||||||
|
|
||||||
|
**Conclusion:** Don't encode the hash function, since the hash will depend on
|
||||||
|
the version specific redaction algorithm anyway.
|
||||||
|
|
||||||
|
The proposal is therefore that the event IDs are a sha256 hash, encoded using
|
||||||
|
[unpadded
|
||||||
|
Base64](https://matrix.org/docs/spec/appendices.html#unpadded-base64), and
|
||||||
|
prefixed with `$` (to aid distinguishing different types of identifiers). For
|
||||||
|
example, an event ID might be: `$CD66HAED5npg6074c6pDtLKalHjVfYb2q4Q3LZgrW6o`.
|
||||||
|
|
||||||
|
The hash is calculated in the same way as previous event reference hashes were,
|
||||||
|
which is:
|
||||||
|
|
||||||
|
1. Redact the event
|
||||||
|
2. Remove `signatures` field from the event
|
||||||
|
3. Serialize the event to canonical JSON
|
||||||
|
4. Compute the hash of the JSON bytes
|
||||||
|
|
||||||
|
Event IDs will no longer be included as part of the event, and so must be
|
||||||
|
calculated by servers receiving the event.
|
||||||
|
|
||||||
|
|
||||||
|
## Changes to Event Formats
|
||||||
|
|
||||||
|
As well as changing the format of event IDs, we also change the format of the
|
||||||
|
`auth_events` and `prev_events` keys in events to simply be lists of event IDs
|
||||||
|
(rather than being lists of tuples).
|
||||||
|
|
||||||
|
A full event would therefore look something like (note that this is just an
|
||||||
|
illustrative example, and that the hashes are not correct):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"auth_events": [
|
||||||
|
"$5hdALbO+xIhzcLTxCkspx5uqry9wO8322h/OI9ApnHE",
|
||||||
|
"$Ga0DBIICBsWIZbN292ATv8fTHIGGimwjb++w+zcHLRo",
|
||||||
|
"$zc4ip/DpPI9FZVLM1wN9RLqN19vuVBURmIqAohZ1HXg",
|
||||||
|
],
|
||||||
|
"content": {
|
||||||
|
"body": "Here is the message content",
|
||||||
|
"msgtype": "m.message"
|
||||||
|
},
|
||||||
|
"depth": 6,
|
||||||
|
"hashes": {
|
||||||
|
"sha256": "M6/LmcMMJKc1AZnNHsuzmf0PfwladVGK2Xbz+sUTN9k"
|
||||||
|
},
|
||||||
|
"origin": "localhost:8800",
|
||||||
|
"origin_server_ts": 1548094046693,
|
||||||
|
"prev_events": [
|
||||||
|
"$MoOzCuB/sacqHAvgBNOLICiGLZqGT4zB16MSFOuiO0s",
|
||||||
|
],
|
||||||
|
"room_id": "!eBrhCHJWOgqrOizwwW:localhost:8800",
|
||||||
|
"sender": "@anon-20190121_180719-33:localhost:8800",
|
||||||
|
"signatures": {
|
||||||
|
"localhost:8800": {
|
||||||
|
"ed25519:a_iIHH": "N7hwZjvHyH6r811ebZ4wwLzofKhJuIAtrQzaD3NZbf4WQNijXl5Z2BNB047aWIQCS1JyFOQKPVom4et0q9UOAA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "m.room.message"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Changes to existing APIs
|
||||||
|
|
||||||
|
All APIs that accept event IDs must accept event IDs in the new format.
|
||||||
|
|
||||||
|
For S2S API, whenever a server needs to parse an event from a request or
|
||||||
|
response they must either already know the room version *or* be told the room
|
||||||
|
version in the request/response. There are separate MSCs to update APIs where
|
||||||
|
necessary.
|
||||||
|
|
||||||
|
For C2S API, the only change clients will see is that the event IDs have changed
|
||||||
|
format. Clients should already be treating event IDs as opaque strings, so no
|
||||||
|
changes should be required. Servers must add the `event_id` when sending the
|
||||||
|
event to clients, however.
|
||||||
|
|
||||||
|
Note that the `auth_events` and `prev_events` fields aren't sent to clients, and
|
||||||
|
so the changes proposed above won't affect clients.
|
||||||
|
|
||||||
|
|
||||||
|
## Protocol Changes
|
||||||
|
|
||||||
|
The `auth_events` and `prev_events` fields on an event need to be changed from a
|
||||||
|
list of tuples to a list of strings, i.e. remove the old event ID and simply
|
||||||
|
have the list of hashes.
|
||||||
|
|
||||||
|
The auth rules also need to change:
|
||||||
|
|
||||||
|
- The event no longer needs to be signed by the domain of the event ID (but
|
||||||
|
still needs to be signed by the sender’s domain)
|
||||||
|
|
||||||
|
- We currently allow redactions if the domain of the redaction event ID
|
||||||
|
matches the domain of the event ID it is redacting; which allows self
|
||||||
|
redaction. This check is removed and redaction events are always accepted.
|
||||||
|
Instead, the redaction event only takes effect and is sent down to clients
|
||||||
|
if/when the original event is received, and the domain of the events'
|
||||||
|
senders match. (While this is clearly suboptimal, it is the only practical
|
||||||
|
suggestion)
|
||||||
|
|
||||||
|
|
||||||
|
## Room Version
|
||||||
|
|
||||||
|
There will be a new room version v3 that is the same as v2 except uses the new
|
||||||
|
event format proposed above. v3 will be marked as 'stable' as defined in [MSC1804](https://github.com/matrix-org/matrix-doc/blob/travis/msc/room-version-client-advertising/proposals/1804-advertising-capable-room-versions.md)
|
||||||
|
|
||||||
|
|
@ -43,9 +43,9 @@ certificate validation, and following 30x redirects (being careful to avoid
|
||||||
redirect loops). If the request does not return a 200, continue to step 4,
|
redirect loops). If the request does not return a 200, continue to step 4,
|
||||||
otherwise:
|
otherwise:
|
||||||
|
|
||||||
The response must have a `Content-Type` of `application/json`, and must be
|
The response must be valid JSON which follows the structure documented
|
||||||
valid JSON which follows the structure documented below. Otherwise, the
|
below. Otherwise, continue to the next step in the discovery process. It is
|
||||||
request is aborted.
|
NOT necessary for the response to have a `Content-Type` of `application/json`.
|
||||||
|
|
||||||
If the response is valid, the `m.server` property is parsed as
|
If the response is valid, the `m.server` property is parsed as
|
||||||
`<delegated_server_name>[:<delegated_port>]`, and processed as follows:
|
`<delegated_server_name>[:<delegated_port>]`, and processed as follows:
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,10 @@ As a starting point, a single capability identifier is proposed:
|
||||||
change the user's password via the `POST /_matrix/client/r0/account/password`
|
change the user's password via the `POST /_matrix/client/r0/account/password`
|
||||||
API.
|
API.
|
||||||
|
|
||||||
The value of the `capabilities` object in the response should be the empty
|
The value of the `capabilities` object in the response should contain a single
|
||||||
object.
|
boolean flag, `enabled`, to indicate whether a password change is possible. If
|
||||||
|
the capability is not listed, the client should assume that password changes
|
||||||
|
are possible.
|
||||||
|
|
||||||
### Fallback behaviour
|
### Fallback behaviour
|
||||||
|
|
||||||
|
|
|
||||||
78
proposals/1794-federation-v2-invites.md
Normal file
78
proposals/1794-federation-v2-invites.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# MSC 1794 - Federation v2 Invite API
|
||||||
|
|
||||||
|
This proposal adds a new `/invite` API to federation that supports different
|
||||||
|
room versions.
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
It is planned for future room versions to be able to change the format of events
|
||||||
|
in various ways. To support this, all servers must know the room version
|
||||||
|
whenever they need to parse an event. Currently the `/invite` API does not
|
||||||
|
include the room version, so the target server would be unable to parse the event included in the payload.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
Add a new version of the invite API under the prefix `/_matrix/federation/v2`,
|
||||||
|
which has a payload of:
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /_matrix/federation/v2/invite/<room_id>/<event_id>
|
||||||
|
|
||||||
|
{
|
||||||
|
"room_version": <room_version>,
|
||||||
|
"event": { ... },
|
||||||
|
"invite_room_state": [ ... ]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The differences between this and `v1` are:
|
||||||
|
|
||||||
|
1. The payload in `v1` is the event, while in `v2` the event is instead placed
|
||||||
|
under an `"event"` key. This is for consistency with other APIs, and to allow
|
||||||
|
extra data to be added to the request payload separately from the event.
|
||||||
|
2. A required field called `"room_version"` is added that specifies the room
|
||||||
|
version.
|
||||||
|
3. The `"invite_room_state"` is moved from the `unsigned` section of the event
|
||||||
|
to a top level key. The key `invite_room_state` being in the `event.unsigned`
|
||||||
|
was a hack due to point 1. above.
|
||||||
|
|
||||||
|
|
||||||
|
The response is identical to `v1`, except that:
|
||||||
|
|
||||||
|
1. If the receiving server does not support the given room version the
|
||||||
|
appropriate incompatible-room-version error is returned, in the same way
|
||||||
|
as e.g. for `/make_join` APIs.
|
||||||
|
2. The response payload is no longer in the format of `[200, { ... }]`, and is
|
||||||
|
instead simply the `{ ... }` portion. This fixes a historical accident to
|
||||||
|
bring the invite API into line with the rest of the federation API.
|
||||||
|
|
||||||
|
|
||||||
|
If a call to `v2` `/invite` results in an unrecognised request exception **AND**
|
||||||
|
the room version is `1` or `2` then the sending server should retry the request
|
||||||
|
with the `v1` API.
|
||||||
|
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
|
||||||
|
### Reusing V1 API
|
||||||
|
|
||||||
|
One alternative is to add a `room_version` query string parameter to the `v1`
|
||||||
|
`/invite` API in a similar way as for the `/make_join` APIs. However, older
|
||||||
|
servers would ignore the query string parameter while processing an incoming
|
||||||
|
`/invite` request, resulting in the server attempting to parse the event in the
|
||||||
|
old `v1` format. This would likely result in either a `400` or `500` response,
|
||||||
|
which the sending server could interpret as the receiving server not supporting
|
||||||
|
the room version.
|
||||||
|
|
||||||
|
This method, however, is fragile and could easily mask legitimate `400` and
|
||||||
|
`500` errors that are not due to not supporting the room version.
|
||||||
|
|
||||||
|
|
||||||
|
### Using V1 API for V1 room versions
|
||||||
|
|
||||||
|
Instead of all servers attempting to use the new API and falling back if the API
|
||||||
|
is not found, servers could instead always use the current API for V1 and V2
|
||||||
|
rooms.
|
||||||
|
|
||||||
|
However, this would not allow us to deprecate the `v1` API.
|
||||||
50
proposals/1804-advertising-capable-room-versions.md
Normal file
50
proposals/1804-advertising-capable-room-versions.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Proposal for advertising capable room versions to clients
|
||||||
|
|
||||||
|
Currently clients need to guess at which room versions the server supports, if any. This is particularly
|
||||||
|
difficult to do as it generally requires knowing the state of the ecosystem and what versions are
|
||||||
|
available and how keen users are to upgrade their servers and clients. The impossible judgement call
|
||||||
|
for when to encourage people to upgrade shouldn't be impossible, or even a judgement call.
|
||||||
|
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
Building off of [MSC1753](https://github.com/matrix-org/matrix-doc/pull/1753) (capabilities API) and
|
||||||
|
the [recommendations laid out for room versions](https://github.com/matrix-org/matrix-doc/pull/1773/files#diff-1436075794bb304492ca6953a6692cd0R463),
|
||||||
|
this proposal suggests a `m.room_versions` capability be introduced like the following:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"capabilities": {
|
||||||
|
"m.room_versions": {
|
||||||
|
"default": "1",
|
||||||
|
"available": {
|
||||||
|
"1": "stable",
|
||||||
|
"2": "stable",
|
||||||
|
"state-res-v2-test": "unstable",
|
||||||
|
"event-ids-as-hashes": "unstable",
|
||||||
|
"3": "future-scifi-label"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Clients are encouraged to make use of this capability to determine if the server supports a given
|
||||||
|
version, and at what level of stability. Anything not flagged explicitly as `stable` should be treated
|
||||||
|
as `unstable` (ie: `future-scifi-label` is the same as `unstable`).
|
||||||
|
|
||||||
|
The default version is the version that the server is using to create new rooms with. Clients can
|
||||||
|
make the assumption that the default version is a stable version.
|
||||||
|
|
||||||
|
Clients should encourage people with sufficient permissions to perform an upgrade to upgrade their
|
||||||
|
rooms to the `default` room version when the room is using an `unstable` version.
|
||||||
|
|
||||||
|
|
||||||
|
## Potential issues
|
||||||
|
|
||||||
|
Changes aren't pushed to the client, which means clients may want to poll this endpoint on some
|
||||||
|
heuristic instead. For example, clients may want to poll the endpoint weekly or when the user relaunches
|
||||||
|
the client. Clients may also wish to provide users a way to upgrade without considering the capabilities
|
||||||
|
of the server, expecting that the server may not support the user-provided version - the intention
|
||||||
|
being such a feature would be used by eager room administrators which do not want to relaunch their
|
||||||
|
client, for example.
|
||||||
21
proposals/1812-federation-make-membership.md
Normal file
21
proposals/1812-federation-make-membership.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# MSC 1813 - Federation Make Membership Room Version
|
||||||
|
|
||||||
|
This proposal adds a new `room_version` field to the responses of `/make_leave`
|
||||||
|
and `/make_join` APIs.
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
It is planned for future room versions to be able to change the format of events
|
||||||
|
in various ways. To support this, all servers must know the room version
|
||||||
|
whenever they need to parse an event. Currently the `/make_*` APIs do not
|
||||||
|
include the room version in the response, so the requesting server is unable to
|
||||||
|
parse the event included in the response body.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
Add a new `room_version` field to the response body of the `v1` `/make_join` and
|
||||||
|
`/make_leave` APIs, which describes the room version.
|
||||||
|
|
||||||
|
For backwards compatibility servers must correctly handle responses that do not
|
||||||
|
include the new field. In which case the room version is assumed to be one of
|
||||||
|
either `1` or `2`.
|
||||||
55
proposals/1819-remove-presence-lists.md
Normal file
55
proposals/1819-remove-presence-lists.md
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Remove references to presence lists
|
||||||
|
|
||||||
|
[Presence](https://matrix.org/docs/spec/client_server/r0.4.0.html#id107) lists
|
||||||
|
allow a given user the ability to subscribe to other users and be alerted to
|
||||||
|
their current presence status.
|
||||||
|
|
||||||
|
While spec'd, no established client has implemented support and the only server
|
||||||
|
side implementation raises privacy concerns.
|
||||||
|
|
||||||
|
The proposal is to simply remove references to presence lists with a view to
|
||||||
|
revisiting the same ideas in the future.
|
||||||
|
|
||||||
|
This MSC addresses
|
||||||
|
[#1810](https://github.com/matrix-org/matrix-doc/issues/1810)
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
Presence lists seem like a good fit for ['MSC1769: Extensible profiles as
|
||||||
|
rooms'](https://github.com/matrix-org/matrix-doc/pull/1769) proposal, meaning
|
||||||
|
that the current design will most likely be superceded.
|
||||||
|
|
||||||
|
Additionally, no major client has implemented the behaviour to date and the
|
||||||
|
only server implementation of presence lists (Synapse) auto-accepts invites
|
||||||
|
leading to privacy concerns in the wild.
|
||||||
|
|
||||||
|
With this in mind the most pragmatic solution is to remove presence lists ahead
|
||||||
|
of the r0 release.
|
||||||
|
|
||||||
|
Specifically:-
|
||||||
|
|
||||||
|
CS API: Remove
|
||||||
|
* [POST
|
||||||
|
/_matrix/client/r0/presence/list/{userId}](https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-presence-list-userid)
|
||||||
|
* [GET
|
||||||
|
/_matrix/client/r0/presence/list/{userId}](https://matrix.org/docs/spec/client_server/r0.4.0.html#get-matrix-client-r0-presence-list-userid)
|
||||||
|
|
||||||
|
SS API: Remove
|
||||||
|
* [m.presence_invite](https://matrix.org/docs/spec/server_server/unstable.html#m-presence-invite-schema)
|
||||||
|
* [m.presence_accept](https://matrix.org/docs/spec/server_server/unstable.html#m-presence-accept-schema)
|
||||||
|
* [m.presence_deny](https://matrix.org/docs/spec/server_server/unstable.html#m-presence-deny-schema)
|
||||||
|
|
||||||
|
|
||||||
|
## Tradeoffs
|
||||||
|
|
||||||
|
Ideally this proposal would also come with an alternative design for this
|
||||||
|
functionality. Out of pragmatism the proposal only covers removal of what is
|
||||||
|
there today.
|
||||||
|
|
||||||
|
|
||||||
|
## Conclusions
|
||||||
|
|
||||||
|
This is a common sense attempt to remove unused portions of the spec ahead of
|
||||||
|
an r0 release. It does not suggest that the ability to subscribe to the
|
||||||
|
presence of others is undesirable and assumes that this behvaiour will return
|
||||||
|
again in some form.
|
||||||
25
proposals/1831-srv-after-wellknown.md
Normal file
25
proposals/1831-srv-after-wellknown.md
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Proposal to do SRV lookups after .well-known to discover homeservers
|
||||||
|
|
||||||
|
Currently there is a logistical error proposed by [MSC1708](https://github.com/matrix-org/matrix-doc/pull/1708)
|
||||||
|
which results in some homeservers unable to migrate to the new functionality
|
||||||
|
proposed by [MSC1711](https://github.com/matrix-org/matrix-doc/pull/1711). This
|
||||||
|
can happen if the delegated homeserver cannot obtain a valid TLS certificate for
|
||||||
|
the domain, and an SRV record is used for backwards compatibility reasons.
|
||||||
|
|
||||||
|
Specifically, in order to be compatible with requests from both Synapse 0.34 and 1.0,
|
||||||
|
servers can have both a SRV and a .well-known file, with Synapse presenting a certificate
|
||||||
|
corresponding to the target of the .well-known. Synapse 0.34 is then happy because it
|
||||||
|
will follow the SRV (and won't care about the incorrect certificate); Synapse 1.0 is
|
||||||
|
happy because it will follow the .well-known (and will see the correct cert).
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
We change the order of operations to perform a .well-known lookup before falling
|
||||||
|
back to resolving the SRV record. This allows for domains to delegate to other
|
||||||
|
hostnames and maintains backwards compatibility with older homeservers.
|
||||||
|
|
||||||
|
## Tradeoffs
|
||||||
|
|
||||||
|
More HTTP hits will be made due to the .well-known lookup being first. This is
|
||||||
|
somewhat mitigated by servers caching the responses appropriately, and using
|
||||||
|
connection pools where possible.
|
||||||
14
proposals/1866-invite-unsupported-version-error-code.md
Normal file
14
proposals/1866-invite-unsupported-version-error-code.md
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# MSC 1866 - Unsupported Room Version Error Code for Invites
|
||||||
|
|
||||||
|
It is currently unspecified what error code should be relayed to clients when
|
||||||
|
they attempt to invite a user on a remote server that does not support the room
|
||||||
|
version.
|
||||||
|
|
||||||
|
The proposal is to reuse the `M_UNSUPPORTED_ROOM_VERSION` error code that is
|
||||||
|
currently returned by the create room API.
|
||||||
|
|
||||||
|
Strictly, the error returned by the create room API would mean the local server
|
||||||
|
didn't support the room version, while for the invite API it would mean the
|
||||||
|
remote server didn't. However, there is sufficient overlap that it makes sense
|
||||||
|
to reuse the same error code and rely on the context to differentiate the two
|
||||||
|
cases.
|
||||||
107
proposals/1915-unbind-identity-server-param.md
Normal file
107
proposals/1915-unbind-identity-server-param.md
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
# MSC 1915 - Add unbind 3PID APIs
|
||||||
|
|
||||||
|
Note that this is a simplified version of MSC1194.
|
||||||
|
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
Currently we do not have a reasonable route for a user to unbind/remove a 3PID
|
||||||
|
from their account, particularly when deactivating their account. Users have an
|
||||||
|
expectation to be able to do this, and thus we should have an API to provide it.
|
||||||
|
|
||||||
|
This is meant as a simple extension to the current APIs, and so this explicitly
|
||||||
|
does not try and solve any existing usability concerns.
|
||||||
|
|
||||||
|
|
||||||
|
## API Changes
|
||||||
|
|
||||||
|
### Client-Server 3PID Delete API
|
||||||
|
|
||||||
|
Add an `id_server` param to `POST /_matrix/client/r0/account/3pid/delete` API,
|
||||||
|
which matches the 3PID creation APIs.
|
||||||
|
|
||||||
|
The new `id_server` parameter is optional and if missing the server will attempt
|
||||||
|
to unbind from the identity server used when originally binding the 3pid (if
|
||||||
|
known by the homeserver).
|
||||||
|
|
||||||
|
The 200 response is a JSON object with an `id_server_unbind_result` field whose
|
||||||
|
value is either `success` or `no-support`, where the latter indicates that the
|
||||||
|
identity server (IS) does not support unbinding 3PIDs directly. If the identity
|
||||||
|
server returns an error then that should be returned to the client.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /_matrix/client/r0/account/3pid/delete HTTP/1.1
|
||||||
|
|
||||||
|
{
|
||||||
|
"medium": "email",
|
||||||
|
"address": "foobar@example.com",
|
||||||
|
"id_server": "https://matrix.org
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
{
|
||||||
|
"id_server_unbind_result": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client-Server Deactivate account API
|
||||||
|
|
||||||
|
Add an `id_server` param to `POST /_matrix/client/r0/account/deactivate` API,
|
||||||
|
with the same semantics as above. This is used to unbind any bound threepids
|
||||||
|
from the given identity server.
|
||||||
|
|
||||||
|
|
||||||
|
### Identity Server 3PID Unbind API
|
||||||
|
|
||||||
|
Add `POST /_matrix/identity/api/v1/unbind` with `mxid` and `threepid` fields.
|
||||||
|
The `mxid` is the user's `user_id` and `threepid` is a dict with the usual
|
||||||
|
`medium` and `address` fields.
|
||||||
|
|
||||||
|
If the server returns a 400, 404 or 501 HTTP error code then the homeserver
|
||||||
|
should assume that the identity server doesn't support the `/unbind` API, unless
|
||||||
|
it returns a specific matrix error response (i.e. the body is a JSON object with
|
||||||
|
`error` and `errcode` fields).
|
||||||
|
|
||||||
|
The identity server should authenticate the request in one of two ways:
|
||||||
|
|
||||||
|
1. The request is signed by the homeserver which controls the `user_id`.
|
||||||
|
2. The request includes the `sid` and `client_secret` params (as per `/bind`),
|
||||||
|
which proves ownership of the given 3PID.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /_matrix/identity/api/v1/unbind HTTP/1.1
|
||||||
|
|
||||||
|
{
|
||||||
|
"mxid": "@foobar:example.com",
|
||||||
|
"threepid": {
|
||||||
|
"medium": "email",
|
||||||
|
"address": "foobar@example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
|
||||||
|
{}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Trade-offs
|
||||||
|
|
||||||
|
A homeserver can unbind any 3PID associated with one of its users, and
|
||||||
|
specifically does not require a re-validation of control of the 3PID. This means
|
||||||
|
that users have to trust that their homeserver will not arbitrarily remove valid
|
||||||
|
3PIDs, however users must already trust their homeserver to a large extent. The
|
||||||
|
flip side is that this provides a mechanism for homeservers and users to remove
|
||||||
|
3PIDs directed at their user IDs that they no longer (or never did) have control
|
||||||
|
over.
|
||||||
|
|
||||||
|
Removing a 3PID does not require user interactive auth (UIA), which opens a
|
||||||
|
potential attack whereby a logged in device can remove all associated 3PIDs and
|
||||||
|
then log out all devices. If the user has forgotten their password they would no
|
||||||
|
longer be able to reset their password via a 3PID (e.g. email), resulting in
|
||||||
|
losing access to their account. However, given that clients and servers have
|
||||||
|
implemented these APIs in the wild this is considered a sufficient edge case
|
||||||
|
that adding UIA is unlikely to be worthwhile.
|
||||||
|
|
@ -457,7 +457,7 @@ def main(targets, dest_dir, keep_intermediates, substitutions):
|
||||||
|
|
||||||
rst_file = os.path.join(tmp_dir, "spec_%s.rst" % (target_name,))
|
rst_file = os.path.join(tmp_dir, "spec_%s.rst" % (target_name,))
|
||||||
if version_label:
|
if version_label:
|
||||||
d = os.path.join(dest_dir, target_name)
|
d = os.path.join(dest_dir, target_name.split('@')[0])
|
||||||
if not os.path.exists(d):
|
if not os.path.exists(d):
|
||||||
os.mkdir(d)
|
os.mkdir(d)
|
||||||
html_file = os.path.join(d, "%s.html" % version_label)
|
html_file = os.path.join(d, "%s.html" % version_label)
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,11 @@ from batesian.sections import Sections
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class MatrixSections(Sections):
|
class MatrixSections(Sections):
|
||||||
|
|
||||||
# pass through git ver so it'll be dropped in the input file
|
# pass through git ver so it'll be dropped in the input file
|
||||||
|
|
@ -28,26 +31,14 @@ class MatrixSections(Sections):
|
||||||
def render_git_rev(self):
|
def render_git_rev(self):
|
||||||
return self.units.get("git_version")["revision"]
|
return self.units.get("git_version")["revision"]
|
||||||
|
|
||||||
def render_client_server_changelog(self):
|
def render_changelogs(self):
|
||||||
|
rendered = {}
|
||||||
changelogs = self.units.get("changelogs")
|
changelogs = self.units.get("changelogs")
|
||||||
return changelogs["client_server"]
|
for spec, changelog_text in changelogs.items():
|
||||||
|
spec_var = "%s_changelog" % spec
|
||||||
# TODO: We should make this a generic variable instead of having to add functions all the time.
|
logger.info("Rendering changelog for spec: %s" % spec)
|
||||||
def render_push_gateway_changelog(self):
|
rendered[spec_var] = changelog_text
|
||||||
changelogs = self.units.get("changelogs")
|
return rendered
|
||||||
return changelogs["push_gateway"]
|
|
||||||
|
|
||||||
def render_identity_service_changelog(self):
|
|
||||||
changelogs = self.units.get("changelogs")
|
|
||||||
return changelogs["identity_service"]
|
|
||||||
|
|
||||||
def render_server_server_changelog(self):
|
|
||||||
changelogs = self.units.get("changelogs")
|
|
||||||
return changelogs["server_server"]
|
|
||||||
|
|
||||||
def render_application_service_changelog(self):
|
|
||||||
changelogs = self.units.get("changelogs")
|
|
||||||
return changelogs["application_service"]
|
|
||||||
|
|
||||||
def _render_events(self, filterFn, sortFn):
|
def _render_events(self, filterFn, sortFn):
|
||||||
template = self.env.get_template("events.tmpl")
|
template = self.env.get_template("events.tmpl")
|
||||||
|
|
|
||||||
|
|
@ -774,7 +774,7 @@ class MatrixUnits(Units):
|
||||||
"Privileged server plugins",
|
"Privileged server plugins",
|
||||||
), TypeTableRow(
|
), TypeTableRow(
|
||||||
"`Identity Service API <identity_service/"+is_ver+".html>`_",
|
"`Identity Service API <identity_service/"+is_ver+".html>`_",
|
||||||
"unstable",
|
is_ver,
|
||||||
"Mapping of third party IDs to Matrix IDs",
|
"Mapping of third party IDs to Matrix IDs",
|
||||||
), TypeTableRow(
|
), TypeTableRow(
|
||||||
"`Push Gateway API <push_gateway/"+push_gw_ver+".html>`_",
|
"`Push Gateway API <push_gateway/"+push_gw_ver+".html>`_",
|
||||||
|
|
@ -903,74 +903,112 @@ class MatrixUnits(Units):
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
def load_changelogs(self):
|
def load_changelogs(self, substitutions):
|
||||||
|
"""Loads the changelog unit for later rendering in a section.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
substitutions: dict of variable name to value. Provided by the gendoc script.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dict of API name ("client_server", for example) to changelog.
|
||||||
|
"""
|
||||||
changelogs = {}
|
changelogs = {}
|
||||||
|
|
||||||
for f in os.listdir(CHANGELOG_DIR):
|
# The APIs and versions we'll prepare changelogs for. We use the substitutions
|
||||||
if not f.endswith(".rst"):
|
# to ensure that we pick up the right version for generated documentation. This
|
||||||
continue
|
# defaults to "unstable" as a version for incremental generated documentation (CI).
|
||||||
path = os.path.join(CHANGELOG_DIR, f)
|
prepare_versions = {
|
||||||
name = f[:-4]
|
"server_server": substitutions.get("%SERVER_RELEASE_LABEL%", "unstable"),
|
||||||
|
"client_server": substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable"),
|
||||||
|
"identity_service": substitutions.get("%IDENTITY_RELEASE_LABEL%", "unstable"),
|
||||||
|
"push_gateway": substitutions.get("%PUSH_GATEWAY_RELEASE_LABEL%", "unstable"),
|
||||||
|
"application_service": substitutions.get("%APPSERVICE_RELEASE_LABEL%", "unstable"),
|
||||||
|
}
|
||||||
|
|
||||||
# If there's a directory with the same name, we'll try to generate
|
# Changelogs are split into two places: towncrier for the unstable changelog and
|
||||||
# a towncrier changelog and prepend it to the general changelog.
|
# the RST file for historical versions. If the prepare_versions dict above has
|
||||||
tc_path = os.path.join(CHANGELOG_DIR, name)
|
# a version other than "unstable" specified for an API, we'll use the historical
|
||||||
tc_lines = []
|
# changelog and otherwise generate the towncrier log in-memory.
|
||||||
if os.path.isdir(tc_path):
|
|
||||||
logger.info("Generating towncrier changelog for: %s" % name)
|
|
||||||
p = subprocess.Popen(
|
|
||||||
['towncrier', '--version', 'Unreleased Changes', '--name', name, '--draft'],
|
|
||||||
cwd=tc_path,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
stdout, stderr = p.communicate()
|
|
||||||
if p.returncode != 0:
|
|
||||||
# Something broke - dump as much information as we can
|
|
||||||
logger.error("Towncrier exited with code %s" % p.returncode)
|
|
||||||
logger.error(stdout.decode('UTF-8'))
|
|
||||||
logger.error(stderr.decode('UTF-8'))
|
|
||||||
raw_log = ""
|
|
||||||
else:
|
|
||||||
raw_log = stdout.decode('UTF-8')
|
|
||||||
|
|
||||||
# This is a bit of a hack, but it does mean that the log at least gets *something*
|
for api_name, target_version in prepare_versions.items():
|
||||||
# to tell us it broke
|
logger.info("Generating changelog for %s at %s" % (api_name, target_version,))
|
||||||
if not raw_log.startswith("Unreleased Changes"):
|
|
||||||
logger.error("Towncrier appears to have failed to generate a changelog")
|
|
||||||
logger.error(raw_log)
|
|
||||||
raw_log = ""
|
|
||||||
tc_lines = raw_log.splitlines()
|
|
||||||
|
|
||||||
title_part = None
|
|
||||||
changelog_lines = []
|
changelog_lines = []
|
||||||
with open(path, "r", encoding="utf-8") as f:
|
if target_version == 'unstable':
|
||||||
lines = f.readlines()
|
# generate towncrier log
|
||||||
|
changelog_lines = self._read_towncrier_changelog(api_name)
|
||||||
|
else:
|
||||||
|
# read in the existing RST changelog
|
||||||
|
changelog_lines = self._read_rst_changelog(api_name)
|
||||||
|
|
||||||
|
# Parse the changelog lines to find the header we're looking for and therefore
|
||||||
|
# the changelog body.
|
||||||
prev_line = None
|
prev_line = None
|
||||||
for line in (tc_lines + lines):
|
title_part = None
|
||||||
|
changelog_body_lines = []
|
||||||
|
for line in changelog_lines:
|
||||||
if prev_line is None:
|
if prev_line is None:
|
||||||
prev_line = line
|
prev_line = line
|
||||||
continue
|
continue
|
||||||
if not title_part:
|
if re.match("^[=]{3,}$", line.strip()):
|
||||||
# find the title underline (at least 3 =)
|
# the last line was a header - use that as our new title_part
|
||||||
if re.match("^[=]{3,}$", line.strip()):
|
title_part = prev_line.strip()
|
||||||
title_part = prev_line
|
continue
|
||||||
continue
|
if re.match("^[-]{3,}$", line.strip()):
|
||||||
prev_line = line
|
# the last line is a subheading - drop this line because it's the underline
|
||||||
else: # have title, get body (stop on next title or EOF)
|
# and that causes problems with rendering. We'll keep the header text though.
|
||||||
if re.match("^[=]{3,}$", line.strip()):
|
continue
|
||||||
# we added the title in the previous iteration, pop it
|
if line.strip().startswith(".. "):
|
||||||
# then bail out.
|
# skip comments
|
||||||
changelog_lines.pop()
|
continue
|
||||||
break
|
if title_part == target_version:
|
||||||
# Don't generate subheadings (we'll keep the title though)
|
# if we made it this far, append the line to the changelog body. We indent it so
|
||||||
if re.match("^[-]{3,}$", line.strip()):
|
# that it renders correctly in the section. We also add newlines so that there's
|
||||||
continue
|
# intentionally blank lines that make rst2html happy.
|
||||||
changelog_lines.append(" " + line + '\n')
|
changelog_body_lines.append(" " + line + '\n')
|
||||||
changelogs[name] = "".join(changelog_lines)
|
|
||||||
|
|
||||||
|
if len(changelog_body_lines) > 0:
|
||||||
|
changelogs[api_name] = "".join(changelog_body_lines)
|
||||||
|
else:
|
||||||
|
raise ValueError("No changelog for %s at %s" % (api_name, target_version,))
|
||||||
|
|
||||||
|
# return our `dict[api_name] => changelog` as the last step.
|
||||||
return changelogs
|
return changelogs
|
||||||
|
|
||||||
|
def _read_towncrier_changelog(self, api_name):
|
||||||
|
tc_path = os.path.join(CHANGELOG_DIR, api_name)
|
||||||
|
if os.path.isdir(tc_path):
|
||||||
|
logger.info("Generating towncrier changelog for: %s" % api_name)
|
||||||
|
p = subprocess.Popen(
|
||||||
|
['towncrier', '--version', 'unstable', '--name', api_name, '--draft'],
|
||||||
|
cwd=tc_path,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
if p.returncode != 0:
|
||||||
|
# Something broke - dump as much information as we can
|
||||||
|
logger.error("Towncrier exited with code %s" % p.returncode)
|
||||||
|
logger.error(stdout.decode('UTF-8'))
|
||||||
|
logger.error(stderr.decode('UTF-8'))
|
||||||
|
raw_log = ""
|
||||||
|
else:
|
||||||
|
raw_log = stdout.decode('UTF-8')
|
||||||
|
|
||||||
|
# This is a bit of a hack, but it does mean that the log at least gets *something*
|
||||||
|
# to tell us it broke
|
||||||
|
if not raw_log.startswith("unstable"):
|
||||||
|
logger.error("Towncrier appears to have failed to generate a changelog")
|
||||||
|
logger.error(raw_log)
|
||||||
|
raw_log = ""
|
||||||
|
return raw_log.splitlines()
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _read_rst_changelog(self, api_name):
|
||||||
|
logger.info("Reading changelog RST for %s" % api_name)
|
||||||
|
rst_path = os.path.join(CHANGELOG_DIR, "%s.rst" % api_name)
|
||||||
|
with open(rst_path, 'r', encoding="utf-8") as f:
|
||||||
|
return f.readlines()
|
||||||
|
|
||||||
def load_unstable_warnings(self, substitutions):
|
def load_unstable_warnings(self, substitutions):
|
||||||
warning = """
|
warning = """
|
||||||
.. WARNING::
|
.. WARNING::
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,6 @@ Examples of strings encoded using unpadded Base64::
|
||||||
UNPADDED_BASE64("foobar") = "Zm9vYmFy"
|
UNPADDED_BASE64("foobar") = "Zm9vYmFy"
|
||||||
|
|
||||||
When decoding Base64, implementations SHOULD accept input with or without
|
When decoding Base64, implementations SHOULD accept input with or without
|
||||||
padding characters whereever possible, to ensure maximum interoperability.
|
padding characters wherever possible, to ensure maximum interoperability.
|
||||||
|
|
||||||
.. _`RFC 4648`: https://tools.ietf.org/html/rfc4648
|
.. _`RFC 4648`: https://tools.ietf.org/html/rfc4648
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@
|
||||||
Identifier Grammar
|
Identifier Grammar
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
Some identifiers are specific to given room versions, please refer to the
|
||||||
|
`room versions specification`_ for more information.
|
||||||
|
|
||||||
|
.. _`room versions specification`: index.html#room-versions
|
||||||
|
|
||||||
|
|
||||||
Server Name
|
Server Name
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
@ -28,7 +34,7 @@ following grammar::
|
||||||
|
|
||||||
server_name = hostname [ ":" port ]
|
server_name = hostname [ ":" port ]
|
||||||
|
|
||||||
port = *DIGIT
|
port = 1*5DIGIT
|
||||||
|
|
||||||
hostname = IPv4address / "[" IPv6address "]" / dns-name
|
hostname = IPv4address / "[" IPv6address "]" / dns-name
|
||||||
|
|
||||||
|
|
@ -78,38 +84,6 @@ Some recommendations for a choice of server name follow:
|
||||||
* The length of the complete server name should not exceed 230 characters.
|
* The length of the complete server name should not exceed 230 characters.
|
||||||
* Server names should not use upper-case characters.
|
* Server names should not use upper-case characters.
|
||||||
|
|
||||||
|
|
||||||
Room Versions
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Room versions are used to change properties of rooms that may not be compatible
|
|
||||||
with other servers. For example, changing the rules for event authorization would
|
|
||||||
cause older servers to potentially end up in a split-brain situation due to them
|
|
||||||
not understanding the new rules.
|
|
||||||
|
|
||||||
A room version is defined as a string of characters which MUST NOT exceed 32
|
|
||||||
codepoints in length. Room versions MUST NOT be empty and SHOULD contain only
|
|
||||||
the characters ``a-z``, ``0-9``, ``.``, and ``-``.
|
|
||||||
|
|
||||||
Room versions are not intended to be parsed and should be treated as opaque
|
|
||||||
identifiers. Room versions consisting only of the characters ``0-9`` and ``.``
|
|
||||||
are reserved for future versions of the Matrix protocol.
|
|
||||||
|
|
||||||
The complete grammar for a legal room version is::
|
|
||||||
|
|
||||||
room_version = 1*room_version_char
|
|
||||||
room_version_char = DIGIT
|
|
||||||
/ %x61-7A ; a-z
|
|
||||||
/ "-" / "."
|
|
||||||
|
|
||||||
Examples of valid room versions are:
|
|
||||||
|
|
||||||
* ``1`` (would be reserved by the Matrix protocol)
|
|
||||||
* ``1.2`` (would be reserved by the Matrix protocol)
|
|
||||||
* ``1.2-beta``
|
|
||||||
* ``com.example.version``
|
|
||||||
|
|
||||||
|
|
||||||
Common Identifier Format
|
Common Identifier Format
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
@ -229,7 +203,7 @@ a homeserver creating a user ID for a new user based on the username passed to
|
||||||
|
|
||||||
Implementations are free to do this mapping however they choose. Since the user
|
Implementations are free to do this mapping however they choose. Since the user
|
||||||
ID is opaque except to the implementation which created it, the only
|
ID is opaque except to the implementation which created it, the only
|
||||||
requirement is that the implemention can perform the mapping
|
requirement is that the implementation can perform the mapping
|
||||||
consistently. However, we suggest the following algorithm:
|
consistently. However, we suggest the following algorithm:
|
||||||
|
|
||||||
1. Encode character strings as UTF-8.
|
1. Encode character strings as UTF-8.
|
||||||
|
|
@ -260,18 +234,17 @@ A room has exactly one room ID. A room ID has the format::
|
||||||
|
|
||||||
!opaque_id:domain
|
!opaque_id:domain
|
||||||
|
|
||||||
An event has exactly one event ID. An event ID has the format::
|
An event has exactly one event ID. The format of an event ID depends upon the
|
||||||
|
`room version specification <index.html#room-versions>`_.
|
||||||
|
|
||||||
$opaque_id:domain
|
The ``domain`` of a room ID is the `server name`_ of the homeserver which
|
||||||
|
|
||||||
The ``domain`` of a room/event ID is the `server name`_ of the homeserver which
|
|
||||||
created the room/event. The domain is used only for namespacing to avoid the
|
created the room/event. The domain is used only for namespacing to avoid the
|
||||||
risk of clashes of identifiers between different homeservers. There is no
|
risk of clashes of identifiers between different homeservers. There is no
|
||||||
implication that the room or event in question is still available at the
|
implication that the room or event in question is still available at the
|
||||||
corresponding homeserver.
|
corresponding homeserver.
|
||||||
|
|
||||||
Event IDs and Room IDs are case-sensitive. They are not meant to be human
|
Event IDs and Room IDs are case-sensitive. They are not meant to be human
|
||||||
readable.
|
readable. They are intended to be treated as fully opaque strings by clients.
|
||||||
|
|
||||||
.. TODO-spec
|
.. TODO-spec
|
||||||
What is the grammar for the opaque part? https://matrix.org/jira/browse/SPEC-389
|
What is the grammar for the opaque part? https://matrix.org/jira/browse/SPEC-389
|
||||||
|
|
@ -350,14 +323,27 @@ and instead should perform some sort of action within the client. For example, i
|
||||||
the user were to click on a matrix.to URI for a room alias, the client may open
|
the user were to click on a matrix.to URI for a room alias, the client may open
|
||||||
a view for the user to participate in the room.
|
a view for the user to participate in the room.
|
||||||
|
|
||||||
|
The components of the matrix.to URI (``<identifier>`` and ``<extra parameter>``)
|
||||||
|
are to be percent-encoded as per RFC 3986.
|
||||||
|
|
||||||
Examples of matrix.to URIs are:
|
Examples of matrix.to URIs are:
|
||||||
|
|
||||||
* Room alias: ``https://matrix.to/#/#somewhere:example.org``
|
* Room alias: ``https://matrix.to/#/%23somewhere%3Aexample.org``
|
||||||
* Room: ``https://matrix.to/#/!somewhere:example.org``
|
* Room: ``https://matrix.to/#/!somewhere%3Aexample.org``
|
||||||
* Permalink by room: ``https://matrix.to/#/!somewhere:example.org/$event:example.org``
|
* Permalink by room: ``https://matrix.to/#/!somewhere%3Aexample.org/%24event%3Aexample.org``
|
||||||
* Permalink by room alias: ``https://matrix.to/#/#somewhere:example.org/$event:example.org``
|
* Permalink by room alias: ``https://matrix.to/#/#somewhere:example.org/%24event%3Aexample.org``
|
||||||
* User: ``https://matrix.to/#/@alice:example.org``
|
* User: ``https://matrix.to/#/%40alice%3Aexample.org``
|
||||||
* Group: ``https://matrix.to/#/+example:example.org``
|
* Group: ``https://matrix.to/#/%2Bexample%3Aexample.org``
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
Historically, clients have not produced URIs which are fully encoded. Clients should
|
||||||
|
try to interpret these cases to the best of their ability. For example, an unencoded
|
||||||
|
room alias should still work within the client if possible.
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
Clients should be aware that decoding a matrix.to URI may result in extra slashes
|
||||||
|
appearing due to some `room versions <index.html#room-versions>`_. These slashes
|
||||||
|
should normally be encoded when producing matrix.to URIs, however.
|
||||||
|
|
||||||
.. Note::
|
.. Note::
|
||||||
Room ID permalinks are unroutable as there is no reliable domain to send requests
|
Room ID permalinks are unroutable as there is no reliable domain to send requests
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ MUST be encoded as UTF-8. Clients are authenticated using opaque
|
||||||
``access_token`` strings (see `Client Authentication`_ for details), passed as a
|
``access_token`` strings (see `Client Authentication`_ for details), passed as a
|
||||||
query string parameter on all requests.
|
query string parameter on all requests.
|
||||||
|
|
||||||
The names of the API endponts for the HTTP transport follow a convention of
|
The names of the API endpoints for the HTTP transport follow a convention of
|
||||||
using underscores to separate words (for example ``/delete_devices``). The key
|
using underscores to separate words (for example ``/delete_devices``). The key
|
||||||
names in JSON objects passed over the API also follow this convention.
|
names in JSON objects passed over the API also follow this convention.
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ Other error codes the client might encounter are:
|
||||||
Sent when the room alias given to the ``createRoom`` API is already in use.
|
Sent when the room alias given to the ``createRoom`` API is already in use.
|
||||||
|
|
||||||
:``M_INVALID_ROOM_STATE``:
|
:``M_INVALID_ROOM_STATE``:
|
||||||
Sent when the intial state given to the ``createRoom`` API is invalid.
|
Sent when the initial state given to the ``createRoom`` API is invalid.
|
||||||
|
|
||||||
:``M_THREEPID_IN_USE``:
|
:``M_THREEPID_IN_USE``:
|
||||||
Sent when a threepid given to an API cannot be used because the same threepid is already in use.
|
Sent when a threepid given to an API cannot be used because the same threepid is already in use.
|
||||||
|
|
@ -210,10 +210,18 @@ Other error codes the client might encounter are:
|
||||||
The resource being requested is reserved by an application service, or the
|
The resource being requested is reserved by an application service, or the
|
||||||
application service making the request has not created the resource.
|
application service making the request has not created the resource.
|
||||||
|
|
||||||
|
:``M_RESOURCE_LIMIT_EXCEEDED``:
|
||||||
|
The request cannot be completed because the homeserver has reached a resource
|
||||||
|
limit imposed on it. For example, a homeserver held in a shared hosting environment
|
||||||
|
may reach a resource limit if it starts using too much memory or disk space. The
|
||||||
|
error MUST have an ``admin_contact`` field to provide the user receiving the error
|
||||||
|
a place to reach out to. Typically, this error will appear on routes which attempt
|
||||||
|
to modify state (eg: sending messages, account data, etc) and not routes which only
|
||||||
|
read state (eg: ``/sync``, get account data, etc).
|
||||||
|
|
||||||
.. TODO: More error codes (covered by other issues)
|
.. TODO: More error codes (covered by other issues)
|
||||||
.. * M_CONSENT_NOT_GIVEN - GDPR: https://github.com/matrix-org/matrix-doc/issues/1512
|
.. * M_CONSENT_NOT_GIVEN - GDPR: https://github.com/matrix-org/matrix-doc/issues/1512
|
||||||
.. * M_CANNOT_LEAVE_SERVER_NOTICE_ROOM - GDPR: https://github.com/matrix-org/matrix-doc/issues/1254
|
.. * M_CANNOT_LEAVE_SERVER_NOTICE_ROOM - GDPR: https://github.com/matrix-org/matrix-doc/issues/1254
|
||||||
.. * M_RESOURCE_LIMIT_EXCEEDED - Limits: https://github.com/matrix-org/matrix-doc/issues/1504
|
|
||||||
|
|
||||||
.. _sect:txn_ids:
|
.. _sect:txn_ids:
|
||||||
|
|
||||||
|
|
@ -636,7 +644,7 @@ To use this authentication type, clients should submit an auth dict as follows:
|
||||||
where the ``identifier`` property is a user identifier object, as described in
|
where the ``identifier`` property is a user identifier object, as described in
|
||||||
`Identifier types`_.
|
`Identifier types`_.
|
||||||
|
|
||||||
For example, to authenticate using the user's Matrix ID, clients whould submit:
|
For example, to authenticate using the user's Matrix ID, clients would submit:
|
||||||
|
|
||||||
.. code:: json
|
.. code:: json
|
||||||
|
|
||||||
|
|
@ -650,7 +658,7 @@ For example, to authenticate using the user's Matrix ID, clients whould submit:
|
||||||
"session": "<session ID>"
|
"session": "<session ID>"
|
||||||
}
|
}
|
||||||
|
|
||||||
Alternatively reply using a 3pid bound to the user's account on the homeserver
|
Alternatively reply using a 3PID bound to the user's account on the homeserver
|
||||||
using the |/account/3pid|_ API rather then giving the ``user`` explicitly as
|
using the |/account/3pid|_ API rather then giving the ``user`` explicitly as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
|
|
@ -667,7 +675,7 @@ follows:
|
||||||
"session": "<session ID>"
|
"session": "<session ID>"
|
||||||
}
|
}
|
||||||
|
|
||||||
In the case that the homeserver does not know about the supplied 3pid, the
|
In the case that the homeserver does not know about the supplied 3PID, the
|
||||||
homeserver must respond with 403 Forbidden.
|
homeserver must respond with 403 Forbidden.
|
||||||
|
|
||||||
Google ReCaptcha
|
Google ReCaptcha
|
||||||
|
|
@ -928,10 +936,10 @@ Third-party ID
|
||||||
:Type:
|
:Type:
|
||||||
``m.id.thirdparty``
|
``m.id.thirdparty``
|
||||||
:Description:
|
:Description:
|
||||||
The user is identified by a third-party identifer in canonicalised form.
|
The user is identified by a third-party identifier in canonicalised form.
|
||||||
|
|
||||||
A client can identify a user using a 3pid associated with the user's account on
|
A client can identify a user using a 3PID associated with the user's account on
|
||||||
the homeserver, where the 3pid was previously associated using the
|
the homeserver, where the 3PID was previously associated using the
|
||||||
|/account/3pid|_ API. See the `3PID Types`_ Appendix for a list of Third-party
|
|/account/3pid|_ API. See the `3PID Types`_ Appendix for a list of Third-party
|
||||||
ID media.
|
ID media.
|
||||||
|
|
||||||
|
|
@ -987,7 +995,7 @@ request as follows:
|
||||||
"password": "<password>"
|
"password": "<password>"
|
||||||
}
|
}
|
||||||
|
|
||||||
Alternatively, a client can use a 3pid bound to the user's account on the
|
Alternatively, a client can use a 3PID bound to the user's account on the
|
||||||
homeserver using the |/account/3pid|_ API rather then giving the ``user``
|
homeserver using the |/account/3pid|_ API rather then giving the ``user``
|
||||||
explicitly, as follows:
|
explicitly, as follows:
|
||||||
|
|
||||||
|
|
@ -1002,7 +1010,7 @@ explicitly, as follows:
|
||||||
"password": "<password>"
|
"password": "<password>"
|
||||||
}
|
}
|
||||||
|
|
||||||
In the case that the homeserver does not know about the supplied 3pid, the
|
In the case that the homeserver does not know about the supplied 3PID, the
|
||||||
homeserver must respond with ``403 Forbidden``.
|
homeserver must respond with ``403 Forbidden``.
|
||||||
|
|
||||||
To log in using a login token, clients should submit a ``/login`` request as
|
To log in using a login token, clients should submit a ``/login`` request as
|
||||||
|
|
@ -1070,6 +1078,107 @@ Current account information
|
||||||
|
|
||||||
{{whoami_cs_http_api}}
|
{{whoami_cs_http_api}}
|
||||||
|
|
||||||
|
Capabilities negotiation
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
A homeserver may not support certain operations and clients must be able to
|
||||||
|
query for what the homeserver can and can't offer. For example, a homeserver
|
||||||
|
may not support users changing their password as it is configured to perform
|
||||||
|
authentication against an external system.
|
||||||
|
|
||||||
|
The capabilities advertised through this system are intended to advertise
|
||||||
|
functionality which is optional in the API, or which depend in some way on
|
||||||
|
the state of the user or server. This system should not be used to advertise
|
||||||
|
unstable or experimental features - this is better done by the ``/versions``
|
||||||
|
endpoint.
|
||||||
|
|
||||||
|
Some examples of what a reasonable capability could be are:
|
||||||
|
|
||||||
|
* Whether the server supports user presence.
|
||||||
|
|
||||||
|
* Whether the server supports optional features, such as the user or room
|
||||||
|
directories.
|
||||||
|
|
||||||
|
* The rate limits or file type restrictions imposed on clients by the server.
|
||||||
|
|
||||||
|
Some examples of what should **not** be a capability are:
|
||||||
|
|
||||||
|
* Whether the server supports a feature in the ``unstable`` specification.
|
||||||
|
|
||||||
|
* Media size limits - these are handled by the ``/media/%CLIENT_MAJOR_VERSION%/config``
|
||||||
|
API.
|
||||||
|
|
||||||
|
* Optional encodings or alternative transports for communicating with the
|
||||||
|
server.
|
||||||
|
|
||||||
|
Capabilities prefixed with ``m.`` are reserved for definition in the Matrix
|
||||||
|
specification while other values may be used by servers using the Java package
|
||||||
|
naming convention. The capabilities supported by the Matrix specification are
|
||||||
|
defined later in this section.
|
||||||
|
|
||||||
|
{{capabilities_cs_http_api}}
|
||||||
|
|
||||||
|
|
||||||
|
``m.change_password`` capability
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This capability has a single flag, ``enabled``, which indicates whether or not
|
||||||
|
the user can use the ``/account/password`` API to change their password. If not
|
||||||
|
present, the client should assume that password changes are possible via the
|
||||||
|
API. When present, clients SHOULD respect the capability's ``enabled`` flag
|
||||||
|
and indicate to the user if they are unable to change their password.
|
||||||
|
|
||||||
|
An example of the capability API's response for this capability is::
|
||||||
|
|
||||||
|
{
|
||||||
|
"capabilities": {
|
||||||
|
"m.change_password": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
``m.room_versions`` capability
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This capability describes the default and available room versions a server
|
||||||
|
supports, and at what level of stability. Clients should make use of this
|
||||||
|
capability to determine if users need to be encouraged to upgrade their rooms.
|
||||||
|
|
||||||
|
An example of the capability API's response for this capability is::
|
||||||
|
|
||||||
|
{
|
||||||
|
"capabilities": {
|
||||||
|
"m.room_versions": {
|
||||||
|
"default": "1",
|
||||||
|
"available": {
|
||||||
|
"1": "stable",
|
||||||
|
"2": "stable",
|
||||||
|
"3": "unstable",
|
||||||
|
"custom-version": "unstable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
This capability mirrors the same restrictions of `room versions`_ to describe
|
||||||
|
which versions are stable and unstable. Clients should assume that the ``default``
|
||||||
|
version is ``stable``. Any version not explicitly labelled as ``stable`` in the
|
||||||
|
``available`` versions is to be treated as ``unstable``. For example, a version
|
||||||
|
listed as ``future-stable`` should be treated as ``unstable``.
|
||||||
|
|
||||||
|
The ``default`` version is the version the server is using to create new rooms.
|
||||||
|
Clients should encourage users with sufficient permissions in a room to upgrade
|
||||||
|
their room to the ``default`` version when the room is using an ``unstable``
|
||||||
|
version.
|
||||||
|
|
||||||
|
When this capability is not listed, clients should use ``"1"`` as the default
|
||||||
|
and only stable ``available`` room version.
|
||||||
|
|
||||||
|
.. _`room versions`: ../index.html#room-versions
|
||||||
|
|
||||||
|
|
||||||
Pagination
|
Pagination
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
@ -1166,7 +1275,21 @@ point in time::
|
||||||
|
|
||||||
[E0]->[E1]->[E2]->[E3]->[E4]->[E5]
|
[E0]->[E1]->[E2]->[E3]->[E4]->[E5]
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
|
||||||
|
The format of events can change depending on room version. Check the
|
||||||
|
`room version specification`_ for specific details on what to expect for
|
||||||
|
event formats. Examples contained within the client-server specification
|
||||||
|
are expected to be compatible with all specified room versions, however
|
||||||
|
some differences may still apply.
|
||||||
|
|
||||||
|
For this version of the specification, clients only need to worry about
|
||||||
|
the event ID format being different depending on room version. Clients
|
||||||
|
should not be parsing the event ID, and instead be treating it as an
|
||||||
|
opaque string. No changes should be required to support the currently
|
||||||
|
available room versions.
|
||||||
|
|
||||||
|
.. _`room version specification`: ../index.html#room-versions
|
||||||
|
|
||||||
Types of room events
|
Types of room events
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ Identity Service API
|
||||||
|
|
||||||
The Matrix client-server and server-server APIs are largely expressed in Matrix
|
The Matrix client-server and server-server APIs are largely expressed in Matrix
|
||||||
user identifiers. From time to time, it is useful to refer to users by other
|
user identifiers. From time to time, it is useful to refer to users by other
|
||||||
("third-party") identifiers, or "3pid"s, e.g. their email address or phone
|
("third-party") identifiers, or "3PID"s, e.g. their email address or phone
|
||||||
number. This Identity Service Specification describes how mappings between
|
number. This Identity Service Specification describes how mappings between
|
||||||
third-party identifiers and Matrix user identifiers can be established,
|
third-party identifiers and Matrix user identifiers can be established,
|
||||||
validated, and used. This description technically may apply to any 3pid, but in
|
validated, and used. This description technically may apply to any 3PID, but in
|
||||||
practice has only been applied specifically to email addresses and phone numbers.
|
practice has only been applied specifically to email addresses and phone numbers.
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
.. contents:: Table of Contents
|
||||||
|
|
@ -150,9 +150,9 @@ Identity is a privacy-sensitive issue. While the identity server exists to
|
||||||
provide identity information, access should be restricted to avoid leaking
|
provide identity information, access should be restricted to avoid leaking
|
||||||
potentially sensitive data. In particular, being able to construct large-scale
|
potentially sensitive data. In particular, being able to construct large-scale
|
||||||
connections between identities should be avoided. To this end, in general APIs
|
connections between identities should be avoided. To this end, in general APIs
|
||||||
should allow a 3pid to be mapped to a Matrix user identity, but not in the other
|
should allow a 3PID to be mapped to a Matrix user identity, but not in the other
|
||||||
direction (i.e. one should not be able to get all 3pids associated with a Matrix
|
direction (i.e. one should not be able to get all 3PIDs associated with a Matrix
|
||||||
user ID, or get all 3pids associated with a 3pid).
|
user ID, or get all 3PIDs associated with a 3PID).
|
||||||
|
|
||||||
Web browser clients
|
Web browser clients
|
||||||
-------------------
|
-------------------
|
||||||
|
|
@ -204,10 +204,10 @@ Establishing associations
|
||||||
|
|
||||||
The flow for creating an association is session-based.
|
The flow for creating an association is session-based.
|
||||||
|
|
||||||
Within a session, one may prove that one has ownership of a 3pid.
|
Within a session, one may prove that one has ownership of a 3PID.
|
||||||
Once this has been established, the user can form an association between that
|
Once this has been established, the user can form an association between that
|
||||||
3pid and a Matrix user ID. Note that this association is only proved one way;
|
3PID and a Matrix user ID. Note that this association is only proved one way;
|
||||||
a user can associate *any* Matrix user ID with a validated 3pid,
|
a user can associate *any* Matrix user ID with a validated 3PID,
|
||||||
i.e. I can claim that any email address I own is associated with
|
i.e. I can claim that any email address I own is associated with
|
||||||
@billg:microsoft.com.
|
@billg:microsoft.com.
|
||||||
|
|
||||||
|
|
@ -255,11 +255,11 @@ General
|
||||||
Invitation storage
|
Invitation storage
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
An identity server can store pending invitations to a user's 3pid, which will
|
An identity server can store pending invitations to a user's 3PID, which will
|
||||||
be retrieved and can be either notified on or look up when the 3pid is
|
be retrieved and can be either notified on or look up when the 3PID is
|
||||||
associated with a Matrix user ID.
|
associated with a Matrix user ID.
|
||||||
|
|
||||||
At a later point, if the owner of that particular 3pid binds it with a Matrix user
|
At a later point, if the owner of that particular 3PID binds it with a Matrix user
|
||||||
ID, the identity server will attempt to make an HTTP POST to the Matrix user's
|
ID, the identity server will attempt to make an HTTP POST to the Matrix user's
|
||||||
homeserver via the `/3pid/onbind`_ endpoint. The request MUST be signed with a
|
homeserver via the `/3pid/onbind`_ endpoint. The request MUST be signed with a
|
||||||
long-term private key for the identity server.
|
long-term private key for the identity server.
|
||||||
|
|
@ -279,4 +279,4 @@ this isn't possible.
|
||||||
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
||||||
.. _`3PID Types`: ../appendices.html#pid-types
|
.. _`3PID Types`: ../appendices.html#pid-types
|
||||||
.. _`Signing JSON`: ../appendices.html#signing-json
|
.. _`Signing JSON`: ../appendices.html#signing-json
|
||||||
.. _`/3pid/onbind`: ../server_server/unstable.html#put-matrix-federation-v1-3pid-onbind
|
.. _`/3pid/onbind`: ../server_server/r0.1.1.html#put-matrix-federation-v1-3pid-onbind
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,15 @@ The specification consists of the following parts:
|
||||||
|
|
||||||
{{apis}}
|
{{apis}}
|
||||||
|
|
||||||
|
Additionally, this introduction page contains the key baseline information required to
|
||||||
|
understand the specific APIs, including the sections on `room versions`_
|
||||||
|
and `overall architecture <#architecture>`_.
|
||||||
|
|
||||||
The `Appendices <appendices.html>`_ contain supplemental information not specific to
|
The `Appendices <appendices.html>`_ contain supplemental information not specific to
|
||||||
one of the above APIs.
|
one of the above APIs.
|
||||||
|
|
||||||
The `Matrix Client-Server API Swagger Viewer <https://matrix.org/docs/api/client-server/>`_ is useful for browsing the Client-Server API.
|
The `Matrix Client-Server API Swagger Viewer <https://matrix.org/docs/api/client-server/>`_
|
||||||
|
is useful for browsing the Client-Server API.
|
||||||
|
|
||||||
Introduction to the Matrix APIs
|
Introduction to the Matrix APIs
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
@ -128,6 +133,8 @@ To propose a change to the Matrix Spec, see the explanations at `Proposals
|
||||||
for Spec Changes to Matrix <proposals>`_.
|
for Spec Changes to Matrix <proposals>`_.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`architecture`:
|
||||||
|
|
||||||
Architecture
|
Architecture
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
@ -189,7 +196,7 @@ allocated the account and has the form::
|
||||||
|
|
||||||
@localpart:domain
|
@localpart:domain
|
||||||
|
|
||||||
See `'Identifier Grammar' the appendices <appendices.html#identifier-grammar>`_ for full details of
|
See `'Identifier Grammar' in the appendices <appendices.html#identifier-grammar>`_ for full details of
|
||||||
the structure of user IDs.
|
the structure of user IDs.
|
||||||
|
|
||||||
Devices
|
Devices
|
||||||
|
|
@ -315,8 +322,8 @@ The following conceptual diagram shows an
|
||||||
| Content: { JSON object } |
|
| Content: { JSON object } |
|
||||||
|....................................|
|
|....................................|
|
||||||
|
|
||||||
Federation maintains *shared data structures* per-room between multiple home
|
Federation maintains *shared data structures* per-room between multiple
|
||||||
servers. The data is split into ``message events`` and ``state events``.
|
homeservers. The data is split into ``message events`` and ``state events``.
|
||||||
|
|
||||||
Message events:
|
Message events:
|
||||||
These describe transient 'once-off' activity in a room such as an
|
These describe transient 'once-off' activity in a room such as an
|
||||||
|
|
@ -418,6 +425,75 @@ dedicated API. The API is symmetrical to managing Profile data.
|
||||||
Would it really be overengineered to use the same API for both profile &
|
Would it really be overengineered to use the same API for both profile &
|
||||||
private user data, but with different ACLs?
|
private user data, but with different ACLs?
|
||||||
|
|
||||||
|
.. _`room versions`:
|
||||||
|
|
||||||
|
Room Versions
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Rooms are central to how Matrix operates, and have strict rules for what
|
||||||
|
is allowed to be contained within them. Rooms can also have various
|
||||||
|
algorithms that handle different tasks, such as what to do when two or
|
||||||
|
more events collide in the underlying DAG. To allow rooms to be improved
|
||||||
|
upon through new algorithms or rules, "room versions" are employed to
|
||||||
|
manage a set of expectations for each room. New room versions are assigned
|
||||||
|
as needed.
|
||||||
|
|
||||||
|
There is no implicit ordering or hierarchy to room versions, and their principles
|
||||||
|
are immutable once placed in the specification. Although there is a recommended
|
||||||
|
set of versions, some rooms may benefit from features introduced by other versions.
|
||||||
|
Rooms move between different versions by "upgrading" to the desired version. Due
|
||||||
|
to versions not being ordered or hierarchical, this means a room can "upgrade"
|
||||||
|
from version 2 to version 1, if it is so desired.
|
||||||
|
|
||||||
|
Room version grammar
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Room versions are used to change properties of rooms that may not be compatible
|
||||||
|
with other servers. For example, changing the rules for event authorization would
|
||||||
|
cause older servers to potentially end up in a split-brain situation due to not
|
||||||
|
understanding the new rules.
|
||||||
|
|
||||||
|
A room version is defined as a string of characters which MUST NOT exceed 32
|
||||||
|
codepoints in length. Room versions MUST NOT be empty and SHOULD contain only
|
||||||
|
the characters ``a-z``, ``0-9``, ``.``, and ``-``.
|
||||||
|
|
||||||
|
Room versions are not intended to be parsed and should be treated as opaque
|
||||||
|
identifiers. Room versions consisting only of the characters ``0-9`` and ``.``
|
||||||
|
are reserved for future versions of the Matrix protocol.
|
||||||
|
|
||||||
|
The complete grammar for a legal room version is::
|
||||||
|
|
||||||
|
room_version = 1*room_version_char
|
||||||
|
room_version_char = DIGIT
|
||||||
|
/ %x61-7A ; a-z
|
||||||
|
/ "-" / "."
|
||||||
|
|
||||||
|
Examples of valid room versions are:
|
||||||
|
|
||||||
|
* ``1`` (would be reserved by the Matrix protocol)
|
||||||
|
* ``1.2`` (would be reserved by the Matrix protocol)
|
||||||
|
* ``1.2-beta``
|
||||||
|
* ``com.example.version``
|
||||||
|
|
||||||
|
Complete list of room versions
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Room versions are divided into two distinct groups: stable and unstable. Stable
|
||||||
|
room versions may be used by rooms safely. Unstable room versions are everything
|
||||||
|
else which is either not listed in the specification or flagged as unstable for
|
||||||
|
some other reason. Versions can switch between stable and unstable periodically
|
||||||
|
for a variety of reasons, including discovered security vulnerabilities and age.
|
||||||
|
|
||||||
|
Clients should not ask room administrators to upgrade their rooms if the room is
|
||||||
|
running a stable version. Servers SHOULD use room version 1 as the default room
|
||||||
|
version when creating new rooms.
|
||||||
|
|
||||||
|
The available room versions are:
|
||||||
|
|
||||||
|
* `Version 1 <rooms/v1.html>`_ - **Stable**. The current version of most rooms.
|
||||||
|
* `Version 2 <rooms/v2.html>`_ - **Stable**. Implements State Resolution Version 2.
|
||||||
|
* `Version 3 <rooms/v3.html>`_ - **Stable**. Introduces events whose IDs are the event's hash.
|
||||||
|
|
||||||
Specification Versions
|
Specification Versions
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ The account_data may be either global or scoped to a particular rooms.
|
||||||
Events
|
Events
|
||||||
------
|
------
|
||||||
|
|
||||||
The client recieves the account data as events in the ``account_data`` sections
|
The client receives the account data as events in the ``account_data`` sections
|
||||||
of a ``/sync``.
|
of a ``/sync``.
|
||||||
|
|
||||||
These events can also be received in a ``/events`` response or in the
|
These events can also be received in a ``/events`` response or in the
|
||||||
|
|
|
||||||
|
|
@ -291,8 +291,8 @@ v string **Required.** Version of the encrypted attachments
|
||||||
========= ========= ============================================================
|
========= ========= ============================================================
|
||||||
Parameter Type Description
|
Parameter Type Description
|
||||||
========= ========= ============================================================
|
========= ========= ============================================================
|
||||||
key string **Required.** Key type. Must be ``oct``.
|
kty string **Required.** Key type. Must be ``oct``.
|
||||||
key_opts [string] **Required.** Key operations. Must at least contain
|
key_ops [string] **Required.** Key operations. Must at least contain
|
||||||
``encrypt`` and ``decrypt``.
|
``encrypt`` and ``decrypt``.
|
||||||
alg string **Required.** Algorithm. Must be ``A256CTR``.
|
alg string **Required.** Algorithm. Must be ``A256CTR``.
|
||||||
k string **Required.** The key, encoded as urlsafe unpadded base64.
|
k string **Required.** The key, encoded as urlsafe unpadded base64.
|
||||||
|
|
@ -450,7 +450,7 @@ previously-received ``request`` message with the same ``request_id`` and
|
||||||
.. NOTE::
|
.. NOTE::
|
||||||
|
|
||||||
Key sharing can be a big attack vector, thus it must be done very carefully.
|
Key sharing can be a big attack vector, thus it must be done very carefully.
|
||||||
A reasonable stategy is for a user's client to only send keys requested by the
|
A reasonable strategy is for a user's client to only send keys requested by the
|
||||||
verified devices of the same user.
|
verified devices of the same user.
|
||||||
|
|
||||||
Key exports
|
Key exports
|
||||||
|
|
@ -496,18 +496,9 @@ passphrase, and is created as follows:
|
||||||
Key export format
|
Key export format
|
||||||
<<<<<<<<<<<<<<<<<
|
<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
The exported sessions are formatted as a JSON object of type ``ExportData``
|
The exported sessions are formatted as a JSON array of ``SessionData`` objects
|
||||||
described as follows:
|
described as follows:
|
||||||
|
|
||||||
``ExportData``
|
|
||||||
|
|
||||||
=============== ================= ==============================================
|
|
||||||
Parameter Type Description
|
|
||||||
=============== ================= ==============================================
|
|
||||||
sessions ``[SessionData]`` Required. The sessions that are being
|
|
||||||
exported.
|
|
||||||
=============== ================= ==============================================
|
|
||||||
|
|
||||||
``SessionData``
|
``SessionData``
|
||||||
|
|
||||||
.. table::
|
.. table::
|
||||||
|
|
@ -529,7 +520,7 @@ sessions ``[SessionData]`` Required. The sessions that are being
|
||||||
device which initiated the session
|
device which initiated the session
|
||||||
originally.
|
originally.
|
||||||
sender_claimed_keys {string: Required. The Ed25519 key of the
|
sender_claimed_keys {string: Required. The Ed25519 key of the
|
||||||
integer} device which initiated the session
|
string} device which initiated the session
|
||||||
originally.
|
originally.
|
||||||
session_id string Required. The ID of the session.
|
session_id string Required. The ID of the session.
|
||||||
session_key string Required. The key for the session.
|
session_key string Required. The key for the session.
|
||||||
|
|
@ -696,7 +687,7 @@ An event encrypted using Megolm has the following format:
|
||||||
"sender_key": "<sender_curve25519_key>",
|
"sender_key": "<sender_curve25519_key>",
|
||||||
"device_id": "<sender_device_id>",
|
"device_id": "<sender_device_id>",
|
||||||
"session_id": "<outbound_group_session_id>",
|
"session_id": "<outbound_group_session_id>",
|
||||||
"ciphertext": "<encypted_payload_base_64>"
|
"ciphertext": "<encrypted_payload_base_64>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,25 +185,14 @@ reduced through clients making use of the transaction ID they used to send
|
||||||
a particular event. The transaction ID used will be included in the event's
|
a particular event. The transaction ID used will be included in the event's
|
||||||
``unsigned`` data as ``transaction_id`` when it arrives through the event stream.
|
``unsigned`` data as ``transaction_id`` when it arrives through the event stream.
|
||||||
|
|
||||||
Clients unable to make use of the transaction ID are more likely to experience
|
Clients unable to make use of the transaction ID are likely to experience
|
||||||
flickering due to the following two scenarios, however the effect can be mitigated
|
flickering when the remote echo arrives on the event stream *before*
|
||||||
to a degree:
|
the request to send the message completes. In that case the event
|
||||||
|
arrives before the client has obtained an event ID, making it impossible to
|
||||||
- The client sends a message and the remote echo arrives on the event stream
|
identify it as a remote echo. This results in the client displaying the message
|
||||||
*after* the request to send the message completes.
|
twice for some time (depending on the server responsiveness) before the original
|
||||||
- The client sends a message and the remote echo arrives on the event stream
|
request to send the message completes. Once it completes, the client can take
|
||||||
*before* the request to send the message completes.
|
remedial actions to remove the duplicate event by looking for duplicate event IDs.
|
||||||
|
|
||||||
In the first scenario, the client will receive an event ID when the request to
|
|
||||||
send the message completes. This ID can be used to identify the duplicate event
|
|
||||||
when it arrives on the event stream. However, in the second scenario, the event
|
|
||||||
arrives before the client has obtained an event ID. This makes it impossible to
|
|
||||||
identify it as a duplicate event. This results in the client displaying the
|
|
||||||
message twice for a fraction of a second before the the original request to send
|
|
||||||
the message completes. Once it completes, the client can take remedial actions
|
|
||||||
to remove the duplicate event by looking for duplicate event IDs. A future version
|
|
||||||
of the client-server API will resolve this by attaching the transaction ID of the
|
|
||||||
sending request to the event itself.
|
|
||||||
|
|
||||||
|
|
||||||
Calculating the display name for a user
|
Calculating the display name for a user
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ In addition to using the appropriate ``matrix.to URI`` for the mention,
|
||||||
clients should use the following guidelines when making mentions in events
|
clients should use the following guidelines when making mentions in events
|
||||||
to be sent:
|
to be sent:
|
||||||
|
|
||||||
* When mentioning users, use the user's potentially ambigious display name for
|
* When mentioning users, use the user's potentially ambiguous display name for
|
||||||
the anchor's text. If the user does not have a display name, use the user's
|
the anchor's text. If the user does not have a display name, use the user's
|
||||||
ID.
|
ID.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,8 @@ Each user has the concept of presence information. This encodes:
|
||||||
|
|
||||||
This information is collated from both per-device (``online``, ``idle``,
|
This information is collated from both per-device (``online``, ``idle``,
|
||||||
``last_active``) and per-user (status) data, aggregated by the user's homeserver
|
``last_active``) and per-user (status) data, aggregated by the user's homeserver
|
||||||
and transmitted as an ``m.presence`` event. This is one of the few events which
|
and transmitted as an ``m.presence`` event. Presence events are sent to
|
||||||
are sent *outside the context of a room*. Presence events are sent to all users
|
interested parties where users share a room membership.
|
||||||
who subscribe to this user's presence through a presence list or by sharing
|
|
||||||
membership of a room.
|
|
||||||
|
|
||||||
A presence list is a list of user IDs whose presence the user wants to follow.
|
|
||||||
To be added to this list, the user being added must be invited by the list owner
|
|
||||||
who must accept the invitation.
|
|
||||||
|
|
||||||
User's presence state is represented by the ``presence`` key, which is an enum
|
User's presence state is represented by the ``presence`` key, which is an enum
|
||||||
of one of the following:
|
of one of the following:
|
||||||
|
|
@ -53,17 +47,10 @@ Events
|
||||||
Client behaviour
|
Client behaviour
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Clients can manually set/get their presence/presence list using the HTTP APIs
|
Clients can manually set/get their presence using the HTTP APIs listed below.
|
||||||
listed below.
|
|
||||||
|
|
||||||
{{presence_cs_http_api}}
|
{{presence_cs_http_api}}
|
||||||
|
|
||||||
Server behaviour
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Each user's homeserver stores a "presence list" per user. Once a user accepts
|
|
||||||
a presence list, both user's HSes must track the subscription.
|
|
||||||
|
|
||||||
Last active ago
|
Last active ago
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
The server maintains a timestamp of the last time it saw a pro-active event from
|
The server maintains a timestamp of the last time it saw a pro-active event from
|
||||||
|
|
|
||||||
|
|
@ -660,6 +660,8 @@ When a user changes their push rules a ``m.push_rules`` event is sent to all
|
||||||
clients in the ``account_data`` section of their next ``/sync`` request. The
|
clients in the ``account_data`` section of their next ``/sync`` request. The
|
||||||
content of the event is the current push rules for the user.
|
content of the event is the current push rules for the user.
|
||||||
|
|
||||||
|
{{m_push_rules_event}}
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
++++++++
|
++++++++
|
||||||
|
|
||||||
|
|
|
||||||
78
specification/modules/room_upgrades.rst
Normal file
78
specification/modules/room_upgrades.rst
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
.. Copyright 2019 New Vector Ltd
|
||||||
|
..
|
||||||
|
.. 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.
|
||||||
|
|
||||||
|
Room Upgrades
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. _module:room-upgrades:
|
||||||
|
|
||||||
|
From time to time, a room may need to be upgraded to a different room version for a
|
||||||
|
variety for reasons. This module defines a way for rooms to upgrade to a different
|
||||||
|
room version when needed.
|
||||||
|
|
||||||
|
Events
|
||||||
|
------
|
||||||
|
|
||||||
|
{{m_room_tombstone_event}}
|
||||||
|
|
||||||
|
Client behaviour
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Clients which understand ``m.room.tombstone`` events and the ``predecessor`` field on
|
||||||
|
``m.room.create`` events should communicate to the user that the room was upgraded.
|
||||||
|
One way of accomplishing this would be hiding the old room from the user's room list
|
||||||
|
and showing banners linking between the old and new room - ensuring that permalinks
|
||||||
|
work when referencing the old room. Another approach may be to virtually merge the
|
||||||
|
rooms such that the old room's timeline seamlessly continues into the new timeline
|
||||||
|
without the user having to jump between the rooms.
|
||||||
|
|
||||||
|
{{room_upgrades_cs_http_api}}
|
||||||
|
|
||||||
|
Server behaviour
|
||||||
|
----------------
|
||||||
|
|
||||||
|
When the client requests to upgrade a known room to a known version, the server:
|
||||||
|
|
||||||
|
1. Checks that the user has permission to send ``m.room.tombstone`` events in the room.
|
||||||
|
2. Creates a replacement room with a ``m.room.create`` event containing a ``predecessor``
|
||||||
|
field and the applicable ``room_version``.
|
||||||
|
3. Replicates transferable state events to the new room. The exact details for what is
|
||||||
|
transferred is left as an implementation detail, however the recommended state events
|
||||||
|
to transfer are:
|
||||||
|
|
||||||
|
* ``m.room.server_acl``
|
||||||
|
* ``m.room.encryption``
|
||||||
|
* ``m.room.name``
|
||||||
|
* ``m.room.avatar``
|
||||||
|
* ``m.room.topic``
|
||||||
|
* ``m.room.guest_access``
|
||||||
|
* ``m.room.history_visibility``
|
||||||
|
* ``m.room.join_rules``
|
||||||
|
* ``m.room.power_levels``
|
||||||
|
|
||||||
|
Membership events should not be transferred to the new room due to technical limitations
|
||||||
|
of servers not being able to impersonate people from other homeservers. Additionally,
|
||||||
|
servers should not transfer state events which are sensitive to who sent them, such as
|
||||||
|
events outside of the Matrix namespace where clients may rely on the sender to match
|
||||||
|
certain criteria.
|
||||||
|
|
||||||
|
4. Moves any local aliases to the new room.
|
||||||
|
5. Sends a ``m.room.tombstone`` event to the old room to indicate that it is not intended
|
||||||
|
to be used any further.
|
||||||
|
6. If possible, the power levels in the old room should also be modified to prevent sending
|
||||||
|
of events and inviting new users. For example, setting ``events_default`` and ``invite``
|
||||||
|
to the greater of ``50`` and ``users_default + 1``.
|
||||||
|
|
||||||
|
When a user joins the new room, the server should automatically transfer/replicate some of
|
||||||
|
the user's personalized settings such as notifications, tags, etc.
|
||||||
|
|
@ -48,7 +48,7 @@ The tag namespace is defined as follows:
|
||||||
* The namespace ``u.*`` is reserved for user-defined tags. The portion of the string after the ``u.``
|
* The namespace ``u.*`` is reserved for user-defined tags. The portion of the string after the ``u.``
|
||||||
is defined to be the display name of this tag. No other semantics should be inferred from tags in
|
is defined to be the display name of this tag. No other semantics should be inferred from tags in
|
||||||
this namespace.
|
this namespace.
|
||||||
* A client or app willing to use special tags for advanced functionnality should namespace them similarly to state keys: ``tld.name.*``
|
* A client or app willing to use special tags for advanced functionality should namespace them similarly to state keys: ``tld.name.*``
|
||||||
* Any tag in the ``tld.name.*`` form but not matching the namespace of the current client should be ignored
|
* Any tag in the ``tld.name.*`` form but not matching the namespace of the current client should be ignored
|
||||||
* Any tag not matching the above rules should be interpreted as a user tag from the ``u.*`` namespace, as if
|
* Any tag not matching the above rules should be interpreted as a user tag from the ``u.*`` namespace, as if
|
||||||
the name had already had ``u.`` stripped from the start (ie. the name of the tag is used as the
|
the name had already had ``u.`` stripped from the start (ie. the name of the tag is used as the
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ verification must still be performed, so the attack surface here is minimized.
|
||||||
Security considerations
|
Security considerations
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
There are a number of privary and trust implications to this module.
|
There are a number of privacy and trust implications to this module.
|
||||||
|
|
||||||
It is important for user privacy that leaking the mapping between a matrix user
|
It is important for user privacy that leaking the mapping between a matrix user
|
||||||
ID and a third party identifier is hard. In particular, being able to look up
|
ID and a third party identifier is hard. In particular, being able to look up
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ Name GitHub Label Description
|
||||||
=============================== ============================= ====================================
|
=============================== ============================= ====================================
|
||||||
Proposal Drafting and Feedback N/A A proposal document which is still work-in-progress but is being shared to incorporate feedback. Please prefix your proposal's title with ``[WIP]`` to make it easier for reviewers to skim their notifications list.
|
Proposal Drafting and Feedback N/A A proposal document which is still work-in-progress but is being shared to incorporate feedback. Please prefix your proposal's title with ``[WIP]`` to make it easier for reviewers to skim their notifications list.
|
||||||
Proposal In Review proposal-in-review A proposal document which is now ready and waiting for review by the Spec Core Team and community
|
Proposal In Review proposal-in-review A proposal document which is now ready and waiting for review by the Spec Core Team and community
|
||||||
Proposed Final Comment Period proposed-final-comment-period Currently awaiting signoff of a majority of team members in order to enter the final comment period
|
Proposed Final Comment Period proposed-final-comment-period Currently awaiting signoff of a 75% majority of team members in order to enter the final comment period
|
||||||
Final Comment Period final-comment-period A proposal document which has reached final comment period either for merge, closure or postponement
|
Final Comment Period final-comment-period A proposal document which has reached final comment period either for merge, closure or postponement
|
||||||
Final Commment Period Complete finished-final-comment-period The final comment period has been completed. Waiting for a demonstration implementation
|
Final Commment Period Complete finished-final-comment-period The final comment period has been completed. Waiting for a demonstration implementation
|
||||||
Spec PR Missing spec-pr-missing The proposal has been agreed, and proven with a demonstration implementation. Waiting for a PR against the Spec
|
Spec PR Missing spec-pr-missing The proposal has been agreed, and proven with a demonstration implementation. Waiting for a PR against the Spec
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ This describes the format used by "HTTP" pushers to send notifications of
|
||||||
events to Push Gateways. If the endpoint returns an HTTP error code, the
|
events to Push Gateways. If the endpoint returns an HTTP error code, the
|
||||||
homeserver SHOULD retry for a reasonable amount of time using exponential backoff.
|
homeserver SHOULD retry for a reasonable amount of time using exponential backoff.
|
||||||
|
|
||||||
When pushing notifications for events, the hoemserver is expected to include all of
|
When pushing notifications for events, the homeserver is expected to include all of
|
||||||
the event-related fields in the ``/notify`` request. When the homeserver is performing
|
the event-related fields in the ``/notify`` request. When the homeserver is performing
|
||||||
a push where the ``format`` is ``"event_id_only"``, only the ``event_id``, ``room_id``,
|
a push where the ``format`` is ``"event_id_only"``, only the ``event_id``, ``room_id``,
|
||||||
``counts``, and ``devices`` are required to be populated.
|
``counts``, and ``devices`` are required to be populated.
|
||||||
|
|
|
||||||
297
specification/rooms/v1.rst
Normal file
297
specification/rooms/v1.rst
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
.. Copyright 2017,2019 New Vector Ltd
|
||||||
|
..
|
||||||
|
.. 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.
|
||||||
|
|
||||||
|
Room Version 1
|
||||||
|
==============
|
||||||
|
|
||||||
|
This room version is the first ever version for rooms, and contains the building
|
||||||
|
blocks for other room versions.
|
||||||
|
|
||||||
|
.. contents:: Table of Contents
|
||||||
|
.. sectnum::
|
||||||
|
|
||||||
|
Server implementation components
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
The information contained in this section is strictly for server implementors.
|
||||||
|
Applications which use the Client-Server API are generally unaffected by the
|
||||||
|
details contained here, and can safely ignore their presence.
|
||||||
|
|
||||||
|
|
||||||
|
The algorithms defined here should only apply to version 1 rooms. Other algorithms
|
||||||
|
may be used by other room versions, and as such servers should be aware of which
|
||||||
|
version room they are dealing with prior to executing a given algorithm.
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
Although room version 1 is the most popular room version, it is known to have
|
||||||
|
undesirable effects. Servers implementing support for room version 1 should be
|
||||||
|
aware that restrictions should be generally relaxed and that inconsistencies
|
||||||
|
may occur until room version 2 (or later) is ready and adopted.
|
||||||
|
|
||||||
|
State resolution
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
This section documents the state resolution algorithm as implemented by
|
||||||
|
Synapse as of December 2017 (and therefore the de-facto Matrix protocol).
|
||||||
|
However, this algorithm is known to have some problems.
|
||||||
|
|
||||||
|
The room state :math:`S'(E)` after an event :math:`E` is defined in terms of
|
||||||
|
the room state :math:`S(E)` before :math:`E`, and depends on whether
|
||||||
|
:math:`E` is a state event or a message event:
|
||||||
|
|
||||||
|
* If :math:`E` is a message event, then :math:`S'(E) = S(E)`.
|
||||||
|
|
||||||
|
* If :math:`E` is a state event, then :math:`S'(E)` is :math:`S(E)`, except
|
||||||
|
that its entry corresponding to :math:`E`'s ``event_type`` and ``state_key``
|
||||||
|
is replaced by :math:`E`'s ``event_id``.
|
||||||
|
|
||||||
|
The room state :math:`S(E)` before :math:`E` is the *resolution* of the set of
|
||||||
|
states :math:`\{ S'(E'), S'(E''), … \}` consisting of the states after each of
|
||||||
|
:math:`E`'s ``prev_event``\s :math:`\{ E', E'', … \}`.
|
||||||
|
|
||||||
|
The *resolution* of a set of states is defined as follows. The resolved state
|
||||||
|
is built up in a number of passes; here we use :math:`R` to refer to the
|
||||||
|
results of the resolution so far.
|
||||||
|
|
||||||
|
* Start by setting :math:`R` to the union of the states to be resolved,
|
||||||
|
excluding any *conflicting* events.
|
||||||
|
|
||||||
|
* First we resolve conflicts between ``m.room.power_levels`` events. If there
|
||||||
|
is no conflict, this step is skipped, otherwise:
|
||||||
|
|
||||||
|
* Assemble all the ``m.room.power_levels`` events from the states to
|
||||||
|
be resolved into a list.
|
||||||
|
|
||||||
|
* Sort the list by ascending ``depth`` then descending ``sha1(event_id)``.
|
||||||
|
|
||||||
|
* Add the first event in the list to :math:`R`.
|
||||||
|
|
||||||
|
* For each subsequent event in the list, check that the event would be
|
||||||
|
allowed by the authorization rules for a room in state :math:`R`. If the
|
||||||
|
event would be allowed, then update :math:`R` with the event and continue
|
||||||
|
with the next event in the list. If it would not be allowed, stop and
|
||||||
|
continue below with ``m.room.join_rules`` events.
|
||||||
|
|
||||||
|
* Repeat the above process for conflicts between ``m.room.join_rules`` events.
|
||||||
|
|
||||||
|
* Repeat the above process for conflicts between ``m.room.member`` events.
|
||||||
|
|
||||||
|
* No other events affect the authorization rules, so for all other conflicts,
|
||||||
|
just pick the event with the highest depth and lowest ``sha1(event_id)`` that
|
||||||
|
passes authentication in :math:`R` and add it to :math:`R`.
|
||||||
|
|
||||||
|
A *conflict* occurs between states where those states have different
|
||||||
|
``event_ids`` for the same ``(state_type, state_key)``. The events thus
|
||||||
|
affected are said to be *conflicting* events.
|
||||||
|
|
||||||
|
|
||||||
|
Authorization rules
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The types of state events that affect authorization are:
|
||||||
|
|
||||||
|
- ``m.room.create``
|
||||||
|
- ``m.room.member``
|
||||||
|
- ``m.room.join_rules``
|
||||||
|
- ``m.room.power_levels``
|
||||||
|
- ``m.room.third_party_invite``
|
||||||
|
|
||||||
|
The rules are as follows:
|
||||||
|
|
||||||
|
1. If type is ``m.room.create``:
|
||||||
|
|
||||||
|
a. If it has any previous events, reject.
|
||||||
|
b. If the domain of the ``room_id`` does not match the domain of the
|
||||||
|
``sender``, reject.
|
||||||
|
c. If ``content.room_version`` is present and is not a recognised version,
|
||||||
|
reject.
|
||||||
|
d. If ``content`` has no ``creator`` field, reject.
|
||||||
|
e. Otherwise, allow.
|
||||||
|
|
||||||
|
#. Reject if event has ``auth_events`` that:
|
||||||
|
|
||||||
|
a. have duplicate entries for a given ``type`` and ``state_key`` pair
|
||||||
|
#. have entries whose ``type`` and ``state_key`` don't match those
|
||||||
|
specified by the `auth events selection`_ algorithm described in the
|
||||||
|
server specification.
|
||||||
|
|
||||||
|
#. If event does not have a ``m.room.create`` in its ``auth_events``, reject.
|
||||||
|
|
||||||
|
#. If type is ``m.room.aliases``:
|
||||||
|
|
||||||
|
a. If event has no ``state_key``, reject.
|
||||||
|
b. If sender's domain doesn't matches ``state_key``, reject.
|
||||||
|
c. Otherwise, allow.
|
||||||
|
|
||||||
|
#. If type is ``m.room.member``:
|
||||||
|
|
||||||
|
a. If no ``state_key`` key or ``membership`` key in ``content``, reject.
|
||||||
|
|
||||||
|
#. If ``membership`` is ``join``:
|
||||||
|
|
||||||
|
i. If the only previous event is an ``m.room.create``
|
||||||
|
and the ``state_key`` is the creator, allow.
|
||||||
|
|
||||||
|
#. If the ``sender`` does not match ``state_key``, reject.
|
||||||
|
|
||||||
|
#. If the ``sender`` is banned, reject.
|
||||||
|
|
||||||
|
#. If the ``join_rule`` is ``invite`` then allow if membership state
|
||||||
|
is ``invite`` or ``join``.
|
||||||
|
|
||||||
|
#. If the ``join_rule`` is ``public``, allow.
|
||||||
|
|
||||||
|
#. Otherwise, reject.
|
||||||
|
|
||||||
|
#. If ``membership`` is ``invite``:
|
||||||
|
|
||||||
|
i. If ``content`` has ``third_party_invite`` key:
|
||||||
|
|
||||||
|
#. If *target user* is banned, reject.
|
||||||
|
|
||||||
|
#. If ``content.third_party_invite`` does not have a
|
||||||
|
``signed`` key, reject.
|
||||||
|
|
||||||
|
#. If ``signed`` does not have ``mxid`` and ``token`` keys, reject.
|
||||||
|
|
||||||
|
#. If ``mxid`` does not match ``state_key``, reject.
|
||||||
|
|
||||||
|
#. If there is no ``m.room.third_party_invite`` event in the
|
||||||
|
current room state with ``state_key`` matching ``token``, reject.
|
||||||
|
|
||||||
|
#. If ``sender`` does not match ``sender`` of the
|
||||||
|
``m.room.third_party_invite``, reject.
|
||||||
|
|
||||||
|
#. If any signature in ``signed`` matches any public key in the
|
||||||
|
``m.room.third_party_invite`` event, allow. The public keys are
|
||||||
|
in ``content`` of ``m.room.third_party_invite`` as:
|
||||||
|
|
||||||
|
#. A single public key in the ``public_key`` field.
|
||||||
|
#. A list of public keys in the ``public_keys`` field.
|
||||||
|
|
||||||
|
#. Otherwise, reject.
|
||||||
|
|
||||||
|
#. If the ``sender``'s current membership state is not ``join``, reject.
|
||||||
|
|
||||||
|
#. If *target user*'s current membership state is ``join`` or ``ban``,
|
||||||
|
reject.
|
||||||
|
|
||||||
|
#. If the ``sender``'s power level is greater than or equal to the *invite
|
||||||
|
level*, allow.
|
||||||
|
|
||||||
|
#. Otherwise, reject.
|
||||||
|
|
||||||
|
#. If ``membership`` is ``leave``:
|
||||||
|
|
||||||
|
i. If the ``sender`` matches ``state_key``, allow if and only if that user's
|
||||||
|
current membership state is ``invite`` or ``join``.
|
||||||
|
|
||||||
|
#. If the ``sender``'s current membership state is not ``join``, reject.
|
||||||
|
|
||||||
|
#. If the *target user*'s current membership state is ``ban``, and the
|
||||||
|
``sender``'s power level is less than the *ban level*, reject.
|
||||||
|
|
||||||
|
#. If the ``sender``'s power level is greater than or equal to the *kick
|
||||||
|
level*, and the *target user*'s power level is less than the
|
||||||
|
``sender``'s power level, allow.
|
||||||
|
|
||||||
|
#. Otherwise, reject.
|
||||||
|
|
||||||
|
#. If ``membership`` is ``ban``:
|
||||||
|
|
||||||
|
i. If the ``sender``'s current membership state is not ``join``, reject.
|
||||||
|
|
||||||
|
#. If the ``sender``'s power level is greater than or equal to the *ban
|
||||||
|
level*, and the *target user*'s power level is less than the
|
||||||
|
``sender``'s power level, allow.
|
||||||
|
|
||||||
|
#. Otherwise, reject.
|
||||||
|
|
||||||
|
#. Otherwise, the membership is unknown. Reject.
|
||||||
|
|
||||||
|
#. If the ``sender``'s current membership state is not ``join``, reject.
|
||||||
|
|
||||||
|
#. If type is ``m.room.third_party_invite``:
|
||||||
|
|
||||||
|
a. Allow if and only if ``sender``'s current power level is greater than
|
||||||
|
or equal to the *invite level*.
|
||||||
|
|
||||||
|
#. If the event type's *required power level* is greater than the ``sender``'s power
|
||||||
|
level, reject.
|
||||||
|
|
||||||
|
#. If the event has a ``state_key`` that starts with an ``@`` and does not match
|
||||||
|
the ``sender``, reject.
|
||||||
|
|
||||||
|
#. If type is ``m.room.power_levels``:
|
||||||
|
|
||||||
|
a. If ``users`` key in ``content`` is not a dictionary with keys that are
|
||||||
|
valid user IDs with values that are integers (or a string that is an
|
||||||
|
integer), reject.
|
||||||
|
|
||||||
|
#. If there is no previous ``m.room.power_levels`` event in the room, allow.
|
||||||
|
|
||||||
|
#. For each of the keys ``users_default``, ``events_default``,
|
||||||
|
``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as
|
||||||
|
each entry being changed under the ``events`` or ``users`` keys:
|
||||||
|
|
||||||
|
i. If the current value is higher than the ``sender``'s current power level,
|
||||||
|
reject.
|
||||||
|
|
||||||
|
#. If the new value is higher than the ``sender``'s current power level,
|
||||||
|
reject.
|
||||||
|
|
||||||
|
#. For each entry being changed under the ``users`` key, other than the
|
||||||
|
``sender``'s own entry:
|
||||||
|
|
||||||
|
i. If the current value is equal to the ``sender``'s current power level,
|
||||||
|
reject.
|
||||||
|
|
||||||
|
#. Otherwise, allow.
|
||||||
|
|
||||||
|
#. If type is ``m.room.redaction``:
|
||||||
|
|
||||||
|
a. If the ``sender``'s power level is greater than or equal to the *redact
|
||||||
|
level*, allow.
|
||||||
|
|
||||||
|
#. If the domain of the ``event_id`` of the event being redacted is the same
|
||||||
|
as the domain of the ``event_id`` of the ``m.room.redaction``, allow.
|
||||||
|
|
||||||
|
#. Otherwise, reject.
|
||||||
|
|
||||||
|
#. Otherwise, allow.
|
||||||
|
|
||||||
|
.. NOTE::
|
||||||
|
|
||||||
|
Some consequences of these rules:
|
||||||
|
|
||||||
|
* Unless you are a member of the room, the only permitted operations (apart
|
||||||
|
from the initial create/join) are: joining a public room; accepting or
|
||||||
|
rejecting an invitation to a room.
|
||||||
|
|
||||||
|
* To unban somebody, you must have power level greater than or equal to both
|
||||||
|
the kick *and* ban levels, *and* greater than the target user's power
|
||||||
|
level.
|
||||||
|
|
||||||
|
Event format
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Events in version 1 rooms have the following structure:
|
||||||
|
|
||||||
|
{{definition_ss_pdu}}
|
||||||
|
|
||||||
|
|
||||||
|
.. _`auth events selection`: ../../server_server/r0.1.1.html#auth-events-selection
|
||||||
|
.. _`Signing Events`: ../../server_server/r0.1.1.html#signing-events
|
||||||
204
specification/rooms/v2.rst
Normal file
204
specification/rooms/v2.rst
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
.. Copyright 2018-2019 New Vector Ltd
|
||||||
|
..
|
||||||
|
.. 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.
|
||||||
|
|
||||||
|
Room Version 2
|
||||||
|
==============
|
||||||
|
|
||||||
|
This room version builds off of `version 1 <v1.html>`_ with an improved state
|
||||||
|
resolution algorithm.
|
||||||
|
|
||||||
|
.. contents:: Table of Contents
|
||||||
|
.. sectnum::
|
||||||
|
|
||||||
|
Server implementation components
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
The information contained in this section is strictly for server implementors.
|
||||||
|
Applications which use the Client-Server API are generally unaffected by the
|
||||||
|
details contained here, and can safely ignore their presence.
|
||||||
|
|
||||||
|
|
||||||
|
Room version 2 uses the base components of `room version 1 <v1.html>`_, changing
|
||||||
|
only the state resolution algorithm.
|
||||||
|
|
||||||
|
|
||||||
|
State resolution
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The room state :math:`S'(E)` after an event :math:`E` is defined in terms of
|
||||||
|
the room state :math:`S(E)` before :math:`E`, and depends on whether
|
||||||
|
:math:`E` is a state event or a message event:
|
||||||
|
|
||||||
|
* If :math:`E` is a message event, then :math:`S'(E) = S(E)`.
|
||||||
|
|
||||||
|
* If :math:`E` is a state event, then :math:`S'(E)` is :math:`S(E)`, except
|
||||||
|
that its entry corresponding to :math:`E`'s ``event_type`` and ``state_key``
|
||||||
|
is replaced by :math:`E`'s ``event_id``.
|
||||||
|
|
||||||
|
The room state :math:`S(E)` before :math:`E` is the *resolution* of the set of
|
||||||
|
states :math:`\{ S'(E_1), S'(E_2), … \}` consisting of the states after each of
|
||||||
|
:math:`E`'s ``prev_event``\s :math:`\{ E_1, E_2, … \}`, where the resolution of
|
||||||
|
a set of states is given in the algorithm below.
|
||||||
|
|
||||||
|
Definitions
|
||||||
|
+++++++++++
|
||||||
|
|
||||||
|
The state resolution algorithm for version 2 rooms uses the following
|
||||||
|
definitions, given the set of room states :math:`\{ S_1, S_2, \ldots \}`:
|
||||||
|
|
||||||
|
Power events
|
||||||
|
A *power event* is a state event with type ``m.room.power_levels`` or
|
||||||
|
``m.room.join_rules``, or a state event with type ``m.room.member`` where the
|
||||||
|
``membership`` is ``leave`` or ``ban`` and the ``sender`` does not match the
|
||||||
|
``state_key``. The idea behind this is that power events are events that might
|
||||||
|
remove someone's ability to do something in the room.
|
||||||
|
|
||||||
|
Unconflicted state map and conflicted state set
|
||||||
|
The *unconflicted state map* is the state where the value of each key exists
|
||||||
|
and is the same in each state :math:`S_i`. The *conflicted state set* is the
|
||||||
|
set of all other state events. Note that the unconflicted state map only has
|
||||||
|
one event per ``(event_type, state_key)``, whereas the conflicted state set
|
||||||
|
may have multiple events.
|
||||||
|
|
||||||
|
Auth difference
|
||||||
|
The *auth difference* is calculated by first calculating the full auth chain
|
||||||
|
for each state :math:`S_i`, that is the union of the auth chains for each
|
||||||
|
event in :math:`S_i`, and then taking every event that doesn't appear in
|
||||||
|
every auth chain. If :math:`C_i` is the full auth chain of :math:`S_i`, then
|
||||||
|
the auth difference is :math:`\cup C_i - \cap C_i`.
|
||||||
|
|
||||||
|
Full conflicted set
|
||||||
|
The *full conflicted set* is the union of the conflicted state set and the
|
||||||
|
auth difference.
|
||||||
|
|
||||||
|
Reverse topological power ordering
|
||||||
|
The *reverse topological power ordering* of a set of events is the
|
||||||
|
lexicographically smallest topological ordering based on the DAG formed by
|
||||||
|
auth events. The reverse topological power ordering is ordered from earliest
|
||||||
|
event to latest. For comparing two topological orderings to determine which
|
||||||
|
is the lexicographically smallest, the following comparison relation on
|
||||||
|
events is used: for events :math:`x` and :math:`y`, :math:`x<y` if
|
||||||
|
|
||||||
|
1. :math:`x`'s sender has *greater* power level than :math:`y`'s sender,
|
||||||
|
when looking at their respective ``auth_event``\s; or
|
||||||
|
2. the senders have the same power level, but :math:`x`'s
|
||||||
|
``origin_server_ts`` is *less* than :math:`y`'s ``origin_server_ts``; or
|
||||||
|
3. the senders have the same power level and the events have the same
|
||||||
|
``origin_server_ts``, but :math:`x`'s ``event_id`` is *less* than
|
||||||
|
:math:`y`'s ``event_id``.
|
||||||
|
|
||||||
|
The reverse topological power ordering can be found by sorting the events
|
||||||
|
using Kahn's algorithm for topological sorting, and at each step selecting,
|
||||||
|
among all the candidate vertices, the smallest vertex using the above
|
||||||
|
comparison relation.
|
||||||
|
|
||||||
|
Mainline ordering
|
||||||
|
Given an ``m.room.power_levels`` event :math:`P`, the *mainline of* :math:`P`
|
||||||
|
is the list of events generated by starting with :math:`P` and recursively
|
||||||
|
taking the ``m.room.power_levels`` events from the ``auth_events``, ordered
|
||||||
|
such that :math:`P` is last. Given another event :math:`e`, the *closest
|
||||||
|
mainline event to* :math:`e` is the first event encountered in the mainline
|
||||||
|
when iteratively descending through the ``m.room.power_levels`` events in the
|
||||||
|
``auth_events`` starting at :math:`e`. If no mainline event is encountered
|
||||||
|
when iteratively descending through the ``m.room.power_levels`` events, then
|
||||||
|
the closest mainline event to :math:`e` can be considered to be a dummy event
|
||||||
|
that is before any other event in the mainline of :math:`P` for the purposes
|
||||||
|
of condition 1 below.
|
||||||
|
|
||||||
|
The *mainline ordering based on* :math:`P` of a set of events is the
|
||||||
|
ordering, from smallest to largest, using the following comparison relation
|
||||||
|
on events: for events :math:`x` and :math:`y`, :math:`x<y` if
|
||||||
|
|
||||||
|
1. the closest mainline event to :math:`x` appears *before* the closest
|
||||||
|
mainline event to :math:`y`; or
|
||||||
|
2. the closest mainline events are the same, but :math:`x`\'s
|
||||||
|
``origin_server_ts`` is *less* than :math:`y`\'s ``origin_server_ts``; or
|
||||||
|
3. the closest mainline events are the same and the events have the same
|
||||||
|
``origin_server_ts``, but :math:`x`\'s ``event_id`` is *less* than
|
||||||
|
:math:`y`\'s ``event_id``.
|
||||||
|
|
||||||
|
Iterative auth checks
|
||||||
|
The *iterative auth checks algorithm* takes as input an initial room state
|
||||||
|
and a sorted list of state events, and constructs a new room state by
|
||||||
|
iterating through the event list and applying the state event to the room
|
||||||
|
state if the state event is allowed by the `authorization rules`_. If the
|
||||||
|
state event is not allowed by the authorization rules, then the event is
|
||||||
|
ignored. If a ``(event_type, state_key)`` key that is required for checking
|
||||||
|
the authorization rules is not present in the state, then the appropriate
|
||||||
|
state event from the event's ``auth_events`` is used if the auth event is
|
||||||
|
not rejected.
|
||||||
|
|
||||||
|
Algorithm
|
||||||
|
+++++++++
|
||||||
|
|
||||||
|
The *resolution* of a set of states is obtained as follows:
|
||||||
|
|
||||||
|
1. Take all *power events* and any events in their auth chains, recursively,
|
||||||
|
that appear in the *full conflicted set* and order them by the *reverse
|
||||||
|
topological power ordering*.
|
||||||
|
2. Apply the *iterative auth checks algorithm* on the *unconflicted state map*
|
||||||
|
and the list of events from the previous step to get a partially resolved
|
||||||
|
state.
|
||||||
|
3. Take all remaining events that weren't picked in step 1 and order them by
|
||||||
|
the mainline ordering based on the power level in the partially resolved
|
||||||
|
state obtained in step 2.
|
||||||
|
4. Apply the *iterative auth checks algorithm* on the partial resolved
|
||||||
|
state and the list of events from the previous step.
|
||||||
|
5. Update the result by replacing any event with the event with the same key
|
||||||
|
from the *unconflicted state map*, if such an event exists, to get the final
|
||||||
|
resolved state.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`authorization rules`: ../server_server/r0.1.1.html#authorization-rules
|
||||||
|
|
||||||
|
Rejected events
|
||||||
|
+++++++++++++++
|
||||||
|
|
||||||
|
Events that have been rejected due to failing auth based on the state at the
|
||||||
|
event (rather than based on their auth chain) are handled as usual by the
|
||||||
|
algorithm, unless otherwise specified.
|
||||||
|
|
||||||
|
Note that no events rejected due to failure to auth against their auth chain
|
||||||
|
should appear in the process, as they should not appear in state (the algorithm
|
||||||
|
only uses events that appear in either the state sets or in the auth chain of
|
||||||
|
the events in the state sets).
|
||||||
|
|
||||||
|
.. admonition:: Rationale
|
||||||
|
|
||||||
|
This helps ensure that different servers' view of state is more likely to
|
||||||
|
converge, since rejection state of an event may be different. This can happen if
|
||||||
|
a third server gives an incorrect version of the state when a server joins a
|
||||||
|
room via it (either due to being faulty or malicious). Convergence of state is a
|
||||||
|
desirable property as it ensures that all users in the room have a (mostly)
|
||||||
|
consistent view of the state of the room. If the view of the state on different
|
||||||
|
servers diverges it can lead to bifurcation of the room due to e.g. servers
|
||||||
|
disagreeing on who is in the room.
|
||||||
|
|
||||||
|
Intuitively, using rejected events feels dangerous, however:
|
||||||
|
|
||||||
|
1. Servers cannot arbitrarily make up state, since they still need to pass the
|
||||||
|
auth checks based on the event's auth chain (e.g. they can't grant themselves
|
||||||
|
power levels if they didn't have them before).
|
||||||
|
2. For a previously rejected event to pass auth there must be a set of state
|
||||||
|
that allows said event. A malicious server could therefore produce a
|
||||||
|
fork where it claims the state is that particular set of state, duplicate the
|
||||||
|
rejected event to point to that fork, and send the event. The
|
||||||
|
duplicated event would then pass the auth checks. Ignoring rejected events
|
||||||
|
would therefore not eliminate any potential attack vectors.
|
||||||
|
|
||||||
|
|
||||||
|
Rejected auth events are deliberately excluded from use in the iterative auth
|
||||||
|
checks, as auth events aren't re-authed (although non-auth events are) during
|
||||||
|
the iterative auth checks.
|
||||||
124
specification/rooms/v3.rst
Normal file
124
specification/rooms/v3.rst
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
.. Copyright 2018-2019 New Vector Ltd
|
||||||
|
..
|
||||||
|
.. 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.
|
||||||
|
|
||||||
|
Room Version 3
|
||||||
|
==============
|
||||||
|
|
||||||
|
This room version builds on `version 2 <v2.html>`_ with an improved event format.
|
||||||
|
|
||||||
|
.. note:
|
||||||
|
All requirements listed in this room version specification are scoped to rooms
|
||||||
|
which actually use this room version. For example, a requirement of "all APIs must
|
||||||
|
accept the new event format" does in fact apply to all APIs, but only so much as
|
||||||
|
where the contextual room of the request is using this room version. Rooms using
|
||||||
|
other room versions should not be affected by these sweeping requirements.
|
||||||
|
|
||||||
|
.. contents:: Table of Contents
|
||||||
|
.. sectnum::
|
||||||
|
|
||||||
|
|
||||||
|
Client considerations
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This room version changes the format for event IDs sent to clients. Clients should be
|
||||||
|
aware that these event IDs may contain slashes and other potentially problematic
|
||||||
|
characters. Clients should be treating event IDs as opaque identifiers and should not
|
||||||
|
be attempting to parse them into a usable form, just like with other room versions.
|
||||||
|
|
||||||
|
Clients should expect to see event IDs changed from the format of ``$randomstring:example.org``
|
||||||
|
to something like ``$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk`` (note the lack of
|
||||||
|
domain and the potentially problematic slash).
|
||||||
|
|
||||||
|
|
||||||
|
Server implementation components
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
.. WARNING::
|
||||||
|
The information contained in this section is strictly for server implementors.
|
||||||
|
Applications which use the Client-Server API are generally unaffected by the
|
||||||
|
intricacies contained here. The section above regarding client considerations
|
||||||
|
is the resource that Client-Server API use cases should reference.
|
||||||
|
|
||||||
|
|
||||||
|
Room version 3 uses the state resolution algorithm defined in `room version 2 <v2.html>`_,
|
||||||
|
and the event format defined here.
|
||||||
|
|
||||||
|
Event IDs
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
.. admonition:: Rationale
|
||||||
|
|
||||||
|
In other room versions (namely version 1 and 2) the event ID is a distinct field
|
||||||
|
from the remainder of the event, which must be tracked as such. This leads to
|
||||||
|
complications where servers receive multiple events with the same ID in either the
|
||||||
|
same or different rooms where the server cannot easily keep track of which event it
|
||||||
|
should be using. By removing the use of a dedicated event ID, servers are required
|
||||||
|
to track the hashes on an event to determine its ID.
|
||||||
|
|
||||||
|
The event ID is the `reference hash`_ of the event encoded using `Unpadded Base64`_,
|
||||||
|
prefixed with ``$``. A resulting event ID using this approach should look similar to
|
||||||
|
``$CD66HAED5npg6074c6pDtLKalHjVfYb2q4Q3LZgrW6o``.
|
||||||
|
|
||||||
|
Event IDs should not be sent over federation to servers when the room uses
|
||||||
|
this room version. On the receiving end of an event, the server should compute
|
||||||
|
the relevant event ID for itself.
|
||||||
|
|
||||||
|
Additionally, the ``auth_events`` and ``prev_events`` have had a format change
|
||||||
|
compared to other room versions to make it easier to handle. Instead of a tuple
|
||||||
|
of values, they are now plain lists of events.
|
||||||
|
|
||||||
|
{{definition_ss_pdu_v3}}
|
||||||
|
|
||||||
|
Changes to APIs
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Due to the event ID being removed from the event, some APIs need to change. All
|
||||||
|
APIs which currently accept an event ID must do so with the new format. Servers
|
||||||
|
must append the calculated event ID to all events sent to clients where an event
|
||||||
|
ID would normally be expected.
|
||||||
|
|
||||||
|
Because the format of events has changed, servers must be aware of the room version
|
||||||
|
where the event resides so that the server may parse and handle the event. The
|
||||||
|
federation API has taken this concern into consideration by ensuring that servers
|
||||||
|
are aware of (or can find) the room version during a request.
|
||||||
|
|
||||||
|
Authorization rules for events
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The authorization rules for a given event have changed in this room version due
|
||||||
|
to the change in event format:
|
||||||
|
|
||||||
|
* The event no longer needs to be signed by the domain of the event ID (as there
|
||||||
|
is no domain in the event ID), but still needs to be signed by the sender's
|
||||||
|
domain.
|
||||||
|
|
||||||
|
* In past room versions, redactions were only permitted to enter the DAG if the
|
||||||
|
sender's domain matched the domain in the event ID being redacted, or the sender
|
||||||
|
had appropriate permissions per the power levels. Due to servers now not being
|
||||||
|
able to determine where an event came from during event authorization, redaction
|
||||||
|
events are always accepted (provided the event is allowed by ``events`` and
|
||||||
|
``events_default`` in the power levels). However, servers should not apply or send
|
||||||
|
redactions to clients until both the redaction event and original event have been
|
||||||
|
seen, and are valid. Servers should only apply redactions to events where the
|
||||||
|
sender's domains match, or the sender of the redaction has the appropriate
|
||||||
|
permissions per the power levels.
|
||||||
|
|
||||||
|
|
||||||
|
The remaining rules are the same as `room version 1 <v1.html#authorization-rules>`_.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
||||||
|
.. _`Canonical JSON`: ../appendices.html#canonical-json
|
||||||
|
.. _`Signing Events`: ../server_server/r0.1.1.html#signing-events
|
||||||
|
.. _`reference hash`: ../server_server/r0.1.1.html#reference-hashes
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
.. Copyright 2016 OpenMarket Ltd
|
.. Copyright 2016 OpenMarket Ltd
|
||||||
.. Copyright 2017 New Vector Ltd
|
.. Copyright 2017-2019 New Vector Ltd
|
||||||
.. Copyright 2018 New Vector Ltd
|
|
||||||
..
|
..
|
||||||
.. Licensed under the Apache License, Version 2.0 (the "License");
|
.. Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
.. you may not use this file except in compliance with the License.
|
.. you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,9 +16,7 @@
|
||||||
Federation API
|
Federation API
|
||||||
==============
|
==============
|
||||||
|
|
||||||
.. WARNING::
|
{{unstable_warning_block_SERVER_RELEASE_LABEL}}
|
||||||
This API is unstable and will change without warning or discussion while
|
|
||||||
we work towards a r0 release (scheduled for August 2018).
|
|
||||||
|
|
||||||
Matrix homeservers use the Federation APIs (also known as server-server APIs)
|
Matrix homeservers use the Federation APIs (also known as server-server APIs)
|
||||||
to communicate with each other. Homeservers use these APIs to push messages to
|
to communicate with each other. Homeservers use these APIs to push messages to
|
||||||
|
|
@ -77,13 +74,14 @@ This version of the specification is generated from
|
||||||
For the full historical changelog, see
|
For the full historical changelog, see
|
||||||
https://github.com/matrix-org/matrix-doc/blob/master/changelogs/server_server.rst
|
https://github.com/matrix-org/matrix-doc/blob/master/changelogs/server_server.rst
|
||||||
|
|
||||||
|
|
||||||
Other versions of this specification
|
Other versions of this specification
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The following other versions are also available, in reverse chronological order:
|
The following other versions are also available, in reverse chronological order:
|
||||||
|
|
||||||
- `HEAD <https://matrix.org/docs/spec/server_server/unstable.html>`_: Includes all changes since the latest versioned release.
|
- `HEAD <https://matrix.org/docs/spec/server_server/unstable.html>`_: Includes all changes since the latest versioned release.
|
||||||
|
- `r0.1.1 <https://matrix.org/docs/spec/server_server/r0.1.1.html>`_
|
||||||
|
- `r0.1.0 <https://matrix.org/docs/spec/server_server/r0.1.0.html>`_
|
||||||
|
|
||||||
Server discovery
|
Server discovery
|
||||||
----------------
|
----------------
|
||||||
|
|
@ -91,35 +89,107 @@ Server discovery
|
||||||
Resolving server names
|
Resolving server names
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Each matrix homeserver is identified by a server name consisting of a hostname
|
Each Matrix homeserver is identified by a server name consisting of a hostname
|
||||||
and an optional port, as described by the `grammar
|
and an optional port, as described by the `grammar
|
||||||
<../appendices.html#server-name>`_. Server names should be resolved to an IP
|
<../appendices.html#server-name>`_. Where applicable, a delegated server name
|
||||||
address and port using the following process:
|
uses the same grammar.
|
||||||
|
|
||||||
* If the hostname is an IP literal, then that IP address should be used,
|
Server names are resolved to an IP address and port to connect to, and have
|
||||||
together with the given port number, or 8448 if no port is given.
|
various conditions affecting which certificates and ``Host`` headers to send.
|
||||||
|
The process overall is as follows:
|
||||||
|
|
||||||
* Otherwise, if the port is present, then an IP address is discovered by
|
.. Note from the author: The repetitive "use this Host header and this cert"
|
||||||
looking up an AAAA or A record for the hostname, and the specified port is
|
comments are intentional. The process is overall quite complicated, and
|
||||||
used.
|
explaining explicitly what requests look like at each step helps ease the
|
||||||
|
understanding and ensure everyone is on the same page. Implementations
|
||||||
|
are of course welcome to realize where the process can be optimized, and
|
||||||
|
do so - just ensure that the result is the same!
|
||||||
|
|
||||||
* If the hostname is not an IP literal and no port is given, the server is
|
1. If the hostname is an IP literal, then that IP address should be used,
|
||||||
discovered by first looking up a ``_matrix._tcp`` SRV record for the
|
together with the given port number, or 8448 if no port is given. The
|
||||||
hostname, which may give a hostname (to be looked up using AAAA or A queries)
|
target server must present a valid certificate for the IP address.
|
||||||
and port. If the SRV record does not exist, then the server is discovered by
|
The ``Host`` header in the request should be set to the server name,
|
||||||
looking up an AAAA or A record on the hostname and taking the default
|
including the port if the server name included one.
|
||||||
fallback port number of 8448.
|
|
||||||
|
|
||||||
Homeservers may use SRV records to load balance requests between multiple TLS
|
2. If the hostname is not an IP literal, and the server name includes an
|
||||||
endpoints or to failover to another endpoint if an endpoint fails.
|
explicit port, resolve the IP address using AAAA or A records. Requests
|
||||||
|
are made to the resolved IP address and given port with a ``Host`` header
|
||||||
|
of the original server name (with port). The target server must present a
|
||||||
|
valid certificate for the hostname.
|
||||||
|
|
||||||
When making requests to servers, use the hostname of the target server in the
|
3. If the hostname is not an IP literal, a regular HTTPS request is made
|
||||||
``Host`` header, regardless of any hostname given in the SRV record. For
|
to ``https://<hostname>/.well-known/matrix/server``, expecting the
|
||||||
example, if the server name is ``example.org``, and the SRV record resolves to
|
schema defined later in this section. 30x redirects should be followed,
|
||||||
``matrix.example.org``, the ``Host`` header in the request should be
|
however redirection loops should be avoided. Responses (successful or
|
||||||
``example.org``. If an explicit port was given in the server name, it should be
|
otherwise) to the ``/.well-known`` endpoint should be cached by the
|
||||||
included in the ``Host`` header; otherwise, no port number should be given in
|
requesting server. Servers should respect the cache control headers
|
||||||
the ``Host`` header.
|
present on the response, or use a sensible default when headers are not
|
||||||
|
present. The recommended sensible default is 24 hours. Servers should
|
||||||
|
additionally impose a maximum cache time for responses: 48 hours is
|
||||||
|
recommended. Errors are recommended to be cached for up to an hour,
|
||||||
|
and servers are encouraged to exponentially back off for repeated
|
||||||
|
failures. The schema of the ``/.well-known`` request is later in this
|
||||||
|
section. If the response is invalid (bad JSON, missing properties, non-200
|
||||||
|
response, etc), skip to step 4. If the response is valid, the ``m.server``
|
||||||
|
property is parsed as ``<delegated_hostname>[:<delegated_port>]`` and
|
||||||
|
processed as follows:
|
||||||
|
|
||||||
|
* If ``<delegated_hostname>`` is an IP literal, then that IP address
|
||||||
|
should be used together with the ``<delegated_port>`` or 8448 if no
|
||||||
|
port is provided. The target server must present a valid TLS certificate
|
||||||
|
for the IP address. Requests must be made with a ``Host`` header containing
|
||||||
|
the IP address, including the port if one was provided.
|
||||||
|
|
||||||
|
* If ``<delegated_hostname>`` is not an IP literal, and ``<delegated_port>``
|
||||||
|
is present, an IP address is discovered by looking up an AAAA or A
|
||||||
|
record for ``<delegated_hostname>``. The resulting IP address is
|
||||||
|
used, alongside the ``<delegated_port>``. Requests must be made with a
|
||||||
|
``Host`` header of ``<delegated_hostname>:<delegated_port>``. The
|
||||||
|
target server must present a valid certificate for ``<delegated_hostname>``.
|
||||||
|
|
||||||
|
* If ``<delegated_hostname>`` is not an IP literal and no
|
||||||
|
``<delegated_port>`` is present, an SRV record is looked up for
|
||||||
|
``_matrix._tcp.<delegated_hostname>``. This may result in another
|
||||||
|
hostname (to be resolved using AAAA or A records) and port. Requests
|
||||||
|
should be made to the resolved IP address and port with a ``Host``
|
||||||
|
header containing the ``<delegated_hostname>``. The target server
|
||||||
|
must present a valid certificate for ``<delegated_hostname>``.
|
||||||
|
|
||||||
|
* If no SRV record is found, an IP address is resolved using AAAA
|
||||||
|
or A records. Requests are then made to the resolve IP address
|
||||||
|
and a port of 8448, using a ``Host`` header of ``<delegated_hostname>``.
|
||||||
|
The target server must present a valid certificate for ``<delegated_hostname>``.
|
||||||
|
|
||||||
|
4. If the ``/.well-known`` request resulted in an error response, a server
|
||||||
|
is found by resolving an SRV record for ``_matrix._tcp.<hostname>``. This
|
||||||
|
may result in a hostname (to be resolved using AAAA or A records) and
|
||||||
|
port. Requests are made to the resolved IP address and port, using 8448
|
||||||
|
as a default port, with a ``Host`` header of ``<hostname>``. The target
|
||||||
|
server must present a valid certificate for ``<hostname>``.
|
||||||
|
|
||||||
|
5. If the ``/.well-known`` request returned an error response, and the SRV
|
||||||
|
record was not found, an IP address is resolved using AAAA and A records.
|
||||||
|
Requests are made to the resolved IP address using port 8448 and a ``Host``
|
||||||
|
header containing the ``<hostname>``. The target server must present a
|
||||||
|
valid certificate for ``<hostname>``.
|
||||||
|
|
||||||
|
|
||||||
|
The TLS certificate provided by the target server must be signed by a known
|
||||||
|
Certificate Authority. Servers are ultimately responsible for determining
|
||||||
|
the trusted Certificate Authorities, however are strongly encouraged to
|
||||||
|
rely on the operating system's judgement. Servers can offer administrators
|
||||||
|
a means to override the trusted authorities list. Servers can additionally
|
||||||
|
skip the certificate validation for a given whitelist of domains or netmasks
|
||||||
|
for the purposes of testing or in networks where verification is done
|
||||||
|
elsewhere, such as with ``.onion`` addresses. Servers should respect SNI
|
||||||
|
when making requests where possible: a SNI should be sent for the certificate
|
||||||
|
which is expected, unless that certificate is expected to be an IP address in
|
||||||
|
which case SNI is not supported and should not be sent.
|
||||||
|
|
||||||
|
Servers are encouraged to make use of the
|
||||||
|
`Certificate Transparency <https://www.certificate-transparency.org/>`_ project.
|
||||||
|
|
||||||
|
{{wellknown_ss_http_api}}
|
||||||
|
|
||||||
Server implementation
|
Server implementation
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -131,7 +201,7 @@ Retrieving server keys
|
||||||
|
|
||||||
.. NOTE::
|
.. NOTE::
|
||||||
There was once a "version 1" of the key exchange. It has been removed from the
|
There was once a "version 1" of the key exchange. It has been removed from the
|
||||||
specification due to lack of significance. It may be reviewed `here
|
specification due to lack of significance. It may be reviewed `from the historical draft
|
||||||
<https://github.com/matrix-org/matrix-doc/blob/51faf8ed2e4a63d4cfd6d23183698ed169956cc0/specification/server_server_api.rst#232version-1>`_.
|
<https://github.com/matrix-org/matrix-doc/blob/51faf8ed2e4a63d4cfd6d23183698ed169956cc0/specification/server_server_api.rst#232version-1>`_.
|
||||||
|
|
||||||
Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``.
|
Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``.
|
||||||
|
|
@ -153,12 +223,11 @@ server by querying other servers.
|
||||||
Publishing Keys
|
Publishing Keys
|
||||||
+++++++++++++++
|
+++++++++++++++
|
||||||
|
|
||||||
Homeservers publish the allowed TLS fingerprints and signing keys in a JSON
|
Homeservers publish their signing keys in a JSON
|
||||||
object at ``/_matrix/key/v2/server/{key_id}``. The response contains a list of
|
object at ``/_matrix/key/v2/server/{key_id}``. The response contains a list of
|
||||||
``verify_keys`` that are valid for signing federation requests made by the
|
``verify_keys`` that are valid for signing federation requests made by the
|
||||||
homeserver and for signing events. It contains a list of ``old_verify_keys`` which
|
homeserver and for signing events. It contains a list of ``old_verify_keys`` which
|
||||||
are only valid for signing events. Finally the response contains a list of TLS
|
are only valid for signing events.
|
||||||
certificate fingerprints to validate any connection made to the homeserver.
|
|
||||||
|
|
||||||
{{keys_server_ss_http_api}}
|
{{keys_server_ss_http_api}}
|
||||||
|
|
||||||
|
|
@ -282,6 +351,8 @@ Transactions are limited in size; they can have at most 50 PDUs and 100 EDUs.
|
||||||
|
|
||||||
{{transactions_ss_http_api}}
|
{{transactions_ss_http_api}}
|
||||||
|
|
||||||
|
.. _`Persistent Data Unit schema`:
|
||||||
|
|
||||||
PDUs
|
PDUs
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -328,7 +399,7 @@ following subset of the room state:
|
||||||
``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.
|
||||||
|
|
||||||
{{definition_ss_pdu}}
|
For a full schema of what a PDU looks like, see the `room version specification`_.
|
||||||
|
|
||||||
Checks performed on receipt of a PDU
|
Checks performed on receipt of a PDU
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -380,189 +451,9 @@ Authorization rules
|
||||||
|
|
||||||
The rules governing whether an event is authorized depends on a set of state. A
|
The rules governing whether an event is authorized depends on a set of state. A
|
||||||
given event is checked multiple times against different sets of state, as
|
given event is checked multiple times against different sets of state, as
|
||||||
specified above. The types of state events that affect authorization are:
|
specified above. Each room version can have a different algorithm for how the
|
||||||
|
rules work, and which rules are applied. For more detailed information, please
|
||||||
- ``m.room.create``
|
see the `room version specification`_.
|
||||||
- ``m.room.member``
|
|
||||||
- ``m.room.join_rules``
|
|
||||||
- ``m.room.power_levels``
|
|
||||||
- ``m.room.third_party_invite``
|
|
||||||
|
|
||||||
The rules are as follows:
|
|
||||||
|
|
||||||
1. If type is ``m.room.create``:
|
|
||||||
|
|
||||||
a. If it has any previous events, reject.
|
|
||||||
b. If the domain of the ``room_id`` does not match the domain of the
|
|
||||||
``sender``, reject.
|
|
||||||
c. If ``content.room_version`` is present and is not a recognised version,
|
|
||||||
reject.
|
|
||||||
d. If ``content`` has no ``creator`` field, reject.
|
|
||||||
e. Otherwise, allow.
|
|
||||||
|
|
||||||
#. Reject if event has ``auth_events`` that:
|
|
||||||
|
|
||||||
a. have duplicate entries for a given ``type`` and ``state_key`` pair
|
|
||||||
#. have entries whose ``type`` and ``state_key`` don't match those
|
|
||||||
specified by the `auth events selection`_ algorithm described above.
|
|
||||||
|
|
||||||
#. If event does not have a ``m.room.create`` in its ``auth_events``, reject.
|
|
||||||
|
|
||||||
#. If type is ``m.room.aliases``:
|
|
||||||
|
|
||||||
a. If event has no ``state_key``, reject.
|
|
||||||
b. If sender's domain doesn't matches ``state_key``, reject.
|
|
||||||
c. Otherwise, allow.
|
|
||||||
|
|
||||||
#. If type is ``m.room.member``:
|
|
||||||
|
|
||||||
a. If no ``state_key`` key or ``membership`` key in ``content``, reject.
|
|
||||||
|
|
||||||
#. If ``membership`` is ``join``:
|
|
||||||
|
|
||||||
i. If the only previous event is an ``m.room.create``
|
|
||||||
and the ``state_key`` is the creator, allow.
|
|
||||||
|
|
||||||
#. If the ``sender`` does not match ``state_key``, reject.
|
|
||||||
|
|
||||||
#. If the ``sender`` is banned, reject.
|
|
||||||
|
|
||||||
#. If the ``join_rule`` is ``invite`` then allow if membership state
|
|
||||||
is ``invite`` or ``join``.
|
|
||||||
|
|
||||||
#. If the ``join_rule`` is ``public``, allow.
|
|
||||||
|
|
||||||
#. Otherwise, reject.
|
|
||||||
|
|
||||||
#. If ``membership`` is ``invite``:
|
|
||||||
|
|
||||||
i. If ``content`` has ``third_party_invite`` key:
|
|
||||||
|
|
||||||
#. If *target user* is banned, reject.
|
|
||||||
|
|
||||||
#. If ``content.third_party_invite`` does not have a
|
|
||||||
``signed`` key, reject.
|
|
||||||
|
|
||||||
#. If ``signed`` does not have ``mxid`` and ``token`` keys, reject.
|
|
||||||
|
|
||||||
#. If ``mxid`` does not match ``state_key``, reject.
|
|
||||||
|
|
||||||
#. If there is no ``m.room.third_party_invite`` event in the
|
|
||||||
current room state with ``state_key`` matching ``token``, reject.
|
|
||||||
|
|
||||||
#. If ``sender`` does not match ``sender`` of the
|
|
||||||
``m.room.third_party_invite``, reject.
|
|
||||||
|
|
||||||
#. If any signature in ``signed`` matches any public key in the
|
|
||||||
``m.room.third_party_invite`` event, allow. The public keys are
|
|
||||||
in ``content`` of ``m.room.third_party_invite`` as:
|
|
||||||
|
|
||||||
#. A single public key in the ``public_key`` field.
|
|
||||||
#. A list of public keys in the ``public_keys`` field.
|
|
||||||
|
|
||||||
#. Otherwise, reject.
|
|
||||||
|
|
||||||
#. If the ``sender``'s current membership state is not ``join``, reject.
|
|
||||||
|
|
||||||
#. If *target user*'s current membership state is ``join`` or ``ban``,
|
|
||||||
reject.
|
|
||||||
|
|
||||||
#. If the ``sender``'s power level is greater than or equal to the *invite
|
|
||||||
level*, allow.
|
|
||||||
|
|
||||||
#. Otherwise, reject.
|
|
||||||
|
|
||||||
#. If ``membership`` is ``leave``:
|
|
||||||
|
|
||||||
i. If the ``sender`` matches ``state_key``, allow if and only if that user's
|
|
||||||
current membership state is ``invite`` or ``join``.
|
|
||||||
|
|
||||||
#. If the ``sender``'s current membership state is not ``join``, reject.
|
|
||||||
|
|
||||||
#. If the *target user*'s current membership state is ``ban``, and the
|
|
||||||
``sender``'s power level is less than the *ban level*, reject.
|
|
||||||
|
|
||||||
#. If the ``sender``'s power level is greater than or equal to the *kick
|
|
||||||
level*, and the *target user*'s power level is less than the
|
|
||||||
``sender``'s power level, allow.
|
|
||||||
|
|
||||||
#. Otherwise, reject.
|
|
||||||
|
|
||||||
#. If ``membership`` is ``ban``:
|
|
||||||
|
|
||||||
i. If the ``sender``'s current membership state is not ``join``, reject.
|
|
||||||
|
|
||||||
#. If the ``sender``'s power level is greater than or equal to the *ban
|
|
||||||
level*, and the *target user*'s power level is less than the
|
|
||||||
``sender``'s power level, allow.
|
|
||||||
|
|
||||||
#. Otherwise, reject.
|
|
||||||
|
|
||||||
#. Otherwise, the membership is unknown. Reject.
|
|
||||||
|
|
||||||
#. If the ``sender``'s current membership state is not ``join``, reject.
|
|
||||||
|
|
||||||
#. If type is ``m.room.third_party_invite``:
|
|
||||||
|
|
||||||
a. Allow if and only if ``sender``'s current power level is greater than
|
|
||||||
or equal to the *invite level*.
|
|
||||||
|
|
||||||
#. If the event type's *required power level* is greater than the ``sender``'s power
|
|
||||||
level, reject.
|
|
||||||
|
|
||||||
#. If the event has a ``state_key`` that starts with an ``@`` and does not match
|
|
||||||
the ``sender``, reject.
|
|
||||||
|
|
||||||
#. If type is ``m.room.power_levels``:
|
|
||||||
|
|
||||||
a. If ``users`` key in ``content`` is not a dictionary with keys that are
|
|
||||||
valid user IDs with values that are integers (or a string that is an
|
|
||||||
integer), reject.
|
|
||||||
|
|
||||||
#. If there is no previous ``m.room.power_levels`` event in the room, allow.
|
|
||||||
|
|
||||||
#. For each of the keys ``users_default``, ``events_default``,
|
|
||||||
``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as
|
|
||||||
each entry being changed under the ``events`` or ``users`` keys:
|
|
||||||
|
|
||||||
i. If the current value is higher than the ``sender``'s current power level,
|
|
||||||
reject.
|
|
||||||
|
|
||||||
#. If the new value is higher than the ``sender``'s current power level,
|
|
||||||
reject.
|
|
||||||
|
|
||||||
#. For each entry being changed under the ``users`` key, other than the
|
|
||||||
``sender``'s own entry:
|
|
||||||
|
|
||||||
i. If the current value is equal to the ``sender``'s current power level,
|
|
||||||
reject.
|
|
||||||
|
|
||||||
#. Otherwise, allow.
|
|
||||||
|
|
||||||
#. If type is ``m.room.redaction``:
|
|
||||||
|
|
||||||
a. If the ``sender``'s power level is greater than or equal to the *redact
|
|
||||||
level*, allow.
|
|
||||||
|
|
||||||
#. If the domain of the ``event_id`` of the event being redacted is the same
|
|
||||||
as the domain of the ``event_id`` of the ``m.room.redaction``, allow.
|
|
||||||
|
|
||||||
#. Otherwise, reject.
|
|
||||||
|
|
||||||
#. Otherwise, allow.
|
|
||||||
|
|
||||||
.. NOTE::
|
|
||||||
|
|
||||||
Some consequences of these rules:
|
|
||||||
|
|
||||||
* Unless you are a member of the room, the only permitted operations (apart
|
|
||||||
from the intial create/join) are: joining a public room; accepting or
|
|
||||||
rejecting an invitation to a room.
|
|
||||||
|
|
||||||
* To unban somebody, you must have power level greater than or equal to both
|
|
||||||
the kick *and* ban levels, *and* greater than the target user's power
|
|
||||||
level.
|
|
||||||
|
|
||||||
|
|
||||||
Rejection
|
Rejection
|
||||||
+++++++++
|
+++++++++
|
||||||
|
|
@ -752,191 +643,8 @@ is at the top)::
|
||||||
Suppose E3 and E4 are both ``m.room.name`` events which set the name of the
|
Suppose E3 and E4 are both ``m.room.name`` events which set the name of the
|
||||||
room. What should the name of the room be at E5?
|
room. What should the name of the room be at E5?
|
||||||
|
|
||||||
Servers should follow one of the following recursively-defined algorithms,
|
The algorithm to be used for state resolution depends on the room version. For
|
||||||
depending on the room version, to determine the room state at a given point on
|
a description of each room version's algorithm, please see the `room version specification`_.
|
||||||
the DAG.
|
|
||||||
|
|
||||||
State resolution algorithm for version 2 rooms
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The room state :math:`S'(E)` after an event :math:`E` is defined in terms of
|
|
||||||
the room state :math:`S(E)` before :math:`E`, and depends on whether
|
|
||||||
:math:`E` is a state event or a message event:
|
|
||||||
|
|
||||||
* If :math:`E` is a message event, then :math:`S'(E) = S(E)`.
|
|
||||||
|
|
||||||
* If :math:`E` is a state event, then :math:`S'(E)` is :math:`S(E)`, except
|
|
||||||
that its entry corresponding to :math:`E`'s ``event_type`` and ``state_key``
|
|
||||||
is replaced by :math:`E`'s ``event_id``.
|
|
||||||
|
|
||||||
The room state :math:`S(E)` before :math:`E` is the *resolution* of the set of
|
|
||||||
states :math:`\{ S'(E_1), S'(E_2), … \}` consisting of the states after each of
|
|
||||||
:math:`E`'s ``prev_event``\s :math:`\{ E_1, E_2, … \}`, where the resolution of
|
|
||||||
a set of states is given in the algorithm below.
|
|
||||||
|
|
||||||
Definitions
|
|
||||||
+++++++++++
|
|
||||||
|
|
||||||
The state resolution algorithm for version 2 rooms uses the following
|
|
||||||
definitions, given the set of room states :math:`\{ S_1, S_2, \ldots \}`:
|
|
||||||
|
|
||||||
Power events
|
|
||||||
A *power event* is a state event with type ``m.room.power_levels`` or
|
|
||||||
``m.room.join_rules``, or a state event with type ``m.room.member`` where the
|
|
||||||
``membership`` is ``leave`` or ``ban`` and the ``sender`` does not match the
|
|
||||||
``state_key``. The idea behind this is that power events are events that have
|
|
||||||
may remove someone's ability to do something in the room.
|
|
||||||
|
|
||||||
Unconflicted state map and conflicted state set
|
|
||||||
The *unconflicted state map* is the state where the value of each key exists
|
|
||||||
and is the same in each state :math:`S_i`. The *conflicted state set* is the
|
|
||||||
set of all other state events. Note that the unconflicted state map only has
|
|
||||||
one event per ``(event_type, state_key)``, whereas the conflicted state set
|
|
||||||
may have multiple events.
|
|
||||||
|
|
||||||
Auth difference
|
|
||||||
The *auth difference* is calculated by first calculating the full auth chain
|
|
||||||
for each state :math:`S_i`, that is the union of the auth chains for each
|
|
||||||
event in :math:`S_i`, and then taking every event that doesn't appear in
|
|
||||||
every auth chain. If :math:`C_i` is the full auth chain of :math:`S_i`, then
|
|
||||||
the auth difference is :math:`\cup C_i - \cap C_i`.
|
|
||||||
|
|
||||||
Full conflicted set
|
|
||||||
The *full conflicted set* is the union of the conflicted state set and the
|
|
||||||
auth difference.
|
|
||||||
|
|
||||||
Reverse topological power ordering
|
|
||||||
The *reverse topological power ordering* of a set of events is the
|
|
||||||
lexicographically smallest topological ordering based on the DAG formed by
|
|
||||||
auth events. The reverse topological power ordering is ordered from earliest
|
|
||||||
event to latest. For comparing two topological orderings to determine which
|
|
||||||
is the lexicographically smallest, the following comparison relation on
|
|
||||||
events is used: for events :math:`x` and :math:`y`, :math:`x<y` if
|
|
||||||
|
|
||||||
1. :math:`x`'s sender has *greater* power level than :math:`y`'s sender,
|
|
||||||
when looking at their respective ``auth_event``\s; or
|
|
||||||
2. the senders have the same power level, but :math:`x`'s
|
|
||||||
``origin_server_ts`` is *less* than :math:`y`'s ``origin_server_ts``; or
|
|
||||||
3. the senders have the same power level and the events have the same
|
|
||||||
``origin_server_ts``, but :math:`x`'s ``event_id`` is *less* than
|
|
||||||
:math:`y`'s ``event_id``.
|
|
||||||
|
|
||||||
The reverse topological power ordering can be found by sorting the events
|
|
||||||
using Kahn's algorithm for topological sorting, and at each step selecting,
|
|
||||||
among all the candidate vertices, the smallest vertex using the above
|
|
||||||
comparison relation.
|
|
||||||
|
|
||||||
Mainline ordering
|
|
||||||
Given an ``m.room.power_levels`` event :math:`P`, the *mainline of* :math:`P`
|
|
||||||
is the list of events generated by starting with :math:`P` and recursively
|
|
||||||
taking the ``m.room.power_levels`` events from the ``auth_events``, ordered
|
|
||||||
such that :math:`P` is last. Given another event :math:`e`, the *closest
|
|
||||||
mainline event to* :math:`e` is the first event encountered in the mainline
|
|
||||||
when iteratively descending through the ``m.room.power_levels`` events in the
|
|
||||||
``auth_events`` starting at :math:`e`. If no mainline event is encountered
|
|
||||||
when iteratively descending through the ``m.room.power_levels`` events, then
|
|
||||||
the closest mainline event to :math:`e` can be considered to be a dummy event
|
|
||||||
that is before any other event in the mainline of :math:`P` for the purposes
|
|
||||||
of condition 1 below.
|
|
||||||
|
|
||||||
The *mainline ordering based on* :math:`P` of a set of events is the
|
|
||||||
ordering, from smallest to largest, using the following comparision relation
|
|
||||||
on events: for events :math:`x` and :math:`y`, :math:`x<y` if
|
|
||||||
|
|
||||||
1. the closest mainline event to :math:`x` appears *before* the closest
|
|
||||||
mainline event to :math:`y`; or
|
|
||||||
2. the closest mainline events are the same, but :math:`x`\'s
|
|
||||||
``origin_server_ts`` is *less* than :math:`y`\'s ``origin_server_ts``; or
|
|
||||||
3. the closest mainline events are the same and the events have the same
|
|
||||||
``origin_server_ts``, but :math:`x`\'s ``event_id`` is *less* than
|
|
||||||
:math:`y`\'s ``event_id``.
|
|
||||||
|
|
||||||
Iterative auth checks
|
|
||||||
The *iterative auth checks algorithm* takes as input an initial room state
|
|
||||||
and a sorted list of state events, and constructs a new room state by
|
|
||||||
iterating through the event list and applying the state event to the room
|
|
||||||
state if the state event is allowed by the `authorization rules`_. If the
|
|
||||||
state event is not allowed by the authorization rules, then the event is
|
|
||||||
ignored. If a ``(event_type, state_key)`` key that is required for checking
|
|
||||||
the authorization rules is not present in the state, then the appropriate
|
|
||||||
state event from the event's ``auth_events`` is used.
|
|
||||||
|
|
||||||
Algorithm
|
|
||||||
+++++++++
|
|
||||||
|
|
||||||
The *resolution* of a set of states is obtained as follows:
|
|
||||||
|
|
||||||
1. Take all *power events* and any events in their auth chains, recursively,
|
|
||||||
that appear in the *full conflicted set* and order them by the *reverse
|
|
||||||
topological power ordering*.
|
|
||||||
2. Apply the *iterative auth checks algorithm* on the *unconflicted state map*
|
|
||||||
and the list of events from the previous step to get a partially resolved
|
|
||||||
state.
|
|
||||||
3. Take all remaining events that weren't picked in step 1 and order them by
|
|
||||||
the mainline ordering based on the power level in the partially resolved
|
|
||||||
state obtained in step 2.
|
|
||||||
4. Apply the *iterative auth checks algorithm* on the partial resolved
|
|
||||||
state and the list of events from the previous step.
|
|
||||||
5. Update the result by replacing any event with the event with the same key
|
|
||||||
from the *unconflicted state map*, if such an event exists, to get the final
|
|
||||||
resolved state.
|
|
||||||
|
|
||||||
State resolution algorithm for version 1 rooms
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. WARNING::
|
|
||||||
This section documents the state resolution algorithm as implemented by
|
|
||||||
Synapse as of December 2017 (and therefore the de-facto Matrix protocol).
|
|
||||||
However, this algorithm is known to have some problems.
|
|
||||||
|
|
||||||
The room state :math:`S'(E)` after an event :math:`E` is defined in terms of
|
|
||||||
the room state :math:`S(E)` before :math:`E`, and depends on whether
|
|
||||||
:math:`E` is a state event or a message event:
|
|
||||||
|
|
||||||
* If :math:`E` is a message event, then :math:`S'(E) = S(E)`.
|
|
||||||
|
|
||||||
* If :math:`E` is a state event, then :math:`S'(E)` is :math:`S(E)`, except
|
|
||||||
that its entry corresponding to :math:`E`'s ``event_type`` and ``state_key``
|
|
||||||
is replaced by :math:`E`'s ``event_id``.
|
|
||||||
|
|
||||||
The room state :math:`S(E)` before :math:`E` is the *resolution* of the set of
|
|
||||||
states :math:`\{ S'(E'), S'(E''), … \}` consisting of the states after each of
|
|
||||||
:math:`E`'s ``prev_event``\s :math:`\{ E', E'', … \}`.
|
|
||||||
|
|
||||||
The *resolution* of a set of states is defined as follows. The resolved state
|
|
||||||
is built up in a number of passes; here we use :math:`R` to refer to the
|
|
||||||
results of the resolution so far.
|
|
||||||
|
|
||||||
* Start by setting :math:`R` to the union of the states to be resolved,
|
|
||||||
excluding any *conflicting* events.
|
|
||||||
|
|
||||||
* First we resolve conflicts between ``m.room.power_levels`` events. If there
|
|
||||||
is no conflict, this step is skipped, otherwise:
|
|
||||||
|
|
||||||
* Assemble all the ``m.room.power_levels`` events from the states to
|
|
||||||
be resolved into a list.
|
|
||||||
|
|
||||||
* Sort the list by ascending ``depth`` then descending ``sha1(event_id)``.
|
|
||||||
|
|
||||||
* Add the first event in the list to :math:`R`.
|
|
||||||
|
|
||||||
* For each subsequent event in the list, check that the event would be
|
|
||||||
allowed by the `authorization rules`_ for a room in state :math:`R`. If the
|
|
||||||
event would be allowed, then update :math:`R` with the event and continue
|
|
||||||
with the next event in the list. If it would not be allowed, stop and
|
|
||||||
continue below with ``m.room.join_rules`` events.
|
|
||||||
|
|
||||||
* Repeat the above process for conflicts between ``m.room.join_rules`` events.
|
|
||||||
|
|
||||||
* Repeat the above process for conflicts between ``m.room.member`` events.
|
|
||||||
|
|
||||||
* No other events affect the authorization rules, so for all other conflicts,
|
|
||||||
just pick the event with the highest depth and lowest ``sha1(event_id)`` that
|
|
||||||
passes authentication in :math:`R` and add it to :math:`R`.
|
|
||||||
|
|
||||||
A *conflict* occurs between states where those states have different
|
|
||||||
``event_ids`` for the same ``(state_type, state_key)``. The events thus
|
|
||||||
affected are said to be *conflicting* events.
|
|
||||||
|
|
||||||
|
|
||||||
Backfilling and retrieving missing events
|
Backfilling and retrieving missing events
|
||||||
|
|
@ -1072,7 +780,9 @@ the homeserver may sign the membership event itself and skip the process defined
|
||||||
here. However, when a user invites another user on a different homeserver, a request
|
here. However, when a user invites another user on a different homeserver, a request
|
||||||
to that homeserver to have the event signed and verified must be made.
|
to that homeserver to have the event signed and verified must be made.
|
||||||
|
|
||||||
{{invites_ss_http_api}}
|
{{invites_v1_ss_http_api}}
|
||||||
|
|
||||||
|
{{invites_v2_ss_http_api}}
|
||||||
|
|
||||||
Leaving Rooms (Rejecting Invites)
|
Leaving Rooms (Rejecting Invites)
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
@ -1195,15 +905,8 @@ The server API for presence is based entirely on exchange of the following
|
||||||
EDUs. There are no PDUs or Federation Queries involved.
|
EDUs. There are no PDUs or Federation Queries involved.
|
||||||
|
|
||||||
Servers should only send presence updates for users that the receiving server
|
Servers should only send presence updates for users that the receiving server
|
||||||
would be interested in. This can include the receiving server sharing a room
|
would be interested in. Such as the receiving server sharing a room
|
||||||
with a given user, or a user on the receiving server has added one of the
|
with a given user.
|
||||||
sending server's users to their presence list.
|
|
||||||
|
|
||||||
Clients may define lists of users that they are interested in via "Presence
|
|
||||||
Lists" through the `Client-Server API`_. When users are added to a presence
|
|
||||||
list, a ``m.presence_invite`` EDU is sent to them. The user may then accept
|
|
||||||
or deny their involvement in the list by sending either an ``m.presence_accept``
|
|
||||||
or ``m.presence_deny`` EDU back.
|
|
||||||
|
|
||||||
.. TODO-doc
|
.. TODO-doc
|
||||||
- Explain the timing-based round-trip reduction mechanism for presence
|
- Explain the timing-based round-trip reduction mechanism for presence
|
||||||
|
|
@ -1213,13 +916,6 @@ or ``m.presence_deny`` EDU back.
|
||||||
|
|
||||||
{{definition_ss_event_schemas_m_presence}}
|
{{definition_ss_event_schemas_m_presence}}
|
||||||
|
|
||||||
{{definition_ss_event_schemas_m_presence_invite}}
|
|
||||||
|
|
||||||
{{definition_ss_event_schemas_m_presence_accept}}
|
|
||||||
|
|
||||||
{{definition_ss_event_schemas_m_presence_deny}}
|
|
||||||
|
|
||||||
|
|
||||||
Receipts
|
Receipts
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
@ -1297,7 +993,7 @@ which should be used to correlate with subsequent ``m.device_list_update`` EDUs.
|
||||||
|
|
||||||
.. TODO: this whole thing desperately feels like it should just be state in a room,
|
.. TODO: this whole thing desperately feels like it should just be state in a room,
|
||||||
rather than inventing a whole different DAG. The same room could be used for
|
rather than inventing a whole different DAG. The same room could be used for
|
||||||
profiles, presence lists, etc.
|
profiles etc.
|
||||||
|
|
||||||
{{user_devices_ss_http_api}}
|
{{user_devices_ss_http_api}}
|
||||||
|
|
||||||
|
|
@ -1412,6 +1108,24 @@ been given a redacted version of the event. To enforce this, the receiving
|
||||||
server should use the redacted copy it calculated rather than the full copy it
|
server should use the redacted copy it calculated rather than the full copy it
|
||||||
received.
|
received.
|
||||||
|
|
||||||
|
.. _`reference hashes`:
|
||||||
|
|
||||||
|
Calculating the reference hash for an event
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The *reference hash* of an event covers the essential fields of an event,
|
||||||
|
including content hashes. It is calculated as follows.
|
||||||
|
|
||||||
|
1. The event is put through the redaction algorithm.
|
||||||
|
|
||||||
|
2. The ``signatures``, ``age_ts``, and ``unsigned`` properties are removed
|
||||||
|
from the event, if present.
|
||||||
|
|
||||||
|
3. The event is converted into `Canonical JSON`_.
|
||||||
|
|
||||||
|
4. A sha256 hash is calculated on the resulting JSON object.
|
||||||
|
|
||||||
|
|
||||||
Calculating the content hash for an event
|
Calculating the content hash for an event
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
@ -1454,7 +1168,7 @@ Example code
|
||||||
# Keys under "unsigned" can be modified by other servers.
|
# Keys under "unsigned" can be modified by other servers.
|
||||||
# They are useful for conveying information like the age of an
|
# They are useful for conveying information like the age of an
|
||||||
# event that will change in transit.
|
# event that will change in transit.
|
||||||
# Since they can be modifed we need to exclude them from the hash.
|
# Since they can be modified we need to exclude them from the hash.
|
||||||
event_object.pop("unsigned", None)
|
event_object.pop("unsigned", None)
|
||||||
|
|
||||||
# Signatures will depend on the current value of the "hashes" key.
|
# Signatures will depend on the current value of the "hashes" key.
|
||||||
|
|
@ -1476,7 +1190,7 @@ Example code
|
||||||
|
|
||||||
[[TODO(markjh): Since the ``hash`` object cannot be redacted a server
|
[[TODO(markjh): Since the ``hash`` object cannot be redacted a server
|
||||||
shouldn't allow too many hashes to be listed, otherwise a server might embed
|
shouldn't allow too many hashes to be listed, otherwise a server might embed
|
||||||
illict data within the ``hash`` object.
|
illicit data within the ``hash`` object.
|
||||||
|
|
||||||
We might want to specify a maximum number of keys for the
|
We might want to specify a maximum number of keys for the
|
||||||
``hash`` and we might want to specify the maximum output size of a hash]]
|
``hash`` and we might want to specify the maximum output size of a hash]]
|
||||||
|
|
@ -1485,6 +1199,16 @@ Example code
|
||||||
known hash functions like SHA-256 when none of the keys have been redacted]]
|
known hash functions like SHA-256 when none of the keys have been redacted]]
|
||||||
|
|
||||||
|
|
||||||
|
Security considerations
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
When a domain's ownership changes, the new controller of the domain can masquerade
|
||||||
|
as the previous owner, receiving messages (similarly to email) and request past
|
||||||
|
messages from other servers. In the future, proposals like
|
||||||
|
`MSC1228 <https://github.com/matrix-org/matrix-doc/issues/1228>`_ will address this
|
||||||
|
issue.
|
||||||
|
|
||||||
|
|
||||||
.. |/query/directory| replace:: ``/query/directory``
|
.. |/query/directory| replace:: ``/query/directory``
|
||||||
.. _/query/directory: #get-matrix-federation-v1-query-directory
|
.. _/query/directory: #get-matrix-federation-v1-query-directory
|
||||||
|
|
||||||
|
|
@ -1500,3 +1224,4 @@ Example code
|
||||||
.. _`Checking for a signature`: ../appendices.html#checking-for-a-signature
|
.. _`Checking for a signature`: ../appendices.html#checking-for-a-signature
|
||||||
.. _`Device Management module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#device-management
|
.. _`Device Management module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#device-management
|
||||||
.. _`End-to-End Encryption module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption
|
.. _`End-to-End Encryption module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption
|
||||||
|
.. _`room version specification`: ../index.html#room-versions
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue