From e561a663d30810c0e58ca30b89bc3bc759e92aec Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Tue, 13 Oct 2015 16:53:27 +0100 Subject: [PATCH 01/14] Tweaks to intro, start using swagger APIs in the CS API section. --- specification/0-intro.rst | 46 ++++++++++++--------------- specification/1-client_server_api.rst | 44 ++----------------------- 2 files changed, 22 insertions(+), 68 deletions(-) diff --git a/specification/0-intro.rst b/specification/0-intro.rst index 445b32ef..1c18a4f0 100644 --- a/specification/0-intro.rst +++ b/specification/0-intro.rst @@ -99,23 +99,23 @@ Architecture ------------ Matrix defines APIs for synchronising extensible JSON objects known as -``events`` between compatible clients, servers and services. Clients are +"events" between compatible clients, servers and services. Clients are typically messaging/VoIP applications or IoT devices/hubs and communicate by -synchronising communication history with their ``homeserver`` using the -``Client-Server API``. Each homeserver stores the communication history and +synchronising communication history with their "homeserver" using the +"Client-Server API". Each homeserver stores the communication history and account information for all of its clients, and shares data with the wider Matrix ecosystem by synchronising communication history with other homeservers and their clients. Clients typically communicate with each other by emitting events in the -context of a virtual ``room``. Room data is replicated across *all of the +context of a virtual "room". Room data is replicated across *all of the homeservers* whose users are participating in a given room. As such, *no single homeserver has control or ownership over a given room*. Homeservers model communication history as a partially ordered graph of events known as -the room's ``event graph``, which is synchronised with eventual consistency -between the participating servers using the ``Server-Server API``. This process +the room's "event graph", which is synchronised with eventual consistency +between the participating servers using the "Server-Server API". This process of synchronising shared conversation history between homeservers run by -different parties is called ``Federation``. Matrix optimises for the the +different parties is called "Federation". Matrix optimises for the the Availability and Partitioned properties of CAP theorem at the expense of Consistency. @@ -151,13 +151,13 @@ Users ~~~~~ Each client is associated with a user account, which is identified in Matrix -using a unique "User ID". This ID is namespaced to the home server which +using a unique "User ID". This ID is namespaced to the homeserver which allocated the account and has the form:: @localpart:domain The ``localpart`` of a user ID may be a user name, or an opaque ID identifying -this user. They are case-insensitive. +this user. The ``domain`` of a user ID is the domain of the homeserver. .. TODO-spec - Need to specify precise grammar for Matrix IDs @@ -183,9 +183,9 @@ Event Graphs .. _sect:event-graph: Events exchanged in the context of a room are stored in a directed acyclic graph -(DAG) called an ``event graph``. The partial ordering of this graph gives the +(DAG) called an "event graph". The partial ordering of this graph gives the chronological ordering of events within the room. Each event in the graph has a -list of zero or more ``parent`` events, which refer to any preceding events +list of zero or more "parent" events, which refer to any preceding events which have no chronological successor from the perspective of the homeserver which created the event. @@ -292,11 +292,10 @@ Each room can also have multiple "Room Aliases", which look like:: A room alias "points" to a room ID and is the human-readable label by which rooms are publicised and discovered. The room ID the alias is pointing to can -be obtained by visiting the domain specified. They are case-insensitive. Note -that the mapping from a room alias to a room ID is not fixed, and may change -over time to point to a different room ID. For this reason, Clients SHOULD -resolve the room alias to a room ID once and then use that ID on subsequent -requests. +be obtained by visiting the domain specified. Note that the mapping from a room +alias to a room ID is not fixed, and may change over time to point to a +different room ID. For this reason, Clients SHOULD resolve the room alias to a +room ID once and then use that ID on subsequent requests. When resolving a room alias the server will also respond with a list of servers that are in the room that can be used to join via. @@ -339,12 +338,9 @@ Profiles ~~~~~~~~ Users may publish arbitrary key/value data associated with their account - such -as a human readable ``display name``, a profile photo URL, contact information +as a human readable display name, a profile photo URL, contact information (email address, phone numbers, website URLs etc). -In Client-Server API v2, profile data is typed using namespaced keys for -interoperability, much like events - e.g. ``m.profile.display_name``. - .. TODO Actually specify the different types of data - e.g. what format are display names allowed to be? @@ -431,13 +427,11 @@ Some requests have unique error codes: :``M_BAD_PAGINATION``: Encountered when specifying bad pagination query parameters. -:``M_LOGIN_EMAIL_URL_NOT_YET``: - Encountered when polling for an email link which has not been clicked yet. -The C-S API typically uses ``HTTP POST`` to submit requests. This means these -requests are not idempotent. The C-S API also allows ``HTTP PUT`` to make -requests idempotent. In order to use a ``PUT``, paths should be suffixed with -``/{txnId}``. ``{txnId}`` is a unique client-generated transaction ID which +The Client-Server API typically uses ``HTTP POST`` to submit requests. This +means these requests are not idempotent. The C-S API also allows ``HTTP PUT`` to +make requests idempotent. In order to use a ``PUT``, paths should be suffixed +with ``/{txnId}``. ``{txnId}`` is a unique client-generated transaction ID which identifies the request, and is scoped to a given Client (identified by that client's ``access_token``). Crucially, it **only** serves to identify new requests from retransmits. After the request has finished, the ``{txnId}`` diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index 59e6b68e..94d1a184 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -528,7 +528,7 @@ Room events are split into two categories: :Message events: These are events which describe transient "once-off" activity in a room: typically communication such as sending an instant message or setting up a - VoIP call. These used to be called 'non-state' events. + VoIP call. This specification outlines several events, all with the event type prefix ``m.``. However, applications may wish to add their own type of event, and this @@ -600,9 +600,6 @@ See `Room Events`_ for the ``m.`` event specification. Syncing rooms ~~~~~~~~~~~~~ -.. NOTE:: - This section is a work in progress. - When a client logs in, they may have a list of rooms which they have already joined. These rooms may also have a list of events associated with them. The purpose of 'syncing' is to present the current room and event information in a @@ -620,45 +617,8 @@ presence events will also be returned. A single syncing API is provided: onwards. The event stream cannot do this for a single room currently. As a result, commenting room-scoped initial sync at this time. -The |initialSync|_ API contains the following keys: - -``presence`` - Description: - Contains a list of presence information for users the client is interested - in. - Format: - A JSON array of ``m.presence`` events. - -``end`` - Description: - Contains an event stream token which can be used with the `Event Stream`_. - Format: - A string containing the event stream token. -``rooms`` - Description: - Contains a list of room information for all rooms the client has joined, - and limited room information on rooms the client has been invited to. - Format: - A JSON array containing Room Information JSON objects. - -Room Information: - Description: - Contains all state events for the room, along with a limited amount of - the most recent events, configured via the ``limit`` query - parameter. Also contains additional keys with room metadata, such as the - ``room_id`` and the client's ``membership`` to the room. - Format: - A JSON object with the following keys: - ``room_id`` - A string containing the ID of the room being described. - ``membership`` - A string representing the client's membership status in this room. - ``messages`` - An event stream JSON object containing a ``chunk`` of recent - events (both state events and non-state events), along with an ``end`` token. - ``state`` - A JSON array containing all the current state events for this room. +{{sync_http_api}} Getting events for a room ~~~~~~~~~~~~~~~~~~~~~~~~~ From e716e819635babb0216c971940f9e7a8cdbeacc4 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 09:58:03 +0100 Subject: [PATCH 02/14] Add `dir` parameter to pagination. Remove path references This section needs a lot of work to not lie. --- specification/1-client_server_api.rst | 30 +++++++++++++++------------ 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index 94d1a184..a4f62b4f 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -348,11 +348,13 @@ Pagination Querying large datasets in Matrix always uses the same pagination API pattern to to give clients a consistent way of selecting subsets of a potentially changing -dataset. Requests pass in ``from``, ``to`` and ``limit`` parameters which describe -where to read from the stream. ``from`` and ``to`` are opaque textual 'stream -tokens' which describe positions in the dataset. The response returns new -``start`` and ``end`` stream token values which can then be passed to subsequent -requests to continue pagination. +dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters +which describe where to read from the stream. ``from`` and ``to`` are opaque +textual 'stream tokens' which describe the current position in the dataset. +The ``dir`` parameter is an enum representing the direction of events to return: +either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and +``end`` stream token values which can then be passed to subsequent requests to +continue pagination. Pagination Request Query Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -367,24 +369,26 @@ Query parameters: limit: integer - An integer representing the maximum number of items to return. + dir: + f|b - The direction to return events in. Typically this is ``b`` to paginate + backwards in time. 'START' and 'END' are placeholder values used in these examples to describe the start and end of the dataset respectively. -Unless specified, the default pagination parameters are from=START, to=END, -without a limit set. This allows you to hit an API like -/events without any query parameters to get everything. +Unless specified, the default pagination parameters are ``from=START``, +``to=END``, without a limit set. -For example, the event stream has events E1 -> E15. The client wants the last 5 +For example, if an endpoint had events E1 -> E15. The client wants the last 5 events and doesn't know any previous events:: S E |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-| | | | | _____| | - |__________________ | ___________________| - | | | - GET /events?to=START&limit=5&from=END + |__________________ | _______________| + | | | + GET /somepath?to=START&limit=5&from=END Returns: E15,E14,E13,E12,E11 @@ -401,7 +405,7 @@ now show page 3 (rooms R11 -> 15):: Currently | viewing | | - GET /rooms/list?from=9&to=END&limit=5 + GET /roomslist?from=9&to=END&limit=5 Returns: R11,R12,R13,R14,R15 Note that tokens are treated in an *exclusive*, not inclusive, manner. The end From 7bdb71b1c9697eb9ded20e028723a500b1d71a02 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 10:25:39 +0100 Subject: [PATCH 03/14] Tweak the syncing section Bring together disparate sections to make it more cohesive. --- api/client-server/v1/sync.yaml | 6 +- specification/1-client_server_api.rst | 99 +++++++++++---------------- 2 files changed, 43 insertions(+), 62 deletions(-) diff --git a/api/client-server/v1/sync.yaml b/api/client-server/v1/sync.yaml index 7c1d43f3..398b0773 100644 --- a/api/client-server/v1/sync.yaml +++ b/api/client-server/v1/sync.yaml @@ -30,7 +30,9 @@ paths: - in: query type: string name: from - description: The token to stream from. + description: |- + The token to stream from. This token is either from the a previous + request to this API or from the initial sync API. required: false x-example: "s3456_9_0" - in: query @@ -40,7 +42,7 @@ paths: required: false x-example: "35000" - in: query - type: string + type: boolean name: archived description: |- Whether to include rooms that the user has left. If absent then diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index a4f62b4f..fefdf511 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -1,9 +1,6 @@ Client-Server API ================= -Overview --------- - The client-server API provides a simple lightweight API to let clients send messages, control rooms and synchronise conversation history. It is designed to support both lightweight clients which store no state and lazy-load data from @@ -31,7 +28,7 @@ return with a status of 401 and the error code, ``M_MISSING_TOKEN`` or ``M_UNKNOWN_TOKEN`` respectively. User-Interactive Authentication API ------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This section refers to API Version 2. Some API endpoints such as ``login`` or ``register`` require authentication that @@ -159,7 +156,7 @@ absence of that login stage type in the 'completed' array indicating whether that stage is complete. Example -~~~~~~~ ++++++++ At a high level, the requests made for an API call completing an auth flow with three stages will resemble the following diagram:: @@ -201,7 +198,7 @@ This specification defines the following login types: - ``m.login.dummy`` Password-based -~~~~~~~~~~~~~~ +++++++++++++++ :Type: ``m.login.password`` :Description: @@ -216,7 +213,7 @@ To respond to this type, reply with an auth dict as follows:: } Google ReCaptcha -~~~~~~~~~~~~~~~~ +++++++++++++++++ :Type: ``m.login.recaptcha`` :Description: @@ -230,7 +227,7 @@ To respond to this type, reply with an auth dict as follows:: } Token-based -~~~~~~~~~~~ ++++++++++++ :Type: ``m.login.token`` :Description: @@ -261,7 +258,7 @@ newly provisioned access_token). The ``token`` must be a macaroon. OAuth2-based -~~~~~~~~~~~~ +++++++++++++ :Type: ``m.login.oauth2`` :Description: @@ -285,7 +282,7 @@ the OAuth flow has completed, the client retries the request with the session only, as above. Email-based (identity server) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++++++++++++++++++++++++++++++ :Type: ``m.login.email.identity`` :Description: @@ -310,7 +307,7 @@ To respond to this type, reply with an auth dict as follows:: } Dummy Auth -~~~~~~~~~~ +++++++++++ :Type: ``m.login.dummy`` :Description: @@ -327,7 +324,7 @@ if provided:: Fallback -~~~~~~~~ +++++++++ Clients cannot be expected to be able to know how to process every single login type. If a client does not know how to handle a given login type, it can direct the user to a web browser with the URL of a fallback page which will allow the @@ -346,7 +343,15 @@ the authentication has been completed. Pagination ---------- -Querying large datasets in Matrix always uses the same pagination API pattern to +.. NOTE:: + The paths referred to in this section are not actual endpoints. They only + serve as examples to explain how pagination functions. + +Pagination is the process of dividing a dataset into multiple discrete pages. +Matrix makes use of pagination to allow clients to view extremely large datasets. +These datasets are not limited to events in a room (for example clients may want +to paginate rooms in addition to events within those rooms). Regardless of *what* +is being paginated, there is a common underlying API which is used to to give clients a consistent way of selecting subsets of a potentially changing dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters which describe where to read from the stream. ``from`` and ``to`` are opaque @@ -354,7 +359,8 @@ textual 'stream tokens' which describe the current position in the dataset. The ``dir`` parameter is an enum representing the direction of events to return: either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and ``end`` stream token values which can then be passed to subsequent requests to -continue pagination. +continue pagination. Not all endpoints will make use of all the parameters +outlined here: see the specific endpoint in question for more information. Pagination Request Query Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -385,10 +391,10 @@ events and doesn't know any previous events:: S E |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-| | | | - | _____| | - |__________________ | _______________| - | | | - GET /somepath?to=START&limit=5&from=END + | _____| <--backwards-- | + |__________________ | | ________| + | | | | + GET /somepath?to=START&limit=5&dir=b&from=END Returns: E15,E14,E13,E12,E11 @@ -433,9 +439,6 @@ Events .. _sect:events: -Overview -~~~~~~~~ - The model of conversation history exposed by the client-server API can be considered as a list of events. The server 'linearises' the eventually-consistent event graph of events into an 'event stream' at any given @@ -463,7 +466,7 @@ You can visualise the range of events being returned as:: | | start: '1-2-3' end: 'a-b-c' -Now, to receive future events in real-time on the eventstream, you simply GET +Now, to receive future events in real-time on the event stream, you simply GET $PREFIX/events with a ``from`` parameter of 'a-b-c': in other words passing in the ``end`` token returned by initial sync. The request blocks until new events are available or until your specified timeout elapses, and then returns a @@ -493,31 +496,30 @@ To continue paginating backwards, one calls the /messages API again, supplying the new ``start`` value as the ``from`` parameter. -Receiving live updates on a client -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Syncing +~~~~~~~ -Clients receive new events by long-polling the home server via the -$PREFIX/events API, specifying a timeout in milliseconds in the timeout -parameter. This will hold open the HTTP connection for a short period of time -waiting for new events, returning early if an event occurs. This is called the -`Event Stream`_. All events which are visible to the client will appear in the -event stream. When the request returns, an ``end`` token is included in the +Clients receive new events by "long-polling" the home server via the events API. +This involves specifying a timeout in the request which will hold +open the HTTP connection for a short period of time waiting for new events, +returning early if an event occurs. Only the events API supports long-polling. +All events which are visible to the client will appear in the +events API. When the request returns, an ``end`` token is included in the response. This token can be used in the next request to continue where the -last request left off. - -All events must be de-duplicated based on their event ID. +last request left off. Multiple events can be returned per long-poll. All events +must be de-duplicated based on their event ID. .. TODO is deduplication actually a hard requirement in CS v2? .. TODO-spec - Do we ever return multiple events in a single request? - Don't we get lots of request setup RTT latency if we only do one event per request? Do we ever support streaming requests? Why not websockets? When the client first logs in, they will need to initially synchronise with -their home server. This is achieved via the |initialSync|_ API. This API also -returns an ``end`` token which can be used with the event stream. See the 'Room Sync' section below. +their home server. This is achieved via the initial sync API. This API also +returns an ``end`` token which can be used with the event stream. + +{{sync_http_api}} Events in a room ~~~~~~~~~~~~~~~~ @@ -601,29 +603,6 @@ example:: See `Room Events`_ for the ``m.`` event specification. -Syncing rooms -~~~~~~~~~~~~~ - -When a client logs in, they may have a list of rooms which they have already -joined. These rooms may also have a list of events associated with them. The -purpose of 'syncing' is to present the current room and event information in a -convenient, compact manner. The events returned are not limited to room events; -presence events will also be returned. A single syncing API is provided: - - - |initialSync|_ : A global sync which will present room and event information - for all rooms the user has joined. - -.. TODO-spec room-scoped initial sync - - |/rooms//initialSync|_ : A sync scoped to a single room. Presents - room and event information for this room only. - - Room-scoped initial sync is Very Tricky because typically people would - want to sync the room then listen for any new content from that point - onwards. The event stream cannot do this for a single room currently. - As a result, commenting room-scoped initial sync at this time. - - -{{sync_http_api}} - Getting events for a room ~~~~~~~~~~~~~~~~~~~~~~~~~ From 07d7a3fa3a4d0c9d7e4db70d62a24bc266824dbb Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 11:03:53 +0100 Subject: [PATCH 04/14] Shuffle pagination section around --- specification/1-client_server_api.rst | 201 +++++++++++++------------- 1 file changed, 103 insertions(+), 98 deletions(-) diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index fefdf511..d8b9299a 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -340,100 +340,6 @@ This MUST return an HTML page which can perform this authentication stage. This page must attempt to call the JavaScript function ``window.onAuthDone`` when the authentication has been completed. -Pagination ----------- - -.. NOTE:: - The paths referred to in this section are not actual endpoints. They only - serve as examples to explain how pagination functions. - -Pagination is the process of dividing a dataset into multiple discrete pages. -Matrix makes use of pagination to allow clients to view extremely large datasets. -These datasets are not limited to events in a room (for example clients may want -to paginate rooms in addition to events within those rooms). Regardless of *what* -is being paginated, there is a common underlying API which is used to -to give clients a consistent way of selecting subsets of a potentially changing -dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters -which describe where to read from the stream. ``from`` and ``to`` are opaque -textual 'stream tokens' which describe the current position in the dataset. -The ``dir`` parameter is an enum representing the direction of events to return: -either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and -``end`` stream token values which can then be passed to subsequent requests to -continue pagination. Not all endpoints will make use of all the parameters -outlined here: see the specific endpoint in question for more information. - -Pagination Request Query Parameters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Query parameters: - from: - $streamtoken - The opaque token to start streaming from. - to: - $streamtoken - The opaque token to end streaming at. Typically, - clients will not know the item of data to end at, so this will usually be - omitted. - limit: - integer - An integer representing the maximum number of items to - return. - dir: - f|b - The direction to return events in. Typically this is ``b`` to paginate - backwards in time. - -'START' and 'END' are placeholder values used in these examples to describe the -start and end of the dataset respectively. - -Unless specified, the default pagination parameters are ``from=START``, -``to=END``, without a limit set. - -For example, if an endpoint had events E1 -> E15. The client wants the last 5 -events and doesn't know any previous events:: - - S E - |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-| - | | | - | _____| <--backwards-- | - |__________________ | | ________| - | | | | - GET /somepath?to=START&limit=5&dir=b&from=END - Returns: - E15,E14,E13,E12,E11 - - -Another example: a public room list has rooms R1 -> R17. The client is showing 5 -rooms at a time on screen, and is on page 2. They want to -now show page 3 (rooms R11 -> 15):: - - S E - | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | stream token - |-R1-R2-R3-R4-R5-R6-R7-R8-R9-R10-R11-R12-R13-R14-R15-R16-R17| room - |____________| |________________| - | | - Currently | - viewing | - | - GET /roomslist?from=9&to=END&limit=5 - Returns: R11,R12,R13,R14,R15 - -Note that tokens are treated in an *exclusive*, not inclusive, manner. The end -token from the initial request was '9' which corresponded to R10. When the 2nd -request was made, R10 did not appear again, even though from=9 was specified. If -you know the token, you already have the data. - -Pagination Response -~~~~~~~~~~~~~~~~~~~ - -Responses to pagination requests MUST follow the format:: - - { - "chunk": [ ... , Responses , ... ], - "start" : $streamtoken, - "end" : $streamtoken - } - -Where $streamtoken is an opaque token which can be used in another query to -get the next set of results. The "start" and "end" keys can only be omitted if -the complete dataset is provided in "chunk". - Events ------ @@ -521,8 +427,8 @@ returns an ``end`` token which can be used with the event stream. {{sync_http_api}} -Events in a room -~~~~~~~~~~~~~~~~ +Types of room events +~~~~~~~~~~~~~~~~~~~~ Room events are split into two categories: @@ -544,7 +450,7 @@ convention, e.g. ``com.example.myapp.event``. This ensures event types are suitably namespaced for each application and reduces the risk of clashes. State events -~~~~~~~~~~~~ +++++++++++++ State events can be sent by ``PUT`` ing to |/rooms//state//|_. These events will be @@ -587,7 +493,7 @@ In some cases, there may be no need for a ``state_key``, so it can be omitted:: See `Room Events`_ for the ``m.`` event specification. Message events -~~~~~~~~~~~~~~ +++++++++++++++ Message events can be sent by sending a request to |/rooms//send/|_. These requests *can* use transaction @@ -655,6 +561,105 @@ The redaction event should be added under the key ``redacted_because``. When a client receives a redaction event it should change the redacted event in the same way a server does. +Pagination +---------- + +.. NOTE:: + The paths referred to in this section are not actual endpoints. They only + serve as examples to explain how pagination functions. + +Pagination is the process of dividing a dataset into multiple discrete pages. +Matrix makes use of pagination to allow clients to view extremely large datasets. +These datasets are not limited to events in a room (for example clients may want +to paginate rooms in addition to events within those rooms). Regardless of *what* +is being paginated, there is a common underlying API which is used to +to give clients a consistent way of selecting subsets of a potentially changing +dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters +which describe where to read from the stream. ``from`` and ``to`` are opaque +textual 'stream tokens' which describe the current position in the dataset. +The ``dir`` parameter is an enum representing the direction of events to return: +either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and +``end`` stream token values which can then be passed to subsequent requests to +continue pagination. Not all endpoints will make use of all the parameters +outlined here: see the specific endpoint in question for more information. + +Pagination Request Query Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Query parameters: + from: + $streamtoken - The opaque token to start streaming from. + to: + $streamtoken - The opaque token to end streaming at. Typically, + clients will not know the item of data to end at, so this will usually be + omitted. + limit: + integer - An integer representing the maximum number of items to + return. + dir: + f|b - The direction to return events in. Typically this is ``b`` to paginate + backwards in time. + +'START' and 'END' are placeholder values used in these examples to describe the +start and end of the dataset respectively. + +Unless specified, the default pagination parameters are ``from=START``, +``to=END``, without a limit set. + +For example, if an endpoint had events E1 -> E15. The client wants the last 5 +events and doesn't know any previous events:: + + S E + |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-| + | | | + | _____| <--backwards-- | + |__________________ | | ________| + | | | | + GET /somepath?to=START&limit=5&dir=b&from=END + Returns: + E15,E14,E13,E12,E11 + + +Another example: a public room list has rooms R1 -> R17. The client is showing 5 +rooms at a time on screen, and is on page 2. They want to +now show page 3 (rooms R11 -> 15):: + + S E + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | stream token + |-R1-R2-R3-R4-R5-R6-R7-R8-R9-R10-R11-R12-R13-R14-R15-R16-R17| room + |____________| |________________| + | | + Currently | + viewing | + | + GET /roomslist?from=9&to=END&limit=5 + Returns: R11,R12,R13,R14,R15 + +Note that tokens are treated in an *exclusive*, not inclusive, manner. The end +token from the initial request was '9' which corresponded to R10. When the 2nd +request was made, R10 did not appear again, even though from=9 was specified. If +you know the token, you already have the data. + +Pagination Response +~~~~~~~~~~~~~~~~~~~ + +Responses to pagination requests MUST follow the format:: + + { + "chunk": [ ... , Responses , ... ], + "start" : $streamtoken, + "end" : $streamtoken + } + +Where $streamtoken is an opaque token which can be used in another query to +get the next set of results. The "start" and "end" keys can only be omitted if +the complete dataset is provided in "chunk". + +Pagination APIs +~~~~~~~~~~~~~~~ + +{{message_pagination_http_api}} + Rooms ----- From 41fb0645a975d5bfb4e6394db1f7c4fef59463eb Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 11:16:58 +0100 Subject: [PATCH 05/14] Add message pagination API --- api/client-server/v1/message_pagination.yaml | 131 +++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 api/client-server/v1/message_pagination.yaml diff --git a/api/client-server/v1/message_pagination.yaml b/api/client-server/v1/message_pagination.yaml new file mode 100644 index 00000000..b3317c13 --- /dev/null +++ b/api/client-server/v1/message_pagination.yaml @@ -0,0 +1,131 @@ +swagger: '2.0' +info: + title: "Matrix Client-Server v1 Rooms API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: /_matrix/client/api/v1 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + accessToken: + type: apiKey + description: The user_id or application service access_token + name: access_token + in: query +paths: + "/rooms/{roomId}/messages": + get: + summary: Get a list of events for this room + description: |- + This API returns a list of message and state events for a room. It uses + pagination query parameters to paginate history in the room. + security: + - accessToken: [] + parameters: + - in: path + type: string + name: roomId + description: The room to get events from. + required: true + x-example: "!636q39766251:example.com" + - in: query + type: string + name: from + description: |- + The token to start returning events from. This token can be obtained + from the initial sync API. + required: true + x-example: "s345_678_333" + - in: query + type: string + enum: ["b", "f"] + name: dir + description: |- + The direction to return events from. + required: true + x-example: "b" + - in: query + type: integer + name: limit + description: |- + The maximum number of events to return. Default: 10. + x-example: "3" + responses: + 200: + description: A list of messages with a new token to request more. + schema: + type: object + description: A list of messages with a new token to request more. + properties: + start: + type: string + description: |- + The token to start paginating from. If ``dir=b`` this will be + the token supplied in ``from``. + end: + type: string + description: |- + The token the pagination ends at. If ``dir=b`` this token should + be used again to request even earlier events. + chunk: + type: array + description: |- + A list of room events. + items: + type: object + title: RoomEvent + examples: + application/json: |- + { + "start": "t47429-4392820_219380_26003_2265", + "end": "t47409-4357353_219380_26003_2265", + "chunk": [ + { + "origin_server_ts": 1444812213737, + "user_id": "@alice:example.com", + "event_id": "$1444812213350496Caaaa:example.com", + "content": { + "body": "hello world", + "msgtype":"m.text" + }, + "room_id":"!Xq3620DUiqCaoxq:example.com", + "type":"m.room.message", + "age": 1042 + }, + { + "origin_server_ts": 1444812194656 , + "user_id": "@bob:example.com", + "event_id": "$1444812213350496Cbbbb:example.com", + "content": { + "body": "the world is big", + "msgtype":"m.text" + }, + "room_id":"!Xq3620DUiqCaoxq:example.com", + "type":"m.room.message", + "age": 20123 + }, + { + "origin_server_ts": 1444812163990, + "user_id": "@bob:example.com", + "event_id": "$1444812213350496Ccccc:example.com", + "content": { + "name": "New room name" + }, + "prev_content": { + "name": "Old room name" + }, + "state_key": "", + "room_id":"!Xq3620DUiqCaoxq:example.com", + "type":"m.room.name", + "age": 50789 + } + ] + } + 403: + description: > + You aren't a member of the room. \ No newline at end of file From 6f6861a11d45b86c5cbcad7b864fd527a77f5724 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 13:17:51 +0100 Subject: [PATCH 06/14] Swaggerify the createRoom API --- api/client-server/v1/create_room.yaml | 148 ++++++++++++++++++++++++++ specification/1-client_server_api.rst | 135 ++--------------------- 2 files changed, 155 insertions(+), 128 deletions(-) create mode 100644 api/client-server/v1/create_room.yaml diff --git a/api/client-server/v1/create_room.yaml b/api/client-server/v1/create_room.yaml new file mode 100644 index 00000000..5bb4e17c --- /dev/null +++ b/api/client-server/v1/create_room.yaml @@ -0,0 +1,148 @@ +swagger: '2.0' +info: + title: "Matrix Client-Server v1 Room Creation API" + version: "1.0.0" +host: localhost:8008 +schemes: + - https + - http +basePath: /_matrix/client/api/v1 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + accessToken: + type: apiKey + description: The user_id or application service access_token + name: access_token + in: query +paths: + "/createRoom": + post: + summary: Create a new room + description: |- + Create a new room with various configuration options. + security: + - accessToken: [] + parameters: + - in: body + name: body + description: The desired room configuration. + schema: + type: object + example: |- + { + "preset": "public_chat", + "room_alias_name": "thepub", + "name": "The Grand Duke Pub", + "topic": "All about happy hour", + "creation_content": { + "m.federate": false + } + } + properties: + visibility: + type: string + enum: ["public", "private"] + description: |- + A ``public`` visibility indicates that the room will be shown + in the published room list. A ``private`` visibility will hide + the room from the published room list. Rooms default to + ``private`` visibility if this key is not included. NB: This + should not be confused with ``join_rules`` which also uses the + word ``public``. + room_alias_name: + type: string + description: |- + The desired room alias **local part**. If this is included, a + room alias will be created and mapped to the newly created + room. The alias will belong on the *same* home server which + created the room. For example, if this was set to "foo" and + sent to the homeserver "example.com" the complete room alias + would be ``#foo:example.com``. + name: + type: string + description: |- + If this is included, an ``m.room.name`` event will be sent + into the room to indicate the name of the room. See Room + Events for more information on ``m.room.name``. + topic: + type: string + description: |- + If this is included, an ``m.room.topic`` event will be sent + into the room to indicate the topic for the room. See Room + Events for more information on ``m.room.topic``. + invite: + type: array + description: |- + A list of user IDs to invite to the room. This will tell the + server to invite everyone in the list to the newly created room. + items: + type: string + creation_content: + title: CreationContent + type: object + description: |- + Extra keys to be added to the content of the ``m.room.create``. + The server will clober the following keys: ``creator``. Future + versions of the specification may allow the server to clobber + other keys. + initial_state: + type: array + description: |- + A list of state events to set in the new room. This allows + the user to override the default state events set in the new + room. The expected format of the state events are an object + with type, state_key and content keys set. + Takes precedence over events set by ``presets``, but gets + overriden by ``name`` and ``topic`` keys. + items: + type: object + title: StateEvent + properties: + type: + type: string + state_key: + type: string + content: + type: string + preset: + type: string + enum: ["private_chat", "public_chat", "trusted_private_chat"] + description: |- + Convenience parameter for setting various default state events + based on a preset. Must be either: + + ``private_chat`` => + ``join_rules`` is set to ``invite``. + ``history_visibility`` is set to ``shared``. + + ``trusted_private_chat`` => + ``join_rules`` is set to ``invite``. + ``history_visibility`` is set to ``shared``. + All invitees are given the same power level as the room creator. + + ``public_chat``: => + ``join_rules`` is set to ``public``. + ``history_visibility`` is set to ``shared``. + + responses: + 200: + description: Information about the newly created room. + schema: + type: object + description: Information about the newly created room. + properties: + room_id: + type: string + description: |- + The created room's ID. + examples: + application/json: |- + { + "room_id": "!sefiuhWgwghwWgh:example.com" + } + 400: + description: > + The request body is malformed or the room alias specified is already taken. \ No newline at end of file diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index d8b9299a..f27e4d42 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -665,140 +665,19 @@ Rooms Creation ~~~~~~~~ -To create a room, a client has to use the |createRoom|_ API. There are various -options which can be set when creating a room: - -``visibility`` - Type: - String - Optional: - Yes - Value: - Either ``public`` or ``private``. - Description: - A ``public`` visibility indicates that the room will be shown in the public - room list. A ``private`` visibility will hide the room from the public room - list. Rooms default to ``private`` visibility if this key is not included. - -``room_alias_name`` - Type: - String - Optional: - Yes - Value: - The room alias localpart. - Description: - If this is included, a room alias will be created and mapped to the newly - created room. The alias will belong on the same home server which created - the room, e.g. ``!qadnasoi:domain.com >>> #room_alias_name:domain.com`` - -``name`` - Type: - String - Optional: - Yes - Value: - The ``name`` value for the ``m.room.name`` state event. - Description: - If this is included, an ``m.room.name`` event will be sent into the room to - indicate the name of the room. See `Room Events`_ for more information on - ``m.room.name``. - -``topic`` - Type: - String - Optional: - Yes - Value: - The ``topic`` value for the ``m.room.topic`` state event. - Description: - If this is included, an ``m.room.topic`` event will be sent into the room - to indicate the topic for the room. See `Room Events`_ for more information - on ``m.room.topic``. - -``invite`` - Type: - List - Optional: - Yes - Value: - A list of user ids to invite. - Description: - This will tell the server to invite everyone in the list to the newly - created room. - -``creation_content`` - Type: - Object - Optional: - Yes - Value: - Extra keys to be added to the content of the ``m.room.create``. The server - will clober the following keys: ``creator``. Future versions of this - spec may allow the server to clobber other keys if required. - Description: - Allows clients to add keys to the content of ``m.room.create``. - -``preset`` - Type: - String - Optional: - Yes - Value: - ``private_chat``, ``trusted_private_chat`` or ``public_chat`` - Description: - Convenience parameter for setting various default state events based on a - preset. - - Three presets are defined: - - - ``private_chat``: Sets the ``join_rules`` to ``invite`` and - ``history_visibility`` to ``shared`` - - ``trusted_private_chat``: Set the ``join_rules`` to ``invite``, - ``history_visibility`` to ``shared`` and gives all invitees the same - power level as the creator. - - ``public_chat``: Sets the ``join_rules`` to ``public`` and - ``history_visibility`` to ``shared`` - -``initial_state`` - Type: - List - Optional: - Yes - Value: - A list of state events to set in the new room. - Description: - Allows the user to override the default state events set in the new room. - - The expected format of the state events are an object with ``type``, - ``state_key`` and ``content`` keys set. - - Takes precedence over events set by ``presets``, but gets overriden by - ``name`` and ``topic`` keys. - -Example:: - - { - "preset": "public_chat", - "room_alias_name": "thepub", - "name": "The Grand Duke Pub", - "topic": "All about happy hour", - "creation_content": { - "m.federate": false - } - } - -The home server will create a ``m.room.create`` event when the room is created, -which serves as the root of the PDU graph for this room. This event also has a +The home server will create a ``m.room.create`` event when a room is created, +which serves as the root of the event graph for this room. This event also has a ``creator`` key which contains the user ID of the room creator. It will also generate several other events in order to manage permissions in this room. This includes: - - ``m.room.power_levels`` : Sets the power levels of users and required power - levels. + - ``m.room.power_levels`` : Sets the power levels of users and required power levels. - ``m.room.join_rules`` : Whether the room is "invite-only" or not. -See `Room Events`_ for more information on these events. +See `Room Events`_ for more information on these events. To create a room, a +client has to use the the following API. + +{{create_room_http_api}} Room aliases ~~~~~~~~~~~~ From 34bd8edec5395a8accde330be4b04dbca41f770b Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 13:26:58 +0100 Subject: [PATCH 07/14] Move related auth sections together --- specification/0-events.rst | 4 +- specification/1-client_server_api.rst | 274 +++++++++++++------------- 2 files changed, 138 insertions(+), 140 deletions(-) diff --git a/specification/0-events.rst b/specification/0-events.rst index 16948462..64007568 100644 --- a/specification/0-events.rst +++ b/specification/0-events.rst @@ -1,5 +1,5 @@ -Events -====== +Event Structure +=============== All communication in Matrix is expressed in the form of data objects called Events. These are the fundamental building blocks common to the client-server, diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index f27e4d42..319fed91 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -340,6 +340,141 @@ This MUST return an HTML page which can perform this authentication stage. This page must attempt to call the JavaScript function ``window.onAuthDone`` when the authentication has been completed. +Registration +~~~~~~~~~~~~ +This section refers to API Version 2. These API calls currently use the prefix +``/_matrix/client/v2_alpha``. + +Registering for a user account is done using the request:: + + POST $V2PREFIX/register + +This API endpoint uses the User-Interactive Authentication API. +This API endpoint does not require an access token. + +The body of the POST request is a JSON object containing: + +username + Optional. This is the local part of the desired Matrix ID. If omitted, the + Home Server must generate a Matrix ID local part. +password + Required. The desired password for the account. +bind_email + Optional. If ``true``, the server binds the email used for authentication to + the Matrix ID with the ID Server. + +On success, this returns a JSON object with keys: + +user_id + The fully-qualified Matrix ID that has been registered. +access_token + An access token for the new account. +home_server + The hostname of the Home Server on which the account has been registered. + +This endpoint may also return the following error codes: + +M_USER_IN_USE + If the Matrix ID is already in use +M_EXCLUSIVE + If the requested Matrix ID is in the exclusive namespace of an application + service. + +Home Servers MUST perform the relevant checks and return these codes before +performing User-Interactive Authentication, although they may also return +them after authentication is completed if, for example, the requested user ID +was registered whilst the client was performing authentication. + +Old V1 API docs: |register|_ + +{{login_http_api}} + +Changing Password ++++++++++++++++++ +This section refers to API Version 2. These API calls currently use the prefix +``/_matrix/client/v2_alpha``. + +Request:: + + POST $V2PREFIX/account/password + +This API endpoint uses the User-Interactive Authentication API. An access token +should be submitted to this endpoint if the client has an active session. The +Home Server may change the flows available depending on whether a valid access +token is provided. + +The body of the POST request is a JSON object containing: + +new_password + The new password for the account. + +On success, an empty JSON object is returned. + +The error code M_NOT_FOUND is returned if the user authenticated with a third +party identifier but the Home Server could not find a matching account in its +database. + +Adding a Third Party Identifier ++++++++++++++++++++++++++++++++ +This section refers to API Version 2. These API calls currently use the prefix +``/_matrix/client/v2_alpha``. + +Request:: + + POST $V2PREFIX/account/3pid + +Used to add a third party identifier to the user's account. + +The body of the POST request is a JSON object containing: + +threePidCreds + An object containing third party identifier credentials. +bind + Optional. A boolean indicating whether the Home Server should also bind this + third party identifier to the account's matrix ID with the Identity Server. If + supplied and true, the Home Server must bind the 3pid accordingly. + +The third party identifier credentials object comprises: + +id_server + The colon-separated hostname and port of the Identity Server used to + authenticate the third party identifier. If the port is the default, it and the + colon should be omitted. +sid + The session ID given by the Identity Server +client_secret + The client secret used in the session with the Identity Server. + +On success, the empty JSON object is returned. + +May also return error codes: + +M_THREEPID_AUTH_FAILED + If the credentials provided could not be verified with the ID Server. + +Fetching Currently Associated Third Party Identifiers ++++++++++++++++++++++++++++++++++++++++++++++++++++++ +This section refers to API Version 2. These API calls currently use the prefix +``/_matrix/client/v2_alpha``. + +Request:: + + GET $V2PREFIX/account/3pid + +This returns a list of third party identifiers that the Home Server has +associated with the user's account. This is *not* the same as the list of third +party identifiers bound to the user's Matrix ID in Identity Servers. Identifiers +in this list may be used by the Home Server as, for example, identifiers that it +will accept to reset the user's account password. + +Returns a JSON object with the key ``threepids`` whose contents is an array of +objects with the following keys: + +medium + The medium of the 3pid (eg, ``email``) +address + The textual address of the 3pid, eg. the email address + Events ------ @@ -742,7 +877,7 @@ certain operations such as kicking, banning and sending state events. See `m.room.power_levels`_ for more information. Joining rooms -------------- +~~~~~~~~~~~~~ Users need to be a member of a room in order to send and receive events in that room. There are several states in which a user may be, in relation to a room: @@ -821,143 +956,6 @@ member's state, by making a request to "membership": "ban" } - -Registration ------------- -This section refers to API Version 2. These API calls currently use the prefix -``/_matrix/client/v2_alpha``. - -Registering for a user account is done using the request:: - - POST $V2PREFIX/register - -This API endpoint uses the User-Interactive Authentication API. -This API endpoint does not require an access token. - -The body of the POST request is a JSON object containing: - -username - Optional. This is the local part of the desired Matrix ID. If omitted, the - Home Server must generate a Matrix ID local part. -password - Required. The desired password for the account. -bind_email - Optional. If ``true``, the server binds the email used for authentication to - the Matrix ID with the ID Server. - -On success, this returns a JSON object with keys: - -user_id - The fully-qualified Matrix ID that has been registered. -access_token - An access token for the new account. -home_server - The hostname of the Home Server on which the account has been registered. - -This endpoint may also return the following error codes: - -M_USER_IN_USE - If the Matrix ID is already in use -M_EXCLUSIVE - If the requested Matrix ID is in the exclusive namespace of an application - service. - -Home Servers MUST perform the relevant checks and return these codes before -performing User-Interactive Authentication, although they may also return -them after authentication is completed if, for example, the requested user ID -was registered whilst the client was performing authentication. - -Old V1 API docs: |register|_ - -{{login_http_api}} - -Changing Password -~~~~~~~~~~~~~~~~~ -This section refers to API Version 2. These API calls currently use the prefix -``/_matrix/client/v2_alpha``. - -Request:: - - POST $V2PREFIX/account/password - -This API endpoint uses the User-Interactive Authentication API. An access token -should be submitted to this endpoint if the client has an active session. The -Home Server may change the flows available depending on whether a valid access -token is provided. - -The body of the POST request is a JSON object containing: - -new_password - The new password for the account. - -On success, an empty JSON object is returned. - -The error code M_NOT_FOUND is returned if the user authenticated with a third -party identifier but the Home Server could not find a matching account in its -database. - -Adding a Third Party Identifier -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This section refers to API Version 2. These API calls currently use the prefix -``/_matrix/client/v2_alpha``. - -Request:: - - POST $V2PREFIX/account/3pid - -Used to add a third party identifier to the user's account. - -The body of the POST request is a JSON object containing: - -threePidCreds - An object containing third party identifier credentials. -bind - Optional. A boolean indicating whether the Home Server should also bind this - third party identifier to the account's matrix ID with the Identity Server. If - supplied and true, the Home Server must bind the 3pid accordingly. - -The third party identifier credentials object comprises: - -id_server - The colon-separated hostname and port of the Identity Server used to - authenticate the third party identifier. If the port is the default, it and the - colon should be omitted. -sid - The session ID given by the Identity Server -client_secret - The client secret used in the session with the Identity Server. - -On success, the empty JSON object is returned. - -May also return error codes: - -M_THREEPID_AUTH_FAILED - If the credentials provided could not be verified with the ID Server. - -Fetching Currently Associated Third Party Identifiers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This section refers to API Version 2. These API calls currently use the prefix -``/_matrix/client/v2_alpha``. - -Request:: - - GET $V2PREFIX/account/3pid - -This returns a list of third party identifiers that the Home Server has -associated with the user's account. This is *not* the same as the list of third -party identifiers bound to the user's Matrix ID in Identity Servers. Identifiers -in this list may be used by the Home Server as, for example, identifiers that it -will accept to reset the user's account password. - -Returns a JSON object with the key ``threepids`` whose contents is an array of -objects with the following keys: - -medium - The medium of the 3pid (eg, ``email``) -address - The textual address of the 3pid, eg. the email address - - Profiles -------- From 84af5776d7487473aae3d8679120e8d3992b4d4e Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 17:02:39 +0100 Subject: [PATCH 08/14] Newlines --- api/client-server/v1/create_room.yaml | 2 +- api/client-server/v1/message_pagination.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/client-server/v1/create_room.yaml b/api/client-server/v1/create_room.yaml index 5bb4e17c..051c4b84 100644 --- a/api/client-server/v1/create_room.yaml +++ b/api/client-server/v1/create_room.yaml @@ -145,4 +145,4 @@ paths: } 400: description: > - The request body is malformed or the room alias specified is already taken. \ No newline at end of file + The request body is malformed or the room alias specified is already taken. diff --git a/api/client-server/v1/message_pagination.yaml b/api/client-server/v1/message_pagination.yaml index b3317c13..d2bc0554 100644 --- a/api/client-server/v1/message_pagination.yaml +++ b/api/client-server/v1/message_pagination.yaml @@ -128,4 +128,4 @@ paths: } 403: description: > - You aren't a member of the room. \ No newline at end of file + You aren't a member of the room. From 1f2f14dc08a8b4dbed83e37dfc667a0777e4accb Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 17:07:25 +0100 Subject: [PATCH 09/14] YAML tweaks --- api/client-server/v1/sync.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/client-server/v1/sync.yaml b/api/client-server/v1/sync.yaml index 398b0773..50af8546 100644 --- a/api/client-server/v1/sync.yaml +++ b/api/client-server/v1/sync.yaml @@ -31,7 +31,7 @@ paths: type: string name: from description: |- - The token to stream from. This token is either from the a previous + The token to stream from. This token is either from a previous request to this API or from the initial sync API. required: false x-example: "s3456_9_0" @@ -45,10 +45,10 @@ paths: type: boolean name: archived description: |- - Whether to include rooms that the user has left. If absent then + Whether to include rooms that the user has left. If ``false`` then only rooms that the user has been invited to or has joined are - included. If set to "true" then rooms that the user has left are - included as well. + included. If set to ``true`` then rooms that the user has left are + included as well. By default this is ``false``. required: false x-example: "true" responses: From e6eb19c46115f1e324fa3c474341c627b4219cf9 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Wed, 14 Oct 2015 17:34:25 +0100 Subject: [PATCH 10/14] Review comments --- specification/1-client_server_api.rst | 37 +++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index 319fed91..ecd5a3e2 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -29,6 +29,9 @@ return with a status of 401 and the error code, ``M_MISSING_TOKEN`` or User-Interactive Authentication API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _sect:auth-api: + This section refers to API Version 2. Some API endpoints such as ``login`` or ``register`` require authentication that @@ -349,9 +352,11 @@ Registering for a user account is done using the request:: POST $V2PREFIX/register -This API endpoint uses the User-Interactive Authentication API. +This API endpoint uses the `User-Interactive Authentication API`_. This API endpoint does not require an access token. +.. _User-Interactive Authentication API: `sect:auth-api`_ + The body of the POST request is a JSON object containing: username @@ -371,6 +376,9 @@ access_token An access token for the new account. home_server The hostname of the Home Server on which the account has been registered. +refresh_token + A token that may be exchanged for a new ``access_token`` using the + ``/tokenrefresh`` API endpoint. This endpoint may also return the following error codes: @@ -381,10 +389,12 @@ M_EXCLUSIVE service. Home Servers MUST perform the relevant checks and return these codes before -performing User-Interactive Authentication, although they may also return +performing `User-Interactive Authentication`_, although they may also return them after authentication is completed if, for example, the requested user ID was registered whilst the client was performing authentication. +.. _User-Interactive Authentication: `sect:auth-api`_ + Old V1 API docs: |register|_ {{login_http_api}} @@ -414,8 +424,8 @@ The error code M_NOT_FOUND is returned if the user authenticated with a third party identifier but the Home Server could not find a matching account in its database. -Adding a Third Party Identifier -+++++++++++++++++++++++++++++++ +Adding Account Administrative Contact Information ++++++++++++++++++++++++++++++++++++++++++++++++++ This section refers to API Version 2. These API calls currently use the prefix ``/_matrix/client/v2_alpha``. @@ -423,18 +433,18 @@ Request:: POST $V2PREFIX/account/3pid -Used to add a third party identifier to the user's account. +Used to add contact information to the user's account. The body of the POST request is a JSON object containing: threePidCreds - An object containing third party identifier credentials. + An object containing contact information. bind Optional. A boolean indicating whether the Home Server should also bind this third party identifier to the account's matrix ID with the Identity Server. If supplied and true, the Home Server must bind the 3pid accordingly. -The third party identifier credentials object comprises: +The contact information object comprises: id_server The colon-separated hostname and port of the Identity Server used to @@ -452,8 +462,8 @@ May also return error codes: M_THREEPID_AUTH_FAILED If the credentials provided could not be verified with the ID Server. -Fetching Currently Associated Third Party Identifiers -+++++++++++++++++++++++++++++++++++++++++++++++++++++ +Fetching Currently Associated Contact Information ++++++++++++++++++++++++++++++++++++++++++++++++++ This section refers to API Version 2. These API calls currently use the prefix ``/_matrix/client/v2_alpha``. @@ -706,8 +716,8 @@ Pagination Pagination is the process of dividing a dataset into multiple discrete pages. Matrix makes use of pagination to allow clients to view extremely large datasets. These datasets are not limited to events in a room (for example clients may want -to paginate rooms in addition to events within those rooms). Regardless of *what* -is being paginated, there is a common underlying API which is used to +to paginate a list of rooms in addition to events within those rooms). Regardless +of *what* is being paginated, there is a common underlying API which is used to to give clients a consistent way of selecting subsets of a potentially changing dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters which describe where to read from the stream. ``from`` and ``to`` are opaque @@ -800,13 +810,14 @@ Rooms Creation ~~~~~~~~ -The home server will create a ``m.room.create`` event when a room is created, +The home server will create an ``m.room.create`` event when a room is created, which serves as the root of the event graph for this room. This event also has a ``creator`` key which contains the user ID of the room creator. It will also generate several other events in order to manage permissions in this room. This includes: - - ``m.room.power_levels`` : Sets the power levels of users and required power levels. + - ``m.room.power_levels`` : Sets the power levels of users and required power + levels for various actions within the room such as sending events. - ``m.room.join_rules`` : Whether the room is "invite-only" or not. See `Room Events`_ for more information on these events. To create a room, a From 6b72ddfb8cbf8628f2ea2efe24d05a609588a211 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 15 Oct 2015 13:36:43 +0100 Subject: [PATCH 11/14] Spelling and typos --- specification/3-application_service_api.rst | 19 ++++++++++--------- specification/4-server_server_api.rst | 2 +- specification/6-appendices.rst | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/specification/3-application_service_api.rst b/specification/3-application_service_api.rst index 8d0efdef..cf4942af 100644 --- a/specification/3-application_service_api.rst +++ b/specification/3-application_service_api.rst @@ -322,7 +322,7 @@ including the AS token on a ``/register`` request, along with a login type of Application services which attempt to create users or aliases *outside* of their defined namespaces will receive an error code ``M_EXCLUSIVE``. Similarly, -normal users who attempt to create users or alises *inside* an application +normal users who attempt to create users or aliases *inside* an application service-defined namespace will receive the same ``M_EXCLUSIVE`` error code, but only if the application service has defined the namespace as ``exclusive``. @@ -375,9 +375,10 @@ an API is exposed. Room Aliases ++++++++++++ We may want to expose some 3P network rooms so Matrix users can join them directly, -e.g. IRC rooms. We don't want to expose every 3P network room though, e.g. mailto, -tel. Rooms which are publicly accessible (e.g. IRC rooms) can be exposed as an alias by -the application service. Private rooms (e.g. sending an email to someone) should not +e.g. IRC rooms. We don't want to expose every 3P network room though, e.g. +``mailto``, ``tel``. Rooms which are publicly accessible (e.g. IRC rooms) can be +exposed as an alias by the application service. Private rooms +(e.g. sending an email to someone) should not be exposed in this way, but should instead operate using normal invite/join semantics. Therefore, the ID conventions discussed below are only valid for public rooms which expose room aliases. @@ -397,9 +398,9 @@ SHOULD be mapped in the same way as "user" URIs. Event fields ++++++++++++ -We recommend that any gatewayed events should include an ``external_url`` field -in their content to provide a way for Matrix clients to link into the 'native' -client from which the event originated. For instance, this could contain the -message-ID for emails/nntp posts, or a link to a blog comment when gatewaying -blog comment traffic in & out of matrix +We recommend that any events that originated from a remote network should +include an ``external_url`` field in their content to provide a way for Matrix +clients to link into the 'native' client from which the event originated. +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. diff --git a/specification/4-server_server_api.rst b/specification/4-server_server_api.rst index c5ff2b87..66367cb0 100644 --- a/specification/4-server_server_api.rst +++ b/specification/4-server_server_api.rst @@ -630,7 +630,7 @@ because HTTP services like Matrix are often deployed behind load balancers that handle the TLS and these load balancers make it difficult to check TLS client certificates. -A home server may provide a TLS client certficate and the receiving home server +A home server may provide a TLS client certificate and the receiving home server may check that the client certificate matches the certificate of the origin home server. diff --git a/specification/6-appendices.rst b/specification/6-appendices.rst index de1ac290..c45aa0a5 100644 --- a/specification/6-appendices.rst +++ b/specification/6-appendices.rst @@ -24,7 +24,7 @@ Threat: Unrecoverable Consistency Violations ++++++++++++++++++++++++++++++++++++++++++++ An attacker could send messages which created an unrecoverable "split-brain" -state in the cluster such that the victim's servers could no longer dervive a +state in the cluster such that the victim's servers could no longer derive a consistent view of the chatroom state. Threat: Bad History @@ -63,7 +63,7 @@ Spoofing An attacker could try to send a message claiming to be from the victim without the victim having sent the message in order to: -* Impersonate the victim while performing illict activity. +* Impersonate the victim while performing illicit activity. * Obtain privileges of the victim. Threat: Altering Message Contents @@ -81,7 +81,7 @@ with a phony "origin" field. Spamming ~~~~~~~~ -The attacker could try to send a high volume of solicicted or unsolicted +The attacker could try to send a high volume of solicited or unsolicited messages to the victim in order to: * Find victims for scams. From 3d087df5387f59c1d18f3d0020d0aa26914d2208 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 15 Oct 2015 13:40:05 +0100 Subject: [PATCH 12/14] Kill number prefixes for good --- .../{6-appendices.rst => appendices.rst} | 0 ...ce_api.rst => application_service_api.rst} | 0 ...t_server_api.rst => client_server_api.rst} | 0 ...{0-event_signing.rst => event_signing.rst} | 0 specification/{0-events.rst => events.rst} | 0 ...ture_profiles.rst => feature_profiles.rst} | 0 ...ntity_servers.rst => identity_servers.rst} | 0 specification/{0-intro.rst => intro.rst} | 0 specification/{2-modules.rst => modules.rst} | 0 ...r_server_api.rst => server_server_api.rst} | 0 specification/targets.yaml | 20 +++++++++---------- 11 files changed, 10 insertions(+), 10 deletions(-) rename specification/{6-appendices.rst => appendices.rst} (100%) rename specification/{3-application_service_api.rst => application_service_api.rst} (100%) rename specification/{1-client_server_api.rst => client_server_api.rst} (100%) rename specification/{0-event_signing.rst => event_signing.rst} (100%) rename specification/{0-events.rst => events.rst} (100%) rename specification/{0-feature_profiles.rst => feature_profiles.rst} (100%) rename specification/{5-identity_servers.rst => identity_servers.rst} (100%) rename specification/{0-intro.rst => intro.rst} (100%) rename specification/{2-modules.rst => modules.rst} (100%) rename specification/{4-server_server_api.rst => server_server_api.rst} (100%) diff --git a/specification/6-appendices.rst b/specification/appendices.rst similarity index 100% rename from specification/6-appendices.rst rename to specification/appendices.rst diff --git a/specification/3-application_service_api.rst b/specification/application_service_api.rst similarity index 100% rename from specification/3-application_service_api.rst rename to specification/application_service_api.rst diff --git a/specification/1-client_server_api.rst b/specification/client_server_api.rst similarity index 100% rename from specification/1-client_server_api.rst rename to specification/client_server_api.rst diff --git a/specification/0-event_signing.rst b/specification/event_signing.rst similarity index 100% rename from specification/0-event_signing.rst rename to specification/event_signing.rst diff --git a/specification/0-events.rst b/specification/events.rst similarity index 100% rename from specification/0-events.rst rename to specification/events.rst diff --git a/specification/0-feature_profiles.rst b/specification/feature_profiles.rst similarity index 100% rename from specification/0-feature_profiles.rst rename to specification/feature_profiles.rst diff --git a/specification/5-identity_servers.rst b/specification/identity_servers.rst similarity index 100% rename from specification/5-identity_servers.rst rename to specification/identity_servers.rst diff --git a/specification/0-intro.rst b/specification/intro.rst similarity index 100% rename from specification/0-intro.rst rename to specification/intro.rst diff --git a/specification/2-modules.rst b/specification/modules.rst similarity index 100% rename from specification/2-modules.rst rename to specification/modules.rst diff --git a/specification/4-server_server_api.rst b/specification/server_server_api.rst similarity index 100% rename from specification/4-server_server_api.rst rename to specification/server_server_api.rst diff --git a/specification/targets.yaml b/specification/targets.yaml index c2b6eeda..4ac34ae3 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -1,17 +1,17 @@ targets: main: # arbitrary name to identify this build target files: # the sort order of files to cat - - 0-intro.rst - - 1-client_server_api.rst - - { 1: 0-events.rst } - - { 1: 0-event_signing.rst } - - 2-modules.rst - - { 1: 0-feature_profiles.rst } + - intro.rst + - client_server_api.rst + - { 1: events.rst } + - { 1: event_signing.rst } + - modules.rst + - { 1: feature_profiles.rst } - { 1: "group:modules" } # reference a group of files - - 3-application_service_api.rst - - 4-server_server_api.rst - - 5-identity_servers.rst - - 6-appendices.rst + - application_service_api.rst + - server_server_api.rst + - identity_servers.rst + - appendices.rst groups: # reusable blobs of files when prefixed with 'group:' modules: - modules/instant_messaging.rst From 4bb042daeb3b6bce59f75c308f059910517bd9b0 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Fri, 16 Oct 2015 15:22:50 +0100 Subject: [PATCH 13/14] Review comments round II --- api/client-server/v1/sync.yaml | 30 ++-- specification/1-client_server_api.rst | 210 +++++++++++++------------- 2 files changed, 122 insertions(+), 118 deletions(-) diff --git a/api/client-server/v1/sync.yaml b/api/client-server/v1/sync.yaml index 50af8546..d07e9399 100644 --- a/api/client-server/v1/sync.yaml +++ b/api/client-server/v1/sync.yaml @@ -41,16 +41,6 @@ paths: description: The maximum time in milliseconds to wait for an event. required: false x-example: "35000" - - in: query - type: boolean - name: archived - description: |- - Whether to include rooms that the user has left. If ``false`` then - only rooms that the user has been invited to or has joined are - included. If set to ``true`` then rooms that the user has left are - included as well. By default this is ``false``. - required: false - x-example: "true" responses: 200: description: "The events received, which may be none." @@ -80,19 +70,19 @@ paths: start: type: string description: |- - A token which correlates to the first value in ``chunk``. Used - for pagination. + A token which correlates to the first value in ``chunk``. This + is usually the same token supplied to ``from=``. end: type: string description: |- - A token which correlates to the last value in ``chunk``. Used - for pagination. + A token which correlates to the last value in ``chunk``. This + token should be used in the next request to ``/events``. chunk: type: array description: "An array of events." items: type: object - title: RoomEvent + title: Event allOf: - "$ref": "core-event-schema/room_event.json" 400: @@ -112,6 +102,16 @@ paths: description: The maximum number of messages to return for each room. required: false x-example: "2" + - in: query + type: boolean + name: archived + description: |- + Whether to include rooms that the user has left. If ``false`` then + only rooms that the user has been invited to or has joined are + included. If set to ``true`` then rooms that the user has left are + included as well. By default this is ``false``. + required: false + x-example: "true" responses: 200: description: The user's current state. diff --git a/specification/1-client_server_api.rst b/specification/1-client_server_api.rst index b96b4bb3..96f62c9b 100644 --- a/specification/1-client_server_api.rst +++ b/specification/1-client_server_api.rst @@ -491,6 +491,100 @@ medium address The textual address of the 3pid, eg. the email address +Pagination +---------- + +.. NOTE:: + The paths referred to in this section are not actual endpoints. They only + serve as examples to explain how pagination functions. + +Pagination is the process of dividing a dataset into multiple discrete pages. +Matrix makes use of pagination to allow clients to view extremely large datasets. +These datasets are not limited to events in a room (for example clients may want +to paginate a list of rooms in addition to events within those rooms). Regardless +of *what* is being paginated, there is a common underlying API which is used to +to give clients a consistent way of selecting subsets of a potentially changing +dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters +which describe where to read from the stream. ``from`` and ``to`` are opaque +textual 'stream tokens' which describe the current position in the dataset. +The ``dir`` parameter is an enum representing the direction of events to return: +either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and +``end`` stream token values which can then be passed to subsequent requests to +continue pagination. Not all endpoints will make use of all the parameters +outlined here: see the specific endpoint in question for more information. + +Pagination Request Query Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Query parameters: + from: + $streamtoken - The opaque token to start streaming from. + to: + $streamtoken - The opaque token to end streaming at. Typically, + clients will not know the item of data to end at, so this will usually be + omitted. + limit: + integer - An integer representing the maximum number of items to + return. + dir: + f|b - The direction to return events in. Typically this is ``b`` to paginate + backwards in time. + +'START' and 'END' are placeholder values used in these examples to describe the +start and end of the dataset respectively. + +Unless specified, the default pagination parameters are ``from=START``, +``to=END``, without a limit set. + +For example, if an endpoint had events E1 -> E15. The client wants the last 5 +events and doesn't know any previous events:: + + S E + |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-| + | | | + | _____| <--backwards-- | + |__________________ | | ________| + | | | | + GET /somepath?to=START&limit=5&dir=b&from=END + Returns: + E15,E14,E13,E12,E11 + + +Another example: a public room list has rooms R1 -> R17. The client is showing 5 +rooms at a time on screen, and is on page 2. They want to +now show page 3 (rooms R11 -> 15):: + + S E + | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | stream token + |-R1-R2-R3-R4-R5-R6-R7-R8-R9-R10-R11-R12-R13-R14-R15-R16-R17| room + |____________| |________________| + | | + Currently | + viewing | + | + GET /roomslist?from=9&to=END&limit=5 + Returns: R11,R12,R13,R14,R15 + +Note that tokens are treated in an *exclusive*, not inclusive, manner. The end +token from the initial request was '9' which corresponded to R10. When the 2nd +request was made, R10 did not appear again, even though from=9 was specified. If +you know the token, you already have the data. + +Pagination Response +~~~~~~~~~~~~~~~~~~~ + +Responses to pagination requests MUST follow the format:: + + { + "chunk": [ ... , Responses , ... ], + "start" : $streamtoken, + "end" : $streamtoken + } + +Where $streamtoken is an opaque token which can be used in another query to +get the next set of results. The "start" and "end" keys can only be omitted if +the complete dataset is provided in "chunk". + Events ------ @@ -563,8 +657,14 @@ returning early if an event occurs. Only the events API supports long-polling. All events which are visible to the client will appear in the events API. When the request returns, an ``end`` token is included in the response. This token can be used in the next request to continue where the -last request left off. Multiple events can be returned per long-poll. All events -must be de-duplicated based on their event ID. +last request left off. Multiple events can be returned per long-poll. + +.. Warning:: + Events are ordered in this API according to the arrival time of the event on + the homeserver. This can conflict with other APIs which order events based on + their partial ordering in the event graph. This can result in duplicate events + being received (once per API call). Clients SHOULD de-duplicate events based + on the event ID when this happens. .. TODO is deduplication actually a hard requirement in CS v2? @@ -573,8 +673,8 @@ must be de-duplicated based on their event ID. Do we ever support streaming requests? Why not websockets? When the client first logs in, they will need to initially synchronise with -their home server. This is achieved via the initial sync API. This API also -returns an ``end`` token which can be used with the event stream. +their home server. This is achieved via the initial sync API described below. +This API also returns an ``end`` token which can be used with the event stream. {{sync_http_api}} @@ -667,6 +767,9 @@ There are several APIs provided to ``GET`` events for a room: {{rooms_http_api}} + +{{message_pagination_http_api}} + Redactions ~~~~~~~~~~ Since events are extensible it is possible for malicious users and/or servers @@ -712,105 +815,6 @@ The redaction event should be added under the key ``redacted_because``. When a client receives a redaction event it should change the redacted event in the same way a server does. -Pagination ----------- - -.. NOTE:: - The paths referred to in this section are not actual endpoints. They only - serve as examples to explain how pagination functions. - -Pagination is the process of dividing a dataset into multiple discrete pages. -Matrix makes use of pagination to allow clients to view extremely large datasets. -These datasets are not limited to events in a room (for example clients may want -to paginate a list of rooms in addition to events within those rooms). Regardless -of *what* is being paginated, there is a common underlying API which is used to -to give clients a consistent way of selecting subsets of a potentially changing -dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters -which describe where to read from the stream. ``from`` and ``to`` are opaque -textual 'stream tokens' which describe the current position in the dataset. -The ``dir`` parameter is an enum representing the direction of events to return: -either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and -``end`` stream token values which can then be passed to subsequent requests to -continue pagination. Not all endpoints will make use of all the parameters -outlined here: see the specific endpoint in question for more information. - -Pagination Request Query Parameters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Query parameters: - from: - $streamtoken - The opaque token to start streaming from. - to: - $streamtoken - The opaque token to end streaming at. Typically, - clients will not know the item of data to end at, so this will usually be - omitted. - limit: - integer - An integer representing the maximum number of items to - return. - dir: - f|b - The direction to return events in. Typically this is ``b`` to paginate - backwards in time. - -'START' and 'END' are placeholder values used in these examples to describe the -start and end of the dataset respectively. - -Unless specified, the default pagination parameters are ``from=START``, -``to=END``, without a limit set. - -For example, if an endpoint had events E1 -> E15. The client wants the last 5 -events and doesn't know any previous events:: - - S E - |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-| - | | | - | _____| <--backwards-- | - |__________________ | | ________| - | | | | - GET /somepath?to=START&limit=5&dir=b&from=END - Returns: - E15,E14,E13,E12,E11 - - -Another example: a public room list has rooms R1 -> R17. The client is showing 5 -rooms at a time on screen, and is on page 2. They want to -now show page 3 (rooms R11 -> 15):: - - S E - | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | stream token - |-R1-R2-R3-R4-R5-R6-R7-R8-R9-R10-R11-R12-R13-R14-R15-R16-R17| room - |____________| |________________| - | | - Currently | - viewing | - | - GET /roomslist?from=9&to=END&limit=5 - Returns: R11,R12,R13,R14,R15 - -Note that tokens are treated in an *exclusive*, not inclusive, manner. The end -token from the initial request was '9' which corresponded to R10. When the 2nd -request was made, R10 did not appear again, even though from=9 was specified. If -you know the token, you already have the data. - -Pagination Response -~~~~~~~~~~~~~~~~~~~ - -Responses to pagination requests MUST follow the format:: - - { - "chunk": [ ... , Responses , ... ], - "start" : $streamtoken, - "end" : $streamtoken - } - -Where $streamtoken is an opaque token which can be used in another query to -get the next set of results. The "start" and "end" keys can only be omitted if -the complete dataset is provided in "chunk". - -Pagination APIs -~~~~~~~~~~~~~~~ - -{{message_pagination_http_api}} - Rooms ----- From 62d53b4f3321d27cb0b3bc95e5b7625c1efe454d Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Fri, 16 Oct 2015 15:58:11 +0100 Subject: [PATCH 14/14] Review comments round III --- specification/client_server_api.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index 96f62c9b..ee70d9d3 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -663,11 +663,8 @@ last request left off. Multiple events can be returned per long-poll. Events are ordered in this API according to the arrival time of the event on the homeserver. This can conflict with other APIs which order events based on their partial ordering in the event graph. This can result in duplicate events - being received (once per API call). Clients SHOULD de-duplicate events based - on the event ID when this happens. - -.. TODO - is deduplication actually a hard requirement in CS v2? + being received (once per distinct API called). Clients SHOULD de-duplicate + events based on the event ID when this happens. .. TODO-spec Do we ever support streaming requests? Why not websockets?