mirror of
https://github.com/matrix-org/matrix-spec
synced 2026-01-01 05:28:38 +01:00
Merge branch 'master' into travis/1.0/event-ids
This commit is contained in:
commit
f047e235df
|
|
@ -163,6 +163,14 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
id_server:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The identity server to unbind from. If not provided, the homeserver
|
||||||
|
MUST use the ``id_server`` the identifier was added through. If the
|
||||||
|
homeserver does not know the original ``id_server``, it MUST return
|
||||||
|
a ``id_server_unbind_result`` of ``no-support``.
|
||||||
|
example: "example.org"
|
||||||
medium:
|
medium:
|
||||||
type: string
|
type: string
|
||||||
description: The medium of the third party identifier being removed.
|
description: The medium of the third party identifier being removed.
|
||||||
|
|
@ -180,7 +188,24 @@ paths:
|
||||||
user.
|
user.
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties: {}
|
properties:
|
||||||
|
id_server_unbind_result:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
# XXX: I don't know why, but the order matters here so that "no-support"
|
||||||
|
# doesn't become "no- support" by the renderer.
|
||||||
|
- "no-support"
|
||||||
|
- "success"
|
||||||
|
description: |-
|
||||||
|
An indicator as to whether or not the homeserver was able to unbind
|
||||||
|
the 3PID from the identity server. ``success`` indicates that the
|
||||||
|
indentity server has unbound the identifier whereas ``no-support``
|
||||||
|
indicates that the identity server refuses to support the request
|
||||||
|
or the homeserver was not able to determine an identity server to
|
||||||
|
unbind from.
|
||||||
|
example: "success"
|
||||||
|
required:
|
||||||
|
- id_server_unbind_result
|
||||||
tags:
|
tags:
|
||||||
- User data
|
- User data
|
||||||
"/account/3pid/email/requestToken":
|
"/account/3pid/email/requestToken":
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,8 @@ paths:
|
||||||
post:
|
post:
|
||||||
summary: Register for an account on this homeserver.
|
summary: Register for an account on this homeserver.
|
||||||
description: |-
|
description: |-
|
||||||
This API endpoint uses the `User-Interactive Authentication API`_.
|
This API endpoint uses the `User-Interactive Authentication API`_, except in
|
||||||
|
the cases where a guest account is being registered.
|
||||||
|
|
||||||
Register for an account on this homeserver.
|
Register for an account on this homeserver.
|
||||||
|
|
||||||
|
|
@ -60,6 +61,11 @@ paths:
|
||||||
invalidate any access token previously associated with that device. See
|
invalidate any access token previously associated with that device. See
|
||||||
`Relationship between access tokens and devices`_.
|
`Relationship between access tokens and devices`_.
|
||||||
|
|
||||||
|
When registering a guest account, all parameters in the request body
|
||||||
|
with the exception of ``initial_device_display_name`` MUST BE ignored
|
||||||
|
by the server. The server MUST pick a ``device_id`` for the account
|
||||||
|
regardless of input.
|
||||||
|
|
||||||
Any user ID returned by this API must conform to the grammar given in the
|
Any user ID returned by this API must conform to the grammar given in the
|
||||||
`Matrix specification <../appendices.html#user-identifiers>`_.
|
`Matrix specification <../appendices.html#user-identifiers>`_.
|
||||||
operationId: register
|
operationId: register
|
||||||
|
|
@ -75,7 +81,7 @@ paths:
|
||||||
enum:
|
enum:
|
||||||
- guest
|
- guest
|
||||||
- user
|
- user
|
||||||
description: The kind of account to register. Defaults to `user`.
|
description: The kind of account to register. Defaults to ``user``.
|
||||||
- in: body
|
- in: body
|
||||||
name: body
|
name: body
|
||||||
schema:
|
schema:
|
||||||
|
|
@ -83,13 +89,11 @@ paths:
|
||||||
properties:
|
properties:
|
||||||
auth:
|
auth:
|
||||||
description: |-
|
description: |-
|
||||||
Additional authentication information for the
|
Additional authentication information for the
|
||||||
user-interactive authentication API. Note that this
|
user-interactive authentication API. Note that this
|
||||||
information is *not* used to define how the registered user
|
information is *not* used to define how the registered user
|
||||||
should be authenticated, but is instead used to
|
should be authenticated, but is instead used to
|
||||||
authenticate the ``register`` call itself. It should be
|
authenticate the ``register`` call itself.
|
||||||
left empty, or omitted, unless an earlier call returned an
|
|
||||||
response with status code 401.
|
|
||||||
"$ref": "definitions/auth_data.yaml"
|
"$ref": "definitions/auth_data.yaml"
|
||||||
bind_email:
|
bind_email:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
@ -97,6 +101,12 @@ paths:
|
||||||
If true, the server binds the email used for authentication to
|
If true, the server binds the email used for authentication to
|
||||||
the Matrix ID with the identity server.
|
the Matrix ID with the identity server.
|
||||||
example: false
|
example: false
|
||||||
|
bind_msisdn:
|
||||||
|
type: boolean
|
||||||
|
description: |-
|
||||||
|
If true, the server binds the phone number used for authentication
|
||||||
|
to the Matrix ID with the identity server.
|
||||||
|
example: false
|
||||||
username:
|
username:
|
||||||
type: string
|
type: string
|
||||||
description: |-
|
description: |-
|
||||||
|
|
@ -197,6 +207,18 @@ paths:
|
||||||
The homeserver requires additional authentication information.
|
The homeserver requires additional authentication information.
|
||||||
schema:
|
schema:
|
||||||
"$ref": "definitions/auth_response.yaml"
|
"$ref": "definitions/auth_response.yaml"
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The homeserver does not permit registering the account. This response
|
||||||
|
can be used to identify that a particular ``kind`` of account is not
|
||||||
|
allowed, or that registration is generally not supported by the homeserver.
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "Registration is disabled"
|
||||||
|
}
|
||||||
|
schema:
|
||||||
|
"$ref": "definitions/errors/error.yaml"
|
||||||
429:
|
429:
|
||||||
description: This request was rate-limited.
|
description: This request was rate-limited.
|
||||||
schema:
|
schema:
|
||||||
|
|
@ -527,13 +549,39 @@ paths:
|
||||||
description: |-
|
description: |-
|
||||||
Additional authentication information for the user-interactive authentication API.
|
Additional authentication information for the user-interactive authentication API.
|
||||||
"$ref": "definitions/auth_data.yaml"
|
"$ref": "definitions/auth_data.yaml"
|
||||||
|
id_server:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The identity server to unbind all of the user's 3PIDs from.
|
||||||
|
If not provided, the homeserver MUST use the ``id_server``
|
||||||
|
that was originally use to bind each identifier. If the
|
||||||
|
homeserver does not know which ``id_server`` that was,
|
||||||
|
it must return an ``id_server_unbind_result`` of
|
||||||
|
``no-support``.
|
||||||
|
example: "example.org"
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: The account has been deactivated.
|
description: The account has been deactivated.
|
||||||
examples:
|
|
||||||
application/json: {}
|
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
properties:
|
||||||
|
id_server_unbind_result:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "success"
|
||||||
|
- "no-support"
|
||||||
|
description: |-
|
||||||
|
An indicator as to whether or not the homeserver was able to unbind
|
||||||
|
the user's 3PIDs from the identity server(s). ``success`` indicates
|
||||||
|
that all identifiers have been unbound from the identity server while
|
||||||
|
``no-support`` indicates that one or more identifiers failed to unbind
|
||||||
|
due to the identity server refusing the request or the homeserver
|
||||||
|
being unable to determine an identity server to unbind from. This
|
||||||
|
must be ``success`` if the homeserver has no identifiers to unbind
|
||||||
|
for the user.
|
||||||
|
example: "success"
|
||||||
|
required:
|
||||||
|
- id_server_unbind_result
|
||||||
401:
|
401:
|
||||||
description: |-
|
description: |-
|
||||||
The homeserver requires additional authentication information.
|
The homeserver requires additional authentication information.
|
||||||
|
|
|
||||||
|
|
@ -212,30 +212,7 @@ paths:
|
||||||
events:
|
events:
|
||||||
description: The StrippedState events that form the invite state.
|
description: The StrippedState events that form the invite state.
|
||||||
items:
|
items:
|
||||||
description: |-
|
$ref: "definitions/event-schemas/schema/stripped_state.yaml"
|
||||||
A stripped down state event, with only the ``type``, ``state_key``,
|
|
||||||
``sender``, and ``content`` keys.
|
|
||||||
properties:
|
|
||||||
content:
|
|
||||||
description: The ``content`` for the event.
|
|
||||||
title: EventContent
|
|
||||||
type: object
|
|
||||||
state_key:
|
|
||||||
description: The ``state_key`` for the event.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: The ``type`` for the event.
|
|
||||||
type: string
|
|
||||||
sender:
|
|
||||||
description: The ``sender`` for the event.
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- type
|
|
||||||
- state_key
|
|
||||||
- content
|
|
||||||
- sender
|
|
||||||
title: StrippedState
|
|
||||||
type: object
|
|
||||||
type: array
|
type: array
|
||||||
leave:
|
leave:
|
||||||
title: Left rooms
|
title: Left rooms
|
||||||
|
|
|
||||||
|
|
@ -201,3 +201,86 @@ paths:
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
$ref: "../client-server/definitions/errors/error.yaml"
|
$ref: "../client-server/definitions/errors/error.yaml"
|
||||||
|
"/3pid/unbind":
|
||||||
|
post:
|
||||||
|
summary: Remove an association between a session and a Matrix user ID.
|
||||||
|
description: |-
|
||||||
|
Remove an association between a session and a Matrix user ID.
|
||||||
|
|
||||||
|
Future calls to ``/lookup`` for any of the session's 3pids will not
|
||||||
|
return the removed association.
|
||||||
|
|
||||||
|
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`` parameters,
|
||||||
|
as per ``/3pid/bind``, which proves ownership of the 3PID.
|
||||||
|
|
||||||
|
If this endpoint returns a JSON Matrix error, that error should be passed
|
||||||
|
through to the client requesting an unbind through a homeserver, if the
|
||||||
|
homeserver is acting on behalf of a client.
|
||||||
|
operationId: unbind
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
example: {
|
||||||
|
"sid": "1234",
|
||||||
|
"client_secret": "monkeys_are_GREAT",
|
||||||
|
"mxid": "@ears:example.org",
|
||||||
|
"threepid": {
|
||||||
|
"medium": "email",
|
||||||
|
"address": "monkeys_have_ears@example.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
properties:
|
||||||
|
sid:
|
||||||
|
type: string
|
||||||
|
description: The Session ID generated by the ``requestToken`` call.
|
||||||
|
client_secret:
|
||||||
|
type: string
|
||||||
|
description: The client secret passed to the ``requestToken`` call.
|
||||||
|
mxid:
|
||||||
|
type: string
|
||||||
|
description: The Matrix user ID to remove from the 3pids.
|
||||||
|
threepid:
|
||||||
|
type: object
|
||||||
|
title: 3PID
|
||||||
|
description: |-
|
||||||
|
The 3PID to remove. Must match the 3PID used to generate the session
|
||||||
|
if using ``sid`` and ``client_secret`` to authenticate this request.
|
||||||
|
properties:
|
||||||
|
medium:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
A medium from the `3PID Types`_ Appendix, matching the medium
|
||||||
|
of the identifier to unbind.
|
||||||
|
address:
|
||||||
|
type: string
|
||||||
|
description: The 3PID address to remove.
|
||||||
|
required: ['medium', 'address']
|
||||||
|
required: ["threepid", "mxid"]
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: The association was successfully removed.
|
||||||
|
examples:
|
||||||
|
application/json: {}
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
400:
|
||||||
|
description: |-
|
||||||
|
If the response body is not a JSON Matrix error, the identity server
|
||||||
|
does not support unbinds. If a JSON Matrix error is in the response
|
||||||
|
body, the requesting party should respect the error.
|
||||||
|
404:
|
||||||
|
description: |-
|
||||||
|
If the response body is not a JSON Matrix error, the identity server
|
||||||
|
does not support unbinds. If a JSON Matrix error is in the response
|
||||||
|
body, the requesting party should respect the error.
|
||||||
|
501:
|
||||||
|
description: |-
|
||||||
|
If the response body is not a JSON Matrix error, the identity server
|
||||||
|
does not support unbinds. If a JSON Matrix error is in the response
|
||||||
|
body, the requesting party should respect the error.
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ paths:
|
||||||
A transaction containing the PDUs that preceded the given event(s), including the given
|
A transaction containing the PDUs that preceded the given event(s), including the given
|
||||||
event(s), up to the given limit.
|
event(s), up to the given limit.
|
||||||
schema:
|
schema:
|
||||||
$ref: "definitions/transaction.yaml"
|
$ref: "definitions/unlimited_pdu_transaction.yaml"
|
||||||
"/get_missing_events/{roomId}":
|
"/get_missing_events/{roomId}":
|
||||||
post:
|
post:
|
||||||
summary: Retrieves events that the sender is missing
|
summary: Retrieves events that the sender is missing
|
||||||
|
|
|
||||||
32
api/server-server/definitions/single_pdu_transaction.yaml
Normal file
32
api/server-server/definitions/single_pdu_transaction.yaml
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
type: object
|
||||||
|
allOf:
|
||||||
|
- $ref: "transaction.yaml"
|
||||||
|
properties:
|
||||||
|
pdus:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
A single PDU. 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>`_ 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']
|
||||||
33
api/server-server/definitions/unlimited_pdu_transaction.yaml
Normal file
33
api/server-server/definitions/unlimited_pdu_transaction.yaml
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
type: object
|
||||||
|
allOf:
|
||||||
|
- $ref: "transaction.yaml"
|
||||||
|
properties:
|
||||||
|
pdus:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
List of persistent updates to rooms. 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>`_ 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']
|
||||||
|
|
@ -156,4 +156,4 @@ paths:
|
||||||
200:
|
200:
|
||||||
description: A transaction containing a single PDU which is the event requested.
|
description: A transaction containing a single PDU which is the event requested.
|
||||||
schema:
|
schema:
|
||||||
$ref: "definitions/transaction.yaml"
|
$ref: "definitions/single_pdu_transaction.yaml"
|
||||||
|
|
|
||||||
|
|
@ -82,35 +82,9 @@ paths:
|
||||||
identify the room. The recommended events to include are the join rules,
|
identify the room. The recommended events to include are the join rules,
|
||||||
canonical alias, avatar, and name of the room.
|
canonical alias, avatar, and name of the room.
|
||||||
items:
|
items:
|
||||||
type: object
|
$ref: "../../event-schemas/schema/stripped_state.yaml"
|
||||||
title: Invite Room State Event
|
example:
|
||||||
properties:
|
$ref: "../../event-schemas/examples/invite_room_state.json"
|
||||||
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
example: {
|
example: {
|
||||||
"$ref": "examples/minimal_pdu.json",
|
"$ref": "examples/minimal_pdu.json",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
|
|
@ -118,26 +92,6 @@ paths:
|
||||||
"origin": "example.org",
|
"origin": "example.org",
|
||||||
"origin_server_ts": 1549041175876,
|
"origin_server_ts": 1549041175876,
|
||||||
"sender": "@someone:example.org",
|
"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": {
|
"content": {
|
||||||
"membership": "invite"
|
"membership": "invite"
|
||||||
},
|
},
|
||||||
|
|
@ -180,24 +134,9 @@ paths:
|
||||||
"origin_server_ts": 1549041175876,
|
"origin_server_ts": 1549041175876,
|
||||||
"sender": "@someone:example.org",
|
"sender": "@someone:example.org",
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"invite_room_state": [
|
"invite_room_state": {
|
||||||
{
|
"$ref": "../../../event-schemas/examples/invite_room_state.json"
|
||||||
"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": {
|
"content": {
|
||||||
"membership": "invite"
|
"membership": "invite"
|
||||||
|
|
|
||||||
|
|
@ -83,35 +83,9 @@ paths:
|
||||||
identify the room. The recommended events to include are the join rules,
|
identify the room. The recommended events to include are the join rules,
|
||||||
canonical alias, avatar, and name of the room.
|
canonical alias, avatar, and name of the room.
|
||||||
items:
|
items:
|
||||||
type: object
|
$ref: "../../event-schemas/schema/stripped_state.yaml"
|
||||||
title: Invite Room State Event
|
example:
|
||||||
properties:
|
$ref: "../../event-schemas/examples/invite_room_state.json"
|
||||||
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']
|
required: ['room_version', 'event']
|
||||||
example: {
|
example: {
|
||||||
"room_version": "2",
|
"room_version": "2",
|
||||||
|
|
@ -130,25 +104,7 @@ paths:
|
||||||
"ed25519:key_version": "SomeSignatureHere"
|
"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:
|
responses:
|
||||||
200:
|
200:
|
||||||
|
|
@ -174,24 +130,9 @@ paths:
|
||||||
"origin_server_ts": 1549041175876,
|
"origin_server_ts": 1549041175876,
|
||||||
"sender": "@someone:example.org",
|
"sender": "@someone:example.org",
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"invite_room_state": [
|
"invite_room_state": {
|
||||||
{
|
"$ref": "../../../event-schemas/examples/invite_room_state.json"
|
||||||
"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": {
|
"content": {
|
||||||
"membership": "invite"
|
"membership": "invite"
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ paths:
|
||||||
`room version specification`_ for precise event formats. **The response body
|
`room version specification`_ for precise event formats. **The response body
|
||||||
here describes the common event fields in more detail and may be missing other
|
here describes the common event fields in more detail and may be missing other
|
||||||
required fields for a PDU.**
|
required fields for a PDU.**
|
||||||
schema:
|
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ paths:
|
||||||
servers:
|
servers:
|
||||||
type: array
|
type: array
|
||||||
description: |-
|
description: |-
|
||||||
An array of server names that are likely to hold the given room. This
|
An array of server names that are likely to hold the given room. This
|
||||||
list may or may not include the server answering the query.
|
list may or may not include the server answering the query.
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -128,7 +128,7 @@ paths:
|
||||||
x-example: "@someone:example.org"
|
x-example: "@someone:example.org"
|
||||||
- in: query
|
- in: query
|
||||||
name: field
|
name: field
|
||||||
type: enum
|
type: string
|
||||||
enum: ['displayname', 'avatar_url']
|
enum: ['displayname', 'avatar_url']
|
||||||
description: |-
|
description: |-
|
||||||
The field to query. If specified, the server will only return the given field
|
The field to query. If specified, the server will only return the given field
|
||||||
|
|
@ -139,7 +139,7 @@ paths:
|
||||||
description: |-
|
description: |-
|
||||||
The profile for the user. If a ``field`` is specified in the request, only the
|
The profile for the user. If a ``field`` is specified in the request, only the
|
||||||
matching field should be included in the response. If no ``field`` was specified,
|
matching field should be included in the response. If no ``field`` was specified,
|
||||||
the response should include the fields of the user's profile that can be made
|
the response should include the fields of the user's profile that can be made
|
||||||
public, such as the display name and avatar.
|
public, such as the display name and avatar.
|
||||||
|
|
||||||
If the user does not have a particular field set on their profile, the server
|
If the user does not have a particular field set on their profile, the server
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ paths:
|
||||||
description: |-
|
description: |-
|
||||||
The user ID to retrieve devices for. Must be a user local to the
|
The user ID to retrieve devices for. Must be a user local to the
|
||||||
receiving homeserver.
|
receiving homeserver.
|
||||||
required: true
|
|
||||||
x-example: "@alice:example.org"
|
x-example: "@alice:example.org"
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
|
|
@ -82,4 +81,4 @@ paths:
|
||||||
description: Optional display name for the device.
|
description: Optional display name for the device.
|
||||||
example: "Alice's Mobile Phone"
|
example: "Alice's Mobile Phone"
|
||||||
required: ['device_id', 'keys']
|
required: ['device_id', 'keys']
|
||||||
required: ['user_id', 'stream_id', 'devices']
|
required: ['user_id', 'stream_id', 'devices']
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ paths:
|
||||||
get:
|
get:
|
||||||
summary: Get the implementation name and version of this homeserver.
|
summary: Get the implementation name and version of this homeserver.
|
||||||
description: Get the implementation name and version of this homeserver.
|
description: Get the implementation name and version of this homeserver.
|
||||||
|
operationId: getVersion
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ paths:
|
||||||
Gets information about the delegated server for server-server communication
|
Gets information about the delegated server for server-server communication
|
||||||
between Matrix homeservers. Servers should follow 30x redirects, carefully
|
between Matrix homeservers. Servers should follow 30x redirects, carefully
|
||||||
avoiding redirect loops, and use normal X.509 certificate validation.
|
avoiding redirect loops, and use normal X.509 certificate validation.
|
||||||
|
operationId: getWellKnown
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
1
changelogs/client_server/newsfragments/2030.feature
Normal file
1
changelogs/client_server/newsfragments/2030.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add MSISDN (phone number) support to User-Interactive Authentication.
|
||||||
1
changelogs/client_server/newsfragments/2046.feature
Normal file
1
changelogs/client_server/newsfragments/2046.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add ``id_server`` to ``/deactivate`` and ``/3pid/delete`` endpoints to unbind from a specific identity server.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify that User-Interactive Authentication stages cannot be attempted more than once.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify which parameters apply in what scenarios on ``/register``.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify exactly what invite_room_state consists of.
|
||||||
1
changelogs/client_server/newsfragments/2072.feature
Normal file
1
changelogs/client_server/newsfragments/2072.feature
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add interactive device verification, including a common framework for device verification.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify when and where CORS headers should be returned.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify when authorization and rate-limiting are not applicable.
|
||||||
1
changelogs/identity_service/newsfragments/2046.new
Normal file
1
changelogs/identity_service/newsfragments/2046.new
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Add ``/3pid/unbind`` for removing 3PIDs.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify that the default transport is JSON over HTTP.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify exactly what invite_room_state consists of.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify which servers are supposed to sign events.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Clarify how many PDUs are contained in transaction objects for various endpoints.
|
||||||
66
data-definitions/sas-emoji.json
Normal file
66
data-definitions/sas-emoji.json
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
[
|
||||||
|
{"number": 0, "emoji": "🐶", "description": "Dog", "unicode": "U+1F436"},
|
||||||
|
{"number": 1, "emoji": "🐱", "description": "Cat", "unicode": "U+1F431"},
|
||||||
|
{"number": 2, "emoji": "🦁", "description": "Lion", "unicode": "U+1F981"},
|
||||||
|
{"number": 3, "emoji": "🐎", "description": "Horse", "unicode": "U+1F40E"},
|
||||||
|
{"number": 4, "emoji": "🦄", "description": "Unicorn", "unicode": "U+1F984"},
|
||||||
|
{"number": 5, "emoji": "🐷", "description": "Pig", "unicode": "U+1F437"},
|
||||||
|
{"number": 6, "emoji": "🐘", "description": "Elephant", "unicode": "U+1F418"},
|
||||||
|
{"number": 7, "emoji": "🐰", "description": "Rabbit", "unicode": "U+1F430"},
|
||||||
|
{"number": 8, "emoji": "🐼", "description": "Panda", "unicode": "U+1F43C"},
|
||||||
|
{"number": 9, "emoji": "🐓", "description": "Rooster", "unicode": "U+1F413"},
|
||||||
|
{"number": 10, "emoji": "🐧", "description": "Penguin", "unicode": "U+1F427"},
|
||||||
|
{"number": 11, "emoji": "🐢", "description": "Turtle", "unicode": "U+1F422"},
|
||||||
|
{"number": 12, "emoji": "🐟", "description": "Fish", "unicode": "U+1F41F"},
|
||||||
|
{"number": 13, "emoji": "🐙", "description": "Octopus", "unicode": "U+1F419"},
|
||||||
|
{"number": 14, "emoji": "🦋", "description": "Butterfly", "unicode": "U+1F98B"},
|
||||||
|
{"number": 15, "emoji": "🌷", "description": "Flower", "unicode": "U+1F337"},
|
||||||
|
{"number": 16, "emoji": "🌳", "description": "Tree", "unicode": "U+1F333"},
|
||||||
|
{"number": 17, "emoji": "🌵", "description": "Cactus", "unicode": "U+1F335"},
|
||||||
|
{"number": 18, "emoji": "🍄", "description": "Mushroom", "unicode": "U+1F344"},
|
||||||
|
{"number": 19, "emoji": "🌏", "description": "Globe", "unicode": "U+1F30F"},
|
||||||
|
{"number": 20, "emoji": "🌙", "description": "Moon", "unicode": "U+1F319"},
|
||||||
|
{"number": 21, "emoji": "☁️", "description": "Cloud", "unicode": "U+2601U+FE0F"},
|
||||||
|
{"number": 22, "emoji": "🔥", "description": "Fire", "unicode": "U+1F525"},
|
||||||
|
{"number": 23, "emoji": "🍌", "description": "Banana", "unicode": "U+1F34C"},
|
||||||
|
{"number": 24, "emoji": "🍎", "description": "Apple", "unicode": "U+1F34E"},
|
||||||
|
{"number": 25, "emoji": "🍓", "description": "Strawberry", "unicode": "U+1F353"},
|
||||||
|
{"number": 26, "emoji": "🌽", "description": "Corn", "unicode": "U+1F33D"},
|
||||||
|
{"number": 27, "emoji": "🍕", "description": "Pizza", "unicode": "U+1F355"},
|
||||||
|
{"number": 28, "emoji": "🎂", "description": "Cake", "unicode": "U+1F382"},
|
||||||
|
{"number": 29, "emoji": "❤️", "description": "Heart", "unicode": "U+2764U+FE0F"},
|
||||||
|
{"number": 30, "emoji": "😀", "description": "Smiley", "unicode": "U+1F600"},
|
||||||
|
{"number": 31, "emoji": "🤖", "description": "Robot", "unicode": "U+1F916"},
|
||||||
|
{"number": 32, "emoji": "🎩", "description": "Hat", "unicode": "U+1F3A9"},
|
||||||
|
{"number": 33, "emoji": "👓", "description": "Glasses", "unicode": "U+1F453"},
|
||||||
|
{"number": 34, "emoji": "🔧", "description": "Spanner", "unicode": "U+1F527"},
|
||||||
|
{"number": 35, "emoji": "🎅", "description": "Santa", "unicode": "U+1F385"},
|
||||||
|
{"number": 36, "emoji": "👍", "description": "Thumbs Up", "unicode": "U+1F44D"},
|
||||||
|
{"number": 37, "emoji": "☂️", "description": "Umbrella", "unicode": "U+2602U+FE0F"},
|
||||||
|
{"number": 38, "emoji": "⌛", "description": "Hourglass", "unicode": "U+231B"},
|
||||||
|
{"number": 39, "emoji": "⏰", "description": "Clock", "unicode": "U+23F0"},
|
||||||
|
{"number": 40, "emoji": "🎁", "description": "Gift", "unicode": "U+1F381"},
|
||||||
|
{"number": 41, "emoji": "💡", "description": "Light Bulb", "unicode": "U+1F4A1"},
|
||||||
|
{"number": 42, "emoji": "📕", "description": "Book", "unicode": "U+1F4D5"},
|
||||||
|
{"number": 43, "emoji": "✏️", "description": "Pencil", "unicode": "U+270FU+FE0F"},
|
||||||
|
{"number": 44, "emoji": "📎", "description": "Paperclip", "unicode": "U+1F4CE"},
|
||||||
|
{"number": 45, "emoji": "✂️", "description": "Scissors", "unicode": "U+2702U+FE0F"},
|
||||||
|
{"number": 46, "emoji": "🔒", "description": "Lock", "unicode": "U+1F512"},
|
||||||
|
{"number": 47, "emoji": "🔑", "description": "Key", "unicode": "U+1F511"},
|
||||||
|
{"number": 48, "emoji": "🔨", "description": "Hammer", "unicode": "U+1F528"},
|
||||||
|
{"number": 49, "emoji": "☎️", "description": "Telephone", "unicode": "U+260EU+FE0F"},
|
||||||
|
{"number": 50, "emoji": "🏁", "description": "Flag", "unicode": "U+1F3C1"},
|
||||||
|
{"number": 51, "emoji": "🚂", "description": "Train", "unicode": "U+1F682"},
|
||||||
|
{"number": 52, "emoji": "🚲", "description": "Bicycle", "unicode": "U+1F6B2"},
|
||||||
|
{"number": 53, "emoji": "✈️", "description": "Aeroplane", "unicode": "U+2708U+FE0F"},
|
||||||
|
{"number": 54, "emoji": "🚀", "description": "Rocket", "unicode": "U+1F680"},
|
||||||
|
{"number": 55, "emoji": "🏆", "description": "Trophy", "unicode": "U+1F3C6"},
|
||||||
|
{"number": 56, "emoji": "⚽", "description": "Ball", "unicode": "U+26BD"},
|
||||||
|
{"number": 57, "emoji": "🎸", "description": "Guitar", "unicode": "U+1F3B8"},
|
||||||
|
{"number": 58, "emoji": "🎺", "description": "Trumpet", "unicode": "U+1F3BA"},
|
||||||
|
{"number": 59, "emoji": "🔔", "description": "Bell", "unicode": "U+1F514"},
|
||||||
|
{"number": 60, "emoji": "⚓", "description": "Anchor", "unicode": "U+2693"},
|
||||||
|
{"number": 61, "emoji": "🎧", "description": "Headphones", "unicode": "U+1F3A7"},
|
||||||
|
{"number": 62, "emoji": "📁", "description": "Folder", "unicode": "U+1F4C1"},
|
||||||
|
{"number": 63, "emoji": "📌", "description": "Pin", "unicode": "U+1F4CC"}
|
||||||
|
]
|
||||||
|
|
@ -106,6 +106,9 @@ def check_example_dir(exampledir, schemadir):
|
||||||
if filename.startswith("."):
|
if filename.startswith("."):
|
||||||
# Skip over any vim .swp files.
|
# Skip over any vim .swp files.
|
||||||
continue
|
continue
|
||||||
|
if filename.endswith(".json"):
|
||||||
|
# Skip over any explicit examples (partial event definitions)
|
||||||
|
continue
|
||||||
cwd = os.path.basename(os.path.dirname(os.path.join(root, filename)))
|
cwd = os.path.basename(os.path.dirname(os.path.join(root, filename)))
|
||||||
if cwd == "core":
|
if cwd == "core":
|
||||||
# Skip checking the underlying definitions
|
# Skip checking the underlying definitions
|
||||||
|
|
|
||||||
18
event-schemas/examples/invite_room_state.json
Normal file
18
event-schemas/examples/invite_room_state.json
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "m.room.name",
|
||||||
|
"sender": "@bob:example.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"name": "Example Room"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "m.room.join_rules",
|
||||||
|
"sender": "@bob:example.org",
|
||||||
|
"state_key": "",
|
||||||
|
"content": {
|
||||||
|
"join_rule": "invite"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
12
event-schemas/examples/m.key.verification.accept
Normal file
12
event-schemas/examples/m.key.verification.accept
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.accept",
|
||||||
|
"content": {
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"method": "m.sas.v1",
|
||||||
|
"key_agreement_protocol": "curve25519",
|
||||||
|
"hash": "sha256",
|
||||||
|
"message_authentication_code": "hkdf-hmac-sha256",
|
||||||
|
"short_authentication_string": ["decimal", "emoji"],
|
||||||
|
"commitment": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
event-schemas/examples/m.key.verification.cancel
Normal file
8
event-schemas/examples/m.key.verification.cancel
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.cancel",
|
||||||
|
"content": {
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"code": "m.user",
|
||||||
|
"reason": "User rejected the key verification request"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
event-schemas/examples/m.key.verification.key
Normal file
7
event-schemas/examples/m.key.verification.key
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.key",
|
||||||
|
"content": {
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"key": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
event-schemas/examples/m.key.verification.mac
Normal file
10
event-schemas/examples/m.key.verification.mac
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.mac",
|
||||||
|
"content": {
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"keys": "2Wptgo4CwmLo/Y8B8qinxApKaCkBG2fjTWB7AbP5Uy+aIbygsSdLOFzvdDjww8zUVKCmI02eP9xtyJxc/cLiBA",
|
||||||
|
"mac": {
|
||||||
|
"ed25519:ABCDEF": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
event-schemas/examples/m.key.verification.request
Normal file
11
event-schemas/examples/m.key.verification.request
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.request",
|
||||||
|
"content": {
|
||||||
|
"from_device": "AliceDevice2",
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"methods": [
|
||||||
|
"m.sas.v1"
|
||||||
|
],
|
||||||
|
"timestamp": 1559598944869
|
||||||
|
}
|
||||||
|
}
|
||||||
8
event-schemas/examples/m.key.verification.start
Normal file
8
event-schemas/examples/m.key.verification.start
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.start",
|
||||||
|
"content": {
|
||||||
|
"from_device": "BobDevice1",
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"method": "m.sas.v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
12
event-schemas/examples/m.key.verification.start$m.sas.v1
Normal file
12
event-schemas/examples/m.key.verification.start$m.sas.v1
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"type": "m.key.verification.start",
|
||||||
|
"content": {
|
||||||
|
"from_device": "BobDevice1",
|
||||||
|
"transaction_id": "S0meUniqueAndOpaqueString",
|
||||||
|
"method": "m.sas.v1",
|
||||||
|
"key_agreement_protocols": ["curve25519"],
|
||||||
|
"hashes": ["sha256"],
|
||||||
|
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
||||||
|
"short_authentication_string": ["decimal", "emoji"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,21 +7,8 @@
|
||||||
},
|
},
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"age": 1234,
|
"age": 1234,
|
||||||
"invite_room_state": [
|
"invite_room_state": {
|
||||||
{
|
"$ref": "invite_room_state.json"
|
||||||
"type": "m.room.name",
|
}
|
||||||
"state_key": "",
|
|
||||||
"content": {
|
|
||||||
"name": "Forest of Magic"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "m.room.join_rules",
|
|
||||||
"state_key": "",
|
|
||||||
"content": {
|
|
||||||
"join_rule": "invite"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
event-schemas/schema/m.key.verification.accept
Normal file
64
event-schemas/schema/m.key.verification.accept
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Accepts a previously sent ``m.key.verification.start`` messge. Typically sent as a
|
||||||
|
`to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
An opaque identifier for the verification process. Must be the same as
|
||||||
|
the one used for the ``m.key.verification.start`` message.
|
||||||
|
method:
|
||||||
|
type: string
|
||||||
|
enum: ["m.sas.v1"]
|
||||||
|
description: |-
|
||||||
|
The verification method to use.
|
||||||
|
key_agreement_protocol:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The key agreement protocol the device is choosing to use, out of the
|
||||||
|
options in the ``m.key.verification.start`` message.
|
||||||
|
hash:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The hash method the device is choosing to use, out of the options in
|
||||||
|
the ``m.key.verification.start`` message.
|
||||||
|
message_authentication_code:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The message authentication code the device is choosing to use, out of
|
||||||
|
the options in the ``m.key.verification.start`` message.
|
||||||
|
short_authentication_string:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The SAS methods both devices involved in the verification process
|
||||||
|
understand. Must be a subset of the options in the ``m.key.verification.start``
|
||||||
|
message.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
enum: ["decimal", "emoji"]
|
||||||
|
commitment:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The hash (encoded as unpadded base64) of the concatenation of the device's
|
||||||
|
ephemeral public key (encoded as unpadded base64) and the canonical JSON
|
||||||
|
representation of the ``m.key.verification.start`` message.
|
||||||
|
required:
|
||||||
|
- transaction_id
|
||||||
|
- method
|
||||||
|
- key_agreement_protocol
|
||||||
|
- hash
|
||||||
|
- message_authentication_code
|
||||||
|
- short_authentication_string
|
||||||
|
- commitment
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.accept
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
70
event-schemas/schema/m.key.verification.cancel
Normal file
70
event-schemas/schema/m.key.verification.cancel
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Cancels a key verification process/request. Typically sent as a `to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The opaque identifier for the verification process/request.
|
||||||
|
reason:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
A human readable description of the ``code``. The client should only rely on this
|
||||||
|
string if it does not understand the ``code``.
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
# Note: this is not an enum because we go into detail about the different
|
||||||
|
# error codes. If we made this an enum, we'd be repeating information.
|
||||||
|
# Also, we can't put a real bulleted list in here because the HTML2RST parser
|
||||||
|
# cuts the text at weird points, breaking the list completely.
|
||||||
|
description: |-
|
||||||
|
The error code for why the process/request was cancelled by the user. Error
|
||||||
|
codes should use the Java package naming convention if not in the following
|
||||||
|
list:
|
||||||
|
|
||||||
|
``m.user``: The user cancelled the verification.
|
||||||
|
|
||||||
|
``m.timeout``: The verification process timed out. Verification processes
|
||||||
|
can define their own timeout parameters.
|
||||||
|
|
||||||
|
``m.unknown_transaction``: The device does not know about the given transaction
|
||||||
|
ID.
|
||||||
|
|
||||||
|
``m.unknown_method``: The device does not know how to handle the requested
|
||||||
|
method. This should be sent for ``m.key.verification.start`` messages and
|
||||||
|
messages defined by individual verification processes.
|
||||||
|
|
||||||
|
``m.unexpected_message``: The device received an unexpected message. Typically
|
||||||
|
raised when one of the parties is handling the verification out of order.
|
||||||
|
|
||||||
|
``m.key_mismatch``: The key was not verified.
|
||||||
|
|
||||||
|
``m.user_mismatch``: The expected user did not match the user verified.
|
||||||
|
|
||||||
|
``m.invalid_message``: The message received was invalid.
|
||||||
|
|
||||||
|
``m.accepted``: A ``m.key.verification.request`` was accepted by a different
|
||||||
|
device. The device receiving this error can ignore the verification request.
|
||||||
|
|
||||||
|
Clients should be careful to avoid error loops. For example, if a device sends
|
||||||
|
an incorrect message and the client returns ``m.invalid_message`` to which it
|
||||||
|
gets an unexpected response with ``m.unexpected_message``, the client should not
|
||||||
|
respond again with ``m.unexpected_message`` to avoid the other device potentially
|
||||||
|
sending another error response.
|
||||||
|
|
||||||
|
.. The above blank line is important for RST.
|
||||||
|
required:
|
||||||
|
- transaction_id
|
||||||
|
- code
|
||||||
|
- reason
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.cancel
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
28
event-schemas/schema/m.key.verification.key
Normal file
28
event-schemas/schema/m.key.verification.key
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Sends the ephemeral public key for a device to the partner device. Typically sent as a
|
||||||
|
`to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
An opaque identifier for the verification process. Must be the same as
|
||||||
|
the one used for the ``m.key.verification.start`` message.
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The device's ephemeral public key, encoded as unpadded base64.
|
||||||
|
required:
|
||||||
|
- transaction_id
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.key
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
38
event-schemas/schema/m.key.verification.mac
Normal file
38
event-schemas/schema/m.key.verification.mac
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Sends the MAC of a device's key to the partner device. Typically sent as a
|
||||||
|
`to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
An opaque identifier for the verification process. Must be the same as
|
||||||
|
the one used for the ``m.key.verification.start`` message.
|
||||||
|
mac:
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
A map of the key ID to the MAC of the key, using the algorithm in the
|
||||||
|
verification process. The MAC is encoded as unpadded base64.
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: The key's MAC, encoded as unpadded base64.
|
||||||
|
keys:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The MAC of the comma-separated, sorted, list of key IDs given in the ``mac``
|
||||||
|
property, encoded as unpadded base64.
|
||||||
|
required:
|
||||||
|
- transaction_id
|
||||||
|
- mac
|
||||||
|
- keys
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.mac
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
43
event-schemas/schema/m.key.verification.request
Normal file
43
event-schemas/schema/m.key.verification.request
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Requests a key verification with another user's devices. Typically sent as a
|
||||||
|
`to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
from_device:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The device ID which is initiating the request.
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
An opaque identifier for the verification request. Must be unique
|
||||||
|
with respect to the devices involved.
|
||||||
|
methods:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The verification methods supported by the sender.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
description: |-
|
||||||
|
The POSIX timestamp in milliseconds for when the request was made. If
|
||||||
|
the request is in the future by more than 5 minutes or more than 10
|
||||||
|
minutes in the past, the message should be ignored by the receiver.
|
||||||
|
required:
|
||||||
|
- from_device
|
||||||
|
- transaction_id
|
||||||
|
- methods
|
||||||
|
- timestamp
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.request
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
39
event-schemas/schema/m.key.verification.start
Normal file
39
event-schemas/schema/m.key.verification.start
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Begins a key verification process. Typically sent as a `to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
from_device:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The device ID which is initiating the process.
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
An opaque identifier for the verification process. Must be unique
|
||||||
|
with respect to the devices involved. Must be the same as the
|
||||||
|
``transaction_id`` given in the ``m.key.verification.request``
|
||||||
|
if this process is originating from a request.
|
||||||
|
method:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The verification method to use.
|
||||||
|
next_method:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
Optional method to use to verify the other user's key with. Applicable
|
||||||
|
when the ``method`` chosen only verifies one user's key.
|
||||||
|
required:
|
||||||
|
- from_device
|
||||||
|
- transaction_id
|
||||||
|
- method
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.start
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
69
event-schemas/schema/m.key.verification.start$m.sas.v1
Normal file
69
event-schemas/schema/m.key.verification.start$m.sas.v1
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
Begins a SAS key verification process. Typically sent as a `to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
from_device:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The device ID which is initiating the process.
|
||||||
|
transaction_id:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
An opaque identifier for the verification process. Must be unique
|
||||||
|
with respect to the devices involved. Must be the same as the
|
||||||
|
``transaction_id`` given in the ``m.key.verification.request``
|
||||||
|
if this process is originating from a request.
|
||||||
|
method:
|
||||||
|
type: string
|
||||||
|
enum: ["m.sas.v1"]
|
||||||
|
description: |-
|
||||||
|
The verification method to use. Must be ``m.sas.v1``.
|
||||||
|
key_agreement_protocols:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The key agreement protocols the sending device understands. Must
|
||||||
|
include at least ``curve25519``.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
hashes:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The hash methods the sending device understands. Must include at least
|
||||||
|
``sha256``.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
message_authentication_codes:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The message authentication codes that the sending device understands.
|
||||||
|
Must include at least ``hkdf-hmac-sha256``.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
short_authentication_string:
|
||||||
|
type: array
|
||||||
|
description: |-
|
||||||
|
The SAS methods the sending device (and the sending device's user)
|
||||||
|
understands. Must include at least ``decimal``. Optionally can include
|
||||||
|
``emoji``.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
enum: ["decimal", "emoji"]
|
||||||
|
required:
|
||||||
|
- from_device
|
||||||
|
- transaction_id
|
||||||
|
- method
|
||||||
|
- key_agreement_protocols
|
||||||
|
- hashes
|
||||||
|
- message_authentication_codes
|
||||||
|
- short_authentication_string
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.key.verification.start
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
|
@ -104,24 +104,7 @@ properties:
|
||||||
invite_room_state:
|
invite_room_state:
|
||||||
description: 'A subset of the state of the room at the time of the invite, if ``membership`` is ``invite``. Note that this state is informational, and SHOULD NOT be trusted; once the client has joined the room, it SHOULD fetch the live state from the server and discard the invite_room_state. Also, clients must not rely on any particular state being present here; they SHOULD behave properly (with possibly a degraded but not a broken experience) in the absence of any particular events here. If they are set on the room, at least the state for ``m.room.avatar``, ``m.room.canonical_alias``, ``m.room.join_rules``, and ``m.room.name`` SHOULD be included.'
|
description: 'A subset of the state of the room at the time of the invite, if ``membership`` is ``invite``. Note that this state is informational, and SHOULD NOT be trusted; once the client has joined the room, it SHOULD fetch the live state from the server and discard the invite_room_state. Also, clients must not rely on any particular state being present here; they SHOULD behave properly (with possibly a degraded but not a broken experience) in the absence of any particular events here. If they are set on the room, at least the state for ``m.room.avatar``, ``m.room.canonical_alias``, ``m.room.join_rules``, and ``m.room.name`` SHOULD be included.'
|
||||||
items:
|
items:
|
||||||
description: 'A stripped down state event, with only the ``type``, ``state_key`` and ``content`` keys.'
|
$ref: "stripped_state.yaml"
|
||||||
properties:
|
|
||||||
content:
|
|
||||||
description: The ``content`` for the event.
|
|
||||||
title: EventContent
|
|
||||||
type: object
|
|
||||||
state_key:
|
|
||||||
description: The ``state_key`` for the event.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: The ``type`` for the event.
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- type
|
|
||||||
- state_key
|
|
||||||
- content
|
|
||||||
title: StrippedState
|
|
||||||
type: object
|
|
||||||
type: array
|
type: array
|
||||||
required:
|
required:
|
||||||
- membership
|
- membership
|
||||||
|
|
|
||||||
44
event-schemas/schema/stripped_state.yaml
Normal file
44
event-schemas/schema/stripped_state.yaml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Copyright 2019 The Matrix.org Foundation C.I.C.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Note: this, and the example, are in the `event-schemas` directory because
|
||||||
|
# the CS API uses a symlink. In order for the `m.room.member` event to
|
||||||
|
# reference this, we'd need to use relative pathing. The symlink makes this
|
||||||
|
# difficult because the schema would be at two different locations, with
|
||||||
|
# different relative pathing.
|
||||||
|
|
||||||
|
title: StrippedState
|
||||||
|
type: object
|
||||||
|
description: |-
|
||||||
|
A stripped down state event, with only the ``type``, ``state_key``,
|
||||||
|
``sender``, and ``content`` keys.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
description: The ``content`` for the event.
|
||||||
|
title: EventContent
|
||||||
|
type: object
|
||||||
|
state_key:
|
||||||
|
description: The ``state_key`` for the event.
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: The ``type`` for the event.
|
||||||
|
type: string
|
||||||
|
sender:
|
||||||
|
description: The ``sender`` for the event.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- type
|
||||||
|
- state_key
|
||||||
|
- content
|
||||||
|
- sender
|
||||||
457
proposals/1779-open-governance.md
Normal file
457
proposals/1779-open-governance.md
Normal file
|
|
@ -0,0 +1,457 @@
|
||||||
|
# Proposal for Open Governance of Matrix.org
|
||||||
|
|
||||||
|
This whole document is the proposed constitution proposal for Matrix.org, and
|
||||||
|
will form the basis of the first full Articles of Association (AoA) for [The
|
||||||
|
Matrix.org Foundation
|
||||||
|
C.I.C.](https://beta.companieshouse.gov.uk/company/11648710) - a non-profit
|
||||||
|
legal entity incorporated to act as the neutral guardian of the Matrix
|
||||||
|
decentralised communication standard on behalf of the whole Matrix community.
|
||||||
|
|
||||||
|
See https://matrix.org/blog/2018/10/29/introducing-the-matrix-org-foundation-part-1-of-2/
|
||||||
|
for more context.
|
||||||
|
|
||||||
|
This obsoletes [MSC1318](https://github.com/matrix-org/matrix-doc/issues/1318).
|
||||||
|
|
||||||
|
**This MSC is now formalised in the official Rules of the Matrix.org Foundation,
|
||||||
|
maintained at https://docs.google.com/document/d/1MhqsuIUxPc7Vf_y8D250mKZlLeQS6E39DPY6Azpc2NY**
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Historically the core team of Matrix has been paid to work on it by the same
|
||||||
|
employer (currently New Vector; the startup incorporated to hire the core
|
||||||
|
team in Aug 2017). Whilst convenient in initially getting Matrix built, we
|
||||||
|
recognise that this could create a potential conflict of interest between the
|
||||||
|
core team’s responsibilities to neutrally support the wider Matrix.org ecosystem
|
||||||
|
versus the need for New Vector to be able to support the team, and it has always
|
||||||
|
been the plan to set up a completely neutral custodian for the standard once it
|
||||||
|
had reached sufficient maturity.
|
||||||
|
|
||||||
|
This proposal seeks to establish a new open governance process for Matrix.org,
|
||||||
|
such that once the specification has finally been ‘born’ and reached an initial
|
||||||
|
‘r0’ release across all APIs, control of Matrix.org can be decoupled from New
|
||||||
|
Vector and better support contributions from the whole ecosystem.
|
||||||
|
|
||||||
|
The concepts here are somewhat inspired by [Rust’s Governance
|
||||||
|
Model](https://github.com/rust-lang/rfcs/blob/master/text/1068-rust-governance.md);
|
||||||
|
a highly regarded solution to a similar problem: an ambitious
|
||||||
|
open-source project which has been too many years in the making, incubated at
|
||||||
|
first by a single company (Mozilla Corporation), which also enjoys a very
|
||||||
|
enthusiastic community!
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Governance of the project is split into two teams: the Spec Core Team and the
|
||||||
|
Guardians of the Foundation. In brief:
|
||||||
|
|
||||||
|
The Spec Core Team are the technical experts who curate and edit the Matrix
|
||||||
|
Specification from day to day, and so steer the evolution of the protocol by
|
||||||
|
having final review over which Matrix Spec Changes (MSCs) are merged into the
|
||||||
|
core spec.
|
||||||
|
|
||||||
|
The Guardians are the legal directors of the non-profit Foundation, and are
|
||||||
|
responsible for ensuring that the Foundation (and by extension the Spec Core
|
||||||
|
Team) keeps on mission and neutrally protects the development of Matrix.
|
||||||
|
Guardians are typically independent of the commercial Matrix ecosystem and may
|
||||||
|
even not be members of today’s Matrix community, but are deeply aligned with the
|
||||||
|
mission of the project. Guardians are selected to be respected and trusted by
|
||||||
|
the wider community to uphold the guiding principles of the Foundation and keep
|
||||||
|
the other Guardians honest.
|
||||||
|
|
||||||
|
In other words; the Spec Core Team builds the spec, and the Guardians provide an
|
||||||
|
independent backstop to ensure the spec evolves in line with the Foundation's
|
||||||
|
mission.
|
||||||
|
|
||||||
|
## Guiding Principles
|
||||||
|
|
||||||
|
The guiding principles define the core philosophy of the project, and will be a
|
||||||
|
formal part of the final Articles of Association of the Matrix.org Foundation.
|
||||||
|
|
||||||
|
### Matrix Manifesto
|
||||||
|
|
||||||
|
We believe:
|
||||||
|
|
||||||
|
* People should have full control over their own communication.
|
||||||
|
|
||||||
|
* People should not be locked into centralised communication silos, but instead
|
||||||
|
be free to pick who they choose to host their communication without limiting
|
||||||
|
who they can reach.
|
||||||
|
|
||||||
|
* The ability to converse securely and privately is a basic human right.
|
||||||
|
|
||||||
|
* Communication should be available to everyone as a free and open,
|
||||||
|
unencumbered, standard and global network.
|
||||||
|
|
||||||
|
### Mission
|
||||||
|
|
||||||
|
The Matrix.org Foundation exists to act as a neutral custodian for Matrix and to
|
||||||
|
nurture it as efficiently as possible as a single unfragmented standard, for the
|
||||||
|
greater benefit of the whole ecosystem, not benefiting or privileging any single
|
||||||
|
player or subset of players.
|
||||||
|
|
||||||
|
For clarity: the Matrix ecosystem is defined as anyone who uses the Matrix
|
||||||
|
protocol. This includes (non-exhaustively):
|
||||||
|
|
||||||
|
* End-users of Matrix clients.
|
||||||
|
* Matrix client developers and testers.
|
||||||
|
* Spec developers.
|
||||||
|
* Server admins.
|
||||||
|
* Matrix packagers & maintainers.
|
||||||
|
* Companies building products or services on Matrix.
|
||||||
|
* Bridge developers.
|
||||||
|
* Bot developers.
|
||||||
|
* Widget developers.
|
||||||
|
* Server developers.
|
||||||
|
* Matrix room and community moderators.
|
||||||
|
* End-users who are using Matrix indirectly via bridges.
|
||||||
|
* External systems which are bridged into Matrix.
|
||||||
|
* Anyone using Matrix for data communications.
|
||||||
|
|
||||||
|
"Greater benefit" is defined as maximising:
|
||||||
|
|
||||||
|
* the number of Matrix-native end-users reachable on the open Matrix network.
|
||||||
|
* the number of regular users on the Matrix network (e.g. 30-day retained federated users).
|
||||||
|
* the number of online servers in the open federation.
|
||||||
|
* the number of developers building on Matrix.
|
||||||
|
* the number of independent implementations which use Matrix.
|
||||||
|
* the number of bridged end-users reachable on the open Matrix network.
|
||||||
|
* the signal-to-noise ratio of the content on the open Matrix network (i.e. minimising spam).
|
||||||
|
* the ability for users to discover content on their terms (empowering them to select what to see and what not to see).
|
||||||
|
* the quality and utility of the Matrix spec (as defined by ease and ability
|
||||||
|
with which a developer can implement spec-compliant clients, servers, bots,
|
||||||
|
bridges, and other integrations without needing to refer to any other
|
||||||
|
external material).
|
||||||
|
|
||||||
|
N.B. that we consider success to be the growth of the open federated network
|
||||||
|
rather than closed deployments. For example, if WhatsApp adopted Matrix it
|
||||||
|
wouldn’t be a complete win unless they openly federated with the rest of the
|
||||||
|
Matrix network.
|
||||||
|
|
||||||
|
### Values
|
||||||
|
|
||||||
|
As Matrix evolves, it's critical that the Spec Core Team and Guardians are
|
||||||
|
aligned on the overall philosophy of the project, particularly in more
|
||||||
|
subjective areas. The values we follow are:
|
||||||
|
|
||||||
|
* Supporting the whole long-term ecosystem rather than individual stakeholder gain.
|
||||||
|
* Openness rather than proprietary lock-in.
|
||||||
|
* Interoperability rather than fragmentation.
|
||||||
|
* Cross-platform rather than platform-specific.
|
||||||
|
* Collaboration rather than competition.
|
||||||
|
* Accessibility rather than elitism.
|
||||||
|
* Transparency rather than stealth.
|
||||||
|
* Empathy rather than contrariness.
|
||||||
|
* Pragmatism rather than perfection.
|
||||||
|
* Proof rather than conjecture.
|
||||||
|
|
||||||
|
Patent encumbered IP is strictly prohibited from being added to the standard.
|
||||||
|
|
||||||
|
Making the specification rely on non-standard/unspecified behaviour of other
|
||||||
|
systems or actors (such as SaaS services, even open-sourced, not governed by a
|
||||||
|
standard protocol) shall not be accepted, either.
|
||||||
|
|
||||||
|
## The Spec Core Team
|
||||||
|
|
||||||
|
The contents and direction of the Matrix Spec is governed by the Spec Core Team;
|
||||||
|
a set of experts from across the whole Matrix community, representing all
|
||||||
|
aspects of the Matrix ecosystem. The Spec Core Team acts as a subcommittee of
|
||||||
|
the Foundation.
|
||||||
|
|
||||||
|
Members of the Spec Core Team pledge to act as a neutral custodian for Matrix on
|
||||||
|
behalf of the whole ecosystem and uphold the Guiding Principles of the project
|
||||||
|
as outlined above. In particular, they agree to drive the adoption of Matrix as
|
||||||
|
a single global federation, an open standard unencumbered from any proprietary
|
||||||
|
IP or software patents, minimising fragmentation (whilst encouraging
|
||||||
|
experimentation), evolving rapidly, and prioritising the long-term success and
|
||||||
|
growth of the overall network over individual commercial concerns.
|
||||||
|
|
||||||
|
Spec Core Team members need to have significant proven domain experience/skill
|
||||||
|
and have had clear dedication and commitment to the project and community for >6
|
||||||
|
months. (In future, once we have subteams a la Rust, folks need to have proven
|
||||||
|
themselves there first).
|
||||||
|
|
||||||
|
Members need to demonstrate ability to work constructively with the rest of the
|
||||||
|
team; we want participation in the Spec Core Team to be an efficient, pleasant and
|
||||||
|
productive place, even in the face of inevitable disagreement. We do not want a
|
||||||
|
toxic culture of bullying or competitive infighting. Folks need to be able to
|
||||||
|
compromise; we are not building a culture of folks pushing their personal
|
||||||
|
agendas at the expense of the overall project.
|
||||||
|
|
||||||
|
The team should be particularly vigilant against 'trojan horse' additions to the
|
||||||
|
spec - features which only benefit particular players, or are designed to
|
||||||
|
somehow cripple or fragment the open protocol and ecosystem in favour of
|
||||||
|
competitive advantage. Commercial players are of course free to build
|
||||||
|
proprietary implementations, or use custom event types, or even custom API
|
||||||
|
extensions (e.g. more efficient network transports) - but implementations must
|
||||||
|
fall back to interoperating correctly with the rest of the ecosystem.
|
||||||
|
|
||||||
|
### Spec Core Team logistics
|
||||||
|
|
||||||
|
The Spec Core Team itself will be made up of roughly 8 members + 1 project lead.
|
||||||
|
Roughly half the members are expected to be from the historical core team
|
||||||
|
(similar to Rust). The team must have 5 members to be able to function, with
|
||||||
|
the aim of generally having between 7 and 9 members.
|
||||||
|
|
||||||
|
In future we may also have sub-teams (like Rust - e.g. CS/AS/Push API; SS API;
|
||||||
|
IS API; Crypto), but as a starting point we are beginning with a single core
|
||||||
|
team in the interests of not over-engineering it and scaling up elastically.
|
||||||
|
|
||||||
|
Spec Core Team members need to be able to commit to at least 1 hour a week of
|
||||||
|
availability to work on the spec and (where relevant) reference implementations.
|
||||||
|
Members must arrange their own funding for their time.
|
||||||
|
|
||||||
|
Responsibilities include:
|
||||||
|
|
||||||
|
* Reviewing Matrix Spec Change proposals and Spec PRs.
|
||||||
|
|
||||||
|
* Contributing to and reviewing reference implementations of Matrix Spec Change
|
||||||
|
proposals.
|
||||||
|
|
||||||
|
* Shepherding Matrix Spec Changes on behalf of authors where needed.
|
||||||
|
|
||||||
|
* Triaging Matrix Spec issues.
|
||||||
|
|
||||||
|
* Coordinating reference implementations.
|
||||||
|
|
||||||
|
* Ensuring the code of conduct for +matrix:matrix.org community rooms is
|
||||||
|
maintained and applied.
|
||||||
|
|
||||||
|
If members are absent (uncontactable) for more than 8 weeks without prior
|
||||||
|
agreement, they will be assumed to have left the project.
|
||||||
|
|
||||||
|
Spec Core Team members can resign whenever they want, but must notify the rest
|
||||||
|
of the team and the Guardians on doing so.
|
||||||
|
|
||||||
|
New additions to the team must be approved by all current members of the team.
|
||||||
|
Membership has to be formally proposed by someone already on the Spec Core Team.
|
||||||
|
|
||||||
|
Members can be removed from the team if 75% of the current members approves and
|
||||||
|
agrees they are no longer following the goals and guiding principles of the
|
||||||
|
project. (The 75% is measured of the whole team, including the member in
|
||||||
|
question).
|
||||||
|
|
||||||
|
Guardians act as a safety net, and can appoint or remove Spec Core Team members
|
||||||
|
(requiring approval by 75% of the current Guardians) if the Spec Core Team is
|
||||||
|
unable to function or is failing to align with the Foundation's mission.
|
||||||
|
|
||||||
|
It's suggested that one of the Spec Core Team members should also be a Guardian,
|
||||||
|
to facilitate information exchange between the Guardians and the Spec Core Team,
|
||||||
|
and to represent the technical angle of the project to the other Guardians.
|
||||||
|
|
||||||
|
The project lead role acts to coordinate the team and to help steer the team to
|
||||||
|
consensus in the event of failing to get agreement on a Matrix Spec Change.
|
||||||
|
Every 12 months, a vote of confidence is held in the project lead, requiring the
|
||||||
|
approval of 75% of the current Spec Core Team members for the lead to be
|
||||||
|
renewed. There is no maximum term for the project lead. The lead may be
|
||||||
|
removed by the core team at any point (requiring 75% approval of current
|
||||||
|
members), and may resign the role at any point (notifying the team and the
|
||||||
|
Guardians). The lead automatically resigns the role if they resign from the
|
||||||
|
Spec Core Team. Resignation automatically triggers selection of a new lead, who
|
||||||
|
must be selected from the existing Spec Core Team with 75% approval from current
|
||||||
|
members within 14 days.
|
||||||
|
|
||||||
|
It is vital that the core spec team has strong domain expertise covering all
|
||||||
|
different domains of the spec (e.g. we don't want to end up with a core spec
|
||||||
|
team where nobody has strong experience in cryptography)
|
||||||
|
|
||||||
|
The initial Spec Core Team (and their domain areas) is:
|
||||||
|
|
||||||
|
* Matthew Hodgson (Lead, Guardian)
|
||||||
|
* Erik Johnston (Servers)
|
||||||
|
* Richard van der Hoff (Servers, Cryptography)
|
||||||
|
* David Baker (Clients, IS API, Push API, Media)
|
||||||
|
* Hubert Chathi (Cryptography, General)
|
||||||
|
* Andrew Morgan (Servers, AS API, Spec Process)
|
||||||
|
* Travis Ralston (Bots and Bridges & AS API, Media, acting with Dimension hat on)
|
||||||
|
* Alexey Rusakov (Clients on behalf of Community)
|
||||||
|
* TBD
|
||||||
|
|
||||||
|
MSCs require approval by 75% of the current members of the Spec Core Team to
|
||||||
|
proceed to Final Comment Period (see https://matrix.org/docs/spec/proposals for
|
||||||
|
the rest of the MSC process).
|
||||||
|
|
||||||
|
Even though a threshold of only 75% is required for approval, the Spec Core Team
|
||||||
|
is expected to seek consensus on MSCs.
|
||||||
|
|
||||||
|
The above governance process for the Spec Core Team is considered as part of the
|
||||||
|
spec and is updated using the Matrix Spec Change process. However, changes to
|
||||||
|
the governance process also require approval by 75% of the current Guardians
|
||||||
|
(acting as a formal decision of the Foundation's Directors), in order to ensure
|
||||||
|
changes are aligned with the Foundation's mission. For avoidance of doubt, Spec
|
||||||
|
Core Team votes and Guardians' votes are distinct and a person having both hats
|
||||||
|
has to vote independently on both forums with the respective hat on.
|
||||||
|
|
||||||
|
Spec Core Team decisions (e.g. appointing/removing members and lead)
|
||||||
|
should be published openly and transparently for the public.
|
||||||
|
|
||||||
|
## The Guardians
|
||||||
|
|
||||||
|
*This section will be used as the basis for the legal responsibilities of
|
||||||
|
Directors in the Articles of Association of the Foundation.*
|
||||||
|
|
||||||
|
The Guardians form the legal Board of Directors of The Matrix.org Foundation CIC
|
||||||
|
(Community Interest Company). They are responsible for ensuring the Foundation
|
||||||
|
is following its guiding principles, and provide a safety mechanism if the
|
||||||
|
structure of the Spec Core Team runs into trouble.
|
||||||
|
|
||||||
|
In practice, this means that:
|
||||||
|
|
||||||
|
* Guardians are responsible for ensuring the Spec Core Team continues to
|
||||||
|
function, and have the power to appoint/dismiss members of the spec core team
|
||||||
|
(with the agreement of 75% of the Guardians) to address issues with the Spec
|
||||||
|
Core Team.
|
||||||
|
* Guardians must keep each other honest, providing a ‘checks and balances’.
|
||||||
|
mechanism between each other to ensure that all Guardians and the Spec Core
|
||||||
|
Team act in the best interests of the protocol and ecosystem.
|
||||||
|
* Guardians may dismiss members of the Spec Core Team who are in serious
|
||||||
|
breach of the guiding principles.
|
||||||
|
* Guardians may appoint members of the Spec Core Team to break deadlocks in the
|
||||||
|
unanimous consent requirement for the Spec Core Team when appointing new
|
||||||
|
members.
|
||||||
|
* Guardians may also override deadlocks when appointing a Spec Core Team leader
|
||||||
|
(with approval of 75% of the current Guardians).
|
||||||
|
* Guardians must approve changes to the above Guiding Principles (with approval
|
||||||
|
of 75% of the current Guardians)
|
||||||
|
* Guardians are responsible for approving use of the Foundation's assets
|
||||||
|
(e.g. redistributing donations).
|
||||||
|
* In future, Guardians may also be responsible for ensuring staff are hired by
|
||||||
|
the Foundation to support administrative functions and other roles required
|
||||||
|
to facilitate the Foundation's mission.
|
||||||
|
* As well as the Spec Core Team committee, they may also oversee committees for
|
||||||
|
other areas such as marketing Matrix.org, registering custom event types,
|
||||||
|
or "Made for Matrix" certification.
|
||||||
|
* Guardians are responsible for choosing if, when and how staff are located by
|
||||||
|
the Foundation to fill administrative and other functions required to
|
||||||
|
facilitate the Foundations' mission.
|
||||||
|
* Guardians are responsible for choosing if and when additional committees are
|
||||||
|
formed, and to oversee those committees.
|
||||||
|
* Guardians are not required to be involved on a day-to-day basis, however
|
||||||
|
those not taking a hands on approach are required to monitor to ensure a
|
||||||
|
suitable balance is kept by those that do.
|
||||||
|
|
||||||
|
Guardians are chosen typically to be independent of the commercial Matrix
|
||||||
|
ecosystem (and especially independent from New Vector), and may even not be
|
||||||
|
members of today’s Matrix community. However, they should be deeply aligned with
|
||||||
|
the mission of the project, and respected and trusted by the wider community to
|
||||||
|
uphold the guiding principles of the Foundation and keep the other Guardians
|
||||||
|
honest.
|
||||||
|
|
||||||
|
Guardians are responsible for maintaining and updating the Guiding Principles
|
||||||
|
and Articles of Association of the Foundation if/when necessary. Changes to the
|
||||||
|
Guiding Principles require approval from 75% of the current Guardians and are
|
||||||
|
passed as a 'special resolution' of the board.
|
||||||
|
|
||||||
|
New Guardians may be appointed with approval from 75% of the current Guardians.
|
||||||
|
|
||||||
|
Guardians may resign at any time, with notification to the board.
|
||||||
|
|
||||||
|
Guardians may be removed due to serious breach of the guiding principles with
|
||||||
|
approval by 75% of the other current Guardians, or if absent from 3 consecutive
|
||||||
|
board meetings, or if they are legally disqualified from acting as a Director.
|
||||||
|
|
||||||
|
We aim to recruit roughly 5 Guardians. The initial Guardians are:
|
||||||
|
|
||||||
|
* Matthew Hodgson (CEO/CTO, New Vector)
|
||||||
|
* Amandine Le Pape (COO, New Vector)
|
||||||
|
* TBA (agreed, needs paperwork)
|
||||||
|
* TBD
|
||||||
|
* TBD
|
||||||
|
|
||||||
|
The intention is for Matthew & Amandine (the original founders of Matrix) to
|
||||||
|
form a minority of the Guardians, in order to ensure the neutrality of the
|
||||||
|
Foundation relative to Matthew & Amandine’s day jobs at New Vector.
|
||||||
|
|
||||||
|
Guardians must arrange their own funding for their time.
|
||||||
|
|
||||||
|
Guardian decisions (e.g. appointing/removing guardians; changes to the spec core
|
||||||
|
team; etc) should be published openly and transparently for the public.
|
||||||
|
|
||||||
|
## The Code Core Team (aka The Core Team)
|
||||||
|
|
||||||
|
The "Core Team" (or the "Code Core Team", to disambiguate from the Spec Core
|
||||||
|
Team) is a loose term that describes the set of people with access to commit
|
||||||
|
code to the public https://github.com/matrix-org repositories, who are either
|
||||||
|
working on matrix.org's reference implementations or the spec itself. Commit
|
||||||
|
access is decided by those responsible for the projects in question, much like
|
||||||
|
any other open source project. Anyone is eligible for commit access if they
|
||||||
|
have proved themselves a valuable long-term contributor, uphold the guiding
|
||||||
|
principles and mission of the project and have proved themselves able to
|
||||||
|
collaborate constructively with the existing core team. Active participation in
|
||||||
|
the core team is also signified by membership of the +matrix:matrix.org Matrix
|
||||||
|
community.
|
||||||
|
|
||||||
|
Responsibilities include:
|
||||||
|
* Helping ensure the quality of the projects' code repositories.
|
||||||
|
* Ensuring all commits are reviewed.
|
||||||
|
* Ensuring that all projects follow the Matrix spec.
|
||||||
|
* Helping architect the implementations.
|
||||||
|
* Contributing code to the implementations.
|
||||||
|
* Fostering contributions and engaging with contributors constructively in a
|
||||||
|
way that fosters a healthy and happy community.
|
||||||
|
* Following the Guiding Principles and promoting them within the community.
|
||||||
|
|
||||||
|
Code Core Team members must arrange their own funding for their time.
|
||||||
|
|
||||||
|
## Functions of the Foundation
|
||||||
|
|
||||||
|
* Independent legal entity which acts as neutral custodian of Matrix.
|
||||||
|
* Gathers donations.
|
||||||
|
* Owns the core Matrix IP in an asset lock, which shall be transferred from New Vector:
|
||||||
|
* Owns the matrix.org domain and branding.
|
||||||
|
* Owns the copyright of the reference implementations of Matrix (i.e. everything in https://github.com/matrix-org).
|
||||||
|
By assigning copyright to the Foundation, it’s protected against New Vector ever being tempted to relicense it.
|
||||||
|
* Owns the IP of the website.
|
||||||
|
* Owns the Matrix.org marketing swag (t-shirts, stickers, exhibition stands etc).
|
||||||
|
* Responsible for finding someone to run the Matrix.org homeserver (currently New Vector).
|
||||||
|
* Publishes the spec.
|
||||||
|
* Responsible for tools and documentation that support the spec.
|
||||||
|
* Responsible for ensuring reference implementations and test suite exists for the spec.
|
||||||
|
* Publishes the website (including ensuring This Week In Matrix and similar exist to promote independent projects).
|
||||||
|
* Manages any future IANA-style allocations for Matrix, such as:
|
||||||
|
* mx:// URI scheme.
|
||||||
|
* TCP port 8448.
|
||||||
|
* .well-known URIs
|
||||||
|
* Ensures that Matrix promotion is happening (e.g. ensuring that meetups &
|
||||||
|
events & community activity is supported).
|
||||||
|
|
||||||
|
In future:
|
||||||
|
|
||||||
|
* Contracts entities to work on Matrix if such contracts help the Foundation to
|
||||||
|
fulfil its mission and obey the Guiding Principles (e.g. redistributing
|
||||||
|
donations back to fund development of reference implementations or compliance
|
||||||
|
kits).
|
||||||
|
* Manages a "Made for Matrix" certification process? (to confirm that products
|
||||||
|
are actually compatible with Matrix).
|
||||||
|
|
||||||
|
## Timings
|
||||||
|
|
||||||
|
The Foundation was incorporated in October 2018 as a UK limited by guarantee
|
||||||
|
private company, using generic non-profit articles of association combined with
|
||||||
|
a high-level mission lock aligned with the above:
|
||||||
|
|
||||||
|
> 4. The objects of the Foundation are for the benefit of the community as a whole
|
||||||
|
> to:
|
||||||
|
|
||||||
|
> 4.1.1 empower users to control their communication data and have freedom over
|
||||||
|
> their communications infrastructure by creating, maintaining and promoting
|
||||||
|
> Matrix as an openly standardised secure decentralised communication protocol and
|
||||||
|
> network, open to all, and available to the public for no charge;
|
||||||
|
|
||||||
|
> 4.1.2 build and develop an appropriate governance model for Matrix through the
|
||||||
|
> Foundation, in order to drive the adoption of Matrix as a single global
|
||||||
|
> federation, an open standard unencumbered from any proprietary intellectual
|
||||||
|
> property and/or software patents, minimising fragmentation (whilst encouraging
|
||||||
|
> experimentation), maximising speed of development, and prioritising the long-
|
||||||
|
> term success and growth of the overall network over the commercial concerns of
|
||||||
|
> an individual person or persons.
|
||||||
|
|
||||||
|
The foundation was then converted into a Community Interest Company, formalising
|
||||||
|
its non-profit status under the approval of the independent [Community Interest
|
||||||
|
Companies Regulator](https://www.gov.uk/government/organisations/office-of-the-regulator-of-community-interest-companies),
|
||||||
|
which took effect Jan 2019.
|
||||||
|
|
||||||
|
We are currently planning to release r0 of the Matrix Spec at the end of Jan 2019, and
|
||||||
|
finalise the Foundation's articles of association shortly afterwards based on the
|
||||||
|
contents of this MSC once passed FCP.
|
||||||
|
|
||||||
|
This will coincide with the formal asset transfer of Matrix.org's assets from
|
||||||
|
New Vector Ltd, and the appointment of the remaining Guardians.
|
||||||
|
|
@ -27,7 +27,9 @@ known by the homeserver).
|
||||||
The 200 response is a JSON object with an `id_server_unbind_result` field whose
|
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
|
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
|
identity server (IS) does not support unbinding 3PIDs directly. If the identity
|
||||||
server returns an error then that should be returned to the client.
|
server returns an error then that should be returned to the client. If the homeserver
|
||||||
|
is unable to determine an `id_server` to use, it should return `no-support` for
|
||||||
|
the `id_server_unbind_result`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
|
||||||
42
proposals/2076-enforce-validity-periods.md
Normal file
42
proposals/2076-enforce-validity-periods.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# MSC2076: Enforce key-validity periods when validating event signatures
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
The [Federation API
|
||||||
|
specification](https://matrix.org/docs/spec/server_server/r0.1.1.html#validating-hashes-and-signatures-on-received-events)
|
||||||
|
specifies that events should be validated via the signature verification
|
||||||
|
algorithm, but does not specify how the keys for that check should be obtained
|
||||||
|
and validated.
|
||||||
|
|
||||||
|
In practice, the implementation has been as follows. The receiving server
|
||||||
|
first requests a copy of the key via the [`GET /_matrix/key/v2/server/`
|
||||||
|
API](https://matrix.org/docs/spec/server_server/r0.1.1.html#get-matrix-key-v2-server-keyid)
|
||||||
|
directly from the server which created the signature, or via the [`POST
|
||||||
|
/_matrix/key/v2/query` API](https://matrix.org/docs/spec/server_server/r0.1.1.html#post-matrix-key-v2-query)
|
||||||
|
from a trusted key server. Once such a key is obtained, it is then cached
|
||||||
|
forever. No check is made on the `valid_until_ts` field, and
|
||||||
|
`minimum_valid_until_ts` is set to zero for calls to `POST
|
||||||
|
/_matrix/key/v2/query`.
|
||||||
|
|
||||||
|
This is highly unsatisfactory, as it means that, should a key be compromised,
|
||||||
|
then an attacker can spoof arbitrary events claiming to be from the compromised
|
||||||
|
server forever, since there is no revocation mechanism.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
This MSC proposes to enforce the `valid_until_ts` property when validating
|
||||||
|
event signatures. In particular, the server must ensure that it has a copy of
|
||||||
|
the key with a `valid_until_ts` at least as large as the `origin_server_ts` of
|
||||||
|
the event being validated. If it does not have such a copy, it must try to
|
||||||
|
obtain one via the `GET /_matrix/key/v2/server/` or `POST
|
||||||
|
/_matrix/key/v2/query` APIs. For the latter, it must set
|
||||||
|
`minimum_valid_until_ts` to prompt the notary server to attempt to refresh the
|
||||||
|
key if appropriate.
|
||||||
|
|
||||||
|
Since this changes the rules used to validate events, it will be introduced
|
||||||
|
with a new room version. This will reduce the risk of divergence between
|
||||||
|
servers in a room due to some servers accepting events which others reject.
|
||||||
|
|
||||||
|
This MSC also proposes that the current situation - where `valid_until_ts` is
|
||||||
|
ignored - be formalised for the existing room versions v1-v4, rather than be
|
||||||
|
left as implementation-specific behaviour.
|
||||||
19
proposals/2077-rooms-v5.md
Normal file
19
proposals/2077-rooms-v5.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# MSC2077 - Room version 5
|
||||||
|
|
||||||
|
This MSC proposes creating room version 5, which will enforce the signing key
|
||||||
|
`valid_until_ts` timestamps proposed in
|
||||||
|
[MSC2076](https://github.com/matrix-org/matrix-doc/issues/2076).
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
The new room version is called `5`. The only difference between v5 and v4 is
|
||||||
|
that v5 rooms enforce the `valid_until_ts` timestamp on signing keys as
|
||||||
|
proposed in [MSC2076](https://github.com/matrix-org/matrix-doc/issues/2076).
|
||||||
|
|
||||||
|
It is not yet proposed to change the default room version to v5. Version 5 will
|
||||||
|
be considered a "stable" version.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
See also [MSC2002](./2002-rooms-v4.md), which proposed room v4 but also
|
||||||
|
mentioned that a v5 was anticipated and gave some context for this change.
|
||||||
|
|
@ -52,7 +52,7 @@ func main() {
|
||||||
|
|
||||||
walker := makeWalker(dir, w)
|
walker := makeWalker(dir, w)
|
||||||
paths := []string{"api", "changelogs", "event-schemas", "scripts",
|
paths := []string{"api", "changelogs", "event-schemas", "scripts",
|
||||||
"specification"}
|
"specification", "schemas", "data-definitions"}
|
||||||
|
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
filepath.Walk(path.Join(dir, p), walker)
|
filepath.Walk(path.Join(dir, p), walker)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import inspect
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -225,3 +226,19 @@ class MatrixSections(Sections):
|
||||||
examples=swagger_def['examples'],
|
examples=swagger_def['examples'],
|
||||||
title_kind=subtitle_title_char)
|
title_kind=subtitle_title_char)
|
||||||
return rendered
|
return rendered
|
||||||
|
|
||||||
|
def render_sas_emoji_table(self):
|
||||||
|
emoji = self.units.get("sas_emoji")
|
||||||
|
rendered = ".. csv-table::\n"
|
||||||
|
rendered += " :header: \"Number\", \"Emoji\", \"Unicode\", \"Description\"\n"
|
||||||
|
rendered += " :widths: 10, 10, 15, 20\n"
|
||||||
|
rendered += "\n"
|
||||||
|
for row in emoji:
|
||||||
|
rendered += " %d, \"%s\", \"``%s``\", \"%s\"\n" % (
|
||||||
|
row['number'],
|
||||||
|
row['emoji'],
|
||||||
|
row['unicode'],
|
||||||
|
row['description'],
|
||||||
|
)
|
||||||
|
rendered += "\n"
|
||||||
|
return rendered
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@
|
||||||
|
|
||||||
{{endpoint.desc}}
|
{{endpoint.desc}}
|
||||||
|
|
||||||
{{":Rate-limited: Yes." if endpoint.rate_limited else "" }}
|
{{":Rate-limited: Yes." if endpoint.rate_limited else ":Rate-limited: No." }}
|
||||||
{{":Requires auth: Yes." if endpoint.requires_auth else "" }}
|
{{":Requires auth: Yes." if endpoint.requires_auth else ":Requires auth: No." }}
|
||||||
|
|
||||||
.. class:: httpheaders
|
.. class:: httpheaders
|
||||||
|
|
||||||
Request format:
|
Request format:
|
||||||
|
|
||||||
{% if (endpoint.req_param_by_loc | length) %}
|
{% if (endpoint.req_param_by_loc | length) %}
|
||||||
{{ tables.split_paramtable(endpoint.req_param_by_loc) }}
|
{{ tables.split_paramtable(endpoint.req_param_by_loc) }}
|
||||||
{% if (endpoint.req_body_tables) %}
|
{% if (endpoint.req_body_tables) %}
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
{% if endpoint.res_headers is not none -%}
|
{% if endpoint.res_headers is not none -%}
|
||||||
|
|
||||||
.. class:: httpheaders
|
.. class:: httpheaders
|
||||||
|
|
||||||
Response headers:
|
Response headers:
|
||||||
|
|
||||||
{{ tables.paramtable(endpoint.res_headers.rows) }}
|
{{ tables.paramtable(endpoint.res_headers.rows) }}
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
{% if endpoint.res_tables|length > 0 -%}
|
{% if endpoint.res_tables|length > 0 -%}
|
||||||
|
|
||||||
.. class:: httpheaders
|
.. class:: httpheaders
|
||||||
|
|
||||||
Response format:
|
Response format:
|
||||||
|
|
||||||
{% for table in endpoint.res_tables -%}
|
{% for table in endpoint.res_tables -%}
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
.. class:: httpheaders
|
.. class:: httpheaders
|
||||||
|
|
||||||
Example request:
|
Example request:
|
||||||
|
|
||||||
.. code:: http
|
.. code:: http
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
{% if endpoint.responses|length > 0 -%}
|
{% if endpoint.responses|length > 0 -%}
|
||||||
|
|
||||||
.. class:: httpheaders
|
.. class:: httpheaders
|
||||||
|
|
||||||
Response{{"s" if endpoint.responses|length > 1 else "" }}:
|
Response{{"s" if endpoint.responses|length > 1 else "" }}:
|
||||||
|
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
{% if res["example"] -%}
|
{% if res["example"] -%}
|
||||||
|
|
||||||
.. class:: httpheaders
|
.. class:: httpheaders
|
||||||
|
|
||||||
Example
|
Example
|
||||||
|
|
||||||
.. code:: json
|
.. code:: json
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ TARGETS = os.path.join(matrix_doc_dir, "specification/targets.yaml")
|
||||||
ROOM_EVENT = "core-event-schema/room_event.yaml"
|
ROOM_EVENT = "core-event-schema/room_event.yaml"
|
||||||
STATE_EVENT = "core-event-schema/state_event.yaml"
|
STATE_EVENT = "core-event-schema/state_event.yaml"
|
||||||
|
|
||||||
|
SAS_EMOJI_JSON = os.path.join(matrix_doc_dir, "data-definitions/sas-emoji.json")
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# a yaml Loader which loads mappings into OrderedDicts instead of regular
|
# a yaml Loader which loads mappings into OrderedDicts instead of regular
|
||||||
|
|
@ -1088,3 +1090,21 @@ class MatrixUnits(Units):
|
||||||
"string": git_version,
|
"string": git_version,
|
||||||
"revision": git_commit
|
"revision": git_commit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def load_sas_emoji(self):
|
||||||
|
with open(SAS_EMOJI_JSON, 'r', encoding='utf-8') as sas_json:
|
||||||
|
emoji = json.load(sas_json)
|
||||||
|
|
||||||
|
# Verify the emoji matches the unicode
|
||||||
|
for c in emoji:
|
||||||
|
e = c['emoji']
|
||||||
|
logger.info("Checking emoji %s (%s)", e, c['description'])
|
||||||
|
u = re.sub(r'U\+([0-9a-fA-F]+)', lambda m: chr(int(m.group(1), 16)), c['unicode'])
|
||||||
|
if e != u:
|
||||||
|
raise Exception("Emoji %s should be %s not %s" % (
|
||||||
|
c['description'],
|
||||||
|
repr(e),
|
||||||
|
c['unicode'],
|
||||||
|
))
|
||||||
|
|
||||||
|
return emoji
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,17 @@ Given the following minimally-sized event:
|
||||||
.. code:: json
|
.. code:: json
|
||||||
|
|
||||||
{
|
{
|
||||||
"event_id": "$0:domain",
|
"room_id": "!x:domain",
|
||||||
|
"sender": "@a:domain",
|
||||||
"origin": "domain",
|
"origin": "domain",
|
||||||
"origin_server_ts": 1000000,
|
"origin_server_ts": 1000000,
|
||||||
"signatures": {},
|
"signatures": {},
|
||||||
|
"hashes": {},
|
||||||
"type": "X",
|
"type": "X",
|
||||||
|
"content": {},
|
||||||
|
"prev_events": [],
|
||||||
|
"auth_events": [],
|
||||||
|
"depth": 3,
|
||||||
"unsigned": {
|
"unsigned": {
|
||||||
"age_ts": 1000000
|
"age_ts": 1000000
|
||||||
}
|
}
|
||||||
|
|
@ -106,15 +112,20 @@ The event signing algorithm should emit the following signed event:
|
||||||
.. code:: json
|
.. code:: json
|
||||||
|
|
||||||
{
|
{
|
||||||
"event_id": "$0:domain",
|
"auth_events": [],
|
||||||
|
"content": {},
|
||||||
|
"depth": 3,
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"sha256": "6tJjLpXtggfke8UxFhAKg82QVkJzvKOVOOSjUDK4ZSI"
|
"sha256": "5jM4wQpv6lnBo7CLIghJuHdW+s2CMBJPUOGOC89ncos"
|
||||||
},
|
},
|
||||||
"origin": "domain",
|
"origin": "domain",
|
||||||
"origin_server_ts": 1000000,
|
"origin_server_ts": 1000000,
|
||||||
|
"prev_events": [],
|
||||||
|
"room_id": "!x:domain",
|
||||||
|
"sender": "@a:domain",
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"domain": {
|
"domain": {
|
||||||
"ed25519:1": "2Wptgo4CwmLo/Y8B8qinxApKaCkBG2fjTWB7AbP5Uy+aIbygsSdLOFzvdDjww8zUVKCmI02eP9xtyJxc/cLiBA"
|
"ed25519:1": "KxwGjPSDEtvnFgU00fwFz+l6d2pJM6XBIaMEn81SXPTRl16AqLAYqfIReFGZlHi5KLjAWbOoMszkwsQma+lYAg"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "X",
|
"type": "X",
|
||||||
|
|
@ -129,7 +140,7 @@ Given the following event containing redactable content:
|
||||||
|
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"body": "Here is the message content",
|
"body": "Here is the message content"
|
||||||
},
|
},
|
||||||
"event_id": "$0:domain",
|
"event_id": "$0:domain",
|
||||||
"origin": "domain",
|
"origin": "domain",
|
||||||
|
|
@ -149,7 +160,7 @@ The event signing algorithm should emit the following signed event:
|
||||||
|
|
||||||
{
|
{
|
||||||
"content": {
|
"content": {
|
||||||
"body": "Here is the message content",
|
"body": "Here is the message content"
|
||||||
},
|
},
|
||||||
"event_id": "$0:domain",
|
"event_id": "$0:domain",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ The following other versions are also available, in reverse chronological order:
|
||||||
API Standards
|
API Standards
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
.. TODO: Move a lot of this to a common area for all specs.
|
||||||
|
|
||||||
.. TODO
|
.. TODO
|
||||||
Need to specify any HMAC or access_token lifetime/ratcheting tricks
|
Need to specify any HMAC or access_token lifetime/ratcheting tricks
|
||||||
We need to specify capability negotiation for extensible transports
|
We need to specify capability negotiation for extensible transports
|
||||||
|
|
@ -82,7 +84,6 @@ names in JSON objects passed over the API also follow this convention.
|
||||||
``/createRoom``. A future version of this specification will address the
|
``/createRoom``. A future version of this specification will address the
|
||||||
inconsistency.
|
inconsistency.
|
||||||
|
|
||||||
|
|
||||||
Any errors which occur at the Matrix API level MUST return a "standard error
|
Any errors which occur at the Matrix API level MUST return a "standard error
|
||||||
response". This is a JSON object which looks like:
|
response". This is a JSON object which looks like:
|
||||||
|
|
||||||
|
|
@ -242,6 +243,9 @@ recommended.
|
||||||
|
|
||||||
{{versions_cs_http_api}}
|
{{versions_cs_http_api}}
|
||||||
|
|
||||||
|
|
||||||
|
.. _`CORS`:
|
||||||
|
|
||||||
Web Browser Clients
|
Web Browser Clients
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
@ -250,9 +254,14 @@ web browser or similar environment. In these cases, the homeserver should respon
|
||||||
to pre-flight requests and supply Cross-Origin Resource Sharing (CORS) headers on
|
to pre-flight requests and supply Cross-Origin Resource Sharing (CORS) headers on
|
||||||
all requests.
|
all requests.
|
||||||
|
|
||||||
When a client approaches the server with a pre-flight (``OPTIONS``) request, the
|
Servers MUST expect that clients will approach them with ``OPTIONS`` requests,
|
||||||
server should respond with the CORS headers for that route. The recommended CORS
|
allowing clients to discover the CORS headers. All endpoints in this specification s
|
||||||
headers to be returned by servers on all requests are:
|
upport the ``OPTIONS`` method, however the server MUST NOT perform any logic defined
|
||||||
|
for the endpoints when approached with an ``OPTIONS`` request.
|
||||||
|
|
||||||
|
When a client approaches the server with a request, the server should respond with
|
||||||
|
the CORS headers for that route. The recommended CORS headers to be returned by
|
||||||
|
servers on all requests are:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
|
|
@ -296,6 +305,10 @@ In this section, the following terms are used with specific meanings:
|
||||||
Well-known URI
|
Well-known URI
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
Servers hosting the ``.well-known`` JSON file SHOULD offer CORS headers, as
|
||||||
|
per the `CORS`_ section in this specification.
|
||||||
|
|
||||||
The ``.well-known`` method uses a JSON file at a predetermined location to
|
The ``.well-known`` method uses a JSON file at a predetermined location to
|
||||||
specify parameter values. The flow for this method is as follows:
|
specify parameter values. The flow for this method is as follows:
|
||||||
|
|
||||||
|
|
@ -453,11 +466,10 @@ params
|
||||||
presented, that type may be present as a key in this dictionary. For example,
|
presented, that type may be present as a key in this dictionary. For example,
|
||||||
the public part of an OAuth client ID could be given here.
|
the public part of an OAuth client ID could be given here.
|
||||||
session
|
session
|
||||||
This is a session identifier that the client must pass back to the home
|
This is a session identifier that the client must pass back to the homeserver,
|
||||||
server, if one is provided, in subsequent attempts to authenticate in the same
|
if one is provided, in subsequent attempts to authenticate in the same API call.
|
||||||
API call.
|
|
||||||
|
|
||||||
The client then chooses a flow and attempts to complete one of the stages. It
|
The client then chooses a flow and attempts to complete the first stage. It
|
||||||
does this by resubmitting the same request with the addition of an ``auth``
|
does this by resubmitting the same request with the addition of an ``auth``
|
||||||
key in the object that it submits. This dictionary contains a ``type`` key whose
|
key in the object that it submits. This dictionary contains a ``type`` key whose
|
||||||
value is the name of the authentication type that the client is attempting to complete.
|
value is the name of the authentication type that the client is attempting to complete.
|
||||||
|
|
@ -558,7 +570,10 @@ message in the standard format. For example:
|
||||||
}
|
}
|
||||||
|
|
||||||
If the client has completed all stages of a flow, the homeserver performs the
|
If the client has completed all stages of a flow, the homeserver performs the
|
||||||
API call and returns the result as normal.
|
API call and returns the result as normal. Completed stages cannot be retried
|
||||||
|
by clients, therefore servers must return either a 401 response with the completed
|
||||||
|
stages, or the result of the API call if all stages were completed when a client
|
||||||
|
retries a stage.
|
||||||
|
|
||||||
Some authentication types may be completed by means other than through the
|
Some authentication types may be completed by means other than through the
|
||||||
Matrix client, for example, an email confirmation may be completed when the user
|
Matrix client, for example, an email confirmation may be completed when the user
|
||||||
|
|
@ -623,6 +638,7 @@ This specification defines the following auth types:
|
||||||
- ``m.login.recaptcha``
|
- ``m.login.recaptcha``
|
||||||
- ``m.login.oauth2``
|
- ``m.login.oauth2``
|
||||||
- ``m.login.email.identity``
|
- ``m.login.email.identity``
|
||||||
|
- ``m.login.msisdn``
|
||||||
- ``m.login.token``
|
- ``m.login.token``
|
||||||
- ``m.login.dummy``
|
- ``m.login.dummy``
|
||||||
|
|
||||||
|
|
@ -787,6 +803,34 @@ To use this authentication type, clients should submit an auth dict as follows:
|
||||||
"session": "<session ID>"
|
"session": "<session ID>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Phone number/MSISDN-based (identity server)
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
:Type:
|
||||||
|
``m.login.msisdn``
|
||||||
|
:Description:
|
||||||
|
Authentication is supported by authorising a phone number with an identity
|
||||||
|
server.
|
||||||
|
|
||||||
|
Prior to submitting this, the client should authenticate with an identity
|
||||||
|
server. After authenticating, the session information should be submitted to
|
||||||
|
the homeserver.
|
||||||
|
|
||||||
|
To use this authentication type, clients should submit an auth dict as follows:
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "m.login.msisdn",
|
||||||
|
"threepidCreds": [
|
||||||
|
{
|
||||||
|
"sid": "<identity server session id>",
|
||||||
|
"client_secret": "<identity server client secret>",
|
||||||
|
"id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"session": "<session ID>"
|
||||||
|
}
|
||||||
|
|
||||||
Dummy Auth
|
Dummy Auth
|
||||||
<<<<<<<<<<
|
<<<<<<<<<<
|
||||||
:Type:
|
:Type:
|
||||||
|
|
|
||||||
|
|
@ -485,7 +485,7 @@ some other reason. Versions can switch between stable and unstable periodically
|
||||||
for a variety of reasons, including discovered security vulnerabilities and age.
|
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
|
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
|
running a stable version. Servers SHOULD use room version 4 as the default room
|
||||||
version when creating new rooms.
|
version when creating new rooms.
|
||||||
|
|
||||||
The available room versions are:
|
The available room versions are:
|
||||||
|
|
|
||||||
|
|
@ -384,20 +384,10 @@ man-in-the-middle. This verification process requires an out-of-band channel:
|
||||||
there is no way to do it within Matrix without trusting the administrators of
|
there is no way to do it within Matrix without trusting the administrators of
|
||||||
the homeservers.
|
the homeservers.
|
||||||
|
|
||||||
In Matrix, the basic process for device verification is for Alice to verify
|
In Matrix, verification works by Alice meeting Bob in person, or contacting him
|
||||||
that the public Ed25519 signing key she received via ``/keys/query`` for Bob's
|
via some other trusted medium, and use `SAS Verification`_ to interactively
|
||||||
device corresponds to the private key in use by Bob's device. For now, it is
|
verify Bob's devices. Alice and Bob may also read aloud their unpadded base64
|
||||||
recommended that clients provide mechanisms by which the user can see:
|
encoded Ed25519 public key, as returned by ``/keys/query``.
|
||||||
|
|
||||||
1. The public part of their device's Ed25519 signing key, encoded using
|
|
||||||
`unpadded Base64`_.
|
|
||||||
|
|
||||||
2. The list of devices in use for each user in a room, along with the public
|
|
||||||
Ed25519 signing key for each device, again encoded using unpadded Base64.
|
|
||||||
|
|
||||||
Alice can then meet Bob in person, or contact him via some other trusted
|
|
||||||
medium, and ask him to read out the Ed25519 key shown on his device. She
|
|
||||||
compares this with the value shown for his device on her client.
|
|
||||||
|
|
||||||
Device verification may reach one of several conclusions. For example:
|
Device verification may reach one of several conclusions. For example:
|
||||||
|
|
||||||
|
|
@ -423,6 +413,328 @@ Device verification may reach one of several conclusions. For example:
|
||||||
decrypted by such a device. For the Olm protocol, this is documented at
|
decrypted by such a device. For the Olm protocol, this is documented at
|
||||||
https://matrix.org/git/olm/about/docs/signing.rst.
|
https://matrix.org/git/olm/about/docs/signing.rst.
|
||||||
|
|
||||||
|
|
||||||
|
Key verification framework
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Verifying keys manually by reading out the Ed25519 key is not very user friendly,
|
||||||
|
and can lead to errors. In order to help mitigate errors, and to make the process
|
||||||
|
eaiser for users, some verification methods are supported by the specification.
|
||||||
|
The methods all use a common framework for negotiating the key verification.
|
||||||
|
|
||||||
|
To use this framework, Alice's client would send ``m.key.verification.request``
|
||||||
|
events to Bob's devices. All of the ``to_device`` messages sent to Bob MUST have
|
||||||
|
the same ``transaction_id`` to indicate they are part of the same request. This
|
||||||
|
allows Bob to reject the request on one device, and have it apply to all of his
|
||||||
|
devices. Similarly, it allows Bob to process the verification on one device without
|
||||||
|
having to involve all of his devices.
|
||||||
|
|
||||||
|
When Bob's device receives a ``m.key.verification.request``, it should prompt Bob
|
||||||
|
to verify keys with Alice using one of the supported methods in the request. If
|
||||||
|
Bob's device does not understand any of the methods, it should not cancel the request
|
||||||
|
as one of his other devices may support the request. Instead, Bob's device should
|
||||||
|
tell Bob that an unsupported method was used for starting key verification. The
|
||||||
|
prompt for Bob to accept/reject Alice's request (or the unsupported method prompt)
|
||||||
|
should be automatically dismissed 10 minutes after the ``timestamp`` field or 2
|
||||||
|
minutes after Bob's client receives the message, whichever comes first, if Bob
|
||||||
|
does not interact with the prompt. The prompt should additionally be hidden if
|
||||||
|
an appropriate ``m.key.verification.cancel`` message is received.
|
||||||
|
|
||||||
|
If Bob rejects the request, Bob's client must send a ``m.key.verification.cancel``
|
||||||
|
message to Alice's device. Upon receipt, Alice's device should tell her that Bob
|
||||||
|
does not want to verify her device and send ``m.key.verification.cancel`` messages
|
||||||
|
to all of Bob's devices to notify them that the request was rejected.
|
||||||
|
|
||||||
|
If Bob accepts the request, Bob's device starts the key verification process by
|
||||||
|
sending a ``m.key.verification.start`` message to Alice's device. Upon receipt
|
||||||
|
of this message, Alice's device should send a ``m.key.verification.cancel`` message
|
||||||
|
to all of Bob's other devices to indicate the process has been started. The start
|
||||||
|
message must use the same ``transaction_id`` from the original key verification
|
||||||
|
request if it is in response to the request. The start message can be sent indepdently
|
||||||
|
of any request.
|
||||||
|
|
||||||
|
Individual verification methods may add additional steps, events, and properties to
|
||||||
|
the verification messages. Event types for methods defined in this specification must
|
||||||
|
be under the ``m.key.verification`` namespace and any other event types must be namespaced
|
||||||
|
according to the Java package naming convention.
|
||||||
|
|
||||||
|
Any of Alice's or Bob's devices can cancel the key verification request or process
|
||||||
|
at any time with a ``m.key.verification.cancel`` message to all applicable devices.
|
||||||
|
|
||||||
|
This framework yields the following handshake, assuming both Alice and Bob each have
|
||||||
|
2 devices, Bob's first device accepts the key verification request, and Alice's second
|
||||||
|
device initiates the request. Note how Alice's first device is not involved in the
|
||||||
|
request or verification process.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
+---------------+ +---------------+ +-------------+ +-------------+
|
||||||
|
| AliceDevice1 | | AliceDevice2 | | BobDevice1 | | BobDevice2 |
|
||||||
|
+---------------+ +---------------+ +-------------+ +-------------+
|
||||||
|
| | | |
|
||||||
|
| | m.key.verification.request | |
|
||||||
|
| |---------------------------------->| |
|
||||||
|
| | | |
|
||||||
|
| | m.key.verification.request | |
|
||||||
|
| |-------------------------------------------------->|
|
||||||
|
| | | |
|
||||||
|
| | m.key.verification.start | |
|
||||||
|
| |<----------------------------------| |
|
||||||
|
| | | |
|
||||||
|
| | m.key.verification.cancel | |
|
||||||
|
| |-------------------------------------------------->|
|
||||||
|
| | | |
|
||||||
|
|
||||||
|
|
||||||
|
After the handshake, the verification process begins.
|
||||||
|
|
||||||
|
{{m_key_verification_request_event}}
|
||||||
|
|
||||||
|
{{m_key_verification_start_event}}
|
||||||
|
|
||||||
|
{{m_key_verification_cancel_event}}
|
||||||
|
|
||||||
|
|
||||||
|
.. _`SAS Verification`:
|
||||||
|
|
||||||
|
Short Authentication String (SAS) verification
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
SAS verification is a user-friendly key verification process built off the common
|
||||||
|
framework outlined above. SAS verification is intended to be a highly interactive
|
||||||
|
process for users, and as such exposes verfiication methods which are easier for
|
||||||
|
users to use.
|
||||||
|
|
||||||
|
The verification process is heavily inspired by Phil Zimmerman's ZRTP key agreement
|
||||||
|
handshake. A key part of key agreement in ZRTP is the hash commitment: the party that
|
||||||
|
begins the Diffie-Hellman key sharing sends a hash of their part of the Diffie-Hellman
|
||||||
|
exchange, and does not send their part of the Diffie-Hellman exchange until they have
|
||||||
|
received the other party's part. Thus an attacker essentially only has one attempt to
|
||||||
|
attack the Diffie-Hellman exchange, and hence we can verify fewer bits while still
|
||||||
|
achieving a high degree of security: if we verify n bits, then an attacker has a 1 in
|
||||||
|
2\ :sup:`n` chance of success. For example, if we verify 40 bits, then an attacker has
|
||||||
|
a 1 in 1,099,511,627,776 chance (or less than 1 in 1012 chance) of success. A failed
|
||||||
|
attack would result in a mismatched Short Authentication String, alerting users to the
|
||||||
|
attack.
|
||||||
|
|
||||||
|
The verification process takes place over `to-device`_ messages in two phases:
|
||||||
|
|
||||||
|
1. Key agreement phase (based on `ZRTP key agreement <https://tools.ietf.org/html/rfc6189#section-4.4.1>`_).
|
||||||
|
#. Key verification phase (based on HMAC).
|
||||||
|
|
||||||
|
The process between Alice and Bob verifying each other would be:
|
||||||
|
|
||||||
|
.. |AlicePublicKey| replace:: :math:`K_{A}^{public}`
|
||||||
|
.. |AlicePrivateKey| replace:: :math:`K_{A}^{private}`
|
||||||
|
.. |AliceCurve25519| replace:: :math:`K_{A}^{private},K_{A}^{public}`
|
||||||
|
.. |BobPublicKey| replace:: :math:`K_{B}^{public}`
|
||||||
|
.. |BobPrivateKey| replace:: :math:`K_{B}^{private}`
|
||||||
|
.. |BobCurve25519| replace:: :math:`K_{B}^{private},K_{B}^{public}`
|
||||||
|
.. |BobAliceCurve25519| replace:: :math:`K_{B}^{private}K_{A}^{public}`
|
||||||
|
.. |AliceBobECDH| replace:: :math:`ECDH(K_{A}^{private},K_{B}^{public})`
|
||||||
|
|
||||||
|
1. Alice and Bob establish a secure out-of-band connection, such as meeting
|
||||||
|
in-person or a video call. "Secure" here means that either party cannot be
|
||||||
|
impersonated, not explicit secrecy.
|
||||||
|
#. Alice and Bob communicate which devices they'd like to verify with each other.
|
||||||
|
#. Alice selects Bob's device from the device list and begins verification.
|
||||||
|
#. Alice's client ensures it has a copy of Bob's device key.
|
||||||
|
#. Alice's device sends Bob's device a ``m.key.verification.start`` message.
|
||||||
|
#. Bob's device receives the message and selects a key agreement protocol, hash
|
||||||
|
algorithm, message authentication code, and SAS method supported by Alice's
|
||||||
|
device.
|
||||||
|
#. Bob's device ensures it has a copy of Alice's device key.
|
||||||
|
#. Bob's device creates an ephemeral Curve25519 key pair (|BobCurve25519|), and
|
||||||
|
calculates the hash (using the chosen algorithm) of the public key |BobPublicKey|.
|
||||||
|
#. Bob's device replies to Alice's device with a ``m.key.verification.accept`` message.
|
||||||
|
#. Alice's device receives Bob's message and stores the commitment hash for later use.
|
||||||
|
#. Alice's device creates an ephemeral Curve25519 key pair (|AliceCurve25519|) and
|
||||||
|
replies to Bob's device with a ``m.key.verification.key``, sending only the public
|
||||||
|
key |AlicePublicKey|.
|
||||||
|
#. Bob's device receives Alice's message and replies with its own ``m.key.verification.key``
|
||||||
|
message containing its public key |BobPublicKey|.
|
||||||
|
#. Alice's device receives Bob's message and verifies the commitment hash from earlier
|
||||||
|
matches the hash of the key Bob's device just sent and the content of Alice's
|
||||||
|
``m.key.verification.start`` message.
|
||||||
|
#. Both Alice and Bob's devices perform an Elliptic-curve Diffie-Hellman (|AliceBobECDH|),
|
||||||
|
using the result as the shared secret.
|
||||||
|
#. Both Alice and Bob's devices display a SAS to their users, which is derived
|
||||||
|
from the shared key using one of the methods in this section. If multiple SAS
|
||||||
|
methods are available, clients should allow the users to select a method.
|
||||||
|
#. Alice and Bob compare the strings shown by their devices, and tell their devices if
|
||||||
|
they match or not.
|
||||||
|
#. Assuming they match, Alice and Bob's devices calculate the HMAC of their own device keys
|
||||||
|
and a comma-separated sorted list of of the key IDs that they wish the other user
|
||||||
|
to verify, using SHA-256 as the hash function. HMAC is defined in [RFC 2104](https://tools.ietf.org/html/rfc2104).
|
||||||
|
The key for the HMAC is different for each item and is calculated by generating
|
||||||
|
32 bytes (256 bits) using `the key verification HKDF <#SAS-HKDF>`_.
|
||||||
|
#. Alice's device sends Bob's device a ``m.key.verification.mac`` message containing the
|
||||||
|
MAC of Alice's device keys and the MAC of her key IDs to be verified. Bob's device does
|
||||||
|
the same for Bob's device keys and key IDs concurrently with Alice.
|
||||||
|
#. When the other device receives the ``m.key.verification.mac`` message, the device
|
||||||
|
calculates the HMAC of its copies of the other device's keys given in the message,
|
||||||
|
as well as the HMAC of the comma-seperated, sorted, list of key IDs in the message.
|
||||||
|
The device compares these with the HMAC values given in the message, and if everything
|
||||||
|
matches then the device keys are verified.
|
||||||
|
|
||||||
|
The wire protocol looks like the following between Alice and Bob's devices::
|
||||||
|
|
||||||
|
+-------------+ +-----------+
|
||||||
|
| AliceDevice | | BobDevice |
|
||||||
|
+-------------+ +-----------+
|
||||||
|
| |
|
||||||
|
| m.key.verification.start |
|
||||||
|
|-------------------------------->|
|
||||||
|
| |
|
||||||
|
| m.key.verification.accept |
|
||||||
|
|<--------------------------------|
|
||||||
|
| |
|
||||||
|
| m.key.verification.key |
|
||||||
|
|-------------------------------->|
|
||||||
|
| |
|
||||||
|
| m.key.verification.key |
|
||||||
|
|<--------------------------------|
|
||||||
|
| |
|
||||||
|
| m.key.verification.mac |
|
||||||
|
|-------------------------------->|
|
||||||
|
| |
|
||||||
|
| m.key.verification.mac |
|
||||||
|
|<--------------------------------|
|
||||||
|
| |
|
||||||
|
|
||||||
|
Error and exception handling
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
At any point the interactive verfication can go wrong. The following describes what
|
||||||
|
to do when an error happens:
|
||||||
|
|
||||||
|
* Alice or Bob can cancel the verification at any time. A ``m.key.verification.cancel``
|
||||||
|
message must be sent to signify the cancellation.
|
||||||
|
* The verification can time out. Clients should time out a verification that does not
|
||||||
|
complete within 10 minutes. Additionally, clients should expire a ``transaction_id``
|
||||||
|
which goes unused for 10 minutes after having last sent/received it. The client should
|
||||||
|
inform the user that the verification timed out, and send an appropriate
|
||||||
|
``m.key.verification.cancel`` message to the other device.
|
||||||
|
* When the same device attempts to intiate multiple verification attempts, the receipient
|
||||||
|
should cancel all attempts with that device.
|
||||||
|
* When a device receives an unknown ``transaction_id``, it should send an appropriate
|
||||||
|
``m.key.verfication.cancel`` message to the other device indicating as such. This
|
||||||
|
does not apply for inbound ``m.key.verification.start`` or ``m.key.verification.cancel``
|
||||||
|
messages.
|
||||||
|
* If the two devices do not share a common key share, hash, HMAC, or SAS method then
|
||||||
|
the device should notify the other device with an appropriate ``m.key.verification.cancel``
|
||||||
|
message.
|
||||||
|
* If the user claims the Short Authentication Strings do not match, the device should
|
||||||
|
send an appropriate ``m.key.verification.cancel`` message to the other device.
|
||||||
|
* If the device receives a message out of sequence or that it was not expecting, it should
|
||||||
|
notify the other device with an appropriate ``m.key.verification.cancel`` message.
|
||||||
|
|
||||||
|
|
||||||
|
Verification messages specific to SAS
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
Building off the common framework, the following events are involved in SAS verification.
|
||||||
|
|
||||||
|
The ``m.key.verification.cancel`` event is unchanged, however the following error codes
|
||||||
|
are used in addition to those already specified:
|
||||||
|
|
||||||
|
* ``m.unknown_method``: The devices are unable to agree on the key agreement, hash, MAC,
|
||||||
|
or SAS method.
|
||||||
|
* ``m.mismatched_commitment``: The hash commitment did not match.
|
||||||
|
* ``m.mismatched_sas``: The SAS did not match.
|
||||||
|
|
||||||
|
|
||||||
|
{{m_key_verification_start_m_sas_v1_event}}
|
||||||
|
|
||||||
|
{{m_key_verification_accept_event}}
|
||||||
|
|
||||||
|
{{m_key_verification_key_event}}
|
||||||
|
|
||||||
|
{{m_key_verification_mac_event}}
|
||||||
|
|
||||||
|
|
||||||
|
.. _`SAS-HKDF`:
|
||||||
|
|
||||||
|
HKDF calculation
|
||||||
|
<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
In all of the SAS methods, HKDF is as defined in [RFC 5869](https://tools.ietf.org/html/rfc5869)
|
||||||
|
and uses the previously agreed-upon hash function for the hash function. The shared
|
||||||
|
secret is supplied as the input keying material. No salt is used, and the input
|
||||||
|
parameter is the concatenation of:
|
||||||
|
|
||||||
|
* The string ``MATRIX_KEY_VERIFICATION_SAS``.
|
||||||
|
* The Matrix ID of the user who sent the ``m.key.verification.start`` message.
|
||||||
|
* The Device ID of the device which sent the ``m.key.verification.start`` message.
|
||||||
|
* The Matrix ID of the user who sent the ``m.key.verification.accept`` message.
|
||||||
|
* The Device ID of the device which sent the ``m.key.verification.accept`` message.
|
||||||
|
* The ``transaction_id`` being used.
|
||||||
|
|
||||||
|
.. admonition:: Rationale
|
||||||
|
HKDF is used over the plain shared secret as it results in a harder attack
|
||||||
|
as well as more uniform data to work with.
|
||||||
|
|
||||||
|
For verification of each party's device keys, HKDF is as defined in RFC 5869 and
|
||||||
|
uses SHA-256 as the hash function. The shared secret is supplied as the input keying
|
||||||
|
material. No salt is used, and in the input parameter is the concatenation of:
|
||||||
|
|
||||||
|
* The string ``MATRIX_KEY_VERIFICATION_MAC``.
|
||||||
|
* The Matrix ID of the user whose key is being MAC-ed.
|
||||||
|
* The Device ID of the device sending the MAC.
|
||||||
|
* The Matrix ID of the other user.
|
||||||
|
* The Device ID of the device receiving the MAC.
|
||||||
|
* The ``transaction_id`` being used.
|
||||||
|
* The Key ID of the key being MAC-ed, or the string ``KEY_IDS`` if the item
|
||||||
|
being MAC-ed is the list of key IDs.
|
||||||
|
|
||||||
|
SAS method: ``decimal``
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
Generate 5 bytes using `HKDF <#SAS-HKDF>`_ then take sequences of 13 bits to
|
||||||
|
convert to decimal numbers (resulting in 3 numbers between 0 and 8191 inclusive
|
||||||
|
each). Add 1000 to each calculated number.
|
||||||
|
|
||||||
|
The bitwise operations to get the numbers given the 5 bytes
|
||||||
|
:math:`B_{0}, B_{1}, B_{2}, B_{3}, B_{4}` would be:
|
||||||
|
|
||||||
|
* First: :math:`(B_{0} \ll 5 | B_{1} \gg 3) + 1000`
|
||||||
|
* Second: :math:`((B_{1} \& 0x7) \ll 10 | B_{2} \ll 2 | B_{3} \gg 6) + 1000`
|
||||||
|
* Third: :math:`((B_{3} \& 0x3F) \ll 7 | B_{4} \gg 1) + 1000`
|
||||||
|
|
||||||
|
The digits are displayed to the user either with an appropriate separator,
|
||||||
|
such as dashes, or with the numbers on individual lines.
|
||||||
|
|
||||||
|
SAS method: ``emoji``
|
||||||
|
<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
Generate 6 bytes using `HKDF <#SAS-HKDF>`_ then split the first 42 bits into
|
||||||
|
7 groups of 6 bits, similar to how one would base64 encode something. Convert
|
||||||
|
each group of 6 bits to a number and use the following table to get the corresponding
|
||||||
|
emoji:
|
||||||
|
|
||||||
|
{{sas_emoji_table}}
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
This table is available as JSON at
|
||||||
|
https://github.com/matrix-org/matrix-doc/blob/master/data-definitions/sas-emoji.json
|
||||||
|
|
||||||
|
.. admonition:: Rationale
|
||||||
|
|
||||||
|
The emoji above were chosen to:
|
||||||
|
|
||||||
|
* Be recognisable without colour.
|
||||||
|
* Be recognisable at a small size.
|
||||||
|
* Be recognisable by most cultures.
|
||||||
|
* Be distinguishable from each other.
|
||||||
|
* Easily described by a few words.
|
||||||
|
* Avoid symbols with negative connotations.
|
||||||
|
* Be likely similar across multiple platforms.
|
||||||
|
|
||||||
|
Clients SHOULD show the emoji with the descriptions from the table, or appropriate
|
||||||
|
translation of those descriptions. Client authors SHOULD collaborate to create a
|
||||||
|
common set of translations for all languages.
|
||||||
|
|
||||||
|
|
||||||
.. section name changed, so make sure that old links keep working
|
.. section name changed, so make sure that old links keep working
|
||||||
.. _key-sharing:
|
.. _key-sharing:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,10 @@ everyone, having the proposal being accepted, then actually having your ideas
|
||||||
implemented as committed changes to the `Specification repository
|
implemented as committed changes to the `Specification repository
|
||||||
<https://github.com/matrix-org/matrix-doc>`_.
|
<https://github.com/matrix-org/matrix-doc>`_.
|
||||||
|
|
||||||
.. TODO: Replace GH team link with https://matrix.org/foundation or something
|
|
||||||
|
|
||||||
Meet the `members of the Core Team
|
Meet the `members of the Core Team
|
||||||
<https://github.com/orgs/matrix-org/teams/spec-core-team/members>`_, a group of
|
<https://matrix.org/foundation>`_, a group of
|
||||||
individuals tasked with ensuring the spec process is as smooth and painless as
|
individuals tasked with ensuring the spec process is as smooth and painless as
|
||||||
possible. Members of the Core Team will do their best to participate in
|
possible. Members of the Spec Core Team will do their best to participate in
|
||||||
discussion, summarise when things become long-winded, and generally try to act
|
discussion, summarise when things become long-winded, and generally try to act
|
||||||
towards the benefit of everyone. As a majority, team members have the ability
|
towards the benefit of everyone. As a majority, team members have the ability
|
||||||
to change the state of a proposal, and individually have the final say in
|
to change the state of a proposal, and individually have the final say in
|
||||||
|
|
@ -59,13 +57,21 @@ the first place.
|
||||||
* the number of online servers in the open federation
|
* the number of online servers in the open federation
|
||||||
* the number of developers building on Matrix
|
* the number of developers building on Matrix
|
||||||
* the number of independent implementations which use Matrix
|
* the number of independent implementations which use Matrix
|
||||||
* the quality and utility of the Matrix spec
|
* the number of bridged end-users reachable on the open Matrix network
|
||||||
|
* the signal-to-noise ratio of the content on the open Matrix network (i.e. minimising spam)
|
||||||
|
* the ability for users to discover content on their terms (empowering them to select what to see and what not to see)
|
||||||
|
* the quality and utility of the Matrix spec (as defined by ease and ability
|
||||||
|
with which a developer can implement spec-compliant clients, servers, bots,
|
||||||
|
bridges, and other integrations without needing to refer to any other
|
||||||
|
external material)
|
||||||
|
|
||||||
In addition, proposal authors are expected to uphold the following values in
|
In addition, proposal authors are expected to uphold the following values in
|
||||||
their proposed changes to the Matrix protocol:
|
their proposed changes to the Matrix protocol:
|
||||||
|
|
||||||
* Supporting the whole long-term ecosystem rather than individual stakeholder gain
|
* Supporting the whole long-term ecosystem rather than individual stakeholder gain
|
||||||
* Openness rather than proprietariness
|
* Openness rather than proprietary lock-in
|
||||||
|
* Interoperability rather than fragmentation
|
||||||
|
* Cross-platform rather than platform-specific
|
||||||
* Collaboration rather than competition
|
* Collaboration rather than competition
|
||||||
* Accessibility rather than elitism
|
* Accessibility rather than elitism
|
||||||
* Transparency rather than stealth
|
* Transparency rather than stealth
|
||||||
|
|
@ -73,6 +79,89 @@ their proposed changes to the Matrix protocol:
|
||||||
* Pragmatism rather than perfection
|
* Pragmatism rather than perfection
|
||||||
* Proof rather than conjecture
|
* Proof rather than conjecture
|
||||||
|
|
||||||
|
Please see [MSC1779](https://github.com/matrix-org/matrix-doc/blob/matthew/msc1779/proposals/1779-open-governance.md)
|
||||||
|
for full details of the project's Guiding Principles.
|
||||||
|
|
||||||
|
Technical notes
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Proposals **must** develop Matrix as a layered protocol: with new features
|
||||||
|
building on layers of shared abstractions rather than introducing tight vertical
|
||||||
|
coupling within the stack. This ensures that new features can evolve rapidly by
|
||||||
|
building on existing layers and swapping out old features without impacting the
|
||||||
|
rest of the stack or requiring substantial upgrades to the whole ecosystem.
|
||||||
|
This is critical for Matrix to rapidly evolve and compete effectively with
|
||||||
|
centralised systems, despite being a federated protocol.
|
||||||
|
|
||||||
|
For instance, new features should be implemented using the highest layer
|
||||||
|
abstractions possible (e.g. new event types, which layer on top of the existing
|
||||||
|
room semantics, and so don't even require any API changes). Failing that, the
|
||||||
|
next recourse would be backwards-compatible changes to the next layer down (e.g.
|
||||||
|
room APIs); failing that, considering changes to the format of events or the
|
||||||
|
DAG; etc. It would be a very unusual feature which doesn't build on the
|
||||||
|
existing infrastructure provided by the spec and instead created new primitives
|
||||||
|
or low level APIs.
|
||||||
|
|
||||||
|
Backwards compatibility is very important for Matrix, but not at the expense of
|
||||||
|
hindering the protocol's evolution. Backwards incompatible changes to endpoints
|
||||||
|
are allowed when no other alternative exists, and must be versioned under a new
|
||||||
|
major release of the API. Backwards incompatible changes to the room algorithm
|
||||||
|
are also allowed when no other alternative exists, and must be versioned under a
|
||||||
|
new version of the room algorithm.
|
||||||
|
|
||||||
|
There is sometimes a dilemma over where to include higher level features: for
|
||||||
|
instance, should video conferencing be formalised in the spec, or should it be
|
||||||
|
implemented via widgets? Should reputation systems be specified? Should search
|
||||||
|
engine behaviour be specified?
|
||||||
|
|
||||||
|
There is no universal answer to this, but the following guidelines should be
|
||||||
|
applied:
|
||||||
|
|
||||||
|
1. If the feature would benefit the whole Matrix ecosystem and is aligned with
|
||||||
|
the guiding principles above, then it should be supported by the spec.
|
||||||
|
2. If the spec already makes the feature possible without changing any of the
|
||||||
|
implementations and spec, then it may not need to be added to the spec.
|
||||||
|
3. However, if the best user experience for a feature does require custom
|
||||||
|
implementation behaviour then the behaviour should be defined in the spec
|
||||||
|
such that all implementations may implement it.
|
||||||
|
4. However, the spec must never add dependencies on unspecified/nonstandardised
|
||||||
|
3rd party behaviour.
|
||||||
|
|
||||||
|
As a worked example:
|
||||||
|
|
||||||
|
1. Video conferencing is clearly a feature which would benefit
|
||||||
|
the whole ecosystem, and so the spec should find a way to make it happen.
|
||||||
|
2. Video conferencing can be achieved by widgets without requiring any
|
||||||
|
compulsory changes to changes to clients nor servers to work, and so could be
|
||||||
|
omitted from the spec.
|
||||||
|
3. A better experience could be achieved by embedding Jitsi natively into clients
|
||||||
|
rather than using a widget...
|
||||||
|
4. ...except that would add a dependency on unspecified/nonstandardised 3rd party
|
||||||
|
behaviour, so must not be added to the spec.
|
||||||
|
|
||||||
|
Therefore, our two options in the specific case of video conferencing are
|
||||||
|
either to spec SFU conferencing semantics for WebRTC (or refer to an existing spec
|
||||||
|
for doing so), or to keep it as a widget-based approach (optionally with widget
|
||||||
|
extensions specific for more deeply integrating video conferencing use cases).
|
||||||
|
|
||||||
|
As an alternative example: it's very unlikely that "how to visualise Magnetic
|
||||||
|
Resonsance Imaging data over Matrix" would ever be added to the Matrix spec
|
||||||
|
(other than perhaps a custom event type in a wider standardised Matrix event
|
||||||
|
registry) given that the spec's existing primitives of file transfer and
|
||||||
|
extensible events (MSC1767) give excellent tools for transfering and
|
||||||
|
visualising arbitrary rich data.
|
||||||
|
|
||||||
|
Supporting public search engines are likely to not require custom spec features
|
||||||
|
(other than possibly better bulk access APIs), given they can be implemented as
|
||||||
|
clients using the existing CS API. An exception could be API features required
|
||||||
|
by decentralised search infrastructure (avoiding centralisation of power by
|
||||||
|
a centralised search engine).
|
||||||
|
|
||||||
|
Features such as reactions, threaded messages, editable messages,
|
||||||
|
spam/abuse/content filtering (and reputation systems), are all features which
|
||||||
|
would clearly benefit the whole Matrix ecosystem, and cannot be implemented in an
|
||||||
|
interoperable way using the current spec; so they necessitate a spec change.
|
||||||
|
|
||||||
Process
|
Process
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
@ -131,25 +220,25 @@ follows:
|
||||||
viewpoints and get consensus, but this can sometimes be time-consuming (or
|
viewpoints and get consensus, but this can sometimes be time-consuming (or
|
||||||
the author may be biased), in which case an impartial 'shepherd' can be
|
the author may be biased), in which case an impartial 'shepherd' can be
|
||||||
assigned to help guide the proposal through this process instead. A shepherd is
|
assigned to help guide the proposal through this process instead. A shepherd is
|
||||||
typically a neutral party from the Core Team or an experienced member of
|
typically a neutral party from the Spec Core Team or an experienced member of
|
||||||
the community. There is no formal process for assignment. Simply ask for a
|
the community. There is no formal process for assignment. Simply ask for a
|
||||||
shepherd to help get your proposal through and one will be assigned based
|
shepherd to help get your proposal through and one will be assigned based
|
||||||
on availability. Having a shepherd is not a requirement for proposal
|
on availability. Having a shepherd is not a requirement for proposal
|
||||||
acceptance.
|
acceptance.
|
||||||
|
|
||||||
- Members of the Core Team and community will review and discuss the PR in the
|
- Members of the Spec Core Team and community will review and discuss the PR in the
|
||||||
comments and in relevant rooms on Matrix. Discussion outside of GitHub should
|
comments and in relevant rooms on Matrix. Discussion outside of GitHub should
|
||||||
be summarised in a comment on the PR.
|
be summarised in a comment on the PR.
|
||||||
- When a member of the Core Team believes that no new discussion points are
|
- When a member of the Spec Core Team believes that no new discussion points are
|
||||||
being made, they will propose a motion for a final comment period (FCP),
|
being made, they will propose a motion for a final comment period (FCP),
|
||||||
along with a *disposition* of either merge, close or postpone. This FCP is
|
along with a *disposition* of either merge, close or postpone. This FCP is
|
||||||
provided to allow a short period of time for any invested party to provide a
|
provided to allow a short period of time for any invested party to provide a
|
||||||
final objection before a major decision is made. If sufficient reasoning is
|
final objection before a major decision is made. If sufficient reasoning is
|
||||||
given, an FCP can be cancelled. It is often preceded by a comment summarising
|
given, an FCP can be cancelled. It is often preceded by a comment summarising
|
||||||
the current state of the discussion, along with reasoning for its occurrence.
|
the current state of the discussion, along with reasoning for its occurrence.
|
||||||
- A concern can be raised by a Core Team member at any time, which will block
|
- A concern can be raised by a Spec Core Team member at any time, which will block
|
||||||
an FCP from beginning. An FCP will only begin when a **75% majority** of core
|
an FCP from beginning. An FCP will only begin when 75% of the members of the
|
||||||
team members agree on its outcome, and all existing concerns have been
|
Spec Core Team team agree on its outcome, and all existing concerns have been
|
||||||
resolved.
|
resolved.
|
||||||
- The FCP will then begin and last for 5 days, giving anyone else some time to
|
- The FCP will then begin and last for 5 days, giving anyone else some time to
|
||||||
speak up before it concludes. On its conclusion, the disposition of the FCP
|
speak up before it concludes. On its conclusion, the disposition of the FCP
|
||||||
|
|
@ -239,7 +328,7 @@ Lifetime States
|
||||||
Name GitHub Label Description
|
Name GitHub Label Description
|
||||||
=============================== ============================= ====================================
|
=============================== ============================= ====================================
|
||||||
Proposal Drafting and Feedback N/A A proposal document which is still work-in-progress but is being shared to incorporate feedback. Please prefix your proposal's title with ``[WIP]`` to make it easier for reviewers to skim their notifications list.
|
Proposal Drafting and Feedback N/A A proposal document which is still work-in-progress but is being shared to incorporate feedback. Please prefix your proposal's title with ``[WIP]`` to make it easier for reviewers to skim their notifications list.
|
||||||
Proposal In Review proposal-in-review A proposal document which is now ready and waiting for review by the Core Team and community
|
Proposal In Review proposal-in-review A proposal document which is now ready and waiting for review by the Spec Core Team and community
|
||||||
Proposed Final Comment Period proposed-final-comment-period Currently awaiting signoff of a 75% majority of team members in order to enter the final comment period
|
Proposed Final Comment Period proposed-final-comment-period Currently awaiting signoff of a 75% majority of team members in order to enter the final comment period
|
||||||
Final Comment Period final-comment-period A proposal document which has reached final comment period either for merge, closure or postponement
|
Final Comment Period final-comment-period A proposal document which has reached final comment period either for merge, closure or postponement
|
||||||
Final Commment Period Complete finished-final-comment-period The final comment period has been completed. Waiting for a demonstration implementation
|
Final Commment Period Complete finished-final-comment-period The final comment period has been completed. Waiting for a demonstration implementation
|
||||||
|
|
@ -261,7 +350,7 @@ pull request trackers of the `matrix-doc
|
||||||
<https://github.com/matrix-org/matrix-doc>`_ repo.
|
<https://github.com/matrix-org/matrix-doc>`_ repo.
|
||||||
|
|
||||||
We use labels and some metadata in MSC PR descriptions to generate this page.
|
We use labels and some metadata in MSC PR descriptions to generate this page.
|
||||||
Labels are assigned by the Core Team whilst triaging the proposals based on those
|
Labels are assigned by the Spec Core Team whilst triaging the proposals based on those
|
||||||
which exist in the `matrix-doc <https://github.com/matrix-org/matrix-doc>`_
|
which exist in the `matrix-doc <https://github.com/matrix-org/matrix-doc>`_
|
||||||
repo already.
|
repo already.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -293,5 +293,5 @@ Events in version 1 rooms have the following structure:
|
||||||
{{definition_ss_pdu}}
|
{{definition_ss_pdu}}
|
||||||
|
|
||||||
|
|
||||||
.. _`auth events selection`: ../../server_server/r0.1.1.html#auth-events-selection
|
.. _`auth events selection`: ../server_server/r0.1.1.html#auth-events-selection
|
||||||
.. _`Signing Events`: ../../server_server/r0.1.1.html#signing-events
|
.. _`Signing Events`: ../server_server/r0.1.1.html#signing-events
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,17 @@ The following other versions are also available, in reverse chronological order:
|
||||||
- `r0.1.1 <https://matrix.org/docs/spec/server_server/r0.1.1.html>`_
|
- `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>`_
|
- `r0.1.0 <https://matrix.org/docs/spec/server_server/r0.1.0.html>`_
|
||||||
|
|
||||||
|
|
||||||
|
API standards
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The mandatory baseline for client-server communication in Matrix is exchanging
|
||||||
|
JSON objects over HTTP APIs. More efficient optional transports will in future
|
||||||
|
be supported as optional extensions - e.g. a packed binary encoding over
|
||||||
|
stream-cipher encrypted TCP socket for low-bandwidth/low-roundtrip mobile usage.
|
||||||
|
For the default HTTP transport, all API calls use a Content-Type of
|
||||||
|
``application/json``. In addition, all strings MUST be encoded as UTF-8.
|
||||||
|
|
||||||
Server discovery
|
Server discovery
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
@ -421,9 +432,8 @@ must ensure that the event:
|
||||||
Further details of these checks, and how to handle failures, are described
|
Further details of these checks, and how to handle failures, are described
|
||||||
below.
|
below.
|
||||||
|
|
||||||
.. TODO:
|
The `Signing Events <#signing-events>`_ section has more information on which hashes
|
||||||
Flesh this out a bit more, and probably change the doc to group the various
|
and signatures are expected on events, and how to calculate them.
|
||||||
checks in one place, rather than have them spread out.
|
|
||||||
|
|
||||||
|
|
||||||
Definitions
|
Definitions
|
||||||
|
|
@ -1099,6 +1109,15 @@ originating server, following the algorithm described in `Checking for a signatu
|
||||||
Note that this step should succeed whether we have been sent the full event or
|
Note that this step should succeed whether we have been sent the full event or
|
||||||
a redacted copy.
|
a redacted copy.
|
||||||
|
|
||||||
|
The signatures expected on an event are:
|
||||||
|
|
||||||
|
* The ``sender``'s server, unless the invite was created as a result of 3rd party invite.
|
||||||
|
The sender must already match the 3rd party invite, and the server which actually
|
||||||
|
sends the event may be a different server.
|
||||||
|
* For room versions 1 and 2, the server which created the ``event_id``. Other room
|
||||||
|
versions do not track the ``event_id`` over federation and therefore do not need
|
||||||
|
a signature from those servers.
|
||||||
|
|
||||||
If the signature is found to be valid, the expected content hash is calculated
|
If the signature is found to be valid, the expected content hash is calculated
|
||||||
as described below. The content hash in the ``hashes`` property of the received
|
as described below. The content hash in the ``hashes`` property of the received
|
||||||
event is base64-decoded, and the two are compared for equality.
|
event is base64-decoded, and the two are compared for equality.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue