Merge remote-tracking branch 'matrix-org/master' into travis/c2s/user-directory

pull/1569/head
Travis Ralston 6 years ago
commit 49c5677969

@ -23,9 +23,55 @@ buildswaggerui: &buildswaggerui
wget https://raw.githubusercontent.com/matrix-org/matrix.org/master/scripts/swagger-ui.patch wget https://raw.githubusercontent.com/matrix-org/matrix.org/master/scripts/swagger-ui.patch
patch api/client-server/index.html swagger-ui.patch patch api/client-server/index.html swagger-ui.patch
checkexamples: &checkexamples
name: Check Event Examples
command: |
source /env/bin/activate
cd event-schemas
./check_examples.py
cd ../api
./check_examples.py
genmatrixassets: &genmatrixassets
name: Generate/Verify matrix.org assets
command: |
source /env/bin/activate
./scripts/generate-matrix-org-assets
validateapi: &validateapi
name: Validate OpenAPI specifications
command: |
cd api
npm install
node validator.js -s "client-server"
buildspeculator: &buildspeculator
name: Build Speculator
command: |
cd scripts/speculator
go build -v
buildcontinuserv: &buildcontinuserv
name: Build Continuserv
command: |
cd scripts/continuserv
go build -v
version: 2 version: 2
jobs: jobs:
validate-docs:
docker:
- image: node:alpine
steps:
- checkout
- run: *validateapi
check-docs:
docker:
- image: uhoreg/matrix-doc-build
steps:
- checkout
- run: *checkexamples
- run: *genmatrixassets # We don't actually use the assets, but we do want to make sure they build
build-docs: build-docs:
docker: docker:
- image: uhoreg/matrix-doc-build - image: uhoreg/matrix-doc-build
@ -37,7 +83,6 @@ jobs:
- run: - run:
name: "Doc build is available at:" name: "Doc build is available at:"
command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/scripts/gen/index.html"; echo $DOCS_URL command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/scripts/gen/index.html"; echo $DOCS_URL
build-swagger: build-swagger:
docker: docker:
- image: uhoreg/matrix-doc-build - image: uhoreg/matrix-doc-build
@ -50,6 +95,18 @@ jobs:
- run: - run:
name: "Swagger UI is available at:" name: "Swagger UI is available at:"
command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/api/client-server/index.html"; echo $DOCS_URL command: DOCS_URL="${CIRCLE_BUILD_URL}/artifacts/${CIRCLE_NODE_INDEX}/${CIRCLE_WORKING_DIRECTORY/#\~/$HOME}/api/client-server/index.html"; echo $DOCS_URL
build-dev-scripts:
docker:
- image: golang:1.8
steps:
- checkout
- run:
name: Install Dependencies
command: |
go get -v github.com/hashicorp/golang-lru
go get -v gopkg.in/fsnotify/fsnotify.v1
- run: *buildcontinuserv
- run: *buildspeculator
workflows: workflows:
version: 2 version: 2
@ -58,6 +115,9 @@ workflows:
jobs: jobs:
- build-docs - build-docs
- build-swagger - build-swagger
- check-docs
- validate-docs
- build-dev-scripts
notify: notify:
webhooks: webhooks:

@ -19,12 +19,14 @@ properties:
protocol: protocol:
description: The protocol ID that the third party location is a part of. description: The protocol ID that the third party location is a part of.
type: string type: string
example: irc example: "irc"
fields: fields:
description: Information used to identify this third party location. description: Information used to identify this third party location.
type: object type: object
example: example: {
"network": "freenode" "network": "freenode",
"channel": "#matrix" "channel": "#matrix"
}
required: ['alias', 'protocol', 'fields']
title: Location title: Location
type: object type: object

@ -11,41 +11,60 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
title: Protocol
type: object
properties: properties:
user_fields: user_fields:
description: Fields used to identify a third party user. description: |-
Fields which may be used to identify a third party user. These should be
ordered to suggest the way that entities may be grouped, where higher
groupings are ordered first. For example, the name of a network should be
searched before the nickname of a user.
type: array type: array
items: items:
type: string type: string
description: Field used to identify a third party user. description: Field used to identify a third party user.
example: ["network", "nickname"] example: ["network", "nickname"]
location_fields: location_fields:
description: Fields used to identify a third party location. description: |-
Fields which may be used to identify a third party location. These should be
ordered to suggest the way that entities may be grouped, where higher
groupings are ordered first. For example, the name of a network should be
searched before the name of a channel.
type: array type: array
items: items:
type: string type: string
description: Field used to identify a third party location. description: Field used to identify a third party location.
example: ["network", "channel"] example: ["network", "channel"]
icon: icon:
description: An icon representing the third party protocol. description: A content URI representing an icon for the third party protocol.
type: string type: string
example: "mxc://example.org/aBcDeFgH" example: "mxc://example.org/aBcDeFgH"
field_types: field_types:
title: Field Types title: Field Types
description: All location or user fields should have an entry here. description: |-
The type definitions for the fields defined in the ``user_fields`` and
``location_fields``. Each entry in those arrays MUST have an entry here. The
``string`` key for this object is field name itself.
May be an empty object if no fields are defined.
type: object type: object
properties: additionalProperties:
fieldname:
title: Field Type title: Field Type
description: Definition of valid values for a field. description: Definition of valid values for a field.
type: object type: object
properties: properties:
regexp: regexp:
description: A regular expression for validation of a field's value. description: |-
A regular expression for validation of a field's value. This may be relatively
coarse to verify the value as the application service providing this protocol
may apply additional validation or filtering.
type: string type: string
placeholder: placeholder:
description: An placeholder serving as a valid example of the field value. description: An placeholder serving as a valid example of the field value.
type: string type: string
required: ['regexp', 'placeholder']
required: ['fieldname']
example: { example: {
"network": { "network": {
"regexp": "([a-z0-9]+\\.)*[a-z0-9]+", "regexp": "([a-z0-9]+\\.)*[a-z0-9]+",
@ -63,17 +82,32 @@ properties:
instances: instances:
description: |- description: |-
A list of objects representing independent instances of configuration. A list of objects representing independent instances of configuration.
For instance multiple networks on IRC if multiple are bridged by the For example, multiple networks on IRC if multiple are provided by the
same bridge. same application service.
type: array type: array
items: items:
type: object type: object
title: Protocol Instance
properties:
desc:
type: string
description: A human-readable description for the protocol, such as the name.
example: "Freenode"
icon:
type: string
description: |-
An optional content URI representing the protocol. Overrides the one provided
at the higher level Protocol object.
example: "mxc://example.org/JkLmNoPq"
fields:
type: object
description: Preset values for ``fields`` the client may use to search by.
example: { example: {
"desc": "Freenode", "network": "freenode"
"icon": "mxc://example.org/JkLmNoPq",
"fields": {
"network": "freenode.net",
} }
} network_id:
title: Protocol type: string
type: object description: A unique identifier across all instances.
example: "freenode"
required: ['desc', 'fields', 'network_id']
required: ['user_fields', 'location_fields', 'icon', 'field_types', 'instances']

@ -36,6 +36,7 @@ example: {
}, },
"instances": [ "instances": [
{ {
"network_id": "freenode",
"desc": "Freenode", "desc": "Freenode",
"icon": "mxc://example.org/JkLmNoPq", "icon": "mxc://example.org/JkLmNoPq",
"fields": { "fields": {
@ -59,6 +60,7 @@ example: {
}, },
"instances": [ "instances": [
{ {
"network_id": "gitter",
"desc": "Gitter", "desc": "Gitter",
"icon": "mxc://example.org/zXyWvUt", "icon": "mxc://example.org/zXyWvUt",
"fields": {} "fields": {}

@ -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

@ -21,11 +21,13 @@ properties:
protocol: protocol:
description: The protocol ID that the third party location is a part of. description: The protocol ID that the third party location is a part of.
type: string type: string
example: gitter example: "gitter"
fields: fields:
description: Information used to identify this third party location. description: Information used to identify this third party location.
type: object type: object
example: example: {
"user": "jim" "user": "jim"
}
required: ['userid', 'protocol', 'fields']
title: User title: User
type: object type: object

@ -1,4 +1,3 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2018 New Vector Ltd # Copyright 2018 New Vector Ltd
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
@ -20,83 +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:
"/transactions/{txnId}": "/thirdparty/protocol/{protocol}":
put:
summary: Send some events to the application service.
description: |-
This API is called by the homeserver when it wants to push an event
(or batch of events) to the application service.
Note that the application service should distinguish state events
from message events via the presence of a ``state_key``, rather than
via the event type.
operationId: sendTransaction
parameters:
- in: path
name: txnId
type: string
description: |-
The transaction ID for this set of events. Homeservers generate
these IDs and they are used to ensure idempotency of requests.
required: true
x-example: "35"
- in: body
name: body
description: A list of events.
schema:
type: object
example: {
"events": [
{
"age": 32,
"content": {
"body": "incoming message",
"msgtype": "m.text"
},
"event_id": "$14328055551tzaee:localhost",
"origin_server_ts": 1432804485886,
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"type": "m.room.message",
"user_id": "@bob:localhost"
},
{
"age": 1984,
"content": {
"body": "another incoming message",
"msgtype": "m.text"
},
"event_id": "$1228055551ffsef:localhost",
"origin_server_ts": 1432804485886,
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"type": "m.room.message",
"user_id": "@bob:localhost"
}
]
}
description: "Transaction informations"
properties:
events:
type: array
description: A list of events
items:
type: object
title: Event
required: ["events"]
responses:
200:
description: The transaction was processed successfully.
examples:
application/json: {
}
schema:
type: object
"/_matrix/app/unstable/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: |-
@ -104,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
@ -143,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: |-
@ -151,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
@ -196,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: Retreive 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
@ -247,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: |-
Retreive 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
@ -292,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: |-
Retreive 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

@ -0,0 +1,78 @@
# Copyright 2016 OpenMarket Ltd
# 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.
swagger: '2.0'
info:
title: "Matrix Application Service API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/app/v1
produces:
- application/json
securityDefinitions:
$ref: definitions/security.yaml
paths:
"/transactions/{txnId}":
put:
summary: Send some events to the application service.
description: |-
This API is called by the homeserver when it wants to push an event
(or batch of events) to the application service.
Note that the application service should distinguish state events
from message events via the presence of a ``state_key``, rather than
via the event type.
operationId: sendTransaction
security:
- homeserverAccessToken: []
parameters:
- in: path
name: txnId
type: string
description: |-
The transaction ID for this set of events. Homeservers generate
these IDs and they are used to ensure idempotency of requests.
required: true
x-example: "35"
- in: body
name: body
description: A list of events.
schema:
type: object
example: {
"events": [
{"$ref": "../../event-schemas/examples/m.room.member"},
{"$ref": "../../event-schemas/examples/m.room.message#m.text"}
]
}
description: Transaction information
properties:
events:
type: array
description: |-
A list of events, formatted as per the Client-Server API.
items:
type: object
title: Event
required: ["events"]
responses:
200:
description: The transaction was processed successfully.
examples:
application/json: {}
schema:
type: object

@ -105,7 +105,8 @@ paths:
type: string type: string
description: Most recently seen IP address of the session. description: Most recently seen IP address of the session.
last_seen: last_seen:
type: number type: integer
format: int64
description: Unix timestamp that the session was last active. description: Unix timestamp that the session was last active.
user_agent: user_agent:
type: string type: string

@ -0,0 +1,88 @@
# 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.
swagger: '2.0'
info:
title: "Matrix Client-Server Application Service Room Directory API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
# Note: this is the same access_token definition used elsewhere in the client
# server API, however this expects an access token for an application service.
$ref: definitions/security.yaml
paths:
"/directory/list/appservice/{networkId}/{roomId}":
put:
summary: |-
Updates a room's visibility in the application service's room directory.
description: |-
Updates the visibility of a given room on the application service's room
directory.
This API is similar to the room directory visibility API used by clients
to update the homeserver's more general room directory.
This API requires the use of an application service access token (``as_token``)
instead of a typical client's access_token. This API cannot be invoked by
users who are not identified as application services.
operationId: updateAppserviceRoomDirectoryVsibility
parameters:
- in: path
type: string
name: networkId
description: |-
The protocol (network) ID to update the room list for. This would
have been provided by the application service as being listed as
a supported protocol.
required: true
x-example: "irc"
- in: path
type: string
name: roomId
description: The room ID to add to the directory.
required: true
x-example: "!somewhere:domain.com"
- in: body
name: body
required: true
schema:
type: object
properties:
visibility:
type: string
enum: ["public", "private"]
description: |-
Whether the room should be visible (public) in the directory
or not (private).
example: "public"
required: ['visibility']
security:
# again, this is the appservice's token - not a typical client's
- accessToken: []
responses:
200:
description: The room's directory visibility has been updated.
schema:
type: object
examples:
application/json: {}
tags:
- Application service room directory management

@ -259,7 +259,8 @@ paths:
description: "The URL to get a preview of" description: "The URL to get a preview of"
required: true required: true
- in: query - in: query
type: number type: integer
format: int64
x-example: 1510610716656 x-example: 1510610716656
name: ts name: ts
description: |- description: |-
@ -276,7 +277,8 @@ paths:
type: object type: object
properties: properties:
"matrix:image:size": "matrix:image:size":
type: number type: integer
format: int64
description: |- description: |-
The byte-size of the image. Omitted if there is no image attached. The byte-size of the image. Omitted if there is no image attached.
"og:image": "og:image":
@ -324,7 +326,8 @@ paths:
type: object type: object
properties: properties:
m.upload.size: m.upload.size:
type: number type: integer
format: int64
description: |- description: |-
The maximum size an upload can be in bytes. The maximum size an upload can be in bytes.
Clients SHOULD use this as a guide when uploading content. Clients SHOULD use this as a guide when uploading content.

@ -11,7 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
title: Filter title: EventFilter
properties: properties:
limit: limit:
description: The maximum number of events to return. description: The maximum number of events to return.

@ -45,7 +45,7 @@ properties:
description: |- description: |-
The name of the room, if any. The name of the room, if any.
num_joined_members: num_joined_members:
type: number type: integer
description: |- description: |-
The number of members joined to the room. The number of members joined to the room.
room_id: room_id:
@ -82,7 +82,7 @@ properties:
absence of this token means there are no results before this absence of this token means there are no results before this
batch, i.e. this is the first batch. batch, i.e. this is the first batch.
total_room_count_estimate: total_room_count_estimate:
type: number type: integer
description: |- description: |-
An estimate on the total number of public rooms, if the An estimate on the total number of public rooms, if the
server has an estimate. server has an estimate.

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
allOf: allOf:
- $ref: event_filter.yaml - $ref: event_filter.yaml
- type: object
title: RoomEventFilter title: RoomEventFilter
properties: properties:
not_rooms: not_rooms:
@ -30,6 +31,5 @@ properties:
type: array type: array
contains_url: contains_url:
type: boolean type: boolean
description: If ``true``, includes only events with a url key in their content. If description: If ``true``, includes only events with a ``url`` key in their content. If
``false``, excludes those events. ``false``, excludes those events. Defaults to ``false``.
type: object

@ -11,6 +11,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
type: object
title: Filter
properties: properties:
event_fields: event_fields:
description: List of event fields to include. If this list is absent then all description: List of event fields to include. If this list is absent then all
@ -40,6 +42,7 @@ properties:
room: room:
title: RoomFilter title: RoomFilter
description: Filters to be applied to room data. description: Filters to be applied to room data.
type: object
properties: properties:
not_rooms: not_rooms:
description: A list of room IDs to exclude. If this list is absent then no rooms description: A list of room IDs to exclude. If this list is absent then no rooms
@ -76,5 +79,3 @@ properties:
allOf: allOf:
- $ref: room_event_filter.yaml - $ref: room_event_filter.yaml
description: The per user account data to include for rooms. description: The per user account data to include for rooms.
type: object
type: object

@ -0,0 +1,24 @@
# 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.
title: Homeserver Information
description: |-
Used by clients to discover homeserver information.
type: object
properties:
base_url:
type: string
description: The base URL for the homeserver for client-server connections.
example: https://matrix.example.com
required:
- base_url

@ -0,0 +1,24 @@
# 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.
title: Identity Server Information
description: |-
Used by clients to discover identity server information.
type: object
properties:
base_url:
type: string
description: The base URL for the identity server for client-server connections.
example: https://identity.example.com
required:
- base_url

@ -41,7 +41,7 @@ paths:
required: true required: true
x-example: "#monkeys:matrix.org" x-example: "#monkeys:matrix.org"
- in: body - in: body
name: roomInfo name: body
description: Information about this room alias. description: Information about this room alias.
required: true required: true
schema: schema:
@ -50,6 +50,7 @@ paths:
room_id: room_id:
type: string type: string
description: The room ID to set. description: The room ID to set.
required: ['room_id']
example: { example: {
"room_id": "!abnjk1jdasj98:capuchins.com" "room_id": "!abnjk1jdasj98:capuchins.com"
} }
@ -57,8 +58,7 @@ paths:
200: 200:
description: The mapping was created. description: The mapping was created.
examples: examples:
application/json: { application/json: {}
}
schema: schema:
type: object type: object
409: 409:

@ -81,17 +81,18 @@ paths:
responses: responses:
200: 200:
description: The filter was created. description: The filter was created.
examples:
application/json: {
"filter_id": "66696p746572"
}
schema: schema:
type: object type: object
properties: properties:
filter_id: filter_id:
type: string type: string
description: |- description: |-
The ID of the filter that was created. The ID of the filter that was created. Cannot start
with a ``{`` as this character is used to determine
if the filter provided is inline JSON or a previously
declared filter by homeservers on some APIs.
example: "66696p746572"
required: ['filter_id']
tags: tags:
- Room participation - Room participation
"/user/{userId}/filter/{filterId}": "/user/{userId}/filter/{filterId}":

@ -123,7 +123,7 @@ paths:
parameters: parameters:
- in: query - in: query
name: limit name: limit
type: number type: integer
description: |- description: |-
Limit the number of results returned. Limit the number of results returned.
- in: query - in: query
@ -173,7 +173,7 @@ paths:
type: object type: object
properties: properties:
limit: limit:
type: number type: integer
description: |- description: |-
Limit the number of results returned. Limit the number of results returned.
since: since:
@ -194,8 +194,26 @@ paths:
description: |- description: |-
A string to search for in the room metadata, e.g. name, A string to search for in the room metadata, e.g. name,
topic, canonical alias etc. (Optional). topic, canonical alias etc. (Optional).
include_all_networks:
type: boolean
description: |-
Whether or not to include all known networks/protocols from
application services on the homeserver. Defaults to false.
example: false
third_party_instance_id:
type: string
description: |-
The specific third party network/protocol to request from the
homeserver. Can only be used if ``include_all_networks`` is false.
example: "irc"
example: { example: {
"limit": 10, "filter": {"generic_search_term": "foo"}} "limit": 10,
"filter": {
"generic_search_term": "foo"
},
"include_all_networks": false,
"third_party_instance_id": "irc"
}
responses: responses:
200: 200:
description: A list of the rooms on the server. description: A list of the rooms on the server.
@ -233,7 +251,7 @@ paths:
description: |- description: |-
The name of the room, if any. The name of the room, if any.
num_joined_members: num_joined_members:
type: number type: integer
description: |- description: |-
The number of members joined to the room. The number of members joined to the room.
room_id: room_id:
@ -270,7 +288,7 @@ paths:
absence of this token means there are no results before this absence of this token means there are no results before this
batch, i.e. this is the first batch. batch, i.e. this is the first batch.
total_room_count_estimate: total_room_count_estimate:
type: number type: integer
description: |- description: |-
An estimate on the total number of public rooms, if the An estimate on the total number of public rooms, if the
server has an estimate. server has an estimate.

@ -45,7 +45,7 @@ paths:
required: false required: false
x-example: "xxxxx" x-example: "xxxxx"
- in: query - in: query
type: number type: integer
name: limit name: limit
description: Limit on the number of events to return in this request. description: Limit on the number of events to return in this request.
required: false required: false

@ -343,6 +343,8 @@ paths:
This endpoint allows the creation, modification and deletion of pushers This endpoint allows the creation, modification and deletion of pushers
for this user ID. The behaviour of this endpoint varies depending on the for this user ID. The behaviour of this endpoint varies depending on the
values in the JSON body. values in the JSON body.
When creating push rules, they MUST be enabled by default.
operationId: setPushRule operationId: setPushRule
security: security:
- accessToken: [] - accessToken: []
@ -424,7 +426,7 @@ paths:
required: ["actions"] required: ["actions"]
responses: responses:
200: 200:
description: The pusher was set. description: The push rule was created/updated.
examples: examples:
application/json: { application/json: {
} }

@ -218,7 +218,7 @@ paths:
description: The email address description: The email address
example: "example@example.com" example: "example@example.com"
send_attempt: send_attempt:
type: number type: integer
description: Used to distinguish protocol level retries from requests to re-send the email. description: Used to distinguish protocol level retries from requests to re-send the email.
example: 1 example: 1
required: ["client_secret", "email", "send_attempt"] required: ["client_secret", "email", "send_attempt"]
@ -283,7 +283,7 @@ paths:
description: The phone number. description: The phone number.
example: "example@example.com" example: "example@example.com"
send_attempt: send_attempt:
type: number type: integer
description: Used to distinguish protocol level retries from requests to re-send the SMS message. description: Used to distinguish protocol level retries from requests to re-send the SMS message.
example: 1 example: 1
required: ["client_secret", "country", "phone_number", "send_attempt"] required: ["client_secret", "country", "phone_number", "send_attempt"]

@ -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

@ -41,7 +41,7 @@ paths:
type: string type: string
description: |- description: |-
The point to return events from. If given, this should be a The point to return events from. If given, this should be a
`next_batch` result from a previous call to this endpoint. ``next_batch`` result from a previous call to this endpoint.
x-example: "YWxsCgpOb25lLDM1ODcwOA" x-example: "YWxsCgpOb25lLDM1ODcwOA"
- in: body - in: body
name: body name: body
@ -95,6 +95,7 @@ paths:
# for now :/ # for now :/
description: |- description: |-
This takes a `filter`_. This takes a `filter`_.
$ref: "definitions/room_event_filter.yaml"
order_by: order_by:
title: "Ordering" title: "Ordering"
type: string type: string
@ -179,7 +180,7 @@ paths:
description: Mapping of category name to search criteria. description: Mapping of category name to search criteria.
properties: properties:
count: count:
type: number type: integer
description: An approximate count of the total number of results found. description: An approximate count of the total number of results found.
highlights: highlights:
type: array type: array

@ -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
@ -227,6 +228,14 @@ paths:
room up to the point when the user left. room up to the point when the user left.
allOf: allOf:
- $ref: "definitions/timeline_batch.yaml" - $ref: "definitions/timeline_batch.yaml"
account_data:
title: Account Data
type: object
description: |-
The private data that this user has attached to
this room.
allOf:
- $ref: "definitions/event_batch.yaml"
presence: presence:
title: Presence title: Presence
type: object type: object

@ -73,7 +73,7 @@ paths:
$ref: definitions/errors/error.yaml $ref: definitions/errors/error.yaml
"/thirdparty/location/{protocol}": "/thirdparty/location/{protocol}":
get: get:
summary: Retreive Matrix-side portals rooms leading to a third party location. summary: Retrieve Matrix-side portals rooms leading to a third party location.
description: |- description: |-
Requesting this endpoint with a valid protocol name results in a list Requesting this endpoint with a valid protocol name results in a list
of successful mapping results in a JSON array. Each result contains of successful mapping results in a JSON array. Each result contains
@ -151,7 +151,7 @@ paths:
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: |-
Retreive 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: security:
@ -181,7 +181,7 @@ paths:
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: |-
Retreive 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: security:
- accessToken: [] - accessToken: []

@ -55,7 +55,7 @@ paths:
description: The term to search for description: The term to search for
example: "foo" example: "foo"
limit: limit:
type: number type: integer
description: The maximum number of results to return. Defaults to 10. description: The maximum number of results to return. Defaults to 10.
example: 10 example: 10
required: ["search_term"] required: ["search_term"]

@ -0,0 +1,66 @@
# 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.
swagger: '2.0'
info:
title: "Matrix Client-Server Server Discovery API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
basePath: /.well-known
produces:
- application/json
paths:
"/matrix/client":
get:
summary: Gets Matrix server discovery information about the domain.
description: |-
Gets discovery information about the domain. The file may include
additional keys, which MUST follow the Java package naming convention,
e.g. ``com.example.myapp.property``. This ensures property names are
suitably namespaced for each application and reduces the risk of
clashes.
Note that this endpoint is not necessarily handled by the homeserver,
but by another webserver, to be used for discovering the homeserver URL.
operationId: getWellknown
responses:
200:
description: Server discovery information.
examples:
application/json: {
"m.homeserver": {
"base_url": "https://matrix.example.com"
},
"m.identity_server": {
"base_url": "https://identity.example.com"
}
}
schema:
type: object
properties:
m.homeserver:
description: Information about the homeserver to connect to.
"$ref": "definitions/wellknown/homeserver.yaml"
m.identity_server:
description: Optional. Information about the identity server to connect to.
"$ref": "definitions/wellknown/identity_server.yaml"
additionalProperties:
description: Application-dependent keys using Java package naming convention.
required:
- m.homeserver
404:
description: No server discovery information available.
tags:
- Server administration

@ -62,6 +62,7 @@ paths:
validated_at: validated_at:
type: integer type: integer
description: Timestamp indicating the time that the 3pid was validated. description: Timestamp indicating the time that the 3pid was validated.
required: ['medium', 'address', 'validated_at']
400: 400:
description: |- description: |-
The session has not been validated. The session has not been validated.
@ -74,6 +75,8 @@ paths:
"errcode": "M_SESSION_NOT_VALIDATED", "errcode": "M_SESSION_NOT_VALIDATED",
"error": "This validation session has not yet been completed" "error": "This validation session has not yet been completed"
} }
schema:
$ref: "../client-server/definitions/errors/error.yaml"
404: 404:
description: The Session ID or client secret were not found description: The Session ID or client secret were not found
examples: examples:
@ -81,6 +84,8 @@ paths:
"errcode": "M_NO_VALID_SESSION", "errcode": "M_NO_VALID_SESSION",
"error": "No valid session was found matching that sid and client secret" "error": "No valid session was found matching that sid and client secret"
} }
schema:
$ref: "../client-server/definitions/errors/error.yaml"
"/bind": "/bind":
post: post:
summary: Publish an association between a session and a Matrix user ID. summary: Publish an association between a session and a Matrix user ID.
@ -158,6 +163,15 @@ paths:
signatures: signatures:
type: object type: object
description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services.
$ref: "../../schemas/server-signatures.yaml"
required:
- address
- medium
- mxid
- not_before
- not_after
- ts
- signatures
400: 400:
description: |- description: |-
The association was not published. The association was not published.
@ -170,6 +184,8 @@ paths:
"errcode": "M_SESSION_NOT_VALIDATED", "errcode": "M_SESSION_NOT_VALIDATED",
"error": "This validation session has not yet been completed" "error": "This validation session has not yet been completed"
} }
schema:
$ref: "../client-server/definitions/errors/error.yaml"
404: 404:
description: The Session ID or client secret were not found description: The Session ID or client secret were not found
examples: examples:
@ -177,3 +193,5 @@ paths:
"errcode": "M_NO_VALID_SESSION", "errcode": "M_NO_VALID_SESSION",
"error": "No valid session was found matching that sid and client secret" "error": "No valid session was found matching that sid and client secret"
} }
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -93,12 +93,20 @@ paths:
sid: sid:
type: string type: string
description: The session ID. description: The session ID.
required: ['sid']
400: 400:
description: | description: |
An error ocurred. Some possible errors are: An error ocurred. Some possible errors are:
- ``M_INVALID_EMAIL``: The email address provided was invalid. - ``M_INVALID_EMAIL``: The email address provided was invalid.
- ``M_EMAIL_SEND_ERROR``: The validation email could not be sent. - ``M_EMAIL_SEND_ERROR``: The validation email could not be sent.
examples:
application/json: {
"errcode": "M_INVALID_EMAIL",
"error": "The email address is not valid"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
"/validate/email/submitToken": "/validate/email/submitToken":
post: post:
summary: Validate ownership of an email address. summary: Validate ownership of an email address.
@ -151,6 +159,7 @@ paths:
success: success:
type: boolean type: boolean
description: Whether the validation was successful or not. description: Whether the validation was successful or not.
required: ['success']
get: get:
summary: Validate ownership of an email address. summary: Validate ownership of an email address.
description: |- description: |-

@ -68,9 +68,11 @@ paths:
signatures: signatures:
type: object type: object
description: The signature of the mxid, sender, and token. description: The signature of the mxid, sender, and token.
$ref: "../../schemas/server-signatures.yaml"
token: token:
type: string type: string
description: The token for the invitation. description: The token for the invitation.
required: ['mxid', 'sender', 'signatures', 'token']
examples: examples:
application/json: { application/json: {
"mxid": "@foo:bar.com", "mxid": "@foo:bar.com",
@ -84,7 +86,10 @@ paths:
} }
404: 404:
description: Token was not found. description: Token was not found.
example: { examples:
application/json: {
"errcode": "M_UNRECOGNIZED", "errcode": "M_UNRECOGNIZED",
"error": "Didn't recognize token" "error": "Didn't recognize token"
} }
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -55,7 +55,6 @@ paths:
"not_before": 1428825849161, "not_before": 1428825849161,
"not_after": 4582425849161, "not_after": 4582425849161,
"ts": 1428825849161, "ts": 1428825849161,
"signatures": { "signatures": {
"matrix.org": { "matrix.org": {
"ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ" "ed25519:0": "ENiU2YORYUJgE6WBMitU0mppbQjidDLanAusj8XS2nVRHPu+0t42OKA/r6zV6i2MzUbNQ3c3MiLScJuSsOiVDQ"
@ -86,6 +85,15 @@ paths:
signatures: signatures:
type: object type: object
description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services. description: The signatures of the verifying identity services which show that the association should be trusted, if you trust the verifying identity services.
$ref: "../../schemas/server-signatures.yaml"
required:
- address
- medium
- mxid
- not_before
- not_after
- ts
- signatures
"/bulk_lookup": "/bulk_lookup":
post: post:
summary: Lookup Matrix user IDs for a list of 3pids. summary: Lookup Matrix user IDs for a list of 3pids.
@ -110,9 +118,14 @@ paths:
items: items:
type: array type: array
title: 3PID mappings title: 3PID mappings
minItems: 2
maxItems: 2
items: items:
type: string # TODO: Give real names to these values. Adding a `title` does not work.
title: 3PID medium or address #- type: 3PID Medium
#- type: 3PID Address
- type: string
- type: string
description: an array of arrays containing the `3PID Types`_ with the ``medium`` in first position and the ``address`` in second position. description: an array of arrays containing the `3PID Types`_ with the ``medium`` in first position and the ``address`` in second position.
required: required:
- "threepids" - "threepids"
@ -134,9 +147,16 @@ paths:
items: items:
type: array type: array
title: 3PID mappings title: 3PID mappings
minItems: 3
maxItems: 3
items: items:
type: string # TODO: Give real names to these values. Adding a `title` does not work.
title: 3PID medium or address or the Matrix ID #- type: 3PID Medium
#- type: 3PID Address
#- type: Matrix User ID
- type: string
- type: string
- type: string
description: an array of array containing the `3PID Types`_ with the ``medium`` in first position, the ``address`` in second position and Matrix ID in third position. description: an array of array containing the `3PID Types`_ with the ``medium`` in first position, the ``address`` in second position and Matrix ID in third position.
required: required:
- "threepids" - "threepids"

@ -99,12 +99,20 @@ paths:
sid: sid:
type: string type: string
description: The session ID. description: The session ID.
required: ['sid']
400: 400:
description: | description: |
An error ocurred. Some possible errors are: An error ocurred. Some possible errors are:
- ``M_INVALID_ADDRESS``: The phone number provided was invalid. - ``M_INVALID_ADDRESS``: The phone number provided was invalid.
- ``M_SEND_ERROR``: The validation SMS could not be sent. - ``M_SEND_ERROR``: The validation SMS could not be sent.
examples:
application/json: {
"errcode": "M_INVALID_ADDRESS",
"error": "The phone number is not valid"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
"/validate/msisdn/submitToken": "/validate/msisdn/submitToken":
post: post:
summary: Validate ownership of a phone number. summary: Validate ownership of a phone number.
@ -157,6 +165,7 @@ paths:
success: success:
type: boolean type: boolean
description: Whether the validation was successful or not. description: Whether the validation was successful or not.
required: ['success']
get: get:
summary: Validate ownership of a phone number. summary: Validate ownership of a phone number.
description: |- description: |-

@ -52,6 +52,18 @@ paths:
properties: properties:
public_key: public_key:
type: string type: string
description: Unpadded Base64 encoded public key.
required: ['public_key']
404:
description:
The public key was not found.
examples:
application/json: {
"errcode": "M_NOT_FOUND",
"error": "The public key was not found"
}
schema:
$ref: "../client-server/definitions/errors/error.yaml"
"/pubkey/isvalid": "/pubkey/isvalid":
get: get:
summary: Check whether a long-term public key is valid. summary: Check whether a long-term public key is valid.
@ -80,6 +92,7 @@ paths:
valid: valid:
type: boolean type: boolean
description: Whether the public key is recognised and is currently valid. description: Whether the public key is recognised and is currently valid.
required: ['valid']
"/pubkey/ephemeral/isvalid": "/pubkey/ephemeral/isvalid":
get: get:
summary: Check whether a short-term public key is valid. summary: Check whether a short-term public key is valid.
@ -108,3 +121,4 @@ paths:
valid: valid:
type: boolean type: boolean
description: Whether the public key is recognised and is currently valid. description: Whether the public key is recognised and is currently valid.
required: ['valid']

@ -90,6 +90,7 @@ paths:
display_name: display_name:
type: string type: string
description: The generated (redacted) display_name. description: The generated (redacted) display_name.
required: ['token', 'public_keys', 'display_name']
example: example:
application/json: { application/json: {
"token": "sometoken", "token": "sometoken",
@ -112,3 +113,5 @@ paths:
"error": "Binding already known", "error": "Binding already known",
"mxid": mxid "mxid": mxid
} }
schema:
$ref: "../client-server/definitions/errors/error.yaml"

@ -31,7 +31,7 @@ properties:
example: 1532991320875 example: 1532991320875
pdus: pdus:
type: array type: array
description: List of persistent updates to rooms. description: List of persistent updates to rooms. Must not include more than 50 PDUs.
items: items:
$ref: "pdu.yaml" $ref: "pdu.yaml"
required: ['origin', 'origin_server_ts', 'pdus'] required: ['origin', 'origin_server_ts', 'pdus']

@ -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

@ -49,6 +49,20 @@ paths:
A pagination token from a previous call to this endpoint to fetch more A pagination token from a previous call to this endpoint to fetch more
rooms. rooms.
x-example: "GetMoreRoomsTokenHere" x-example: "GetMoreRoomsTokenHere"
- in: query
name: include_all_networks
type: boolean
description: |-
Whether or not to include all networks/protocols defined by application
services on the homeserver. Defaults to false.
x-example: false
- in: query
name: third_party_instance_id
type: string
description: |-
The specific third party network/protocol to request from the homeserver.
Can only be used if ``include_all_networks`` is false.
x-example: "irc"
responses: responses:
200: 200:
description: The public room list for the homeserver. description: The public room list for the homeserver.

@ -61,7 +61,7 @@ paths:
type: array type: array
description: |- description: |-
List of ephemeral messages. May be omitted if there are no ephemeral List of ephemeral messages. May be omitted if there are no ephemeral
messages to be sent. messages to be sent. Must not include more than 100 EDUs.
items: items:
$ref: "definitions/edu.yaml" $ref: "definitions/edu.yaml"
example: { example: {

@ -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

@ -0,0 +1 @@
Specify how to control the power level required for ``@room``

@ -0,0 +1 @@
Add ``.well-known`` server discovery method

@ -0,0 +1 @@
Share room decryption keys between devices

@ -0,0 +1 @@
Add a common standard for user, room, and group mentions in messages.

@ -0,0 +1 @@
Add server ACLs as an option for controlling federation in a room.

@ -0,0 +1 @@
Clarify that new push rules should be enabled by default, and that unrecognised conditions should not match.

@ -0,0 +1 @@
Add new push rules for encrypted events and ``@room`` notifications.

@ -0,0 +1 @@
Add third party network room directories, as provided by application services.

@ -0,0 +1 @@
Clarify the supported HTML features for room messages.

@ -0,0 +1 @@
Move the ``invite_room_state`` definition under ``unsigned`` where it actually resides.

@ -0,0 +1 @@
Clarify the object structures and defaults for Filters.

@ -0,0 +1 @@
Clarify instances of ``type: number`` in the swagger/OpenAPI schema definitions.

@ -0,0 +1 @@
Clarify that left rooms also have account data in ``/sync``.

@ -0,0 +1 @@
Fix naming of the body field in ``PUT /directory/room``.

@ -0,0 +1 @@
Clarify the filter object schema used in room searching.

@ -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

@ -0,0 +1 @@
Add more presence options to the ``set_presence`` parameter of ``/sync``. (Thanks @mujx!)

@ -0,0 +1,6 @@
r0.1.0
======
The first release of the Push Gateway specification. This release contains
a single endpoint, ``/notify``, that pushers may use to send push notifications
to clients.

@ -0,0 +1,30 @@
[tool.towncrier]
filename = "../push_gateway.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

@ -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"
}

@ -5,6 +5,7 @@
"avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto", "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
"displayname": "Alice Margatroid" "displayname": "Alice Margatroid"
}, },
"unsigned": {
"invite_room_state": [ "invite_room_state": [
{ {
"type": "m.room.name", "type": "m.room.name",
@ -20,7 +21,8 @@
"join_rule": "invite" "join_rule": "invite"
} }
} }
], ]
},
"state_key": "@alice:localhost", "state_key": "@alice:localhost",
"origin_server_ts": 1431961217939, "origin_server_ts": 1431961217939,
"event_id": "$WLGTSEFSEF:localhost", "event_id": "$WLGTSEFSEF:localhost",

@ -2,7 +2,9 @@
"age": 242352, "age": 242352,
"content": { "content": {
"body": "This is an example notice", "body": "This is an example notice",
"msgtype": "m.notice" "msgtype": "m.notice",
"format": "org.matrix.custom.html",
"formatted_body": "This is an <strong>example</strong> notice"
}, },
"origin_server_ts": 1431961217939, "origin_server_ts": 1431961217939,
"event_id": "$WLGTSEFSEF:localhost", "event_id": "$WLGTSEFSEF:localhost",

@ -14,7 +14,10 @@
"users": { "users": {
"@example:localhost": 100 "@example:localhost": 100
}, },
"users_default": 0 "users_default": 0,
"notifications": {
"room": 20
}
}, },
"state_key": "", "state_key": "",
"origin_server_ts": 1431961217939, "origin_server_ts": 1431961217939,

@ -0,0 +1,14 @@
{
"age": 242352,
"content": {
"allow_ip_literals": false,
"allow": ["*"],
"deny": ["*.evil.com", "evil.com"]
},
"state_key": "",
"origin_server_ts": 1431961217939,
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.server_acl",
"room_id": "!Cuyf34gef24t:localhost",
"sender": "@example:localhost"
}

@ -0,0 +1,8 @@
{
"content": {
"action": "cancel_request",
"requesting_device_id": "RJYKSTBOIE",
"request_id": "1495474790150.19"
},
"type": "m.room_key_request"
}

@ -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"
}

@ -16,7 +16,8 @@ properties:
origin_server_ts: origin_server_ts:
description: Timestamp in milliseconds on originating homeserver description: Timestamp in milliseconds on originating homeserver
when this event was sent. when this event was sent.
type: number type: integer
format: int64
unsigned: unsigned:
description: Contains optional extra information about the event. description: Contains optional extra information about the event.
properties: properties:

@ -11,7 +11,11 @@ properties:
state_key: state_key:
description: A unique key which defines the overwriting semantics for this piece description: A unique key which defines the overwriting semantics for this piece
of room state. This value is often a zero-length string. The presence of this of room state. This value is often a zero-length string. The presence of this
key makes this event a State Event. The key MUST NOT start with '_'. key makes this event a State Event.
State keys starting with an ``@`` are reserved for referencing user IDs, such
as room members. With the exception of a few events, state events set with a
given user's ID as the state key MUST only be set by that user.
type: string type: string
required: required:
- state_key - state_key

@ -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

@ -13,8 +13,8 @@ properties:
algorithm: algorithm:
type: string type: string
enum: enum:
- m.olm.curve25519-aes-sha256 - m.olm.v1.curve25519-aes-sha2
- m.megolm.v1.aes-sha - m.megolm.v1.aes-sha2
description: |- description: |-
The encryption algorithm used to encrypt this event. The The encryption algorithm used to encrypt this event. The
value of this field determines which other properties will be value of this field determines which other properties will be

@ -18,7 +18,9 @@ description: |-
The ``third_party_invite`` property will be set if this invite is an ``invite`` event and is the successor of an ``m.room.third_party_invite`` event, and absent otherwise. The ``third_party_invite`` property will be set if this invite is an ``invite`` event and is the successor of an ``m.room.third_party_invite`` event, and absent otherwise.
This event may also include an ``invite_room_state`` key **outside the** ``content`` **key**. If present, this contains an array of ``StrippedState`` Events. These events provide information on a subset of state events such as the room name. This event may also include an ``invite_room_state`` key inside the event's ``unsigned`` data.
If present, this contains an array of ``StrippedState`` Events. These events provide information
on a subset of state events such as the room name.
properties: properties:
content: content:
properties: properties:
@ -71,10 +73,11 @@ properties:
- signed - signed
title: Invite title: Invite
type: object type: object
required: unsigned:
- membership
title: EventContent
type: object type: object
title: UnsignedData
description: Contains optional extra information about the event.
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:
@ -97,8 +100,15 @@ properties:
title: StrippedState title: StrippedState
type: object type: object
type: array type: array
required:
- membership
title: EventContent
type: object
state_key: state_key:
description: The ``user_id`` this membership event relates to. description: |-
The ``user_id`` this membership event relates to. In all cases except for when ``membership`` is
``join``, the user ID sending the event does not need to match the user ID in the ``state_key``,
unlike other events. Regular authorisation rules still apply.
type: string type: string
type: type:
enum: enum:

@ -46,10 +46,10 @@ properties:
properties: properties:
ban: ban:
description: The level required to ban a user. Defaults to 50 if unspecified. description: The level required to ban a user. Defaults to 50 if unspecified.
type: number type: integer
events: events:
additionalProperties: additionalProperties:
type: number type: integer
description: The level required to send specific event types. This is a mapping from event type to power level required. description: The level required to send specific event types. This is a mapping from event type to power level required.
title: Event power levels title: Event power levels
type: object type: object
@ -57,25 +57,25 @@ properties:
description: |- description: |-
The default level required to send message events. Can be The default level required to send message events. Can be
overridden by the ``events`` key. Defaults to 0 if unspecified. overridden by the ``events`` key. Defaults to 0 if unspecified.
type: number type: integer
invite: invite:
description: The level required to invite a user. Defaults to 50 if unspecified. description: The level required to invite a user. Defaults to 50 if unspecified.
type: number type: integer
kick: kick:
description: The level required to kick a user. Defaults to 50 if unspecified. description: The level required to kick a user. Defaults to 50 if unspecified.
type: number type: integer
redact: redact:
description: The level required to redact an event. Defaults to 50 if unspecified. description: The level required to redact an event. Defaults to 50 if unspecified.
type: number type: integer
state_default: state_default:
description: |- description: |-
The default level required to send state events. Can be overridden The default level required to send state events. Can be overridden
by the ``events`` key. Defaults to 50 if unspecified, but 0 if by the ``events`` key. Defaults to 50 if unspecified, but 0 if
there is no ``m.room.power_levels`` event at all. there is no ``m.room.power_levels`` event at all.
type: number type: integer
users: users:
additionalProperties: additionalProperties:
type: number type: integer
description: The power levels for specific users. This is a mapping from ``user_id`` to power level for that user. description: The power levels for specific users. This is a mapping from ``user_id`` to power level for that user.
title: User power levels title: User power levels
type: object type: object
@ -84,7 +84,19 @@ properties:
The default power level for every user in the room, unless their The default power level for every user in the room, unless their
``user_id`` is mentioned in the ``users`` key. Defaults to 0 if ``user_id`` is mentioned in the ``users`` key. Defaults to 0 if
unspecified. unspecified.
type: number type: integer
notifications:
properties:
room:
type: integer
description: The level required to trigger an ``@room`` notification. Defaults to 50 if unspecified.
additionalProperties:
type: integer
description: |-
The power level requirements for specific notification types.
This is a mapping from ``key`` to power level for that notifications key.
title: Notifications
type: object
type: object type: object
state_key: state_key:
description: A zero-length string. description: A zero-length string.

@ -0,0 +1,88 @@
---
title: Server ACL
description: |-
An event to indicate which servers are permitted to participate in the
room. Server ACLs may allow or deny groups of hosts. All servers participating
in the room, including those that are denied, are expected to uphold the
server ACL. Servers that do not uphold the ACLs MUST be added to the denied hosts
list in order for the ACLs to remain effective.
The ``allow`` and ``deny`` lists are lists of globs supporting ``?`` and ``*``
as wildcards. When comparing against the server ACLs, the suspect server's port
number must not be considered. Therefore ``evil.com``, ``evil.com:8448``, and
``evil.com:1234`` would all match rules that apply to ``evil.com``, for example.
The ACLs are applied to servers when they make requests, and are applied in
the following order:
1. If there is no ``m.room.server_acl`` event in the room state, allow.
#. If the server name is an IP address (v4 or v6) literal, and ``allow_ip_literals``
is present and ``false``, deny.
#. If the server name matches an entry in the ``deny`` list, deny.
#. If the server name matches an entry in the ``allow`` list, allow.
#. Otherwise, deny.
.. Note::
Server ACLs do not restrict the events relative to the room DAG via authorisation
rules, but instead act purely at the network layer to determine which servers are
allowed to connect and interact with a given room.
.. WARNING::
Failing to provide an ``allow`` rule of some kind will prevent **all**
servers from participating in the room, including the sender. This renders
the room unusable. A common allow rule is ``[ "*" ]`` which would still
permit the use of the ``deny`` list without losing the room.
.. WARNING::
All compliant servers must implement server ACLs. However, legacy or noncompliant
servers exist which do not uphold ACLs, and these MUST be manually appended to
the denied hosts list when setting an ACL to prevent them from leaking events from
banned servers into a room. Currently, the only way to determine noncompliant hosts is
to check the ``prev_events`` of leaked events, therefore detecting servers which
are not upholding the ACLs. Server versions can also be used to try to detect hosts that
will not uphold the ACLs, although this is not comprehensive. Server ACLs were added
in Synapse v0.32.0, although other server implementations and versions exist in the world.
allOf:
- $ref: core-event-schema/state_event.yaml
type: object
properties:
content:
properties:
allow_ip_literals:
type: boolean
description: |-
True to allow server names that are IP address literals. False to
deny. Defaults to true if missing or otherwise not a boolean.
This is strongly recommended to be set to ``false`` as servers running
with IP literal names are strongly discouraged in order to require
legitimate homeservers to be backed by a valid registered domain name.
allow:
type: array
description: |-
The server names to allow in the room, excluding any port information.
Wildcards may be used to cover a wider range of hosts, where ``*``
matches zero or more characters and ``?`` matches exactly one character.
**This defaults to an empty list when not provided, effectively disallowing
every server.**
items:
type: string
deny:
type: array
description: |-
The server names to disallow in the room, excluding any port information.
Wildcards may be used to cover a wider range of hosts, where ``*``
matches zero or more characters and ``?`` matches exactly one character.
This defaults to an empty list when not provided.
items:
type: string
type: object
state_key:
description: A zero-length string.
pattern: '^$'
type: string
type:
enum: ['m.room.server_acl']
type: string

@ -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

@ -0,0 +1,48 @@
# How to release a specification
There are several specifications that belong to matrix, such as the client-server
specification, server-server specification, and identity server specification. Each
of these gets released independently of each other with their own version numbers.
Once a specification is ready for release, a branch should be created to track the
changes in and to hold potential future hotfixes. This should be the name of the
specification (as it appears in the directory structure of this project) followed
by "release-" and the release version. For example, if the Client-Server Specification
was getting an r0.4.0 release, the branch name would be `client_server/release-r0.4.0`.
*Note*: Historical releases prior to this process may or may not have an appropriate
release branch. Releases after this document came into place will have an appropriate
branch.
The remainder of the process is as follows:
1. Activate your Python 3 virtual environment.
1. Having checked out the new release branch, navigate your way over to `./changelogs`.
1. Follow the release instructions provided in the README.md located there.
1. Update the changelog section of the specification you're releasing to make a reference
to the new version.
1. Update any version/link references across all specifications.
1. Ensure the `targets.yml` file lists the version correctly.
1. Commit the changes and PR them to master.
1. Tag the release with the format `client_server/r0.4.0`.
1. Add the changes to the matrix-org/matrix.org repository (for historic tracking).
* This is done by making a PR to the `unstyled_docs/spec` folder for the version and
specification you're releasing.
* Don't forget to symlink the new release as `latest`.
1. Perform a release on GitHub to tag the release.
1. Yell from the mountaintop to the world about the new release.
### Creating a release for a brand-new specification
Some specifications may not have ever had a release, and therefore need a bit more work
to become ready.
1. Activate your Python 3 virtual environment.
1. Having checked out the new release branch, navigate your way over to `./changelogs`.
1. Follow the "new changelog" instructions provided in the README.md located there.
1. Open the specification RST file and make some changes:
* Using a released specification as a template, update the changelog section.
* Use the appropriate changelog variable in the RST.
1. Create/define the appropriate variables in `gendoc.py`.
1. Update `targets.yml`.
1. Update any version/link references across all specifications.
1. Follow the regular release process.

@ -0,0 +1,24 @@
# Copyright 2018 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
type: object
example: {
"example.com": {
"ed25519:0": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus"
}
}
additionalProperties:
type: object
title: Server Signatures
additionalProperties:
type: string

@ -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,14 @@ 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(
"--push_gateway_release", "-p", action="store", default="unstable",
help="The push gateway release tag to generate, e.g. r1.2"
)
parser.add_argument( parser.add_argument(
"--list_targets", action="store_true", "--list_targets", action="store_true",
help="Do not update the specification. Instead print a list of targets.", help="Do not update the specification. Instead print a list of targets.",
@ -542,6 +549,8 @@ if __name__ == '__main__':
"%CLIENT_MAJOR_VERSION%": "r0", "%CLIENT_MAJOR_VERSION%": "r0",
"%SERVER_RELEASE_LABEL%": args.server_release, "%SERVER_RELEASE_LABEL%": args.server_release,
"%SERVER_MAJOR_VERSION%": extract_major(args.server_release), "%SERVER_MAJOR_VERSION%": extract_major(args.server_release),
"%APPSERVICE_RELEASE_LABEL%": args.appservice_release,
"%PUSH_GATEWAY_RELEASE_LABEL%": args.push_gateway_release,
} }
exit (main(args.target or ["all"], args.dest, args.nodelete, substitutions)) exit (main(args.target or ["all"], args.dest, args.nodelete, substitutions))

@ -8,8 +8,11 @@ cd `dirname $0`/..
mkdir -p assets mkdir -p assets
if [ "$CIRCLECI" != "true" ]
then
# generate specification/proposals.rst # generate specification/proposals.rst
./scripts/proposals.py ./scripts/proposals.py
fi
# generate the spec docs # generate the spec docs
./scripts/gendoc.py -d assets/spec ./scripts/gendoc.py -d assets/spec

@ -32,6 +32,15 @@ class MatrixSections(Sections):
changelogs = self.units.get("changelogs") changelogs = self.units.get("changelogs")
return changelogs["client_server"] return changelogs["client_server"]
# TODO: We should make this a generic variable instead of having to add functions all the time.
def render_push_gateway_changelog(self):
changelogs = self.units.get("changelogs")
return changelogs["push_gateway"]
def render_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(
@ -754,6 +754,8 @@ class MatrixUnits(Units):
def load_apis(self, substitutions): def load_apis(self, substitutions):
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")
as_ver = substitutions.get("%APPSERVICE_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
return TypeTable(rows=[ return TypeTable(rows=[
@ -766,16 +768,16 @@ 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/unstable.html>`_", "`Identity Service API <identity_service/unstable.html>`_",
"unstable", "unstable",
"Mapping of third party IDs to Matrix IDs", "Mapping of third party IDs to Matrix IDs",
), TypeTableRow( ), TypeTableRow(
"`Push Gateway API <push_gateway/unstable.html>`_", "`Push Gateway API <push_gateway/"+push_gw_ver+".html>`_",
"unstable", push_gw_ver,
"Push notifications for Matrix events", "Push notifications for Matrix events",
), ),
]) ])
@ -791,7 +793,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)
@ -829,7 +831,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 = {
@ -875,15 +877,6 @@ class MatrixUnits(Units):
Units.prop(json_schema, "properties/content") Units.prop(json_schema, "properties/content")
) )
# This is horrible because we're special casing a key on m.room.member.
# We need to do this because we want to document a non-content object.
if schema["type"] == "m.room.member":
invite_room_state = get_tables_for_schema(
json_schema["properties"]["invite_room_state"]["items"],
)
schema["content_fields"].extend(invite_room_state)
# grab msgtype if it is the right kind of event # grab msgtype if it is the right kind of event
msgtype = Units.prop( msgtype = Units.prop(
json_schema, "properties/content/properties/msgtype/enum" json_schema, "properties/content/properties/msgtype/enum"
@ -950,7 +943,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):

@ -1,5 +1,5 @@
.. Copyright 2016 Openmarket Ltd. .. Copyright 2016 Openmarket Ltd.
.. Copyright 2017 New Vector Ltd. .. Copyright 2017, 2018 New Vector Ltd.
.. ..
.. Licensed under the Apache License, Version 2.0 (the "License"); .. Licensed under the Apache License, Version 2.0 (the "License");
.. you may not use this file except in compliance with the License. .. you may not use this file except in compliance with the License.
@ -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 = hostname [ ":" port ]
server_name = host [ ":" port]
port = *DIGIT port = *DIGIT
where ``host`` is as defined by `RFC3986, section 3.2.2 hostname = IPv4address / "[" IPv6address "]" / dns-name
<https://tools.ietf.org/html/rfc3986#section-3.2.2>`_.
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
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
@ -283,3 +321,45 @@ domain).
.. TODO-spec .. TODO-spec
- Need to specify precise grammar for Room Aliases. https://matrix.org/jira/browse/SPEC-391 - Need to specify precise grammar for Room Aliases. https://matrix.org/jira/browse/SPEC-391
matrix.to navigation
++++++++++++++++++++
.. NOTE::
This namespacing is in place pending a ``matrix://`` (or similar) URI scheme.
This is **not** meant to be interpreted as an available web service - see
below for more details.
Rooms, users, aliases, and groups may be represented as a "matrix.to" URI.
This URI can be used to reference particular objects in a given context, such
as mentioning a user in a message or linking someone to a particular point
in the room's history (a permalink).
A matrix.to URI has the following format, based upon the specification defined
in RFC 3986:
https://matrix.to/#/<identifier>/<extra parameter>
The identifier may be a room ID, room alias, user ID, or group ID. The extra
parameter is only used in the case of permalinks where an event ID is referenced.
The matrix.to URI, when referenced, must always start with ``https://matrix.to/#/``
followed by the identifier.
Clients should not rely on matrix.to URIs falling back to a web server if accessed
and instead should perform some sort of action within the client. For example, if
the user were to click on a matrix.to URI for a room alias, the client may open
a view for the user to participate in the room.
Examples of matrix.to URIs are:
* Room alias: ``https://matrix.to/#/#somewhere:domain.com``
* Room: ``https://matrix.to/#/!somewhere:domain.com``
* Permalink by room: ``https://matrix.to/#/!somewhere:domain.com/$event:example.org``
* Permalink by room alias: ``https://matrix.to/#/#somewhere:domain.com/$event:example.org``
* User: ``https://matrix.to/#/@alice:example.org``
* Group: ``https://matrix.to/#/+example:domain.com``
.. Note::
Room ID permalinks are unroutable as there is no reliable domain to send requests
to upon receipt of the permalink. Clients should do their best route Room IDs to
where they need to go, however they should also be aware of `issue #1579 <https://github.com/matrix-org/matrix-doc/issues/1579>`_.

@ -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
~~~~~~~~~~~~ ~~~~~~~~~~~~
@ -75,8 +90,7 @@ said to be interested in a given event if one of the application service's names
users is the target of the event, or is a joined member of the room where the event users is the target of the event, or is a joined member of the room where the event
occurred. occurred.
An application An application service can also state whether they should be the only ones who
service can also state whether they should be the only ones who
can manage a specified namespace. This is referred to as an "exclusive" can manage a specified namespace. This is referred to as an "exclusive"
namespace. An exclusive namespace prevents humans and other application namespace. An exclusive namespace prevents humans and other application
services from creating/deleting entities in that namespace. Typically, services from creating/deleting entities in that namespace. Typically,
@ -90,33 +104,77 @@ regular expressions and look like:
users: users:
- exclusive: true - exclusive: true
regex: @_irc.freenode.net_.* regex: "@_irc.freenode.net_.*"
Application services may define the following namespaces (with none being explicitly required):
+------------------+-----------------------------------------------------------+
| Name | Description |
+==================+===========================================================+
| users | Events which are sent from certain users. |
+------------------+-----------------------------------------------------------+
| aliases | Events which are sent in rooms with certain room aliases. |
+------------------+-----------------------------------------------------------+
| rooms | Events which are sent in rooms with certain room IDs. |
+------------------+-----------------------------------------------------------+
Each individual namespace MUST declare the following fields:
+------------------+-----------------------------------------------------------------------------------------------------------------------------------+
| Name | Description |
+==================+===================================================================================================================================+
| exclusive | **Required** A true or false value stating whether this application service has exclusive access to events within this namespace. |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------+
| regex | **Required** A regular expression defining which values this namespace includes. |
+------------------+-----------------------------------------------------------------------------------------------------------------------------------+
Exclusive user and alias namespaces should begin with an underscore after the
sigil to avoid collisions with other users on the homeserver. Application
services should additionally attempt to identify the service they represent
in the reserved namespace. For example, ``@_irc_.*`` would be a good namespace
to register for an application service which deals with IRC.
The registration is represented by a series of key-value pairs, which this The registration is represented by a series of key-value pairs, which this
specification will present as YAML. An example HS configuration required to pass specification will present as YAML. See below for the possible options along
traffic to the AS is: with their explanation:
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| Name | Description |
+==================+====================================================================================================================================================+
| id | **Required.** A unique, user-defined ID of the application service which will never change. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| url | **Required.** The URL for the application service. May include a path after the domain name. Optionally set to ``null`` if no traffic is required. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| as_token | **Required.** A unique token for application services to use to authenticate requests to Homeservers. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| hs_token | **Required.** A unique token for Homeservers to use to authenticate requests to application services. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| sender_localpart | **Required.** The localpart of the user associated with the application service. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| namespaces | **Required.** A list of ``users``, ``aliases`` and ``rooms`` namespaces that the application service controls. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| rate_limited | Whether requests from masqueraded users are rate-limited. The sender is excluded. |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
| protocols | The external protocols which the application service provides (e.g. IRC). |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
An example registration file for an IRC-bridging application service is below:
.. code-block:: yaml .. code-block:: yaml
id: <user-defined unique ID of AS which will never change> id: "IRC Bridge"
url: <base url of AS> url: "http://127.0.0.1:1234"
as_token: <token AS will add to requests to HS> as_token: "30c05ae90a248a4188e620216fa72e349803310ec83e2a77b34fe90be6081f46"
hs_token: <token HS will add to requests to AS> hs_token: "312df522183efd404ec1cd22d2ffa4bbc76a8c1ccf541dd692eef281356bb74e"
sender_localpart: <localpart of AS user> sender_localpart: "_irc_bot" # Will result in @_irc_bot:domain.com
namespaces: namespaces:
users: # Namespaces of users which should be delegated to the AS users:
- exclusive: <bool> - exclusive: true
regex: <regex> regex: "@_irc_bridge_.*"
- ... aliases:
aliases: [] # Namespaces of room aliases which should be delegated to the AS - exclusive: false
rooms: [] # Namespaces of room ids which should be delegated to the AS regex: "#_irc_bridge_.*"
rooms: []
Exclusive user and alias namespaces should begin with an underscore after the
sigil to avoid collisions with other users on the homeserver. Application
services should additionally attempt to identify the service they represent
in the reserved namespace. For example, ``@_irc_.*`` would be a good namespace
to register for an application service which deals with IRC.
.. WARNING:: .. WARNING::
If the homeserver in question has multiple application services, each If the homeserver in question has multiple application services, each
@ -126,6 +184,34 @@ to register for an application service which deals with IRC.
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
++++++++++++++ ++++++++++++++
@ -136,24 +222,26 @@ 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}}
Querying Querying
++++++++ ++++++++
@ -180,13 +268,25 @@ this request (e.g. to join a room alias).
{{query_room_as_http_api}} {{query_room_as_http_api}}
HTTP APIs Third party networks
+++++++++ ++++++++++++++++++++
Application services may declare which protocols they support via their registration
configuration for the homeserver. These networks are generally for third party services
such as IRC that the application service is managing. Application services may populate
a Matrix room directory for their registered protocols, as defined in the Client-Server
API Extensions.
Each protocol may have several "locations" (also known as "third party locations" or "3PLs").
A location within a protocol is a place in the third party network, such as an IRC channel.
Users of the third party network may also be represented by the application service.
This contains application service APIs which are used by the homeserver. All Locations and users can be searched by fields defined by the application service, such
application services MUST implement these APIs. These APIs are defined below. as by display name or other attribute. When clients request the homeserver to search
in a particular "network" (protocol), the search fields will be passed along to the
application service for filtering.
{{application_service_as_http_api}} {{protocols_as_http_api}}
.. _create the user: `sect:asapi-permissions`_ .. _create the user: `sect:asapi-permissions`_
@ -198,6 +298,9 @@ Application services can use a more powerful version of the
client-server API by identifying itself as an application service to the client-server API by identifying itself as an application service to the
homeserver. homeserver.
Endpoints defined in this section MUST be supported by homeservers in the
client-server API as accessible only by application services.
Identity assertion Identity assertion
++++++++++++++++++ ++++++++++++++++++
The client-server API infers the user ID from the ``access_token`` provided in The client-server API infers the user ID from the ``access_token`` provided in
@ -229,8 +332,9 @@ An example request would be::
GET /_matrix/client/%CLIENT_MAJOR_VERSION%/account/whoami?user_id=@_irc_user:example.org GET /_matrix/client/%CLIENT_MAJOR_VERSION%/account/whoami?user_id=@_irc_user:example.org
Authorization: Bearer YourApplicationServiceTokenHere Authorization: Bearer YourApplicationServiceTokenHere
.. TODO-TravisR: Temporarily take out timestamp massaging while we're releasing r0.
Timestamp massaging See https://github.com/matrix-org/matrix-doc/issues/1585
.. Timestamp massaging
+++++++++++++++++++ +++++++++++++++++++
The application service may want to inject events at a certain time (reflecting The application service may want to inject events at a certain time (reflecting
the time on the network they are tracking e.g. irc, xmpp). Application services the time on the network they are tracking e.g. irc, xmpp). Application services
@ -250,6 +354,16 @@ Notes:
Content: The event to send, as per the Client-Server API. Content: The event to send, as per the Client-Server API.
Timestamp massaging
+++++++++++++++++++
Previous drafts of the Application Service API permitted application services
to alter the timestamp of their sent events by providing a ``ts`` query parameter
when sending an event. This API has been excluded from the first release due to
design concerns, however some servers may still support the feature. Please visit
`issue #1585 <https://github.com/matrix-org/matrix-doc/issues/1585>`_ for more
information.
Server admin style permissions Server admin style permissions
++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
@ -266,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.
:: ::
@ -294,13 +408,27 @@ API MUST do so with a virtual user (provide a ``user_id`` via the query string).
is expected that the application service use the transactions pushed to it to is expected that the application service use the transactions pushed to it to
handle events rather than syncing with the user implied by ``sender_localpart``. handle events rather than syncing with the user implied by ``sender_localpart``.
Event fields Application service room directories
~~~~~~~~~~~~ ++++++++++++++++++++++++++++++++++++
Application services can maintain their own room directories for their defined
third party protocols. These room directories may be accessed by clients through
additional parameters on the ``/publicRooms`` client-server endpoint.
{{appservice_room_directory_cs_http_api}}
Referencing messages from a third party network
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
.. TODO-TravisR: Fix this section to be a general "3rd party networks" section Clients should provide users with a way to access the ``external_url`` if it
is present. Clients should additionally ensure the URL has a scheme of ``https``
or ``http`` before making use of it.
We recommend that any events that originated from a remote network should The presence of an ``external_url`` on an event does not necessarily mean the
include an ``external_url`` field in their content to provide a way for Matrix event was sent from an application service. Clients should be wary of the URL
clients to link into the 'native' client from which the event originated. contained within, as it may not be a legitimate reference to the event's source.
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.

@ -189,6 +189,82 @@ headers to be returned by servers on all requests are:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
Server Discovery
----------------
In order to allow users to connect to a Matrix server without needing to
explicitly specify the homeserver's URL or other parameters, clients SHOULD use
an auto-discovery mechanism to determine the server's URL based on a user's
Matrix ID. Auto-discovery should only be done at login time.
In this section, the following terms are used with specific meanings:
``PROMPT``
Retrieve the specific piece of information from the user in a way which
fits within the existing client user experience, if the client is inclined to
do so. Failure can take place instead if no good user experience for this is
possible at this point.
``IGNORE``
Stop the current auto-discovery mechanism. If no more auto-discovery
mechanisms are available, then the client may use other methods of
determining the required parameters, such as prompting the user, or using
default values.
``FAIL_PROMPT``
Inform the user that auto-discovery failed due to invalid/empty data and
``PROMPT`` for the parameter.
``FAIL_ERROR``
Inform the user that auto-discovery did not return any usable URLs. Do not
continue further with the current login process. At this point, valid data
was obtained, but no homeserver is available to serve the client. No further
guess should be attempted and the user should make a conscientious decision
what to do next.
Well-known URI
~~~~~~~~~~~~~~
The ``.well-known`` method uses a JSON file at a predetermined location to
specify parameter values. The flow for this method is as follows:
1. Extract the server name from the user's Matrix ID by splitting the Matrix ID
at the first colon.
2. Extract the hostname from the server name.
3. Make a GET request to ``https://hostname/.well-known/matrix/client``.
a. If the returned status code is 404, then ``IGNORE``.
b. If the returned status code is not 200, or the response body is empty,
then ``FAIL_PROMPT``.
c. Parse the response body as a JSON object
i. If the content cannot be parsed, then ``FAIL_PROMPT``.
d. Extract the ``base_url`` value from the ``m.homeserver`` property. This
value is to be used as the base URL of the homeserver.
i. If this value is not provided, then ``FAIL_PROMPT``.
e. Validate the homeserver base URL:
i. Parse it as a URL. If it is not a URL, then ``FAIL_ERROR``.
ii. Clients SHOULD validate that the URL points to a valid homeserver
before accepting it by connecting to the |/_matrix/client/versions|_
endpoint, ensuring that it does not return an error, and parsing and
validating that the data conforms with the expected response
format. If any step in the validation fails, then
``FAIL_ERROR``. Validation is done as a simple check against
configuration errors, in order to ensure that the discovered address
points to a valid homeserver.
f. If the ``m.identity_server`` property is present, extract the
``base_url`` value for use as the base URL of the identity server.
Validation for this URL is done as in the step above, but using
``/_matrix/identity/api/v1`` as the endpoint to connect to. If the
``m.identity_server`` property is present, but does not have a
``base_url`` value, then ``FAIL_ERROR``.
{{wellknown_cs_http_api}}
Client Authentication Client Authentication
--------------------- ---------------------
@ -1596,5 +1672,8 @@ have to wait in milliseconds before they can try again.
.. |/user/<user_id>/account_data/<type>| replace:: ``/user/<user_id>/account_data/<type>`` .. |/user/<user_id>/account_data/<type>| replace:: ``/user/<user_id>/account_data/<type>``
.. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type .. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type
.. |/_matrix/client/versions| replace:: ``/_matrix/client/versions``
.. _/_matrix/client/versions: #get-matrix-client-versions
.. _`Unpadded Base64`: ../appendices.html#unpadded-base64 .. _`Unpadded Base64`: ../appendices.html#unpadded-base64
.. _`3PID Types`: ../appendices.html#pid-types .. _`3PID Types`: ../appendices.html#pid-types

@ -23,7 +23,7 @@ user identifiers. From time to time, it is useful to refer to users by other
number. This identity service specification describes how mappings between number. This identity service specification describes how mappings between
third-party identifiers and Matrix user identifiers can be established, third-party identifiers and Matrix user identifiers can be established,
validated, and used. This description technically may apply to any 3pid, but in validated, and used. This description technically may apply to any 3pid, but in
practice has only been applied specifically to email addresses. practice has only been applied specifically to email addresses and phone numbers.
.. contents:: Table of Contents .. contents:: Table of Contents
.. sectnum:: .. sectnum::
@ -56,6 +56,75 @@ is left as an exercise for the client.
3PID types are described in `3PID Types`_ Appendix. 3PID types are described in `3PID Types`_ Appendix.
API Standards
-------------
The mandatory baseline for identity service communication in Matrix is exchanging
JSON objects over HTTP APIs. HTTPS is required for communication, and all API calls
use a Content-Type of ``application/json``. In addition, strings MUST be encoded as
UTF-8.
Any errors which occur at the Matrix API level MUST return a "standard error response".
This is a JSON object which looks like:
.. code:: json
{
"errcode": "<error code>",
"error": "<error message>"
}
The ``error`` string will be a human-readable error message, usually a sentence
explaining what went wrong. The ``errcode`` string will be a unique string
which can be used to handle an error message e.g. ``M_FORBIDDEN``. There may be
additional keys depending on the error, but the keys ``error`` and ``errcode``
MUST always be present.
Some standard error codes are below:
:``M_NOT_FOUND``:
The resource requested could not be located.
:``M_MISSING_PARAMS``:
The request was missing one or more parameters.
:``M_INVALID_PARAM``:
The request contained one or more invalid parameters.
:``M_SESSION_NOT_VALIDATED``:
The session has not been validated.
:``M_NO_VALID_SESSION``:
A session could not be located for the given parameters.
:``M_SESSION_EXPIRED``:
The session has expired and must be renewed.
:``M_INVALID_EMAIL``:
The email address provided was not valid.
:``M_EMAIL_SEND_ERROR``:
There was an error sending an email. Typically seen when attempting to verify
ownership of a given email address.
:``M_INVALID_ADDRESS``:
The provided third party address was not valid.
:``M_SEND_ERROR``:
There was an error sending a notification. Typically seen when attempting to
verify ownership of a given third party address.
:``M_UNRECOGNIZED``:
The request contained an unrecognised value, such as an unknown token or medium.
:``M_THREEPID_IN_USE``:
The third party identifier is already in use by another user. Typically this
error will have an additional ``mxid`` property to indicate who owns the
third party identifier.
:``M_UNKNOWN``:
An unknown error has occurred.
Privacy Privacy
------- -------

@ -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
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~

@ -56,6 +56,60 @@ of message being sent. Each type has their own required and optional keys, as
outlined below. If a client cannot display the given ``msgtype`` then it SHOULD outlined below. If a client cannot display the given ``msgtype`` then it SHOULD
display the fallback plain text ``body`` key instead. display the fallback plain text ``body`` key instead.
Some message types support HTML in the event content that clients should prefer
to display if available. Currently ``m.text``, ``m.emote``, and ``m.notice``
support an additional ``format`` parameter of ``org.matrix.custom.html``. When
this field is present, a ``formatted_body`` with the HTML must be provided. The
plain text version of the HTML should be provided in the ``body``.
Clients should limit the HTML they render to avoid Cross-Site Scripting, HTML
injection, and similar attacks. The strongly suggested set of HTML tags to permit,
denying the use and rendering of anything else, is: ``font``, ``del``, ``h1``,
``h2``, ``h3``, ``h4``, ``h5``, ``h6``, ``blockquote``, ``p``, ``a``, ``ul``,
``ol``, ``sup``, ``sub``, ``li``, ``b``, ``i``, ``u``, ``strong``, ``em``,
``strike``, ``code``, ``hr``, ``br``, ``div``, ``table``, ``thead``, ``tbody``,
``tr``, ``th``, ``td``, ``caption``, ``pre``, ``span``, ``img``.
Not all attributes on those tags should be permitted as they may be avenues for
other disruption attempts, such as adding ``onclick`` handlers or excessively
large text. Clients should only permit the attributes listed for the tags below.
Where ``data-mx-bg-color`` and ``data-mx-color`` are listed, clients should
translate the value (a 6-character hex color code) to the appropriate CSS/attributes
for the tag.
:``font``:
``data-mx-bg-color``, ``data-mx-color``
:``span``:
``data-mx-bg-color``, ``data-mx-color``
:``a``:
``name``, ``target``, ``href`` (provided the value is not relative and has a scheme
matching one of: ``https``, ``http``, ``ftp``, ``mailto``, ``magnet``)
:``img``:
``width``, ``height``, ``alt``, ``title``, ``src`` (provided it is a `Matrix Content (MXC) URI`_)
:``ol``:
``start``
:``code``:
``class`` (only classes which start with ``language-`` for syntax highlighting)
Additionally, web clients should ensure that *all* ``a`` tags get a ``rel="noopener"``
to prevent the target page from referencing the client's tab/window.
Tags must not be nested more than 100 levels deep. Clients should only support the subset
of tags they can render, falling back to other representations of the tags where possible.
For example, a client may not be able to render tables correctly and instead could fall
back to rendering tab-delimited text.
.. Note::
A future iteration of the specification will support more powerful and extensible
message formatting options, such as the proposal `MSC1225 <https://github.com/matrix-org/matrix-doc/issues/1225>`_.
{{msgtype_events}} {{msgtype_events}}
@ -297,3 +351,4 @@ Clients should sanitise **all displayed keys** for unsafe HTML to prevent Cross-
Scripting (XSS) attacks. This includes room names and topics. Scripting (XSS) attacks. This includes room names and topics.
.. _`E2E module`: `module:e2e`_ .. _`E2E module`: `module:e2e`_
.. _`Matrix Content (MXC) URI`: `module:content`_

@ -0,0 +1,74 @@
.. 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.
User, room, and group mentions
==============================
.. _module:mentions:
This module allows users to mention other users, rooms, and groups within
a room message. This is achieved by including a `matrix.to URI`_ in the HTML
body of an `m.room.message`_ event. This module does not have any server-specific
behaviour to it.
Mentions apply only to `m.room.message`_ events where the ``msgtype`` is ``m.text``,
``m.emote``, or ``m.notice``. The ``format`` for the event must be ``org.matrix.custom.html``
and therefore requires a ``formatted_body``.
To make a mention, reference the entity being mentioned in the ``formatted_body``
using an anchor, like so::
{
"body": "Hello Alice!",
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"formatted_body": "Hello <a href='https://matrix.to/#/@alice:example.org'>Alice</a>!"
}
Client behaviour
----------------
In addition to using the appropriate ``matrix.to URI`` for the mention,
clients should use the following guidelines when making mentions in events
to be sent:
* When mentioning users, use the user's potentially ambigious display name for
the anchor's text. If the user does not have a display name, use the user's
ID.
* When mentioning rooms, use the canonical alias for the room. If the room
does not have a canonical alias, prefer one of the aliases listed on the
room. If no alias can be found, fall back to the room ID. In all cases,
use the alias/room ID being linked to as the anchor's text.
* When referencing groups, use the group ID as the anchor's text.
The text component of the anchor should be used in the event's ``body`` where
the mention would normally be represented, as shown in the example above.
Clients should display mentions differently from other elements. For example,
this may be done by changing the background color of the mention to indicate
that it is different from a normal link.
If the current user is mentioned in a message (either by a mention as defined
in this module or by a push rule), the client should show that mention differently
from other mentions, such as by using a red background color to signify to the
user that they were mentioned.
When clicked, the mention should navigate the user to the appropriate room, group,
or user information.
.. _`matrix.to URI`: ../appendices.html#matrix-to-navigation

@ -369,6 +369,41 @@ Definition:
} }
``.m.rule.roomnotif``
`````````````````````
Matches any message whose content is unencrypted and contains the
text ``@room``, signifying the whole room should be notified of
the event.
Definition:
.. code:: json
{
"rule_id": ".m.rule.roomnotif",
"default": true,
"enabled": true,
"conditions": [
{
"kind": "event_match",
"key": "content.body",
"pattern": "@room"
},
{
"kind": "sender_notification_permission",
"key": "room"
}
],
"actions": [
"notify",
{
"set_tweak": "highlight",
"value": true
}
]
}
Default Content Rules Default Content Rules
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
@ -428,7 +463,47 @@ Definition:
"value": false "value": false
} }
] ]
}
``.m.rule.encrypted_room_one_to_one``
`````````````````````````````````````
Matches any encrypted event sent in a room with exactly two members.
Unlike other push rules, this rule cannot be matched against the content
of the event by nature of it being encrypted. This causes the rule to
be an "all or nothing" match where it either matches *all* events that
are encrypted (in 1:1 rooms) or none.
Definition:
.. code:: json
{
"rule_id": ".m.rule.encrypted_room_one_to_one",
"default": true,
"enabled": true,
"conditions": [
{
"kind": "room_member_count",
"is": "2"
}
],
"actions": [
"notify",
{
"set_tweak": "sound",
"value": "default"
}, },
{
"set_tweak": "highlight",
"value": false
},
{
"kind": "event_match",
"key": "type",
"pattern": "m.room.encrypted"
}
]
}
``.m.rule.room_one_to_one`` ``.m.rule.room_one_to_one``
``````````````````````````` ```````````````````````````
@ -489,6 +564,37 @@ Definition:
] ]
} }
``.m.rule.encrypted``
`````````````````````
Matches all encrypted events. Unlike other push rules, this rule cannot
be matched against the content of the event by nature of it being encrypted.
This causes the rule to be an "all or nothing" match where it either
matches *all* events that are encrypted (in 1:1 rooms) or none.
Definition:
.. code:: json
{
"rule_id": ".m.rule.encrypted",
"default": true,
"enabled": true,
"conditions": [
{
"kind": "event_match",
"key": "type",
"pattern": "m.room.encrypted"
}
],
"actions": [
"notify",
{
"set_tweak": "highlight",
"value": false
}
]
}
Conditions Conditions
++++++++++ ++++++++++
@ -523,6 +629,21 @@ rule determines its behaviour. The following conditions are defined:
count is strictly less than the given number and so forth. If no prefix is count is strictly less than the given number and so forth. If no prefix is
present, this parameter defaults to ``==``. present, this parameter defaults to ``==``.
``sender_notification_permission``
This takes into account the current power levels in the room, ensuring the
sender of the event has high enough power to trigger the notification.
Parameters:
* ``key``: A string that determines the power level the sender must have to trigger
notifications of a given type, such as ``room``. Refer to the `m.room.power_levels`_
event schema for information about what the defaults are and how to interpret the event.
The ``key`` is used to look up the power level required to send a notification type
from the ``notifications`` object in the power level event content.
Unrecognised conditions MUST NOT match any events, effectively making the push
rule disabled.
Push Rules: API Push Rules: API
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@ -623,4 +744,4 @@ should send a "sync" command to instruct the client to get new events from the
homeserver directly. homeserver directly.
.. _`Push Gateway Specification`: ../push_gateway/unstable.html .. _`Push Gateway Specification`: ../push_gateway/%PUSH_GATEWAY_RELEASE_LABEL%.html

@ -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

@ -63,7 +63,7 @@ If the client sends messages to users on remote domains, those messages should
be sent on to the remote servers via be sent on to the remote servers via
`federation`_. `federation`_.
.. _`federation`: ../server_server/latest.html#send-to-device-messages .. _`federation`: ../server_server/latest.html#send-to-device-messaging
.. TODO-spec: .. TODO-spec:

@ -0,0 +1,70 @@
.. 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.
Server Access Control Lists (ACLs) for rooms
============================================
.. _module:server-acls:
In some scenarios room operators may wish to prevent a malicious or untrusted
server from participating in their room. Sending an `m.room.server_acl`_ state
event into a room is an effective way to prevent the server from participating
in the room at the federation level.
Server ACLs can also be used to make rooms only federate with a limited set of
servers, or retroactively make the room no longer federate with any other server,
similar to setting the ``m.federate`` value on the `m.room.create`_ event.
{{m_room_server_acl_event}}
.. Note::
Port numbers are not supported because it is unclear to parsers whether a
port number should be matched or an IP address literal. Additionally, it
is unlikely that one would trust a server running on a particular domain's
port but not a different port, especially considering the server host can
easily change ports.
.. Note::
CIDR notation is not supported for IP addresses because Matrix does not
encourage the use of IPs for identifying servers. Instead, a blanket
``allow_ip_literals`` is provided to cover banning them.
Client behaviour
----------------
Clients are not expected to perform any additional duties beyond sending the
event. Clients should describe changes to the server ACLs to the user in the
user interface, such as in the timeline.
Clients may wish to kick affected users from the room prior to denying a server
access to the room to help prevent those servers from participating and to
provide feedback to the users that they have been excluded from the room.
Server behaviour
----------------
Servers MUST prevent blacklisted servers from sending events or participating
in the room when an `m.room.server_acl`_ event is present in the room state.
Which APIs are specifically affected are described in the Server-Server API
specification.
Servers should still send events to denied servers if they are still residents
of the room.
Security considerations
-----------------------
Server ACLs are only effective if every server in the room honours them. Servers
that do not honour the ACLs may still permit events sent by denied servers into
the room, leaking them to other servers in the room. To effectively enforce an
ACL in a room, the servers that do not honour the ACLs should be denied in the
room as well.

@ -1,4 +1,5 @@
.. Copyright 2016 OpenMarket Ltd .. Copyright 2016 OpenMarket Ltd
.. Copyright 2018 New Vector Ltd
.. ..
.. Licensed under the Apache License, Version 2.0 (the "License"); .. Licensed under the Apache License, Version 2.0 (the "License");
.. you may not use this file except in compliance with the License. .. you may not use this file except in compliance with the License.
@ -21,13 +22,27 @@ the homeserver. This is managed by a distinct entity called the Push Gateway.
.. contents:: Table of Contents .. contents:: Table of Contents
.. sectnum:: .. sectnum::
Specification version Changelog
--------------------- ---------
.. topic:: Version: %PUSH_GATEWAY_RELEASE_LABEL%
{{push_gateway_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/push_gateway.rst
Other versions of this specification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following other versions are also available, in reverse chronological order:
- `HEAD <https://matrix.org/docs/spec/push_gateway/unstable.html>`_: Includes all changes since the latest versioned release.
- `r0.1.0 <https://matrix.org/docs/spec/push_gateway/r0.1.0.html>`_
Overview Overview
-------- --------

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save