mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-01-04 23:13:43 +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
|
||||
|
||||
All news fragments must have a brief summary explaining the change in the contents
|
||||
of the file. The summary must end in a full stop to be in line with the style guide.
|
||||
All news fragments must have a brief summary explaining the change in the
|
||||
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,
|
||||
CSS, etc should not get a news fragment.
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ def check_response(filepath, request, code, response):
|
|||
filepath, request, code
|
||||
))
|
||||
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:
|
||||
raise ValueError("Error validating JSON schema for %r %r" % (
|
||||
request, code
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ paths:
|
|||
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.
|
||||
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
|
||||
|
|
@ -69,6 +69,41 @@ paths:
|
|||
The account_data was successfully added.
|
||||
tags:
|
||||
- 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}":
|
||||
put:
|
||||
summary: Set some account_data for the user.
|
||||
|
|
@ -85,15 +120,15 @@ paths:
|
|||
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.
|
||||
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 set account_data on.
|
||||
The ID of the room to set account_data on.
|
||||
x-example: "!726s6s6q:example.com"
|
||||
- in: path
|
||||
type: string
|
||||
|
|
@ -118,3 +153,45 @@ paths:
|
|||
The account_data was successfully added.
|
||||
tags:
|
||||
- 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
|
||||
that necessary to set the room name (``errcode`` set to
|
||||
``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:
|
||||
"$ref": "definitions/errors/error.yaml"
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -139,7 +139,15 @@ paths:
|
|||
application/json: {
|
||||
"user_id": "@cheeky_monkey:matrix.org",
|
||||
"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:
|
||||
type: object
|
||||
|
|
@ -166,6 +174,14 @@ paths:
|
|||
description: |-
|
||||
ID of the logged-in device. Will be the same as the
|
||||
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:
|
||||
description: |-
|
||||
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"
|
||||
tags:
|
||||
- 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.
|
||||
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
|
||||
responses:
|
||||
200:
|
||||
description: The versions supported by the server.
|
||||
examples:
|
||||
application/json: {
|
||||
"versions": ["r0.0.1"]
|
||||
"versions": ["r0.0.1"],
|
||||
"unstable_features": {
|
||||
"org.example.my_feature": true
|
||||
}
|
||||
}
|
||||
schema:
|
||||
type: object
|
||||
|
|
@ -50,5 +66,15 @@ paths:
|
|||
items:
|
||||
type: string
|
||||
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:
|
||||
- Server administration
|
||||
|
|
|
|||
|
|
@ -38,28 +38,9 @@ paths:
|
|||
responses:
|
||||
200:
|
||||
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:
|
||||
type: object
|
||||
properties:
|
||||
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
|
||||
"$ref": "definitions/wellknown/full.yaml"
|
||||
404:
|
||||
description: No server discovery information available.
|
||||
tags:
|
||||
|
|
|
|||
|
|
@ -65,22 +65,6 @@ paths:
|
|||
event(s), up to the given limit.
|
||||
schema:
|
||||
$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}":
|
||||
post:
|
||||
summary: Retrieves events that the sender is missing
|
||||
|
|
@ -114,14 +98,14 @@ paths:
|
|||
earliest_events:
|
||||
type: array
|
||||
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``.
|
||||
items:
|
||||
type: string
|
||||
example: ["$missing_event:example.org"]
|
||||
latest_events:
|
||||
type: array
|
||||
description: The events to retrieve the previous events for.
|
||||
description: The event IDs to retrieve the previous events for.
|
||||
items:
|
||||
type: string
|
||||
example: ["$event_that_has_the_missing_event_as_a_previous_event:example.org"]
|
||||
|
|
@ -136,13 +120,16 @@ paths:
|
|||
properties:
|
||||
events:
|
||||
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:
|
||||
$ref: definitions/pdu.yaml
|
||||
type: object
|
||||
title: PDU
|
||||
required: ['events']
|
||||
examples:
|
||||
application/json: {
|
||||
"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
|
||||
# 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:
|
||||
- $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");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
@ -13,15 +13,14 @@
|
|||
# limitations under the License.
|
||||
type: object
|
||||
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:
|
||||
- $ref: "pdu.yaml"
|
||||
- type: object
|
||||
properties:
|
||||
# Note: we override a bunch of parameters to change their descriptions
|
||||
sender:
|
||||
type: string
|
||||
# TODO: Verify/clarify this - it doesn't seem right, given this is a 'regular' invite
|
||||
description: |-
|
||||
The matrix ID of the user who sent the original ``m.room.third_party_invite``.
|
||||
example: "@someone:example.org"
|
||||
|
|
@ -46,7 +45,7 @@ allOf:
|
|||
type: object
|
||||
title: Membership Event Content
|
||||
description: |-
|
||||
The content of the event, matching what is available in the
|
||||
The content of the event, matching what is available in the
|
||||
`Client-Server API`_. Must include a ``membership`` of ``invite``.
|
||||
example: {"membership": "invite"}
|
||||
properties:
|
||||
|
|
@ -55,33 +54,10 @@ allOf:
|
|||
description: The value ``invite``.
|
||||
example: "invite"
|
||||
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:
|
||||
# Every other field is already flagged as required by the $ref
|
||||
- state_key
|
||||
- sender
|
||||
- origin
|
||||
- origin_server_ts
|
||||
- type
|
||||
- content
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ properties:
|
|||
verify_keys:
|
||||
type: object
|
||||
description: |-
|
||||
Public keys of the homeserver for verifying digital signatures.
|
||||
|
||||
The object's key is the algorithm and version combined (``ed25519`` being the
|
||||
Public keys of the homeserver for verifying digital signatures.
|
||||
|
||||
The object's key is the algorithm and version combined (``ed25519`` being the
|
||||
algorithm and ``abc123`` being the version in the example below). Together,
|
||||
this forms the Key ID. The version must have characters matching the regular
|
||||
expression ``[a-zA-Z0-9_]``.
|
||||
|
|
@ -49,9 +49,9 @@ properties:
|
|||
old_verify_keys:
|
||||
type: object
|
||||
description: |-
|
||||
The public keys that the server used to use and when it stopped using them.
|
||||
|
||||
The object's key is the algorithm and version combined (``ed25519`` being the
|
||||
The public keys that the server used to use and when it stopped using them.
|
||||
|
||||
The object's key is the algorithm and version combined (``ed25519`` being the
|
||||
algorithm and ``0ldK3y`` being the version in the example below). Together,
|
||||
this forms the Key ID. The version must have characters matching the regular
|
||||
expression ``[a-zA-Z0-9_]``.
|
||||
|
|
@ -90,17 +90,6 @@ properties:
|
|||
additionalProperties:
|
||||
type: string
|
||||
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:
|
||||
type: integer
|
||||
format: int64
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
# limitations under the License.
|
||||
type: object
|
||||
title: Persistent Data Unit
|
||||
description: A persistent data unit (event)
|
||||
description: A persistent data unit (event) for room versions 1 and 2.
|
||||
example:
|
||||
$ref: "../examples/pdu.json"
|
||||
allOf:
|
||||
|
|
@ -26,13 +26,13 @@ allOf:
|
|||
description: |-
|
||||
Content hashes of the PDU, following the algorithm specified in `Signing Events`_.
|
||||
example: {
|
||||
"sha256": "thishashcoversallfieldsincasethisisredacted"
|
||||
"sha256": "ThisHashCoversAllFieldsInCaseThisIsRedacted"
|
||||
}
|
||||
properties:
|
||||
sha256:
|
||||
type: string
|
||||
description: The hash.
|
||||
example: thishashcoversallfieldsincasthisisredacted
|
||||
example: ThisHashCoversAllFieldsInCaseThisIsRedacted
|
||||
required: ['sha256']
|
||||
signatures:
|
||||
type: object
|
||||
|
|
@ -40,7 +40,7 @@ allOf:
|
|||
Signatures for the PDU, following the algorithm specified in `Signing Events`_.
|
||||
example: {
|
||||
"example.com": {
|
||||
"ed25519:key_version:": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus"
|
||||
"ed25519:key_version:": "86BytesOfSignatureOfTheRedactedEvent"
|
||||
}
|
||||
}
|
||||
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
|
||||
|
|
@ -26,12 +26,22 @@ properties:
|
|||
type: integer
|
||||
format: int64
|
||||
description: |-
|
||||
POSIX timestamp in milliseconds on originating homeserver when this
|
||||
POSIX timestamp in milliseconds on originating homeserver when this
|
||||
transaction started.
|
||||
example: 1532991320875
|
||||
pdus:
|
||||
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:
|
||||
$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']
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
# 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)
|
||||
example:
|
||||
$ref: "../examples/unsigned_pdu.json"
|
||||
properties:
|
||||
event_id:
|
||||
type: string
|
||||
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"}
|
||||
allOf:
|
||||
- $ref: "unsigned_pdu_base.yaml"
|
||||
- type: object
|
||||
properties:
|
||||
age:
|
||||
type: integer
|
||||
description: The number of milliseconds that have passed since this message was sent.
|
||||
example: 4612
|
||||
replaces_state:
|
||||
event_id:
|
||||
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
|
||||
description: The event ID for the PDU.
|
||||
example: "$a4ecee13e2accdadf56c1025:example.com"
|
||||
required:
|
||||
- event_id
|
||||
|
|
|
|||
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
|
||||
|
|
@ -20,7 +20,7 @@ host: localhost:8448
|
|||
schemes:
|
||||
- https
|
||||
basePath: /_matrix/federation/v1
|
||||
consumes:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
|
|
@ -58,10 +58,19 @@ paths:
|
|||
type: array
|
||||
description: |-
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
example: [{"$ref": "examples/pdu.json"}]
|
||||
type: object
|
||||
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']
|
||||
"/query_auth/{roomId}/{eventId}":
|
||||
post:
|
||||
|
|
@ -98,10 +107,20 @@ paths:
|
|||
properties:
|
||||
auth_chain:
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
example: [{"$ref": "examples/pdu.json"}]
|
||||
type: object
|
||||
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:
|
||||
type: array
|
||||
description: |-
|
||||
|
|
@ -142,14 +161,23 @@ paths:
|
|||
type: array
|
||||
description: |-
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
example: [{"$ref": "examples/pdu.json"}]
|
||||
type: object
|
||||
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:
|
||||
type: array
|
||||
description: |-
|
||||
The list of event IDs that the receiver believes it is missing,
|
||||
The list of event IDs that the receiver believes it is missing,
|
||||
after comparing the "remote auth" and "local auth" chains.
|
||||
items:
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -59,17 +59,35 @@ paths:
|
|||
type: array
|
||||
description: |-
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
example: [{"$ref": "examples/pdu.json"}]
|
||||
type: object
|
||||
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:
|
||||
type: array
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
example: [{"$ref": "examples/pdu.json"}]
|
||||
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.
|
||||
properties: []
|
||||
example:
|
||||
$ref: "examples/minimal_pdu.json"
|
||||
required: ['auth_chain', 'pdus']
|
||||
"/state_ids/{roomId}":
|
||||
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"
|
||||
}
|
||||
},
|
||||
"tls_fingerprints": [{
|
||||
"sha256": "VGhpcyBpcyBoYXNoIHdoaWNoIHNob3VsZCBiZSBieXRlcw"
|
||||
}],
|
||||
"valid_until_ts": 1652262000000
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"origin": "matrix.org",
|
||||
"origin_server_ts": 1234567890,
|
||||
"pdus": [{"$ref": "pdu.json"}]
|
||||
}
|
||||
"pdus": [{
|
||||
"$ref": "minimal_pdu.json"
|
||||
}]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,4 @@
|
|||
{
|
||||
"room_id": "!UcYsUzyxTGDxLBEvLy:example.org",
|
||||
"sender": "@alice: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
|
||||
}
|
||||
}
|
||||
"$ref": "unsigned_pdu_base.json",
|
||||
"event_id": "$a4ecee13e2accdadf56c1025:example.com"
|
||||
}
|
||||
|
|
|
|||
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");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
@ -20,7 +20,7 @@ host: localhost:8448
|
|||
schemes:
|
||||
- https
|
||||
basePath: /_matrix/federation/v1
|
||||
consumes:
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
|
|
@ -32,9 +32,18 @@ paths:
|
|||
summary: Invites a remote user to a room
|
||||
description: |-
|
||||
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.
|
||||
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:
|
||||
- signedRequest: []
|
||||
parameters:
|
||||
|
|
@ -103,9 +112,12 @@ paths:
|
|||
}
|
||||
]
|
||||
example: {
|
||||
"$ref": "examples/pdu.json",
|
||||
"$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",
|
||||
"unsigned": {
|
||||
"invite_room_state": [
|
||||
{
|
||||
|
|
@ -139,7 +151,8 @@ paths:
|
|||
200:
|
||||
description: |-
|
||||
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:
|
||||
type: array
|
||||
minItems: 2
|
||||
|
|
@ -160,9 +173,12 @@ paths:
|
|||
200,
|
||||
{
|
||||
"event": {
|
||||
"$ref": "examples/pdu.json",
|
||||
"$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": [
|
||||
{
|
||||
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:
|
||||
200:
|
||||
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:
|
||||
type: object
|
||||
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:
|
||||
allOf:
|
||||
- $ref: "definitions/unsigned_pdu.yaml"
|
||||
- description: |-
|
||||
An unsigned template event.
|
||||
description: |-
|
||||
An unsigned template event. Note that events have a different format
|
||||
depending on the room version - check the `room version specification`_
|
||||
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
|
||||
title: Membership Event Content
|
||||
description: The content of the event.
|
||||
example: {"membership": "join"}
|
||||
properties:
|
||||
# Note: we override a bunch of parameters to change their descriptions
|
||||
sender:
|
||||
membership:
|
||||
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
|
||||
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
|
||||
description: The value ``join``.
|
||||
example: "join"
|
||||
required: ['membership']
|
||||
required:
|
||||
- state_key
|
||||
- origin
|
||||
- origin_server_ts
|
||||
- type
|
||||
- content
|
||||
- sender
|
||||
examples:
|
||||
application/json: {
|
||||
event: {
|
||||
"$ref": "examples/unsigned_pdu.json",
|
||||
"room_version": "2",
|
||||
"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",
|
||||
"content": {
|
||||
"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:
|
||||
|
|
@ -186,7 +166,12 @@ paths:
|
|||
summary: Submit a signed join event to a resident server
|
||||
description: |-
|
||||
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
|
||||
security:
|
||||
- signedRequest: []
|
||||
|
|
@ -208,81 +193,54 @@ paths:
|
|||
type: object
|
||||
required: true
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "definitions/pdu.yaml"
|
||||
- type: object
|
||||
type: object
|
||||
properties:
|
||||
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:
|
||||
# Note: we override a bunch of parameters to change their descriptions
|
||||
sender:
|
||||
membership:
|
||||
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:
|
||||
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
|
||||
description: The value ``join``.
|
||||
example: "join"
|
||||
required: ['membership']
|
||||
required:
|
||||
- state_key
|
||||
- sender
|
||||
- origin
|
||||
- origin_server_ts
|
||||
- type
|
||||
- content
|
||||
example: {
|
||||
"$ref": "examples/pdu.json",
|
||||
"$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",
|
||||
"content": {
|
||||
"membership": "join"
|
||||
}
|
||||
|
|
@ -308,25 +266,44 @@ paths:
|
|||
description: The resident server's DNS name.
|
||||
auth_chain:
|
||||
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:
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
type: object
|
||||
properties: []
|
||||
example:
|
||||
$ref: "examples/minimal_pdu.json"
|
||||
state:
|
||||
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:
|
||||
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:
|
||||
$ref: "definitions/pdu.yaml"
|
||||
type: object
|
||||
properties: []
|
||||
example:
|
||||
$ref: "examples/minimal_pdu.json"
|
||||
required: ["auth_chain", "state", "origin"]
|
||||
examples:
|
||||
application/json: [
|
||||
200,
|
||||
{
|
||||
"origin": "matrix.org",
|
||||
"auth_chain": [{"$ref": "examples/pdu.json"}],
|
||||
"state": [{"$ref": "examples/pdu.json"}]
|
||||
"auth_chain": [{"$ref": "examples/minimal_pdu.json"}],
|
||||
"state": [{"$ref": "examples/minimal_pdu.json"}]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ paths:
|
|||
get:
|
||||
summary: Get the homeserver's public key(s)
|
||||
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
|
||||
number of old keys.
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ paths:
|
|||
type: string
|
||||
description: |-
|
||||
**Deprecated**. Servers should not use this parameter and instead
|
||||
opt to return all keys, not just the requested one. The key ID to
|
||||
opt to return all keys, not just the requested one. The key ID to
|
||||
look up.
|
||||
required: false
|
||||
x-example: "ed25519:abc123"
|
||||
|
|
|
|||
|
|
@ -52,97 +52,81 @@ paths:
|
|||
responses:
|
||||
200:
|
||||
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:
|
||||
type: object
|
||||
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:
|
||||
allOf:
|
||||
- $ref: "definitions/unsigned_pdu.yaml"
|
||||
- description: |-
|
||||
An unsigned template event.
|
||||
description: |-
|
||||
An unsigned template event. Note that events have a different format
|
||||
depending on the room version - check the `room version specification`_
|
||||
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
|
||||
title: Membership Event Content
|
||||
description: The content of the event.
|
||||
example: {"membership": "leave"}
|
||||
properties:
|
||||
# Note: we override a bunch of parameters to change their descriptions
|
||||
sender:
|
||||
membership:
|
||||
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
|
||||
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
|
||||
description: The value ``leave``.
|
||||
example: "leave"
|
||||
required: ['membership']
|
||||
required:
|
||||
- state_key
|
||||
- sender
|
||||
- origin
|
||||
- origin_server_ts
|
||||
- type
|
||||
- content
|
||||
examples:
|
||||
application/json: {
|
||||
"room_version": "2",
|
||||
"event": {
|
||||
"$ref": "examples/unsigned_pdu.json",
|
||||
"$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",
|
||||
"content": {
|
||||
"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:
|
||||
|
|
@ -160,7 +144,12 @@ paths:
|
|||
summary: Submit a signed leave event to a resident server
|
||||
description: |-
|
||||
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
|
||||
security:
|
||||
- signedRequest: []
|
||||
|
|
@ -182,81 +171,59 @@ paths:
|
|||
type: object
|
||||
required: true
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "definitions/pdu.yaml"
|
||||
- type: object
|
||||
type: object
|
||||
properties:
|
||||
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:
|
||||
# Note: we override a bunch of parameters to change their descriptions
|
||||
sender:
|
||||
membership:
|
||||
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:
|
||||
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
|
||||
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
|
||||
required:
|
||||
- state_key
|
||||
- sender
|
||||
- origin
|
||||
- origin_server_ts
|
||||
- type
|
||||
- depth
|
||||
- content
|
||||
example: {
|
||||
"$ref": "examples/pdu.json",
|
||||
"$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",
|
||||
"content": {
|
||||
"membership": "leave"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ paths:
|
|||
User ID of the owner.
|
||||
operationId: exchangeOpenIdToken
|
||||
parameters:
|
||||
- in: path
|
||||
- in: query
|
||||
name: access_token
|
||||
type: string
|
||||
description: |-
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ paths:
|
|||
third_party_invite:
|
||||
type: object
|
||||
description: The third party invite
|
||||
title: Third Party Invite
|
||||
properties:
|
||||
display_name:
|
||||
type: string
|
||||
|
|
@ -97,6 +98,7 @@ paths:
|
|||
description: |-
|
||||
A block of content which has been signed, which servers can use to
|
||||
verify the event.
|
||||
title: Invite Signatures
|
||||
properties:
|
||||
signatures:
|
||||
type: object
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ paths:
|
|||
|
||||
The sending server must wait and retry for a 200 OK response before sending a
|
||||
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
|
||||
security:
|
||||
- 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": {
|
||||
"creator": "@example:example.org",
|
||||
"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:
|
||||
description: The version of the room. Defaults to ``"1"`` if the key does not exist.
|
||||
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:
|
||||
- creator
|
||||
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. 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. 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. Ensure the `targets.yml` file lists the version correctly.
|
||||
1. Commit the changes and PR them to master.
|
||||
1. Tag the release with the format `client_server/r0.4.0`.
|
||||
1. Add the changes to the matrix-org/matrix.org repository (for historic tracking).
|
||||
1. Generate the specification using `./scripts/gendoc.py`, specifying all the
|
||||
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. PR 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
|
||||
specification you're releasing.
|
||||
* 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. Yell from the mountaintop to the world about the new release.
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ When this is called, the server:
|
|||
"state_key": "",
|
||||
"room_id": "!QtykxKocfsgujksjgd:matrix.org",
|
||||
"content": {
|
||||
"version": "2",
|
||||
"room_version": "2",
|
||||
"predecessor": {
|
||||
"room_id": "!cURbaf: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,
|
||||
otherwise:
|
||||
|
||||
The response must have a `Content-Type` of `application/json`, and must be
|
||||
valid JSON which follows the structure documented below. Otherwise, the
|
||||
request is aborted.
|
||||
The response must be valid JSON which follows the structure documented
|
||||
below. Otherwise, continue to the next step in the discovery process. It is
|
||||
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
|
||||
`<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`
|
||||
API.
|
||||
|
||||
The value of the `capabilities` object in the response should be the empty
|
||||
object.
|
||||
The value of the `capabilities` object in the response should contain a single
|
||||
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
|
||||
|
||||
|
|
|
|||
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,))
|
||||
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):
|
||||
os.mkdir(d)
|
||||
html_file = os.path.join(d, "%s.html" % version_label)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,11 @@ from batesian.sections import Sections
|
|||
import inspect
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class MatrixSections(Sections):
|
||||
|
||||
# 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):
|
||||
return self.units.get("git_version")["revision"]
|
||||
|
||||
def render_client_server_changelog(self):
|
||||
def render_changelogs(self):
|
||||
rendered = {}
|
||||
changelogs = self.units.get("changelogs")
|
||||
return changelogs["client_server"]
|
||||
|
||||
# TODO: We should make this a generic variable instead of having to add functions all the time.
|
||||
def render_push_gateway_changelog(self):
|
||||
changelogs = self.units.get("changelogs")
|
||||
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"]
|
||||
for spec, changelog_text in changelogs.items():
|
||||
spec_var = "%s_changelog" % spec
|
||||
logger.info("Rendering changelog for spec: %s" % spec)
|
||||
rendered[spec_var] = changelog_text
|
||||
return rendered
|
||||
|
||||
def _render_events(self, filterFn, sortFn):
|
||||
template = self.env.get_template("events.tmpl")
|
||||
|
|
|
|||
|
|
@ -774,7 +774,7 @@ class MatrixUnits(Units):
|
|||
"Privileged server plugins",
|
||||
), TypeTableRow(
|
||||
"`Identity Service API <identity_service/"+is_ver+".html>`_",
|
||||
"unstable",
|
||||
is_ver,
|
||||
"Mapping of third party IDs to Matrix IDs",
|
||||
), TypeTableRow(
|
||||
"`Push Gateway API <push_gateway/"+push_gw_ver+".html>`_",
|
||||
|
|
@ -903,74 +903,112 @@ class MatrixUnits(Units):
|
|||
|
||||
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 = {}
|
||||
|
||||
for f in os.listdir(CHANGELOG_DIR):
|
||||
if not f.endswith(".rst"):
|
||||
continue
|
||||
path = os.path.join(CHANGELOG_DIR, f)
|
||||
name = f[:-4]
|
||||
# The APIs and versions we'll prepare changelogs for. We use the substitutions
|
||||
# to ensure that we pick up the right version for generated documentation. This
|
||||
# defaults to "unstable" as a version for incremental generated documentation (CI).
|
||||
prepare_versions = {
|
||||
"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
|
||||
# a towncrier changelog and prepend it to the general changelog.
|
||||
tc_path = os.path.join(CHANGELOG_DIR, name)
|
||||
tc_lines = []
|
||||
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')
|
||||
# Changelogs are split into two places: towncrier for the unstable changelog and
|
||||
# the RST file for historical versions. If the prepare_versions dict above has
|
||||
# a version other than "unstable" specified for an API, we'll use the historical
|
||||
# changelog and otherwise generate the towncrier log in-memory.
|
||||
|
||||
# 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("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
|
||||
for api_name, target_version in prepare_versions.items():
|
||||
logger.info("Generating changelog for %s at %s" % (api_name, target_version,))
|
||||
changelog_lines = []
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
lines = f.readlines()
|
||||
if target_version == 'unstable':
|
||||
# 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
|
||||
for line in (tc_lines + lines):
|
||||
title_part = None
|
||||
changelog_body_lines = []
|
||||
for line in changelog_lines:
|
||||
if prev_line is None:
|
||||
prev_line = line
|
||||
continue
|
||||
if not title_part:
|
||||
# find the title underline (at least 3 =)
|
||||
if re.match("^[=]{3,}$", line.strip()):
|
||||
title_part = prev_line
|
||||
continue
|
||||
prev_line = line
|
||||
else: # have title, get body (stop on next title or EOF)
|
||||
if re.match("^[=]{3,}$", line.strip()):
|
||||
# we added the title in the previous iteration, pop it
|
||||
# then bail out.
|
||||
changelog_lines.pop()
|
||||
break
|
||||
# Don't generate subheadings (we'll keep the title though)
|
||||
if re.match("^[-]{3,}$", line.strip()):
|
||||
continue
|
||||
changelog_lines.append(" " + line + '\n')
|
||||
changelogs[name] = "".join(changelog_lines)
|
||||
if re.match("^[=]{3,}$", line.strip()):
|
||||
# the last line was a header - use that as our new title_part
|
||||
title_part = prev_line.strip()
|
||||
continue
|
||||
if re.match("^[-]{3,}$", line.strip()):
|
||||
# the last line is a subheading - drop this line because it's the underline
|
||||
# and that causes problems with rendering. We'll keep the header text though.
|
||||
continue
|
||||
if line.strip().startswith(".. "):
|
||||
# skip comments
|
||||
continue
|
||||
if title_part == target_version:
|
||||
# if we made it this far, append the line to the changelog body. We indent it so
|
||||
# that it renders correctly in the section. We also add newlines so that there's
|
||||
# intentionally blank lines that make rst2html happy.
|
||||
changelog_body_lines.append(" " + line + '\n')
|
||||
|
||||
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
|
||||
|
||||
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):
|
||||
warning = """
|
||||
.. WARNING::
|
||||
|
|
|
|||
|
|
@ -52,6 +52,6 @@ Examples of strings encoded using unpadded Base64::
|
|||
UNPADDED_BASE64("foobar") = "Zm9vYmFy"
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@
|
|||
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
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
|
@ -28,7 +34,7 @@ following grammar::
|
|||
|
||||
server_name = hostname [ ":" port ]
|
||||
|
||||
port = *DIGIT
|
||||
port = 1*5DIGIT
|
||||
|
||||
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.
|
||||
* 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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -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
|
||||
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:
|
||||
|
||||
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
|
||||
|
||||
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/event ID is the `server name`_ of the homeserver which
|
||||
The ``domain`` of a room ID is the `server name`_ of the homeserver which
|
||||
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
|
||||
implication that the room or event in question is still available at the
|
||||
corresponding homeserver.
|
||||
|
||||
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
|
||||
What is the grammar for the opaque part? https://matrix.org/jira/browse/SPEC-389
|
||||
|
|
@ -327,7 +300,7 @@ matrix.to navigation
|
|||
|
||||
.. NOTE::
|
||||
This namespacing is in place pending a ``matrix://`` (or similar) URI scheme.
|
||||
This is **not** meant to be interpreted as an available web service - see
|
||||
This is **not** meant to be interpreted as an available web service - see
|
||||
below for more details.
|
||||
|
||||
Rooms, users, aliases, and groups may be represented as a "matrix.to" URI.
|
||||
|
|
@ -343,21 +316,34 @@ in RFC 3986:
|
|||
The identifier may be a room ID, room alias, user ID, or group ID. The extra
|
||||
parameter is only used in the case of permalinks where an event ID is referenced.
|
||||
The matrix.to URI, when referenced, must always start with ``https://matrix.to/#/``
|
||||
followed by the identifier.
|
||||
followed by the identifier.
|
||||
|
||||
Clients should not rely on matrix.to URIs falling back to a web server if accessed
|
||||
and instead should perform some sort of action within the client. For example, if
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
* Room alias: ``https://matrix.to/#/#somewhere:example.org``
|
||||
* Room: ``https://matrix.to/#/!somewhere:example.org``
|
||||
* Permalink by room: ``https://matrix.to/#/!somewhere:example.org/$event:example.org``
|
||||
* Permalink by room alias: ``https://matrix.to/#/#somewhere:example.org/$event:example.org``
|
||||
* User: ``https://matrix.to/#/@alice:example.org``
|
||||
* Group: ``https://matrix.to/#/+example:example.org``
|
||||
* Room alias: ``https://matrix.to/#/%23somewhere%3Aexample.org``
|
||||
* Room: ``https://matrix.to/#/!somewhere%3Aexample.org``
|
||||
* Permalink by room: ``https://matrix.to/#/!somewhere%3Aexample.org/%24event%3Aexample.org``
|
||||
* Permalink by room alias: ``https://matrix.to/#/#somewhere:example.org/%24event%3Aexample.org``
|
||||
* User: ``https://matrix.to/#/%40alice%3Aexample.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::
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
:``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``:
|
||||
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
|
||||
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)
|
||||
.. * 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_RESOURCE_LIMIT_EXCEEDED - Limits: https://github.com/matrix-org/matrix-doc/issues/1504
|
||||
|
||||
.. _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
|
||||
`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
|
||||
|
||||
|
|
@ -650,7 +658,7 @@ For example, to authenticate using the user's Matrix ID, clients whould submit:
|
|||
"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
|
||||
follows:
|
||||
|
||||
|
|
@ -667,7 +675,7 @@ follows:
|
|||
"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.
|
||||
|
||||
Google ReCaptcha
|
||||
|
|
@ -928,10 +936,10 @@ Third-party ID
|
|||
:Type:
|
||||
``m.id.thirdparty``
|
||||
: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
|
||||
the homeserver, where the 3pid was previously associated using the
|
||||
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
|
||||
|/account/3pid|_ API. See the `3PID Types`_ Appendix for a list of Third-party
|
||||
ID media.
|
||||
|
||||
|
|
@ -987,7 +995,7 @@ request as follows:
|
|||
"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``
|
||||
explicitly, as follows:
|
||||
|
||||
|
|
@ -1002,7 +1010,7 @@ explicitly, as follows:
|
|||
"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``.
|
||||
|
||||
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}}
|
||||
|
||||
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
|
||||
----------
|
||||
|
||||
|
|
@ -1166,7 +1275,21 @@ point in time::
|
|||
|
||||
[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
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ Identity Service API
|
|||
|
||||
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
|
||||
("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
|
||||
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.
|
||||
|
||||
.. 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
|
||||
potentially sensitive data. In particular, being able to construct large-scale
|
||||
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
|
||||
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).
|
||||
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
|
||||
user ID, or get all 3PIDs associated with a 3PID).
|
||||
|
||||
Web browser clients
|
||||
-------------------
|
||||
|
|
@ -204,10 +204,10 @@ Establishing associations
|
|||
|
||||
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
|
||||
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,
|
||||
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,
|
||||
i.e. I can claim that any email address I own is associated with
|
||||
@billg:microsoft.com.
|
||||
|
||||
|
|
@ -255,11 +255,11 @@ General
|
|||
Invitation storage
|
||||
------------------
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
homeserver via the `/3pid/onbind`_ endpoint. The request MUST be signed with a
|
||||
long-term private key for the identity server.
|
||||
|
|
@ -279,4 +279,4 @@ this isn't possible.
|
|||
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
||||
.. _`3PID Types`: ../appendices.html#pid-types
|
||||
.. _`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}}
|
||||
|
||||
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
|
||||
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
|
||||
-------------------------------
|
||||
|
|
@ -128,6 +133,8 @@ To propose a change to the Matrix Spec, see the explanations at `Proposals
|
|||
for Spec Changes to Matrix <proposals>`_.
|
||||
|
||||
|
||||
.. _`architecture`:
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
|
|
@ -189,7 +196,7 @@ allocated the account and has the form::
|
|||
|
||||
@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.
|
||||
|
||||
Devices
|
||||
|
|
@ -315,8 +322,8 @@ The following conceptual diagram shows an
|
|||
| Content: { JSON object } |
|
||||
|....................................|
|
||||
|
||||
Federation maintains *shared data structures* per-room between multiple home
|
||||
servers. The data is split into ``message events`` and ``state events``.
|
||||
Federation maintains *shared data structures* per-room between multiple
|
||||
homeservers. The data is split into ``message events`` and ``state events``.
|
||||
|
||||
Message events:
|
||||
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 &
|
||||
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
|
||||
----------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ The account_data may be either global or scoped to a particular rooms.
|
|||
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``.
|
||||
|
||||
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
|
||||
========= ========= ============================================================
|
||||
key string **Required.** Key type. Must be ``oct``.
|
||||
key_opts [string] **Required.** Key operations. Must at least contain
|
||||
kty string **Required.** Key type. Must be ``oct``.
|
||||
key_ops [string] **Required.** Key operations. Must at least contain
|
||||
``encrypt`` and ``decrypt``.
|
||||
alg string **Required.** Algorithm. Must be ``A256CTR``.
|
||||
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::
|
||||
|
||||
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.
|
||||
|
||||
Key exports
|
||||
|
|
@ -496,18 +496,9 @@ passphrase, and is created as follows:
|
|||
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:
|
||||
|
||||
``ExportData``
|
||||
|
||||
=============== ================= ==============================================
|
||||
Parameter Type Description
|
||||
=============== ================= ==============================================
|
||||
sessions ``[SessionData]`` Required. The sessions that are being
|
||||
exported.
|
||||
=============== ================= ==============================================
|
||||
|
||||
``SessionData``
|
||||
|
||||
.. table::
|
||||
|
|
@ -529,7 +520,7 @@ sessions ``[SessionData]`` Required. The sessions that are being
|
|||
device which initiated the session
|
||||
originally.
|
||||
sender_claimed_keys {string: Required. The Ed25519 key of the
|
||||
integer} device which initiated the session
|
||||
string} device which initiated the session
|
||||
originally.
|
||||
session_id string Required. The ID of 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>",
|
||||
"device_id": "<sender_device_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
|
||||
``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
|
||||
flickering due to the following two scenarios, however the effect can be mitigated
|
||||
to a degree:
|
||||
|
||||
- The client sends a message and the remote echo arrives on the event stream
|
||||
*after* the request to send the message completes.
|
||||
- The client sends a message and the remote echo arrives on the event stream
|
||||
*before* the request to send the message completes.
|
||||
|
||||
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.
|
||||
Clients unable to make use of the transaction ID are likely to experience
|
||||
flickering when the remote echo arrives on the event stream *before*
|
||||
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
|
||||
identify it as a remote echo. This results in the client displaying the message
|
||||
twice for some time (depending on the server responsiveness) before 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.
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
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``,
|
||||
``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
|
||||
are sent *outside the context of a room*. Presence events are sent to all users
|
||||
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.
|
||||
and transmitted as an ``m.presence`` event. Presence events are sent to
|
||||
interested parties where users share a room membership.
|
||||
|
||||
User's presence state is represented by the ``presence`` key, which is an enum
|
||||
of one of the following:
|
||||
|
|
@ -53,17 +47,10 @@ Events
|
|||
Client behaviour
|
||||
----------------
|
||||
|
||||
Clients can manually set/get their presence/presence list using the HTTP APIs
|
||||
listed below.
|
||||
Clients can manually set/get their presence using the HTTP APIs listed below.
|
||||
|
||||
{{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
|
||||
~~~~~~~~~~~~~~~
|
||||
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
|
||||
content of the event is the current push rules for the user.
|
||||
|
||||
{{m_push_rules_event}}
|
||||
|
||||
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.``
|
||||
is defined to be the display name of this tag. No other semantics should be inferred from tags in
|
||||
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 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
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ verification must still be performed, so the attack surface here is minimized.
|
|||
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
|
||||
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 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 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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
|
||||
a push where the ``format`` is ``"event_id_only"``, only the ``event_id``, ``room_id``,
|
||||
``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 2017 New Vector Ltd
|
||||
.. Copyright 2018 New Vector Ltd
|
||||
.. 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.
|
||||
|
|
@ -17,9 +16,7 @@
|
|||
Federation API
|
||||
==============
|
||||
|
||||
.. WARNING::
|
||||
This API is unstable and will change without warning or discussion while
|
||||
we work towards a r0 release (scheduled for August 2018).
|
||||
{{unstable_warning_block_SERVER_RELEASE_LABEL}}
|
||||
|
||||
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
|
||||
|
|
@ -77,13 +74,14 @@ This version of the specification is generated from
|
|||
For the full historical changelog, see
|
||||
https://github.com/matrix-org/matrix-doc/blob/master/changelogs/server_server.rst
|
||||
|
||||
|
||||
Other versions of this specification
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
- `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
|
||||
----------------
|
||||
|
|
@ -91,35 +89,107 @@ Server discovery
|
|||
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
|
||||
<../appendices.html#server-name>`_. Server names should be resolved to an IP
|
||||
address and port using the following process:
|
||||
<../appendices.html#server-name>`_. Where applicable, a delegated server name
|
||||
uses the same grammar.
|
||||
|
||||
* If the hostname is an IP literal, then that IP address should be used,
|
||||
together with the given port number, or 8448 if no port is given.
|
||||
Server names are resolved to an IP address and port to connect to, and have
|
||||
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
|
||||
looking up an AAAA or A record for the hostname, and the specified port is
|
||||
used.
|
||||
.. Note from the author: The repetitive "use this Host header and this cert"
|
||||
comments are intentional. The process is overall quite complicated, and
|
||||
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
|
||||
discovered by first looking up a ``_matrix._tcp`` SRV record for the
|
||||
hostname, which may give a hostname (to be looked up using AAAA or A queries)
|
||||
and port. If the SRV record does not exist, then the server is discovered by
|
||||
looking up an AAAA or A record on the hostname and taking the default
|
||||
fallback port number of 8448.
|
||||
1. If the hostname is an IP literal, then that IP address should be used,
|
||||
together with the given port number, or 8448 if no port is given. The
|
||||
target server must present a valid certificate for the IP address.
|
||||
The ``Host`` header in the request should be set to the server name,
|
||||
including the port if the server name included one.
|
||||
|
||||
Homeservers may use SRV records to load balance requests between multiple TLS
|
||||
endpoints or to failover to another endpoint if an endpoint fails.
|
||||
2. If the hostname is not an IP literal, and the server name includes an
|
||||
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
|
||||
``Host`` header, regardless of any hostname given in the SRV record. For
|
||||
example, if the server name is ``example.org``, and the SRV record resolves to
|
||||
``matrix.example.org``, the ``Host`` header in the request should be
|
||||
``example.org``. If an explicit port was given in the server name, it should be
|
||||
included in the ``Host`` header; otherwise, no port number should be given in
|
||||
the ``Host`` header.
|
||||
3. If the hostname is not an IP literal, a regular HTTPS request is made
|
||||
to ``https://<hostname>/.well-known/matrix/server``, expecting the
|
||||
schema defined later in this section. 30x redirects should be followed,
|
||||
however redirection loops should be avoided. Responses (successful or
|
||||
otherwise) to the ``/.well-known`` endpoint should be cached by the
|
||||
requesting server. Servers should respect the cache control headers
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -131,7 +201,7 @@ Retrieving server keys
|
|||
|
||||
.. NOTE::
|
||||
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>`_.
|
||||
|
||||
Each homeserver publishes its public keys under ``/_matrix/key/v2/server/{keyId}``.
|
||||
|
|
@ -153,12 +223,11 @@ server by querying other servers.
|
|||
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
|
||||
``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
|
||||
are only valid for signing events. Finally the response contains a list of TLS
|
||||
certificate fingerprints to validate any connection made to the homeserver.
|
||||
are only valid for signing events.
|
||||
|
||||
{{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}}
|
||||
|
||||
.. _`Persistent Data Unit schema`:
|
||||
|
||||
PDUs
|
||||
----
|
||||
|
||||
|
|
@ -328,7 +399,7 @@ following subset of the room state:
|
|||
``m.room.third_party_invite`` event with ``state_key`` matching
|
||||
``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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -380,189 +451,9 @@ Authorization rules
|
|||
|
||||
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
|
||||
specified above. 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 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.
|
||||
|
||||
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
|
||||
see the `room version specification`_.
|
||||
|
||||
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
|
||||
room. What should the name of the room be at E5?
|
||||
|
||||
Servers should follow one of the following recursively-defined algorithms,
|
||||
depending on the room version, to determine the room state at a given point on
|
||||
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.
|
||||
The algorithm to be used for state resolution depends on the room version. For
|
||||
a description of each room version's algorithm, please see the `room version specification`_.
|
||||
|
||||
|
||||
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
|
||||
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)
|
||||
---------------------------------
|
||||
|
|
@ -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.
|
||||
|
||||
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
|
||||
with a given user, or a user on the receiving server has added one of the
|
||||
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.
|
||||
would be interested in. Such as the receiving server sharing a room
|
||||
with a given user.
|
||||
|
||||
.. TODO-doc
|
||||
- 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_invite}}
|
||||
|
||||
{{definition_ss_event_schemas_m_presence_accept}}
|
||||
|
||||
{{definition_ss_event_schemas_m_presence_deny}}
|
||||
|
||||
|
||||
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,
|
||||
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}}
|
||||
|
||||
|
|
@ -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
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -1454,7 +1168,7 @@ Example code
|
|||
# Keys under "unsigned" can be modified by other servers.
|
||||
# They are useful for conveying information like the age of an
|
||||
# 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)
|
||||
|
||||
# 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
|
||||
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
|
||||
``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]]
|
||||
|
||||
|
||||
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: #get-matrix-federation-v1-query-directory
|
||||
|
||||
|
|
@ -1500,3 +1224,4 @@ Example code
|
|||
.. _`Checking for a signature`: ../appendices.html#checking-for-a-signature
|
||||
.. _`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
|
||||
.. _`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