Merge remote-tracking branch 'matrix-org/master' into travis/general/r0-prep
This commit is contained in:
commit
2753d24302
32 changed files with 486 additions and 95 deletions
18
api/application-service/definitions/security.yaml
Normal file
18
api/application-service/definitions/security.yaml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright 2018 New Vector Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
homeserverAccessToken:
|
||||||
|
type: apiKey
|
||||||
|
description: The ``hs_token`` provided by the application service's registration.
|
||||||
|
name: access_token
|
||||||
|
in: query
|
|
@ -19,13 +19,15 @@ host: localhost:8008
|
||||||
schemes:
|
schemes:
|
||||||
- https
|
- https
|
||||||
- http
|
- http
|
||||||
basePath: "/"
|
basePath: /_matrix/app/v1
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
paths:
|
paths:
|
||||||
"/_matrix/app/unstable/thirdparty/protocol/{protocol}":
|
"/thirdparty/protocol/{protocol}":
|
||||||
get:
|
get:
|
||||||
summary: Retrieve metadata about a specific protocol that the application service supports.
|
summary: Retrieve metadata about a specific protocol that the application service supports.
|
||||||
description: |-
|
description: |-
|
||||||
|
@ -33,6 +35,8 @@ paths:
|
||||||
with specific information about the various third party networks that
|
with specific information about the various third party networks that
|
||||||
an application service supports.
|
an application service supports.
|
||||||
operationId: getProtocolMetadata
|
operationId: getProtocolMetadata
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: protocol
|
name: protocol
|
||||||
|
@ -72,7 +76,7 @@ paths:
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
$ref: ../client-server/definitions/errors/error.yaml
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
"/_matrix/app/unstable/thirdparty/user/{protocol}":
|
"/thirdparty/user/{protocol}":
|
||||||
get:
|
get:
|
||||||
summary: Retrieve the Matrix User ID of a corresponding third party user.
|
summary: Retrieve the Matrix User ID of a corresponding third party user.
|
||||||
description: |-
|
description: |-
|
||||||
|
@ -80,6 +84,8 @@ paths:
|
||||||
User ID linked to a user on the third party network, given a set of
|
User ID linked to a user on the third party network, given a set of
|
||||||
user parameters.
|
user parameters.
|
||||||
operationId: queryUserByProtocol
|
operationId: queryUserByProtocol
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: protocol
|
name: protocol
|
||||||
|
@ -125,12 +131,14 @@ paths:
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
$ref: ../client-server/definitions/errors/error.yaml
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
"/_matrix/app/unstable/thirdparty/location/{protocol}":
|
"/thirdparty/location/{protocol}":
|
||||||
get:
|
get:
|
||||||
summary: Retrieve Matrix-side portal rooms leading to a third party location.
|
summary: Retrieve Matrix-side portal rooms leading to a third party location.
|
||||||
description: |-
|
description: |-
|
||||||
Retrieve a list of Matrix portal rooms that lead to the matched third party location.
|
Retrieve a list of Matrix portal rooms that lead to the matched third party location.
|
||||||
operationId: queryLocationByProtocol
|
operationId: queryLocationByProtocol
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: protocol
|
name: protocol
|
||||||
|
@ -176,13 +184,15 @@ paths:
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
$ref: ../client-server/definitions/errors/error.yaml
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
"/_matrix/app/unstable/thirdparty/location":
|
"/thirdparty/location":
|
||||||
get:
|
get:
|
||||||
summary: Reverse-lookup third party locations given a Matrix room alias.
|
summary: Reverse-lookup third party locations given a Matrix room alias.
|
||||||
description: |-
|
description: |-
|
||||||
Retrieve an array of third party network locations from a Matrix room
|
Retrieve an array of third party network locations from a Matrix room
|
||||||
alias.
|
alias.
|
||||||
operationId: queryLocationByAlias
|
operationId: queryLocationByAlias
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: query
|
- in: query
|
||||||
name: alias
|
name: alias
|
||||||
|
@ -221,12 +231,14 @@ paths:
|
||||||
}
|
}
|
||||||
schema:
|
schema:
|
||||||
$ref: ../client-server/definitions/errors/error.yaml
|
$ref: ../client-server/definitions/errors/error.yaml
|
||||||
"/_matrix/app/unstable/thirdparty/user":
|
"/thirdparty/user":
|
||||||
get:
|
get:
|
||||||
summary: Reverse-lookup third party users given a Matrix User ID.
|
summary: Reverse-lookup third party users given a Matrix User ID.
|
||||||
description: |-
|
description: |-
|
||||||
Retrieve an array of third party users from a Matrix User ID.
|
Retrieve an array of third party users from a Matrix User ID.
|
||||||
operationId: queryUserByID
|
operationId: queryUserByID
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: query
|
- in: query
|
||||||
name: userid
|
name: userid
|
||||||
|
|
|
@ -20,11 +20,13 @@ host: localhost:8008
|
||||||
schemes:
|
schemes:
|
||||||
- https
|
- https
|
||||||
- http
|
- http
|
||||||
basePath: "/"
|
basePath: /_matrix/app/v1
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
paths:
|
paths:
|
||||||
"/rooms/{roomAlias}":
|
"/rooms/{roomAlias}":
|
||||||
get:
|
get:
|
||||||
|
@ -36,6 +38,8 @@ paths:
|
||||||
homeserver will send this request when it receives a request to join a
|
homeserver will send this request when it receives a request to join a
|
||||||
room alias within the application service's namespace.
|
room alias within the application service's namespace.
|
||||||
operationId: queryRoomByAlias
|
operationId: queryRoomByAlias
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: roomAlias
|
name: roomAlias
|
||||||
|
|
|
@ -20,11 +20,13 @@ host: localhost:8008
|
||||||
schemes:
|
schemes:
|
||||||
- https
|
- https
|
||||||
- http
|
- http
|
||||||
basePath: "/"
|
basePath: /_matrix/app/v1
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
paths:
|
paths:
|
||||||
"/users/{userId}":
|
"/users/{userId}":
|
||||||
get:
|
get:
|
||||||
|
@ -36,6 +38,8 @@ paths:
|
||||||
send this request when it receives an event for an unknown user ID in
|
send this request when it receives an event for an unknown user ID in
|
||||||
the application service's namespace, such as a room invite.
|
the application service's namespace, such as a room invite.
|
||||||
operationId: queryUserById
|
operationId: queryUserById
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: userId
|
name: userId
|
||||||
|
|
|
@ -20,9 +20,11 @@ host: localhost:8008
|
||||||
schemes:
|
schemes:
|
||||||
- https
|
- https
|
||||||
- http
|
- http
|
||||||
basePath: "/"
|
basePath: /_matrix/app/v1
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
|
securityDefinitions:
|
||||||
|
$ref: definitions/security.yaml
|
||||||
paths:
|
paths:
|
||||||
"/transactions/{txnId}":
|
"/transactions/{txnId}":
|
||||||
put:
|
put:
|
||||||
|
@ -35,6 +37,8 @@ paths:
|
||||||
from message events via the presence of a ``state_key``, rather than
|
from message events via the presence of a ``state_key``, rather than
|
||||||
via the event type.
|
via the event type.
|
||||||
operationId: sendTransaction
|
operationId: sendTransaction
|
||||||
|
security:
|
||||||
|
- homeserverAccessToken: []
|
||||||
parameters:
|
parameters:
|
||||||
- in: path
|
- in: path
|
||||||
name: txnId
|
name: txnId
|
||||||
|
|
|
@ -87,6 +87,16 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
description: |-
|
description: |-
|
||||||
A unique identifier for the event.
|
A unique identifier for the event.
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The sender doesn't have permission to send the event into the room.
|
||||||
|
schema:
|
||||||
|
$ref: "definitions/errors/error.yaml"
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You do not have permission to send the event."
|
||||||
|
}
|
||||||
tags:
|
tags:
|
||||||
- Room participation
|
- Room participation
|
||||||
"/rooms/{roomId}/state/{eventType}":
|
"/rooms/{roomId}/state/{eventType}":
|
||||||
|
@ -142,5 +152,15 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
description: |-
|
description: |-
|
||||||
A unique identifier for the event.
|
A unique identifier for the event.
|
||||||
|
403:
|
||||||
|
description: |-
|
||||||
|
The sender doesn't have permission to send the event into the room.
|
||||||
|
schema:
|
||||||
|
$ref: "definitions/errors/error.yaml"
|
||||||
|
examples:
|
||||||
|
application/json: {
|
||||||
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You do not have permission to send the event."
|
||||||
|
}
|
||||||
tags:
|
tags:
|
||||||
- Room participation
|
- Room participation
|
||||||
|
|
|
@ -77,13 +77,14 @@ paths:
|
||||||
- in: query
|
- in: query
|
||||||
name: set_presence
|
name: set_presence
|
||||||
type: string
|
type: string
|
||||||
enum: ["offline"]
|
enum: ["offline", "online", "unavailable"]
|
||||||
description: |-
|
description: |-
|
||||||
Controls whether the client is automatically marked as online by
|
Controls whether the client is automatically marked as online by
|
||||||
polling this API. If this parameter is omitted then the client is
|
polling this API. If this parameter is omitted then the client is
|
||||||
automatically marked as online when it uses this API. Otherwise if
|
automatically marked as online when it uses this API. Otherwise if
|
||||||
the parameter is set to "offline" then the client is not marked as
|
the parameter is set to "offline" then the client is not marked as
|
||||||
being online when it uses this API.
|
being online when it uses this API. When set to "unavailable", the
|
||||||
|
client is marked as being idle.
|
||||||
x-example: "offline"
|
x-example: "offline"
|
||||||
- in: query
|
- in: query
|
||||||
name: timeout
|
name: timeout
|
||||||
|
|
|
@ -49,7 +49,8 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: |-
|
description: |-
|
||||||
The fully resolved state for the room, including the authorization
|
The fully resolved state for the room, prior to considering any state
|
||||||
|
changes induced by the requested event. Includes the authorization
|
||||||
chain for the events.
|
chain for the events.
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
@ -96,7 +97,8 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: |-
|
description: |-
|
||||||
The fully resolved state for the room, including the authorization
|
The fully resolved state for the room, prior to considering any state
|
||||||
|
changes induced by the requested event. Includes the authorization
|
||||||
chain for the events.
|
chain for the events.
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
0
changelogs/application_service.rst
Normal file
0
changelogs/application_service.rst
Normal file
1
changelogs/application_service/newsfragments/.gitignore
vendored
Normal file
1
changelogs/application_service/newsfragments/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
!.gitignore
|
30
changelogs/application_service/pyproject.toml
Normal file
30
changelogs/application_service/pyproject.toml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
[tool.towncrier]
|
||||||
|
filename = "../application_service.rst"
|
||||||
|
directory = "newsfragments"
|
||||||
|
issue_format = "`#{issue} <https://github.com/matrix-org/matrix-doc/issues/{issue}>`_"
|
||||||
|
title_format = "{version}"
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "breaking"
|
||||||
|
name = "Breaking Changes"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "deprecation"
|
||||||
|
name = "Deprecations"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "new"
|
||||||
|
name = "New Endpoints"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "feature"
|
||||||
|
name = "Backwards Compatible Changes"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "clarification"
|
||||||
|
name = "Spec Clarifications"
|
||||||
|
showcontent = true
|
1
changelogs/client_server/newsfragments/1465.feature
Normal file
1
changelogs/client_server/newsfragments/1465.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Share room decryption keys between devices
|
|
@ -0,0 +1 @@
|
||||||
|
Document the 403 error for sending state events.
|
|
@ -0,0 +1 @@
|
||||||
|
specify how to handle multiple olm sessions with the same device
|
1
changelogs/client_server/newsfragments/780.feature
Normal file
1
changelogs/client_server/newsfragments/780.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Add more presence options to the ``set_presence`` parameter of ``/sync``. (Thanks @mujx!)
|
14
event-schemas/examples/m.forwarded_room_key
Normal file
14
event-schemas/examples/m.forwarded_room_key
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"room_id": "!Cuyf34gef24t:localhost",
|
||||||
|
"session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ",
|
||||||
|
"session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf...",
|
||||||
|
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
|
||||||
|
"sender_claimed_ed25519_key": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y",
|
||||||
|
"forwarding_curve25519_key_chain": [
|
||||||
|
"hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type": "m.forwarded_room_key"
|
||||||
|
}
|
8
event-schemas/examples/m.room_key_request#cancel_request
Normal file
8
event-schemas/examples/m.room_key_request#cancel_request
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"action": "cancel_request",
|
||||||
|
"requesting_device_id": "RJYKSTBOIE",
|
||||||
|
"request_id": "1495474790150.19"
|
||||||
|
},
|
||||||
|
"type": "m.room_key_request"
|
||||||
|
}
|
14
event-schemas/examples/m.room_key_request#request
Normal file
14
event-schemas/examples/m.room_key_request#request
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"content": {
|
||||||
|
"body": {
|
||||||
|
"algorithm": "m.megolm.v1.aes-sha2",
|
||||||
|
"room_id": "!Cuyf34gef24t:localhost",
|
||||||
|
"session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ",
|
||||||
|
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU"
|
||||||
|
},
|
||||||
|
"action": "request",
|
||||||
|
"requesting_device_id": "RJYKSTBOIE",
|
||||||
|
"request_id": "1495474790150.19"
|
||||||
|
},
|
||||||
|
"type": "m.room_key_request"
|
||||||
|
}
|
59
event-schemas/schema/m.forwarded_room_key
Normal file
59
event-schemas/schema/m.forwarded_room_key
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
This event type is used to forward keys for end-to-end encryption. Typically
|
||||||
|
it is encrypted as an ``m.room.encrypted`` event, then sent as a `to-device`_
|
||||||
|
event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
algorithm:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The encryption algorithm the key in this event is to be used with.
|
||||||
|
room_id:
|
||||||
|
type: string
|
||||||
|
description: The room where the key is used.
|
||||||
|
sender_key:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The Curve25519 key of the device which initiated the session originally.
|
||||||
|
session_id:
|
||||||
|
type: string
|
||||||
|
description: The ID of the session that the key is for.
|
||||||
|
session_key:
|
||||||
|
type: string
|
||||||
|
description: The key to be exchanged.
|
||||||
|
sender_claimed_ed25519_key:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The Ed25519 key of the device which initiated the session originally.
|
||||||
|
It is 'claimed' because the receiving device has no way to tell that the
|
||||||
|
original room_key actually came from a device which owns the private part of
|
||||||
|
this key unless they have done device verification.
|
||||||
|
forwarding_curve25519_key_chain:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
Chain of Curve25519 keys. It starts out empty, but each time the
|
||||||
|
key is forwarded to another device, the previous sender in the chain is added
|
||||||
|
to the end of the list. For example, if the key is forwarded from A to B to
|
||||||
|
C, this field is empty between A and B, and contains A's Curve25519 key between
|
||||||
|
B and C.
|
||||||
|
required:
|
||||||
|
- algorithm
|
||||||
|
- room_id
|
||||||
|
- session_id
|
||||||
|
- session_key
|
||||||
|
- sender_claimed_ed25519_key
|
||||||
|
- forwarding_curve25519_key_chain
|
||||||
|
- sender_key
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.forwarded_room_key
|
||||||
|
type: string
|
||||||
|
type: object
|
61
event-schemas/schema/m.room_key_request
Normal file
61
event-schemas/schema/m.room_key_request
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
allOf:
|
||||||
|
- $ref: core-event-schema/event.yaml
|
||||||
|
|
||||||
|
description: |-
|
||||||
|
This event type is used to request keys for end-to-end encryption. It is sent as an
|
||||||
|
unencrypted `to-device`_ event.
|
||||||
|
properties:
|
||||||
|
content:
|
||||||
|
properties:
|
||||||
|
body:
|
||||||
|
description: |-
|
||||||
|
Information about the requested key. Required when ``action`` is
|
||||||
|
``request``.
|
||||||
|
properties:
|
||||||
|
algorithm:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The encryption algorithm the requested key in this event is to be used
|
||||||
|
with.
|
||||||
|
room_id:
|
||||||
|
type: string
|
||||||
|
description: The room where the key is used.
|
||||||
|
sender_key:
|
||||||
|
type: string
|
||||||
|
description: |-
|
||||||
|
The Curve25519 key of the device which initiated the session originally.
|
||||||
|
session_id:
|
||||||
|
type: string
|
||||||
|
description: The ID of the session that the key is for.
|
||||||
|
required:
|
||||||
|
- algorithm
|
||||||
|
- room_id
|
||||||
|
- session_id
|
||||||
|
- sender_key
|
||||||
|
type: object
|
||||||
|
title: RequestedKeyInfo
|
||||||
|
action:
|
||||||
|
enum:
|
||||||
|
- request
|
||||||
|
- cancel_request
|
||||||
|
type: string
|
||||||
|
requesting_device_id:
|
||||||
|
description: ID of the device requesting the key.
|
||||||
|
type: string
|
||||||
|
request_id:
|
||||||
|
description: |-
|
||||||
|
A random string uniquely identifying the request for a key. If the key is
|
||||||
|
requested multiple times, it should be reused. It should also reused in order
|
||||||
|
to cancel a request.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- action
|
||||||
|
- requesting_device_id
|
||||||
|
- request_id
|
||||||
|
type: object
|
||||||
|
type:
|
||||||
|
enum:
|
||||||
|
- m.room_key_request
|
||||||
|
type: string
|
||||||
|
type: object
|
|
@ -27,7 +27,7 @@ The remainder of the process is as follows:
|
||||||
1. Add the changes to the matrix-org/matrix.org repository (for historic tracking).
|
1. Add the changes to the matrix-org/matrix.org repository (for historic tracking).
|
||||||
* This is done by making a PR to the `unstyled_docs/spec` folder for the version and
|
* This is done by making a PR to the `unstyled_docs/spec` folder for the version and
|
||||||
specification you're releasing.
|
specification you're releasing.
|
||||||
* Don't forget to symlink the new release as `latest`.
|
* Don't forget to symlink the new release as `latest`.
|
||||||
1. Perform a release on GitHub to tag the release.
|
1. Perform a release on GitHub to tag the release.
|
||||||
1. Yell from the mountaintop to the world about the new release.
|
1. Yell from the mountaintop to the world about the new release.
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ def get_rst(file_info, title_level, title_styles, spec_dir, adjust_titles):
|
||||||
# string are file paths to RST blobs
|
# string are file paths to RST blobs
|
||||||
if isinstance(file_info, str):
|
if isinstance(file_info, str):
|
||||||
log("%s %s" % (">" * (1 + title_level), file_info))
|
log("%s %s" % (">" * (1 + title_level), file_info))
|
||||||
with open(os.path.join(spec_dir, file_info), "r") as f:
|
with open(os.path.join(spec_dir, file_info), "r", encoding="utf-8") as f:
|
||||||
rst = None
|
rst = None
|
||||||
if adjust_titles:
|
if adjust_titles:
|
||||||
rst = load_with_adjusted_titles(
|
rst = load_with_adjusted_titles(
|
||||||
|
@ -186,7 +186,7 @@ def get_rst(file_info, title_level, title_styles, spec_dir, adjust_titles):
|
||||||
|
|
||||||
def build_spec(target, out_filename):
|
def build_spec(target, out_filename):
|
||||||
log("Building templated file %s" % out_filename)
|
log("Building templated file %s" % out_filename)
|
||||||
with open(out_filename, "wb") as outfile:
|
with open(out_filename, "w", encoding="utf-8") as outfile:
|
||||||
for file_info in target["files"]:
|
for file_info in target["files"]:
|
||||||
section = get_rst(
|
section = get_rst(
|
||||||
file_info=file_info,
|
file_info=file_info,
|
||||||
|
@ -195,7 +195,7 @@ def build_spec(target, out_filename):
|
||||||
spec_dir=spec_dir,
|
spec_dir=spec_dir,
|
||||||
adjust_titles=True
|
adjust_titles=True
|
||||||
)
|
)
|
||||||
outfile.write(section.encode('UTF-8'))
|
outfile.write(section)
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -223,8 +223,8 @@ def fix_relative_titles(target, filename, out_filename):
|
||||||
"^[" + re.escape("".join(title_styles)) + "]{3,}$"
|
"^[" + re.escape("".join(title_styles)) + "]{3,}$"
|
||||||
)
|
)
|
||||||
current_title_style = None
|
current_title_style = None
|
||||||
with open(filename, "r") as infile:
|
with open(filename, "r", encoding="utf-8") as infile:
|
||||||
with open(out_filename, "w") as outfile:
|
with open(out_filename, "w", encoding="utf-8") as outfile:
|
||||||
for line in infile.readlines():
|
for line in infile.readlines():
|
||||||
if not relative_title_matcher.match(line):
|
if not relative_title_matcher.match(line):
|
||||||
if title_matcher.match(line):
|
if title_matcher.match(line):
|
||||||
|
@ -263,8 +263,8 @@ def fix_relative_titles(target, filename, out_filename):
|
||||||
|
|
||||||
def rst2html(i, o, stylesheets):
|
def rst2html(i, o, stylesheets):
|
||||||
log("rst2html %s -> %s" % (i, o))
|
log("rst2html %s -> %s" % (i, o))
|
||||||
with open(i, "r") as in_file:
|
with open(i, "r", encoding="utf-8") as in_file:
|
||||||
with open(o, "w") as out_file:
|
with open(o, "w", encoding="utf-8") as out_file:
|
||||||
publish_file(
|
publish_file(
|
||||||
source=in_file,
|
source=in_file,
|
||||||
destination=out_file,
|
destination=out_file,
|
||||||
|
@ -280,16 +280,15 @@ def rst2html(i, o, stylesheets):
|
||||||
def addAnchors(path):
|
def addAnchors(path):
|
||||||
log("add anchors %s" % path)
|
log("add anchors %s" % path)
|
||||||
|
|
||||||
with open(path, "rb") as f:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
|
|
||||||
replacement = r'<p><a class="anchor" id="\2"></a></p>\n\1'
|
replacement = r'<p><a class="anchor" id="\2"></a></p>\n\1'
|
||||||
with open(path, "wb") as f:
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = line.decode("UTF-8")
|
|
||||||
line = re.sub(r'(<h\d id="#?(.*?)">)', replacement, line.rstrip())
|
line = re.sub(r'(<h\d id="#?(.*?)">)', replacement, line.rstrip())
|
||||||
line = re.sub(r'(<div class="section" id="(.*?)">)', replacement, line.rstrip())
|
line = re.sub(r'(<div class="section" id="(.*?)">)', replacement, line.rstrip())
|
||||||
f.write((line + "\n").encode('UTF-8'))
|
f.write(line + "\n")
|
||||||
|
|
||||||
|
|
||||||
def run_through_template(input_files, set_verbose, substitutions):
|
def run_through_template(input_files, set_verbose, substitutions):
|
||||||
|
@ -518,6 +517,10 @@ if __name__ == '__main__':
|
||||||
"--server_release", "-s", action="store", default="unstable",
|
"--server_release", "-s", action="store", default="unstable",
|
||||||
help="The server-server release tag to generate, e.g. r1.2"
|
help="The server-server release tag to generate, e.g. r1.2"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--appservice_release", "-a", action="store", default="unstable",
|
||||||
|
help="The appservice release tag to generate, e.g. r1.2"
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--push_gateway_release", "-p", action="store", default="unstable",
|
"--push_gateway_release", "-p", action="store", default="unstable",
|
||||||
help="The push gateway release tag to generate, e.g. r1.2"
|
help="The push gateway release tag to generate, e.g. r1.2"
|
||||||
|
@ -549,6 +552,7 @@ if __name__ == '__main__':
|
||||||
# have to bump them.
|
# have to bump them.
|
||||||
"%CLIENT_MAJOR_VERSION%": "r0",
|
"%CLIENT_MAJOR_VERSION%": "r0",
|
||||||
"%SERVER_RELEASE_LABEL%": args.server_release,
|
"%SERVER_RELEASE_LABEL%": args.server_release,
|
||||||
|
"%APPSERVICE_RELEASE_LABEL%": args.appservice_release,
|
||||||
"%IDENTITY_RELEASE_LABEL%": args.identity_release,
|
"%IDENTITY_RELEASE_LABEL%": args.identity_release,
|
||||||
"%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release,
|
"%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,11 @@ cd `dirname $0`/..
|
||||||
|
|
||||||
mkdir -p assets
|
mkdir -p assets
|
||||||
|
|
||||||
# generate specification/proposals.rst
|
if [ "$CIRCLECI" != "true" ]
|
||||||
./scripts/proposals.py
|
then
|
||||||
|
# generate specification/proposals.rst
|
||||||
|
./scripts/proposals.py
|
||||||
|
fi
|
||||||
|
|
||||||
# generate the spec docs
|
# generate the spec docs
|
||||||
./scripts/gendoc.py -d assets/spec
|
./scripts/gendoc.py -d assets/spec
|
||||||
|
|
|
@ -45,6 +45,10 @@ class MatrixSections(Sections):
|
||||||
changelogs = self.units.get("changelogs")
|
changelogs = self.units.get("changelogs")
|
||||||
return changelogs["server_server"]
|
return changelogs["server_server"]
|
||||||
|
|
||||||
|
def render_application_service_changelog(self):
|
||||||
|
changelogs = self.units.get("changelogs")
|
||||||
|
return changelogs["application_service"]
|
||||||
|
|
||||||
def _render_events(self, filterFn, sortFn):
|
def _render_events(self, filterFn, sortFn):
|
||||||
template = self.env.get_template("events.tmpl")
|
template = self.env.get_template("events.tmpl")
|
||||||
examples = self.units.get("event_examples")
|
examples = self.units.get("event_examples")
|
||||||
|
|
|
@ -125,7 +125,7 @@ def resolve_references(path, schema):
|
||||||
if '$ref' in schema:
|
if '$ref' in schema:
|
||||||
value = schema['$ref']
|
value = schema['$ref']
|
||||||
path = os.path.join(os.path.dirname(path), value)
|
path = os.path.join(os.path.dirname(path), value)
|
||||||
with open(path) as f:
|
with open(path, encoding="utf-8") as f:
|
||||||
ref = yaml.load(f, OrderedLoader)
|
ref = yaml.load(f, OrderedLoader)
|
||||||
result = resolve_references(path, ref)
|
result = resolve_references(path, ref)
|
||||||
del schema['$ref']
|
del schema['$ref']
|
||||||
|
@ -664,11 +664,11 @@ class MatrixUnits(Units):
|
||||||
continue
|
continue
|
||||||
filepath = os.path.join(path, filename)
|
filepath = os.path.join(path, filename)
|
||||||
logger.info("Reading swagger API: %s" % filepath)
|
logger.info("Reading swagger API: %s" % filepath)
|
||||||
with open(filepath, "r") as f:
|
with open(filepath, "r", encoding="utf-8") as f:
|
||||||
# strip .yaml
|
# strip .yaml
|
||||||
group_name = filename[:-5].replace("-", "_")
|
group_name = filename[:-5].replace("-", "_")
|
||||||
group_name = "%s_%s" % (group_name, suffix)
|
group_name = "%s_%s" % (group_name, suffix)
|
||||||
api = yaml.load(f.read(), OrderedLoader)
|
api = yaml.load(f, OrderedLoader)
|
||||||
api = resolve_references(filepath, api)
|
api = resolve_references(filepath, api)
|
||||||
api["__meta"] = self._load_swagger_meta(
|
api["__meta"] = self._load_swagger_meta(
|
||||||
api, group_name
|
api, group_name
|
||||||
|
@ -698,11 +698,11 @@ class MatrixUnits(Units):
|
||||||
continue
|
continue
|
||||||
filepath = os.path.join(path, filename)
|
filepath = os.path.join(path, filename)
|
||||||
logger.info("Reading swagger definition: %s" % filepath)
|
logger.info("Reading swagger definition: %s" % filepath)
|
||||||
with open(filepath, "r") as f:
|
with open(filepath, "r", encoding="utf-8") as f:
|
||||||
# strip .yaml
|
# strip .yaml
|
||||||
group_name = re.sub(r"[^a-zA-Z0-9_]", "_", filename[:-5])
|
group_name = re.sub(r"[^a-zA-Z0-9_]", "_", filename[:-5])
|
||||||
group_name = "%s_%s" % (prefix, group_name)
|
group_name = "%s_%s" % (prefix, group_name)
|
||||||
definition = yaml.load(f.read(), OrderedLoader)
|
definition = yaml.load(f, OrderedLoader)
|
||||||
definition = resolve_references(filepath, definition)
|
definition = resolve_references(filepath, definition)
|
||||||
if 'type' not in definition:
|
if 'type' not in definition:
|
||||||
continue
|
continue
|
||||||
|
@ -741,7 +741,7 @@ class MatrixUnits(Units):
|
||||||
event_type = filename[:-5] # strip the ".yaml"
|
event_type = filename[:-5] # strip the ".yaml"
|
||||||
logger.info("Reading event schema: %s" % filepath)
|
logger.info("Reading event schema: %s" % filepath)
|
||||||
|
|
||||||
with open(filepath) as f:
|
with open(filepath, encoding="utf-8") as f:
|
||||||
event_schema = yaml.load(f, OrderedLoader)
|
event_schema = yaml.load(f, OrderedLoader)
|
||||||
|
|
||||||
schema_info = process_data_type(
|
schema_info = process_data_type(
|
||||||
|
@ -755,6 +755,7 @@ class MatrixUnits(Units):
|
||||||
cs_ver = substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable")
|
cs_ver = substitutions.get("%CLIENT_RELEASE_LABEL%", "unstable")
|
||||||
fed_ver = substitutions.get("%SERVER_RELEASE_LABEL%", "unstable")
|
fed_ver = substitutions.get("%SERVER_RELEASE_LABEL%", "unstable")
|
||||||
is_ver = substitutions.get("%IDENTITY_RELEASE_LABEL%", "unstable")
|
is_ver = substitutions.get("%IDENTITY_RELEASE_LABEL%", "unstable")
|
||||||
|
as_ver = substitutions.get("%APPSERVICE_RELEASE_LABEL%", "unstable")
|
||||||
push_gw_ver = substitutions.get("%PUSH_GATEWAY_RELEASE_LABEL%", "unstable")
|
push_gw_ver = substitutions.get("%PUSH_GATEWAY_RELEASE_LABEL%", "unstable")
|
||||||
|
|
||||||
# we abuse the typetable to return this info to the templates
|
# we abuse the typetable to return this info to the templates
|
||||||
|
@ -768,8 +769,8 @@ class MatrixUnits(Units):
|
||||||
fed_ver,
|
fed_ver,
|
||||||
"Federation between servers",
|
"Federation between servers",
|
||||||
), TypeTableRow(
|
), TypeTableRow(
|
||||||
"`Application Service API <application_service/unstable.html>`_",
|
"`Application Service API <application_service/"+as_ver+".html>`_",
|
||||||
"unstable",
|
as_ver,
|
||||||
"Privileged server plugins",
|
"Privileged server plugins",
|
||||||
), TypeTableRow(
|
), TypeTableRow(
|
||||||
"`Identity Service API <identity_service/"+is_ver+".html>`_",
|
"`Identity Service API <identity_service/"+is_ver+".html>`_",
|
||||||
|
@ -793,7 +794,7 @@ class MatrixUnits(Units):
|
||||||
filepath = os.path.join(path, filename)
|
filepath = os.path.join(path, filename)
|
||||||
logger.info("Reading event example: %s" % filepath)
|
logger.info("Reading event example: %s" % filepath)
|
||||||
try:
|
try:
|
||||||
with open(filepath, "r") as f:
|
with open(filepath, "r", encoding="utf-8") as f:
|
||||||
example = json.load(f)
|
example = json.load(f)
|
||||||
examples[filename] = examples.get(filename, [])
|
examples[filename] = examples.get(filename, [])
|
||||||
examples[filename].append(example)
|
examples[filename].append(example)
|
||||||
|
@ -831,7 +832,7 @@ class MatrixUnits(Units):
|
||||||
def read_event_schema(self, filepath):
|
def read_event_schema(self, filepath):
|
||||||
logger.info("Reading %s" % filepath)
|
logger.info("Reading %s" % filepath)
|
||||||
|
|
||||||
with open(filepath, "r") as f:
|
with open(filepath, "r", encoding="utf-8") as f:
|
||||||
json_schema = yaml.load(f, OrderedLoader)
|
json_schema = yaml.load(f, OrderedLoader)
|
||||||
|
|
||||||
schema = {
|
schema = {
|
||||||
|
@ -943,7 +944,7 @@ class MatrixUnits(Units):
|
||||||
|
|
||||||
title_part = None
|
title_part = None
|
||||||
changelog_lines = []
|
changelog_lines = []
|
||||||
with open(path, "r") as f:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
prev_line = None
|
prev_line = None
|
||||||
for line in (tc_lines + lines):
|
for line in (tc_lines + lines):
|
||||||
|
|
|
@ -23,13 +23,37 @@ A homeserver is uniquely identified by its server name. This value is used in a
|
||||||
number of identifiers, as described below.
|
number of identifiers, as described below.
|
||||||
|
|
||||||
The server name represents the address at which the homeserver in question can
|
The server name represents the address at which the homeserver in question can
|
||||||
be reached by other homeservers. The complete grammar is::
|
be reached by other homeservers. All valid server names are included by the
|
||||||
|
following grammar::
|
||||||
|
|
||||||
server_name = host [ ":" port]
|
server_name = hostname [ ":" port ]
|
||||||
port = *DIGIT
|
|
||||||
|
|
||||||
where ``host`` is as defined by `RFC3986, section 3.2.2
|
port = *DIGIT
|
||||||
<https://tools.ietf.org/html/rfc3986#section-3.2.2>`_.
|
|
||||||
|
hostname = IPv4address / "[" IPv6address "]" / dns-name
|
||||||
|
|
||||||
|
IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
|
||||||
|
|
||||||
|
IPv6address = 2*45IPv6char
|
||||||
|
|
||||||
|
IPv6char = DIGIT / %x41-46 / %x61-66 / ":" / "."
|
||||||
|
; 0-9, A-F, a-f, :, .
|
||||||
|
|
||||||
|
dns-name = *255dns-char
|
||||||
|
|
||||||
|
dns-char = DIGIT / ALPHA / "-" / "."
|
||||||
|
|
||||||
|
— in other words, the server name is the hostname, followed by an optional
|
||||||
|
numeric port specifier. The hostname may be a dotted-quad IPv4 address literal,
|
||||||
|
an IPv6 address literal surrounded with square brackets, or a DNS name.
|
||||||
|
|
||||||
|
IPv4 literals must be a sequence of four decimal numbers in the
|
||||||
|
range 0 to 255, separated by ``.``. IPv6 literals must be as specified by
|
||||||
|
`RFC3513, section 2.2 <https://tools.ietf.org/html/rfc3513#section-2.2>`_.
|
||||||
|
|
||||||
|
DNS names for use with Matrix should follow the conventional restrictions for
|
||||||
|
internet hostnames: they should consist of a series of labels separated by
|
||||||
|
``.``, where each label consists of the alphanumeric characters or hyphens.
|
||||||
|
|
||||||
Examples of valid server names are:
|
Examples of valid server names are:
|
||||||
|
|
||||||
|
@ -40,6 +64,20 @@ Examples of valid server names are:
|
||||||
* ``[1234:5678::abcd]`` (IPv6 literal)
|
* ``[1234:5678::abcd]`` (IPv6 literal)
|
||||||
* ``[1234:5678::abcd]:5678`` (IPv6 literal with explicit port)
|
* ``[1234:5678::abcd]:5678`` (IPv6 literal with explicit port)
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
This grammar is based on the standard for internet host names, as specified
|
||||||
|
by `RFC1123, section 2.1 <https://tools.ietf.org/html/rfc1123#page-13>`_,
|
||||||
|
with an extension for IPv6 literals.
|
||||||
|
|
||||||
|
Server names must be treated case-sensitively: in other words,
|
||||||
|
``@user:matrix.org`` is a different person from ``@user:MATRIX.ORG``.
|
||||||
|
|
||||||
|
Some recommendations for a choice of server name follow:
|
||||||
|
|
||||||
|
* The length of the complete server name should not exceed 230 characters.
|
||||||
|
* Server names should not use upper-case characters.
|
||||||
|
|
||||||
|
|
||||||
Room Versions
|
Room Versions
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
@ -51,7 +89,7 @@ not understanding the new rules.
|
||||||
|
|
||||||
A room version is defined as a string of characters which MUST NOT exceed 32
|
A room version is defined as a string of characters which MUST NOT exceed 32
|
||||||
codepoints in length. Room versions MUST NOT be empty and SHOULD contain only
|
codepoints in length. Room versions MUST NOT be empty and SHOULD contain only
|
||||||
the characters ``a-z``, ``0-9``, ``.``, and ``-``.
|
the characters ``a-z``, ``0-9``, ``.``, and ``-``.
|
||||||
|
|
||||||
Room versions are not intended to be parsed and should be treated as opaque
|
Room versions are not intended to be parsed and should be treated as opaque
|
||||||
identifiers. Room versions consisting only of the characters ``0-9`` and ``.``
|
identifiers. Room versions consisting only of the characters ``0-9`` and ``.``
|
||||||
|
|
|
@ -30,22 +30,37 @@ irrespective of the underlying homeserver implementation.
|
||||||
.. contents:: Table of Contents
|
.. contents:: Table of Contents
|
||||||
.. sectnum::
|
.. sectnum::
|
||||||
|
|
||||||
Specification version
|
Changelog
|
||||||
---------------------
|
---------
|
||||||
|
|
||||||
|
|
||||||
|
.. topic:: Version: unstable
|
||||||
|
{{application_service_changelog}}
|
||||||
|
|
||||||
This version of the specification is generated from
|
This version of the specification is generated from
|
||||||
`matrix-doc <https://github.com/matrix-org/matrix-doc>`_ as of Git commit
|
`matrix-doc <https://github.com/matrix-org/matrix-doc>`_ as of Git commit
|
||||||
`{{git_version}} <https://github.com/matrix-org/matrix-doc/tree/{{git_rev}}>`_.
|
`{{git_version}} <https://github.com/matrix-org/matrix-doc/tree/{{git_rev}}>`_.
|
||||||
|
|
||||||
|
For the full historical changelog, see
|
||||||
|
https://github.com/matrix-org/matrix-doc/blob/master/changelogs/application_service.rst
|
||||||
|
|
||||||
|
Other versions of this specification
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The following other versions are also available, in reverse chronological order:
|
||||||
|
|
||||||
|
- `HEAD <https://matrix.org/docs/spec/application_service/unstable.html>`_: Includes all changes since the latest versioned release.
|
||||||
|
|
||||||
|
|
||||||
Application Services
|
Application Services
|
||||||
--------------------
|
--------------------
|
||||||
Application services are passive and can only observe events from a given
|
Application services are passive and can only observe events from homeserver.
|
||||||
homeserver (HS). They can inject events into rooms they are participating in.
|
They can inject events into rooms they are participating in.
|
||||||
They cannot prevent events from being sent, nor can they modify the content of
|
They cannot prevent events from being sent, nor can they modify the content of
|
||||||
the event being sent. In order to observe events from a homeserver, the
|
the event being sent. In order to observe events from a homeserver, the
|
||||||
homeserver needs to be configured to pass certain types of traffic to the
|
homeserver needs to be configured to pass certain types of traffic to the
|
||||||
application service. This is achieved by manually configuring the homeserver
|
application service. This is achieved by manually configuring the homeserver
|
||||||
with information about the application service (AS).
|
with information about the application service.
|
||||||
|
|
||||||
Registration
|
Registration
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
@ -169,6 +184,34 @@ An example registration file for an IRC-bridging application service is below:
|
||||||
Homeserver -> Application Service API
|
Homeserver -> Application Service API
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Legacy routes
|
||||||
|
+++++++++++++
|
||||||
|
|
||||||
|
Previous drafts of the application service specification had a mix of endpoints
|
||||||
|
that have been used in the wild for a significant amount of time. The application
|
||||||
|
service specification now defines a version on all endpoints to be more compatible
|
||||||
|
with the rest of the Matrix specification and the future.
|
||||||
|
|
||||||
|
Homeservers should attempt to use the specified endpoints first when communicating
|
||||||
|
with application services. However, if the application service receives an http status
|
||||||
|
code that does not indicate success (ie: 404, 500, 501, etc) then the homeserver
|
||||||
|
should fall back to the older endpoints for the application service.
|
||||||
|
|
||||||
|
The older endpoints have the exact same request body and response format, they
|
||||||
|
just belong at a different path. The equivalent path for each is as follows:
|
||||||
|
|
||||||
|
* ``/_matrix/app/v1/transactions/{txnId}`` becomes ``/transactions/{txnId}``
|
||||||
|
* ``/_matrix/app/v1/users/{userId}`` becomes ``/users/{userId}``
|
||||||
|
* ``/_matrix/app/v1/rooms/{roomAlias}`` becomes ``/rooms/{roomAlias}``
|
||||||
|
* ``/_matrix/app/v1/thirdparty/protocol/{protocol}`` becomes ``/_matrix/app/unstable/thirdparty/protocol/{protocol}``
|
||||||
|
* ``/_matrix/app/v1/thirdparty/user/{user}`` becomes ``/_matrix/app/unstable/thirdparty/user/{user}``
|
||||||
|
* ``/_matrix/app/v1/thirdparty/location/{location}`` becomes ``/_matrix/app/unstable/thirdparty/location/{location}``
|
||||||
|
* ``/_matrix/app/v1/thirdparty/user`` becomes ``/_matrix/app/unstable/thirdparty/user``
|
||||||
|
* ``/_matrix/app/v1/thirdparty/location`` becomes ``/_matrix/app/unstable/thirdparty/location``
|
||||||
|
|
||||||
|
Homeservers should periodically try again for the newer endpoints because the
|
||||||
|
application service may have been updated.
|
||||||
|
|
||||||
Pushing events
|
Pushing events
|
||||||
++++++++++++++
|
++++++++++++++
|
||||||
|
|
||||||
|
@ -179,24 +222,24 @@ events. Each list of events includes a transaction ID, which works as follows:
|
||||||
|
|
||||||
Typical
|
Typical
|
||||||
HS ---> AS : Homeserver sends events with transaction ID T.
|
HS ---> AS : Homeserver sends events with transaction ID T.
|
||||||
<--- : AS sends back 200 OK.
|
<--- : Application Service sends back 200 OK.
|
||||||
|
|
||||||
AS ACK Lost
|
AS ACK Lost
|
||||||
HS ---> AS : Homeserver sends events with transaction ID T.
|
HS ---> AS : Homeserver sends events with transaction ID T.
|
||||||
<-/- : AS 200 OK is lost.
|
<-/- : AS 200 OK is lost.
|
||||||
HS ---> AS : Homeserver retries with the same transaction ID of T.
|
HS ---> AS : Homeserver retries with the same transaction ID of T.
|
||||||
<--- : AS sends back 200 OK. If the AS had processed these events
|
<--- : Application Service sends back 200 OK. If the AS had processed these
|
||||||
already, it can NO-OP this request (and it knows if it is the same
|
events already, it can NO-OP this request (and it knows if it is the
|
||||||
events based on the transaction ID).
|
same events based on the transaction ID).
|
||||||
|
|
||||||
The events sent to the application service should be linearised, as if they were
|
The events sent to the application service should be linearised, as if they were
|
||||||
from the event stream. The homeserver MUST maintain a queue of transactions to
|
from the event stream. The homeserver MUST maintain a queue of transactions to
|
||||||
send to the AS. If the application service cannot be reached, the homeserver
|
send to the application service. If the application service cannot be reached, the
|
||||||
SHOULD backoff exponentially until the application service is reachable again.
|
homeserver SHOULD backoff exponentially until the application service is reachable again.
|
||||||
As application services cannot *modify* the events in any way, these requests can
|
As application services cannot *modify* the events in any way, these requests can
|
||||||
be made without blocking other aspects of the homeserver. Homeservers MUST NOT
|
be made without blocking other aspects of the homeserver. Homeservers MUST NOT
|
||||||
alter (e.g. add more) events they were going to send within that transaction ID
|
alter (e.g. add more) events they were going to send within that transaction ID
|
||||||
on retries, as the AS may have already processed the events.
|
on retries, as the application service may have already processed the events.
|
||||||
|
|
||||||
{{transactions_as_http_api}}
|
{{transactions_as_http_api}}
|
||||||
|
|
||||||
|
@ -337,7 +380,7 @@ users needs API changes in order to:
|
||||||
- Have a 'passwordless' user.
|
- Have a 'passwordless' user.
|
||||||
|
|
||||||
This involves bypassing the registration flows entirely. This is achieved by
|
This involves bypassing the registration flows entirely. This is achieved by
|
||||||
including the AS token on a ``/register`` request, along with a login type of
|
including the ``as_token`` on a ``/register`` request, along with a login type of
|
||||||
``m.login.application_service`` to set the desired user ID without a password.
|
``m.login.application_service`` to set the desired user ID without a password.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -374,13 +417,18 @@ additional parameters on the ``/publicRooms`` client-server endpoint.
|
||||||
|
|
||||||
{{appservice_room_directory_cs_http_api}}
|
{{appservice_room_directory_cs_http_api}}
|
||||||
|
|
||||||
Event fields
|
Referencing messages from a third party network
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. TODO-TravisR: Fix this section to be a general "3rd party networks" section
|
Application services should include an ``external_url`` in the ``content`` of
|
||||||
|
events it emits to indicate where the message came from. This typically applies
|
||||||
|
to application services that bridge other networks into Matrix, such as IRC,
|
||||||
|
where an HTTP URL may be available to reference.
|
||||||
|
|
||||||
We recommend that any events that originated from a remote network should
|
Clients should provide users with a way to access the ``external_url`` if it
|
||||||
include an ``external_url`` field in their content to provide a way for Matrix
|
is present. Clients should additionally ensure the URL has a scheme of ``https``
|
||||||
clients to link into the 'native' client from which the event originated.
|
or ``http`` before making use of it.
|
||||||
For instance, this could contain the message-ID for emails/nntp posts, or a link
|
|
||||||
to a blog comment when bridging blog comment traffic in & out of Matrix.
|
The presence of an ``external_url`` on an event does not necessarily mean the
|
||||||
|
event was sent from an application service. Clients should be wary of the URL
|
||||||
|
contained within, as it may not be a legitimate reference to the event's source.
|
||||||
|
|
|
@ -31,7 +31,7 @@ The client recieves the account data as events in the ``account_data`` sections
|
||||||
of a ``/sync``.
|
of a ``/sync``.
|
||||||
|
|
||||||
These events can also be received in a ``/events`` response or in the
|
These events can also be received in a ``/events`` response or in the
|
||||||
``account_data`` section of a room in ``/initialSync``. ``m.tag``
|
``account_data`` section of a room in ``/sync``. ``m.tag``
|
||||||
events appearing in ``/events`` will have a ``room_id`` with the room
|
events appearing in ``/events`` will have a ``room_id`` with the room
|
||||||
the tags are for.
|
the tags are for.
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,31 @@ 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 sharing
|
||||||
|
-----------
|
||||||
|
|
||||||
|
If Bob has an encrypted conversation with Alice on his computer, and then logs in
|
||||||
|
through his phone for the first time, he may want to have access to the previously
|
||||||
|
exchanged messages. To address this issue, events exist for requesting and sending
|
||||||
|
keys from device to device.
|
||||||
|
|
||||||
|
When a device is missing keys to decrypt messages, it can request the keys by
|
||||||
|
sending `m.room_key_request`_ to-device messages to other devices with
|
||||||
|
``action`` set to ``request``. If a device wishes to share the keys with that
|
||||||
|
device, it can forward the keys to the first device by sending an encrypted
|
||||||
|
`m.forwarded_room_key`_ to-device message. The first device should then send an
|
||||||
|
`m.room_key_request`_ to-device message with ``action`` set to
|
||||||
|
``cancel_request`` to the other devices that it had originally sent the key
|
||||||
|
request to; a device that receives a ``cancel_request`` should disregard any
|
||||||
|
previously-received ``request`` message with the same ``request_id`` and
|
||||||
|
``requesting_device_id``.
|
||||||
|
|
||||||
|
.. NOTE::
|
||||||
|
|
||||||
|
Key sharing can be a big attack vector, thus it must be done very carefully.
|
||||||
|
A reasonable stategy is for a user's client to only send keys requested by the
|
||||||
|
verified devices of the same user.
|
||||||
|
|
||||||
Messaging Algorithms
|
Messaging Algorithms
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -391,6 +416,12 @@ this check, a client cannot be sure that the sender device owns the private
|
||||||
part of the ed25519 key it claims to have in the Olm payload.
|
part of the ed25519 key it claims to have in the Olm payload.
|
||||||
This is crucial when the ed25519 key corresponds to a verified device.
|
This is crucial when the ed25519 key corresponds to a verified device.
|
||||||
|
|
||||||
|
If a client has multiple sessions established with another device, it should
|
||||||
|
use the session from which it last received a message. A client may expire old
|
||||||
|
sessions by defining a maximum number of olm sessions that it will maintain for
|
||||||
|
each device, and expiring sessions on a Least Recently Used basis. The maximum
|
||||||
|
number of olm sessions maintained per device should be at least 4.
|
||||||
|
|
||||||
``m.megolm.v1.aes-sha2``
|
``m.megolm.v1.aes-sha2``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -464,6 +495,10 @@ Events
|
||||||
|
|
||||||
{{m_room_key_event}}
|
{{m_room_key_event}}
|
||||||
|
|
||||||
|
{{m_room_key_request_event}}
|
||||||
|
|
||||||
|
{{m_forwarded_room_key_event}}
|
||||||
|
|
||||||
Key management API
|
Key management API
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,10 @@ single ``event_id``.
|
||||||
Client behaviour
|
Client behaviour
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
In ``/initialSync``, receipts are listed in a separate top level ``receipts``
|
In ``/sync``, receipts are listed under the ``ephemeral`` array of events
|
||||||
key. In ``/sync``, receipts are contained in the ``ephemeral`` block for a
|
for a given room. New receipts that come down the event streams are deltas
|
||||||
room. New receipts that come down the event streams are deltas which update
|
which update existing mappings. Clients should replace older receipt acknowledgements
|
||||||
existing mappings. Clients should replace older receipt acknowledgements based
|
based on ``user_id`` and ``receipt_type`` pairs. For example::
|
||||||
on ``user_id`` and ``receipt_type`` pairs. For example::
|
|
||||||
|
|
||||||
Client receives m.receipt:
|
Client receives m.receipt:
|
||||||
user = @alice:example.com
|
user = @alice:example.com
|
||||||
|
|
|
@ -85,39 +85,41 @@ The following other versions are also available, in reverse chronological order:
|
||||||
|
|
||||||
- `HEAD <https://matrix.org/docs/spec/server_server/unstable.html>`_: Includes all changes since the latest versioned release.
|
- `HEAD <https://matrix.org/docs/spec/server_server/unstable.html>`_: Includes all changes since the latest versioned release.
|
||||||
|
|
||||||
Server Discovery
|
Server discovery
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Resolving Server Names
|
Resolving server names
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Each matrix homeserver is identified by a server name consisting of a hostname
|
Each matrix homeserver is identified by a server name consisting of a hostname
|
||||||
and an optional TLS port.
|
and an optional port, as described by the `grammar
|
||||||
|
<../appendices.html#server-name>`_. Server names should be resolved to an IP
|
||||||
|
address and port using the following process:
|
||||||
|
|
||||||
.. code::
|
* If the hostname is an IP literal, then that IP address should be used,
|
||||||
|
together with the given port number, or 8448 if no port is given.
|
||||||
|
|
||||||
server_name = hostname [ ":" tls_port]
|
* Otherwise, if the port is present, then an IP address is discovered by
|
||||||
tls_port = *DIGIT
|
looking up an AAAA or A record for the hostname, and the specified port is
|
||||||
|
used.
|
||||||
|
|
||||||
.. **
|
* If the hostname is not an IP literal and no port is given, the server is
|
||||||
|
discovered by first looking up a ``_matrix._tcp`` SRV record for the
|
||||||
|
hostname, which may give a hostname (to be looked up using AAAA or A queries)
|
||||||
|
and port. If the SRV record does not exist, then the server is discovered by
|
||||||
|
looking up an AAAA or A record on the hostname and taking the default
|
||||||
|
fallback port number of 8448.
|
||||||
|
|
||||||
If the port is present then the server is discovered by looking up an AAAA or
|
Homeservers may use SRV records to load balance requests between multiple TLS
|
||||||
A record for the hostname and connecting to the specified TLS port. If the port
|
endpoints or to failover to another endpoint if an endpoint fails.
|
||||||
is absent then the server is discovered by looking up a ``_matrix._tcp`` SRV
|
|
||||||
record for the hostname. If this record does not exist then the server is
|
|
||||||
discovered by looking up an AAAA or A record on the hostname and taking the
|
|
||||||
default fallback port number of 8448.
|
|
||||||
Homeservers may use SRV records to load balance requests between multiple TLS
|
|
||||||
endpoints or to failover to another endpoint if an endpoint fails.
|
|
||||||
|
|
||||||
If the DNS name is a literal IP address, the port specified or the fallback
|
When making requests to servers, use the hostname of the target server in the
|
||||||
port should be used.
|
``Host`` header, regardless of any hostname given in the SRV record. For
|
||||||
|
example, if the server name is ``example.org``, and the SRV record resolves to
|
||||||
When making requests to servers, use the DNS name of the target server in the
|
``matrix.example.org``, the ``Host`` header in the request should be
|
||||||
``Host`` header, regardless of the host given in the SRV record. For example,
|
``example.org``. If an explicit port was given in the server name, it should be
|
||||||
if making a request to ``example.org``, and the SRV record resolves to ``matrix.
|
included in the ``Host`` header; otherwise, no port number should be given in
|
||||||
example.org``, the ``Host`` header in the request should be ``example.org``. The
|
the ``Host`` header.
|
||||||
port number for target server should not appear in the ``Host`` header.
|
|
||||||
|
|
||||||
Server implementation
|
Server implementation
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -1123,3 +1125,4 @@ that are too long.
|
||||||
.. _`Inviting to a room`: #inviting-to-a-room
|
.. _`Inviting to a room`: #inviting-to-a-room
|
||||||
.. _`Canonical JSON`: ../appendices.html#canonical-json
|
.. _`Canonical JSON`: ../appendices.html#canonical-json
|
||||||
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64
|
||||||
|
.. _`Server ACLs`: ../client_server/unstable.html#module-server-acls
|
||||||
|
|
|
@ -13,7 +13,7 @@ targets:
|
||||||
application_service:
|
application_service:
|
||||||
files:
|
files:
|
||||||
- application_service_api.rst
|
- application_service_api.rst
|
||||||
version_label: unstable
|
version_label: "%APPSERVICE_RELEASE_LABEL%"
|
||||||
server_server:
|
server_server:
|
||||||
files:
|
files:
|
||||||
- server_server_api.rst
|
- server_server_api.rst
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue