More Instant Messaging Interoperability T. Ralston Internet-Draft M. Hodgson Intended status: Standards Track The Matrix.org Foundation C.I.C. Expires: 29 December 2023 27 June 2023 Linearized Matrix draft-ralston-mimi-linearized-matrix-02 Abstract This document specifies Linearized Matrix for use in messaging interoperability. About This Document This note is to be removed before publishing as an RFC. The latest revision of this draft can be found at https://turt2live.github.io/ietf-mimi-linearized-matrix/draft- ralston-mimi-linearized-matrix.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft- ralston-mimi-linearized-matrix/. Discussion of this document takes place on the More Instant Messaging Interoperability Working Group mailing list (mailto:mimi@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/mimi/. Subscribe at https://www.ietf.org/mailman/listinfo/mimi/. Source for this draft and an issue tracker can be found at https://github.com/turt2live/ietf-mimi-linearized-matrix. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 29 December 2023. Ralston & Hodgson Expires 29 December 2023 [Page 1] Internet-Draft Linearized Matrix June 2023 Copyright Notice Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4 3. Architecture . . . . . . . . . . . . . . . . . . . . . . . . 4 3.1. Server Names . . . . . . . . . . . . . . . . . . . . . . 6 3.2. Rooms . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2.1. Room Versions . . . . . . . . . . . . . . . . . . . . 7 3.3. Users . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.4. Devices . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.5. Events . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.5.1. Linearized PDU . . . . . . . . . . . . . . . . . . . 13 3.5.2. State Events . . . . . . . . . . . . . . . . . . . . 14 3.5.3. Event Types . . . . . . . . . . . . . . . . . . . . . 15 4. Initial Room Version . . . . . . . . . . . . . . . . . . . . 19 5. MLS Considerations . . . . . . . . . . . . . . . . . . . . . 20 6. Event Signing & Authorization . . . . . . . . . . . . . . . . 20 6.1. Receiving Events/PDUs . . . . . . . . . . . . . . . . . . 20 6.2. Rejection . . . . . . . . . . . . . . . . . . . . . . . . 22 6.3. Soft Failure . . . . . . . . . . . . . . . . . . . . . . 22 6.4. Authorization Rules . . . . . . . . . . . . . . . . . . . 22 6.4.1. Auth Events Selection . . . . . . . . . . . . . . . . 22 6.4.2. Auth Rules Algorithm . . . . . . . . . . . . . . . . 23 7. Signing . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 7.1. Signing Events . . . . . . . . . . . . . . . . . . . . . 27 7.2. Signing Arbitrary Objects . . . . . . . . . . . . . . . . 27 7.3. Checking Signatures . . . . . . . . . . . . . . . . . . . 28 8. Canonical JSON . . . . . . . . . . . . . . . . . . . . . . . 28 9. Event Redactions . . . . . . . . . . . . . . . . . . . . . . 28 10. Hashes . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 10.1. Content Hash Calculation . . . . . . . . . . . . . . . . 29 10.2. Reference Hash Calculation . . . . . . . . . . . . . . . 30 11. Unpadded Base64 . . . . . . . . . . . . . . . . . . . . . . . 30 12. Hub Transfers . . . . . . . . . . . . . . . . . . . . . . . . 30 Ralston & Hodgson Expires 29 December 2023 [Page 2] Internet-Draft Linearized Matrix June 2023 13. Transport . . . . . . . . . . . . . . . . . . . . . . . . . . 31 13.1. TLS Certificates . . . . . . . . . . . . . . . . . . . . 31 13.2. API Standards . . . . . . . . . . . . . . . . . . . . . 31 13.2.1. Requests and Responses . . . . . . . . . . . . . . . 31 13.2.2. Errors . . . . . . . . . . . . . . . . . . . . . . . 32 13.2.3. Unsupported Endpoints . . . . . . . . . . . . . . . 33 13.2.4. Malformed Requests . . . . . . . . . . . . . . . . . 33 13.2.5. Transaction Identifiers . . . . . . . . . . . . . . 33 13.2.6. Rate Limiting . . . . . . . . . . . . . . . . . . . 33 13.3. Resolving Server Names . . . . . . . . . . . . . . . . . 34 13.3.1. GET /.well-known/matrix/server . . . . . . . . . . . 37 13.4. Request Authentication . . . . . . . . . . . . . . . . . 37 13.4.1. Retrieving Server Keys . . . . . . . . . . . . . . . 40 13.5. Sending Events . . . . . . . . . . . . . . . . . . . . . 44 13.5.1. PUT /_matrix/federation/v2/send/:txnId . . . . . . . 45 13.6. Event and State APIs . . . . . . . . . . . . . . . . . . 48 13.6.1. GET /_matrix/federation/v2/event/:eventId . . . . . 48 13.6.2. GET /_matrix/federation/v1/state/:roomId . . . . . . 49 13.6.3. GET /_matrix/federation/v1/state_ids/:roomId . . . . 51 13.6.4. GET /_matrix/federation/v2/backfill/:roomId . . . . 51 13.7. Room Membership . . . . . . . . . . . . . . . . . . . . 52 13.7.1. Make and Send Handshake . . . . . . . . . . . . . . 54 13.7.2. Invites . . . . . . . . . . . . . . . . . . . . . . 56 13.7.3. Joins . . . . . . . . . . . . . . . . . . . . . . . 62 13.7.4. Knocks . . . . . . . . . . . . . . . . . . . . . . . 65 13.8. Content Repository . . . . . . . . . . . . . . . . . . . 68 13.9. TODO: Remainder of Transport . . . . . . . . . . . . . . 68 13.9.1. Open Questions . . . . . . . . . . . . . . . . . . . 68 14. User Privacy . . . . . . . . . . . . . . . . . . . . . . . . 68 15. Spam Prevention . . . . . . . . . . . . . . . . . . . . . . . 69 16. Security Considerations . . . . . . . . . . . . . . . . . . . 69 17. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 69 18. References . . . . . . . . . . . . . . . . . . . . . . . . . 70 18.1. Normative References . . . . . . . . . . . . . . . . . . 70 18.2. Informative References . . . . . . . . . . . . . . . . . 72 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 73 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 73 1. Introduction Alongside messaging, Matrix operates as an openly federated communications protocol for VoIP, IoT, and more. The existing Matrix network uses fully decentralized access control within rooms (conversations) and is highly extensible in its structure. These features are not critically important to a strict focus on messaging interoperability, however. Ralston & Hodgson Expires 29 December 2023 [Page 3] Internet-Draft Linearized Matrix June 2023 This document specifies "Linearized Matrix": a modified room model based upon Matrix's existing room model. This document does _not_ explore how to interconnect Linearized Matrix with the existing Matrix room model - interested readers may wish to review [MSC3995] within the Matrix Specification process. At a high level, a central server is designated as the "hub" server, responsible for ensuring events in a given room are provided to all other participants equally. Servers communicate with each other over HTTPS and JSON, using the specified API endpoints. 2. Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. This document uses [I-D.ralston-mimi-terminology] where possible. This document additionally uses the following definitions: * *Room*: Synonymous with "conversation" from I-D.ralston-mimi- terminology. * *Room Member*: Synonymous with "conversation member" from I- D.ralston-mimi-terminology. * *State Event*: Synonymous with "conversation property" from I- D.ralston-mimi-terminology. A state event is a subclass of an event. Further terms are introduced in-context within this document. *TODO*: We should move/copy those definitions up here anyways. 3. Architecture For a given conversation/room: Ralston & Hodgson Expires 29 December 2023 [Page 4] Internet-Draft Linearized Matrix June 2023 .------------. .------------. | Client A | | Client B | '---------+--' '---------+--' ^ | ^ | | | Client-Server API | | | V | V +-----+------------+ +-----+------------+ | +----------( events )------->| | | Provider/Server | | Provider/Server | | A |<---------( events )--------+ B | +-----+------------+ Server-Server API +------------------+ | ^ | | +------------------+ | +----( events )--------+ | | | Provider/Server | +----------( events )------->| C | +------------+-----+ ^ | | | | V .--+---------. | Client C | '------------' In this diagram, Server A is acting as a hub for the other two servers. Servers B and C do not converse directly when sending events to the room: those events are instead sent to the hub which then distributes them back out to all participating servers. Clients are shown in the diagram here for demonstrative purposes only. No Client-Server API or other requirements of clients are specified in this document. This leads to two distinct roles: * *Hub server*: the server responsible for holding conversation history on behalf of other servers in the room. * *Participant server*: any non-hub server. This server is not required to persist conversation history as it can fetch it from the hub if needed. *OPEN QUESTION*: Should we support having multiple hubs for increased trust between participant and hub? (participant can pick the hub it wants to use rather than being forced to use a single hub) Ralston & Hodgson Expires 29 December 2023 [Page 5] Internet-Draft Linearized Matrix June 2023 3.1. Server Names Each server has a "domain name" or "server name" to uniquely identify it. This server name is then used to namespace user IDs, room IDs/ aliases, etc. A server name MUST be compliant with Section 2.1 of [RFC1123] and, when an IPv6 address, encoded per Section 2.2 of [RFC4291] surrounded by square brackets ([]). Improper server names MUST be considered "uncontactable" by a server. A server SHOULD NOT use a literal IPv4 or IPv6 address as a server name. Doing so reduces the ability for the server to move to another internet address later, and IP addresses are generally difficult to acquire certificates for (required in Section 13). Additionally, servers SHOULD NOT use an explicit port in their server name for similar portability reasons. The approximate ABNF [RFC5234] grammar for a server name is: server_name = hostname [ ":" port ] port = 1*5DIGIT hostname = IPv4address / "[" IPv6address "]" / dns-name IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT IPv6address = 2*45IPv6char IPv6char = DIGIT / %x41-46 / %x61-66 / ":" / "." ; 0-9, A-F, a-f, :, . dns-name = 1*255dns-char dns-char = DIGIT / ALPHA / "-" / "." Server names MUST be treated as case sensitive (eXaMpLe.OrG, example.org, and EXAMPLE.ORG are 3 different servers). Server names SHOULD be lower case (example.org) and SHOULD NOT exceed 230 characters for ease of use. The 230 characters specifically gives room for a suitably long localpart while being within the 255 allowable characters from Section 2.1 of [RFC1123]. Examples: * example.org (DNS host name) * example.org:5678 (DNS host name with explicit port) * 127.0.0.1 (literal IPv4 address) * 127.0.0.1:5678 (literal IPv4 address with explicit port) * [2001:DB8:0:0:8:800:200C:417A] (literal IPv6 address) Ralston & Hodgson Expires 29 December 2023 [Page 6] Internet-Draft Linearized Matrix June 2023 * [2001:DB8:0:0:8:800:200C:417A]:5678 (literal IPv6 address with explicit port) 3.2. Rooms Rooms hold the same definition under [I-D.ralston-mimi-terminology]: a conceptual place where users send and receive events. All users with sufficient access to the room receive events sent to that room. The different chat types are represented by rooms through state events (Section 3.5.2), which ultimately change how the different algorithms in the room version (Section 3.2.1) behave. Rooms have a single internal "Room ID" to identify them from another room. The ABNF [RFC5234] grammar for a room ID is: room_id = "!" room_id_localpart ":" server_name room_id_localpart = 1*opaque opaque = DIGIT / ALPHA / "-" / "." / "~" / "_" server_name is inherited from Section 3.1. room_id MUST NOT exceed 255 characters and MUST be treated as case sensitive. Example: !abc:example.org. The server_name for a room ID does _NOT_ indicate the room is "hosted" or served by that domain. The domain is used as a namespace to prevent another server from maliciously taking over a room. The server represented by that domain may no longer be participating in the room. The entire room ID after the ! sigil MUST be treated as opaque. No part of the room ID should be parsed, and cannot be assumed to be human-readable. 3.2.1. Room Versions *TODO*: We should consider naming this something else. A room version is a set of algorithms which define how the room operates, identified by a single string. Room versions are immutable once specified, as otherwise a change in algorithms could cause a split-brain between participating servers. Ralston & Hodgson Expires 29 December 2023 [Page 7] Internet-Draft Linearized Matrix June 2023 Room versions prefixed with I. MUST only be used within the IETF specification process. Room versions consisting solely of 0-9 and . MUST only be used by the Matrix protocol. There is no implicit ordering or hierarchy to room versions. Although there is a recommended default room version, some rooms might benefit from features of a different room version. A room version has the following algorithms defined: * Event authorization - Rules which govern when events are accepted, rejected, or soft-failed by a server. * Redaction - Description of which fields to keep on an event during redaction. Redaction is used by the signing and hash algorithms, meaning they need to be consistent across implementations. * Event format - Which fields are expected to be present on an event, and the schema for each. * Canonical JSON - Specific details about how to canonicalize an event as JSON. This is used by the signing algorithm and must be consistent between implementations. * Hub selection - Rules around picking the hub server and transferring to a new hub. * Identifier grammar - All identifiers (room IDs, user IDs, event IDs, etc) can change grammar within a room version. As such, they SHOULD generally be treated as opaque as possible over a transport. A server is capable of supporting multiple room versions at a time. The transport API decouples specific details regarding room versions from the wire formats. For example, events are treated as JSON blobs in this document's Server-Server API (Section 13). Room versions are normally specified using a dedicated document. An example of this can be found in the existing Matrix Spec Change process as [MSC3820]. Each room version has a "stable" or "unstable" designation. Stable room versions SHOULD be used in production by messaging providers. Unstable room versions might contain bugs or are not yet fully specified and SHOULD NOT be used in production by messaging providers. Ralston & Hodgson Expires 29 December 2023 [Page 8] Internet-Draft Linearized Matrix June 2023 *TODO*: Matrix considers a version as stable once accepted through FCP. When would be the process equivalent for the IETF? The ABNF [RFC5234] grammar for a room version is: room_version = 1*128room_version_char room_version_char = DIGIT / %x61-7A ; a-z / "-" / "." Examples: * 1 * I.1 * org.example.my-room-version Room versions not formally specified SHOULD be prefixed using reverse domain name notation, creating a sort of namespace. org.example.my- room-version is an example of this. 3.3. Users As described by [I-D.ralston-mimi-terminology], a user is typically a human which operates a client. Each user has a distinct user ID. The ABNF [RFC5234] grammar for a user ID is: user_id = "@" user_id_localpart ":" server_name user_id_localpart = 1*user_id_char user_id_char = DIGIT / %x61-7A ; a-z / "-" / "." / "=" / "_" / "/" / "+" server_name is inherited from Section 3.1. user_id MUST NOT exceed 255 characters and MUST be treated as case sensitive. Examples: * @alice:example.org * @watch/for/slashes:example.org Ralston & Hodgson Expires 29 December 2023 [Page 9] Internet-Draft Linearized Matrix June 2023 user_id_localpart SHOULD be human-readable and notably MUST NOT contain uppercase letters. server_name denotes the domain name (Section 3.1) which allocated the ID, or would allocate the ID if the user doesn't exist yet. Identity systems and messaging providers SHOULD NOT use a phone number in a localpart, as the localpart for a user ID is unchangeable. In these cases, a GUID (scoped to the allocating server) is recommended so the associated human can change their phone number without losing chats. This document does not define how a user ID is acquired. It is expected that an identity specification under MIMI will handle resolving email addresses, phone numbers, names, and other common queries to user IDs. User IDs are sometimes informally referenced as "MXIDs", short for "Matrix User IDs". 3.4. Devices Each user can have zero or more devices/active clients. These devices are intended to be members of the MLS group and thus have their own key package material associated with them. *TODO*: Do we need to define grammar and such for device IDs, or is that covered by MLS already? 3.5. Events All data exchanged over Linearized Matrix is expressed as an "event". Each client action (such as sending a message) correlates with exactly one event. All events have a type to distinguish them, and use reverse domain name notation to namespace custom events (for example, org.example.appname.eventname). Event types using m. as a prefix MUST only be used by the protocol. When events are traversing a transport to another server they are referred to as a *Persistent Data Unit* or *PDU*. Structurally, an event and PDU are the same. An event has the following minimum fields: * room_id (string; required) - The room ID for where the event is being sent. This MUST be a valid room ID (Section 3.2). Ralston & Hodgson Expires 29 December 2023 [Page 10] Internet-Draft Linearized Matrix June 2023 * type (string; required) - A UTF-8 [RFC3629] string to distinguish different data types being carried by events. Event types are case sensitive. This MUST NOT exceed 255 characters. * state_key (string; optional) - A UTF-8 [RFC3629] string to further distinguish an event type from other related events. Only specified on State Events (Section 3.5.2). Can be empty. This MUST NOT exceed 255 characters. * sender (string; required) - The user ID which is sending this event. This MUST be a valid user ID (Section 3.3). * origin_server_ts (integer; required) - The milliseconds since the unix epoch for when this event was created. * hub_server (string; technically optional) - The domain name of the hub server which is sending this event to the remainder of the room. All events created within Linearized Matrix MUST have this field set, however events created externally MUST NOT set this field. This MUST be a valid server name (Section 3.1). * content (object; required) - The event content. The specific schema depends on the event type. Clients and servers processing an event MUST NOT assume the content is safe or accurately represented. Malicious clients and servers are able to send payloads which don't comply with a given schema, which may cause unexpected behaviour on the receiving side. For example, a field marked as "required" might be missing. * hashes (object; required) - The _content hashes_ for the event. The lpdu key within this object is an object itself, keyed by hash algorithm with value being the encoded hash. Similarly, outside of lpdu, hashes is keyed by hash algorithm with value being the encoded hash. Events created within Linearized Matrix MUST specify an LPDU hash, however events created externally MUST NOT set such a hash. * signatures (object; required) - Keyed first by domain name then by key ID, the signatures for the event. * auth_events (array of strings; required) - The event IDs which prove the sender is able to send this event in the room. Which specific events are put here are defined by the auth events selection algorithm (Section 6.4.1). Ralston & Hodgson Expires 29 December 2023 [Page 11] Internet-Draft Linearized Matrix June 2023 * prev_events (array of strings; required) - The event IDs which precede the event. Events created within Linearized Matrix MUST only ever have a single event ID here, however events created externally MAY have one or more referenced event IDs. * unsigned (object; optional) - Additional metadata not covered by the signing algorithm. Like content, a receiver MUST NOT trust the values to match any particular schema. Note that an event ID is not specified on the schema. Event IDs are calculated to ensure accuracy and consistency between servers. To determine the ID for an event, calculate the reference hash (Section 10.2) then encode it using URL-safe Unpadded Base64 (Section 11) and prefix that with the event ID sigil, $. For example, $nKHVqt3iyLA_HEE8lT1yUaaVjjBRR-fAqpN4t7opadc. The ABNF [RFC5234] for an event ID is: event_id = "$" reference_hash reference_hash = 1*urlsafe_unpadded_base64_char urlsafe_unpadded_base64_char = ALPHA / DIGIT / "-" / "_" If both the sender and receiver are implementing the algorithms correctly, the event ID will be the same. When different, the receiver will have issues accepting the event (none of the auth_events will make sense, for example). The sender and receiver will need to review that their implementation matches the specification in this case. Events are treated as JSON [RFC8259] within the protocol, but can be encoded and represented by any binary-compatible format. Additional overhead may be introduced when converting between formats, however. An example event is: Ralston & Hodgson Expires 29 December 2023 [Page 12] Internet-Draft Linearized Matrix June 2023 { "room_id": "!abc:example.org", "type": "m.room.member", "state_key": "@alice:first.example.org", "sender": "@bob:second.example.org", "origin_server_ts": 1681340188825, "hub_server": "first.example.org", "content": { "membership": "invite" }, "hashes": { "lpdu": { "sha256": "" }, "sha256": "" }, "signatures": { "first.example.org": { "ed25519:1": "" }, "second.example.org": { "ed25519:1": "" } }, "auth_events": ["$first", "$second"], "prev_events": ["$parent"], "unsigned": { "arbitrary": "fields" } } An event/PDU MUST NOT exceed 65536 bytes when formatted using Canonical JSON (Section 8). Note that this includes all signatures on the event. Fields have no size limit unless specified above, other than the maximum 65536 bytes for the whole event. 3.5.1. Linearized PDU The hub server is responsible for ensuring events are linearly added to the room from all participants, which means participants cannot set fields such as prev_events on their events. Additionally, participant servers are not expected to store past conversation history or even "current state" for the room, further making participants unable to reliably populate auth_events and prev_events. Ralston & Hodgson Expires 29 December 2023 [Page 13] Internet-Draft Linearized Matrix June 2023 To avoid these problems, the participant server MUST NOT populate the following fields on events they are sending to the hub: * auth_events - the participant cannot reliably determine what allows it to send the event. * prev_events - the participant cannot reliably know what event precedes theirs. * hashes (except hashes.lpdu) - top-level hashes cover the above two fields. The participant server MUST populate the hashes.lpdu object, covering a content hash (Section 10.1) of the partial event, giving authenticity to the sender's contents. The participant server additionally signs this partial event before sending it to the hub. The participant server will receive an echo of the fully-formed event from the hub once appended to the room. 3.5.2. State Events State events track metadata for the room, such as name, topic, and members. State is keyed by a tuple of type and state_key, noting that an empty string is a valid state key. State in the room with the same key-tuple will be overwritten as "current state". State events are otherwise processed like regular events in the room: they're appended to the room history and can be referenced by that room history. "Current state" is the state at the time being considered (which is often the implied HEAD of the room). In Linearized Matrix, a simple approach to calculating current state is to iterate over all events in order, overwriting the key-tuple for state events in an adjacent map. That map becomes "current state" when the loop is finished. 3.5.2.1. Stripped State Stripped state event are extremely simplified state events to provide context to an invite or knock. Servers MUST NOT rely on stripped state events being accurate, only using them if the server doesn't have access to the room's real state. When generating stripped state for an invite or knock, the following events SHOULD be included if present in the current room state itself: Ralston & Hodgson Expires 29 December 2023 [Page 14] Internet-Draft Linearized Matrix June 2023 * m.room.create (Section 3.5.3.1) * m.room.name (*TODO*: Link) * m.room.avatar (*TODO*: Link) * m.room.topic (*TODO*: Link) * m.room.join_rules (Section 3.5.3.2) * m.room.canonical_alias (*TODO*: Link) * m.room.encryption (*TODO*: Link) Servers MAY include other event types/state keys. The above set gives users enough context to determine if they'd like to knock/join the room, as features such as the name and avatar are generally key pieces of information for a user. Stripped state events MUST only have sender, type, state_key, and content from the event schema (Section 3.5). Example: { "type": "m.room.create", "sender": "@alice:example.org", "state_key": "", "content": { "room_version": "I.1" } } 3.5.3. Event Types Linearized Matrix defines the following event types. The section headers are the event type. 3.5.3.1. m.room.create The very first event in the room. It MUST NOT have any auth_events or prev_events, and the domain of the sender MUST be the same as the domain in the room_id. The state_key MUST be an empty string. The content for a create event MUST have at least a room_version field to denote what set of algorithms the room is using. Ralston & Hodgson Expires 29 December 2023 [Page 15] Internet-Draft Linearized Matrix June 2023 These conditions are checked as part of the event authorization rules (Section 6.4). 3.5.3.2. m.room.join_rules Defines whether users can join without an invite and other similar conditions. The state_key MUST be an empty string. Any other state key, including lack thereof, serve no meaning and are treated as though they were a custom event. The content for a join rules event MUST have at least a join_rule field to denote the join policy for the room. Allowable values are: * public - anyone can join without an invite. * knock - users must receive an invite to join, and can request an invite (knock) too. * invite - users must receive an invite to join. *TODO*: Describe restricted (and knock_restricted) rooms? *TODO*: What's the default? 3.5.3.3. m.room.member Defines the membership for a user in the room. If the user does not have a membership event then they are presumed to be in the leave state. The state_key MUST be a non-empty string denotating the user ID the membership is affecting. The content for a membership event MUST have at least a membership field to denote the membership state for the user. Allowable values are: * leave - not participating in the room. If the state_key and sender do not match, this was a kick rather than voluntary leave. * join - participating in the room. * knock - requesting an invite to the room. * invite - invited to participate in the room. Ralston & Hodgson Expires 29 December 2023 [Page 16] Internet-Draft Linearized Matrix June 2023 * ban - implies kicked/not participating. Cannot be invited or join the room without being unbanned first (moderator sends a kick, essentially). These conditions are checked as part of the event authorization rules (Section 6.4), as are the rules for moving between membership states. The content for a membership event MAY additionally have a reason field containing a human-readable (and usually human-supplied) description for why the membership change happened. For example, the reason why a user was kicked/banned or why they are requesting an invite by knocking. 3.5.3.4. m.room.power_levels Defines what given users can and can't do, as well as which event types they are able to send. The enforcement of these power levels is determined by the event authorization rules (Section 6.4). The state_key MUST be an empty string. The content for a power levels event SHOULD have at least the following: * ban (integer) - the level required to ban a user. Defaults to 50 if unspecified. * kick (integer) - the level required to kick a user. Defaults to 50 if unspecified. * invite (integer) - the level required to invite a user. Defaults to 0 if unspecified. * redact (integer) - the level required to redact an event sent by another user. Defaults to 50 if unspecified. * events (map) - keyed by event type string, the level required to send that event type to the room. Defaults to an empty map if unspecified. * events_default (integer) - the level required to send events in the room. Overridden by the events map. Defaults to 0 if unspecified. * state_default (integer) - the level required to send state events in the room. Overridden by the events map. Defaults to 50 if unspecified. Ralston & Hodgson Expires 29 December 2023 [Page 17] Internet-Draft Linearized Matrix June 2023 * users (map) - keyed by user ID, the level of that user. Defaults to an empty map if unspecified. * users_default (integer) - the level for users. Overridden by the users map. Defaults to 0 if unspecified. *TODO*: Include notifications for at-room here too? Note that if no power levels event is specified in the room then the room creator (sender of the m.room.create state event) has a default power level of 100. These conditions are checked as part of the event authorization rules (Section 6.4). 3.5.3.4.1. Calculating Power Levels All power levels are calculated with reference to the content of an m.room.power_levels state event. To calculate a user's current power level: 1. If users is present, use the power level for the user ID, if present. 2. If users is not present, or the user ID is not present in users, use users_default. 3. If users_default is not present, use 0. To calculate the required power level to do an action: 1. If the action (kick, ban, invite, or redact) is present, use that power level. 2. If not present, use the default for the action (50 for kick, ban, and redact, 0 for invite). To calculate the required power level to send an event: 1. If events is present, use the power level for the event type, if present. 2. If events is not present, or the event type is not present in events: 1. If state_key is present (including empty), use state_default. Ralston & Hodgson Expires 29 December 2023 [Page 18] Internet-Draft Linearized Matrix June 2023 1. If state_default is not specified, use 50. 2. If state_key is not present, use events_default. 1. If events_default is not specified, use 0. 3.5.3.5. m.room.history_visibility *TODO*: Describe. 3.5.3.5.1. Calculating Event Visibility *TODO*: Describe. (when can a server see an event?) 3.5.3.6. TODO: Other events *TODO*: m.room.name, m.room.topic, m.room.avatar, m.room.encryption, m.room.canonical_alias *TODO*: Drop m.room.encryption and pack it into the create event instead? 4. Initial Room Version Room versions are described by Section 3.2.1. As a whole, this document describes the I.1 room version. Future room versions can build upon this version's principles (or entirely replace them) through dedicated documents. Servers MUST implement support for I.1, and SHOULD implement other specified room versions as needed. Servers SHOULD use I.1 when creating new rooms. I.1 shall be considered "stable". *Implementation note*: Currently I.1 is not a real thing. Use org.matrix.i-d.ralston-mimi-linearized-matrix.02 when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *Implementation note*: org.matrix.i-d.ralston-mimi-linearized- matrix.00 also exists in the wild, defining a set of algorithms which exist in a prior version of this document (00 and 01). *TODO*: Remove implementation notes. The hub server MUST enforce the room version's algorithms upon the room. Participant servers SHOULD enforce the room version's algorithm, but can opt to believe the hub server if they wish. Ralston & Hodgson Expires 29 December 2023 [Page 19] Internet-Draft Linearized Matrix June 2023 5. MLS Considerations MIMI has a chartered requirement to use Messaging Layer Security (MLS) [I-D.ietf-mls-protocol] [I-D.ietf-mls-architecture] for encryption, and MLS requires that all group members (devices) know of all other devices. Each room has a single MLS Group associated with it, starting with the m.room.create event. *TODO*: Details on how key material is stored/shared within the room. *TODO*: What does m.room.encrypted (user message) look like here? 6. Event Signing & Authorization An event has several authenticity properties: * Content hashes (Section 10.1) to cover the LPDU (Section 3.5.1) and event (Section 3.5) contents. * Reference hashes (Section 10.2) which double as the event ID, covering the redacted event. * Signatures from the direct senders (server name of the sender and the hub_server if present), ensuring the entities did actually produce that event. *TODO*: Does the hub's signature actually guard anything? These properties are validated throughout this document. Each property has different behaviour when violated. For example, a difference in content hash ultimately causes the event to be stored as a redacted copy. 6.1. Receiving Events/PDUs When a hub receives an LPDU from a participant it MUST add the missing fields to create a fully formed PDU then MUST send that PDU back out to all participants, including the original sender. A server is considered to have "received" an event when it sees it for the first time. This might be because the server specifically reached out to fetch that specific event, or because the server was pushed that event through normal operation. When a server (hub or participant) receives an event, it MUST: Ralston & Hodgson Expires 29 December 2023 [Page 20] Internet-Draft Linearized Matrix June 2023 1. Verify the event is in a valid shape (Section 3.5). In practice, this means ensuring the overall schema for an event is applied, without considering specific schemas for content. For example, ensuring a type is present, a string, and less than 255 characters. If an event fails to meet this requirement, it is dropped/ignored. 2. Ensure the required signatures are present and that they are valid (Section 7.3). If the event has a hub_server field, the event MUST be signed by that server. The event MUST also be signed by the server implied by the sender, noting that this will be an LPDU if hub_server is present. All other signatures MUST NOT be considered for signature validation, regardless of their individual validity. If the event fails to meet this requirement, it is dropped/ignored. 3. Ensure the event has a valid content hashes (Section 10.1). If the event has a hub_server field, it MUST have a content hash which covers the LPDU. If either the LPDU or PDU content hash doesn't match what the receiving server calculations, the event is redacted before further processing. The server will ultimately persist the redacted copy. Additionally, a hub server MUST complete the following checks. Participant servers SHOULD also complete the checks to validate the hub's behaviour. 1. Ensure the event is not referencing rejected (Section 6.2) events. If it is, it is rejected itself. 2. Ensure the event passes the authorization rules (Section 6.4) for the state identified by the event's auth_events. If it fails, it is rejected (Section 6.2). 3. Ensures the event passes the authorization rules (Section 6.4) for the state of the room immediately before where the event would be inserted. If it fails, it is rejected (Section 6.2). *TODO*: Clarify that this step only applies if you're on the DAG side. On LM, this is the same as Step 6. We may need to adjust the rejection/soft-fail logic. 4. Ensures the event passes the authorization rules (Section 6.4) for the current state of the room (which may very well be the same as the step above). If it fails, it is soft-failed (Section 6.3). Ralston & Hodgson Expires 29 December 2023 [Page 21] Internet-Draft Linearized Matrix June 2023 6.2. Rejection Events which are rejected are not relayed to any local clients and are not appended to the room in any way. Events which reference rejected events through prev_events or auth_events are rejected themselves. Servers which utilize persistence (hub servers) SHOULD persist rejections to make this check faster. 6.3. Soft Failure When an event is "soft-failed" it should not be relayed to any local clients nor be used in auth_events. The event is otherwise handled as per usual. *TODO*: With a linearized DAG, do we have a choice to not use the event in auth_events? 6.4. Authorization Rules These are the rules which govern whether an event is accepted into the room, depending on the state events surrounding that event. A given event is checked against multiple different sets of state. 6.4.1. Auth Events Selection The auth_events on an event MUST consist of the following state events, with the exception of an m.room.create event which has no auth_events. 1. The m.room.create state event. 2. The current m.room.power_levels state event, if any. 3. The sender's current m.room.member state event, if any. 4. If the type is m.room.member: 1. The target's (state_key) current m.room.member state event, if any. 2. If content.membership is join or invite, the current m.room.join_rules state event, if any. *TODO*: Talk about restricted room joins here? Ralston & Hodgson Expires 29 December 2023 [Page 22] Internet-Draft Linearized Matrix June 2023 6.4.2. Auth Rules Algorithm With consideration for default/calculated power levels (Section 3.5.3.4.1), the ordered rules which affect authorization of a given event are as follows. See Section 6.2 for a description of "reject". *TODO*: should we reference m.federate? 1. Events must be signed (Section 7.3) by the server denoted by the sender field. Note that this may be an LPDU if the hub_server is specified and not the same server. 2. If hub_server is present, events must be signed (Section 7.3) by that server. 3. If type is m.room.create: 1. If it has any prev_events, reject. 2. If the domain of the room_id is not the same domain as the sender, reject. 3. If content.room_version is not I.1, reject. 4. Otherwise, allow. 4. Considering the event's auth_events: 1. If there are duplicate entries for a given type and state_key pair, reject. 2. If there are entries whose type and state_key do not match those specified by the auth events selection algorithm (Section 6.4.1), reject. 3. If there are entries where the referenced event was rejected during receipt (Section 6.2), reject. 4. If there is no m.room.create event among the entries, reject. 5. If type is m.room.member: 1. If there is no state_key property, or no membership in content, reject. Ralston & Hodgson Expires 29 December 2023 [Page 23] Internet-Draft Linearized Matrix June 2023 2. If membership is join: 1. If the previous event is an m.room.create event and the state_key is the creator, allow. 2. If sender does not match state_key, reject. 3. If the sender is banned, reject. 4. If the join_rule for m.room.join_rules is invite or knock, then allow if the current membership state is invite or join. 5. If the join_rule for m.room.join_rules is public, allow. 6. Otherwise, reject. 3. If membership is invite: 1. If the sender's current membership state is not join, reject. 2. If the target user's (state_key) membership is join or ban, reject. 3. If the sender's power level is greater than or equal to the power level needed to send invites, allow. 4. Otherwise, reject. 4. If membership is leave: 1. If the sender matches the state_key, allow if and only if that user's current membership state is knock, join, or invite. 2. If the sender's current membership state is not join, reject. 3. If the target user's (state_key) current membership state is ban, and the sender's power level is less than the power level needed to ban other users, reject. 4. If the sender's power level is greater than or equal to the power level needed to kick users, and the target user's (state_key) power level is less than the sender's, allow. Ralston & Hodgson Expires 29 December 2023 [Page 24] Internet-Draft Linearized Matrix June 2023 5. Otherwise, reject. 5. If membership is ban: 1. If the sender's current membership state is not join, reject. 2. If the sender's power level is greater than or equal to the power level needed to ban users, and the target user's (state_key) power level is less than the sender's power level, allow. 3. Otherwise, reject. 6. If membership is knock: 1. If the join_rule for m.room.join_rules is anything other than knock, reject. 2. If the sender does not match the state_key, reject. 3. If the sender's current membership state is not ban or join, allow. 4. Otherwise, reject. 7. Otherwise, the membership is unknown. Reject. 6. If the sender's current membership state is not join, reject. 7. If the event type's required power level is greater than the sender's power level, reject. 8. If the event has a state_key which starts with an @ and does not match the sender, reject. 9. If type is m.room.power_levels: 1. If any of the fields users_default, events_default, state_default, ban, redact, kick, or invite in content are present and not an integer, reject. 2. If events in content is present and not an object with values that are integers, reject. 3. If the users in content is present and not an object with valid user IDs as keys and integers as values, reject. Ralston & Hodgson Expires 29 December 2023 [Page 25] Internet-Draft Linearized Matrix June 2023 4. If there is no previous m.room.power_levels event in the room, allow. 5. For the fields users_default, events_default, state_default, ban, redact, kick, and invite, check if they were added, changed, or removed. For each found alteration: 1. If the current value is higher than the sender's current power level, reject. 2. If the new value is higher than the sender's current power level, reject. 6. For each entry being changed in or removed from events: 1. If the current value is higher than the sender's current power level, reject. 7. For each entry being added to or changed in events: 1. If the new value is greater than the sender's current power level, reject. 8. For each entry being changed in or removed from users, other than the sender's own entry: 1. If the current value is higher than the sender's current power level, reject. 9. For each entry being added to or changed in users: 1. If the new value is greater than the sender's current power level, reject. 10. Otherwise, allow. 10. Otherwise, allow. There are some consequences to these rules: * Unless you are already a member of the room, the only permitted operations (aside from the initial create/join) are being able to join public rooms, accept invites to rooms, and reject invites to rooms. Ralston & Hodgson Expires 29 December 2023 [Page 26] Internet-Draft Linearized Matrix June 2023 * To unban another user, the sender must have a power level greater than or equal to both the kick and ban power levels, _and_ greater than the target user's power level. *TODO*: If we want to enforce a single hub in a room, we'd do so here with auth rules. 7. Signing All servers, including hubs and participants, publish an ed25519 [RFC8032] signing key to be used by other servers when verifying signatures. *TODO*: Verify RFC reference. We might be using a slightly different ed25519 key today? See https://hdevalence.ca/blog/2020-10-04-its- 25519am Each key ID consists of an algorithm name and version. Signing keys MUST use an algorithm of ed25519 (and therefore MUST be an ed25519 key). The key version MUST be valid under the following ABNF [RFC5234]: key_version = 1*key_version_char key_version_char = ALPHA / DIGIT / "_" An algorithm and version combined is a "key ID", deliminated by : as per the following ABNF [RFC5234]: key_id = key_algorithm ":" key_version key_algorithm = "ed25519" Additional key algorithms may be supported by future documents. 7.1. Signing Events To sign an event: 1. Redact it (Section 9). 2. Sign the result as an arbitrary object (Section 7.2). 7.2. Signing Arbitrary Objects To sign an object: 1. Remove signatures and unsigned. 2. Encode the result with Canonical JSON (Section 8). Ralston & Hodgson Expires 29 December 2023 [Page 27] Internet-Draft Linearized Matrix June 2023 3. Using the relevant ed25519 signing key (usually the server's), sign the object. 4. Encode that signature under signatures using unpadded base64 (Section 11). Note that signatures is an object with keys being the entity which did the signing and value being the key ID to encoded signature pair. See Section 3.5 for details on the signatures structure for events specifically. 7.3. Checking Signatures If the signatures field is missing, doesn't contain the entity that is expected to have done the signing (usually a server name), doesn't have a known key ID, or is otherwise structurally invalid then the signature check fails. If decoding the base64 fails, the check fails. If the object is an event, redact (Section 9) it before continuing. If removing the signatures and unsigned properties, canonicalizing the JSON (Section 8), and verifying the signature fails, the check fails. Note that to verify the signature the server may need to fetch another server's key first (Section 13.4.1). Otherwise, the check passes. *TODO*: Which specific signatures are required? If a server has multiple signing keys, possibly a combination of new and old, do we require all or some of them to sign? 8. Canonical JSON When signing a JSON object, such as an event, it is important that the bytes be ordered in the same way for everyone. Otherwise, the signatures will never match. To canonicalize a JSON object, use [RFC8785]. *TODO*: Matrix currently doesn't use RFC8785, but it should (or similar). 9. Event Redactions All fields at the top level except the following are stripped from the event: Ralston & Hodgson Expires 29 December 2023 [Page 28] Internet-Draft Linearized Matrix June 2023 * type * room_id * sender * state_key * content * origin_server_ts * hashes * signatures * prev_events * auth_events * hub_server Additionally, some event types retain specific fields under the event's content. All other fields are stripped. * m.room.create retains all fields in content. * m.room.member retains membership. * m.room.join_rules retains join_rule. * m.room.power_levels retains ban, events, events_default, kick, redact, state_default, users, users_default, and invite. * m.room.history_visibility retains history_visibility. 10. Hashes An event is covered by two hashes: a content hash and a reference hash. The content hash covers the unredacted event to ensure it was not modified in transit. The reference hash covers the essential fields of the event, including content hashes, and serves as the event's ID. 10.1. Content Hash Calculation 1. Remove any existing unsigned and signatures fields. Ralston & Hodgson Expires 29 December 2023 [Page 29] Internet-Draft Linearized Matrix June 2023 1. If calculating an LPDU's content hash, remove any existing hashes field as well. 2. If _not_ calculating an LPDU's content hash, remove any existing fields under hashes except for lpdu. 2. Encode the object using canonical JSON. 3. Hash the resulting bytes with SHA-256 [RFC6234]. 4. Encode the hash using unpadded base64 (Section 11). 10.2. Reference Hash Calculation 1. Redact the event. 2. Remove signatures and unsigned fields. 3. Encode the object using canonical JSON. 4. Hash the resulting bytes with SHA-256 [RFC6234]. 5. Encode the hash using URL-safe unpadded base64 (Section 11). 11. Unpadded Base64 Throughout this document, "unpadded base64" is used to represent binary values as strings. Base64 is as specified by Section 4 of [RFC4648], and "unpadded base64" simply removes any = padding from the resulting string. Implementations SHOULD accept input with or without padding on base64 values, where possible. Section 5 of [RFC4648] describes _URL-safe_ base64. The same changes are adopted here. Namely, the 62nd and 63rd characters are replaced with - and _ respectively. The unpadded behaviour is as described above. 12. Hub Transfers *TODO*: This section, if we want a single canonical hub in the room. Some expected problems in this area are: who signs the transfer event? who _sends_ the transfer event? how does a transfer start? *TODO*: Is this section better placed in the MSC for now? Ralston & Hodgson Expires 29 December 2023 [Page 30] Internet-Draft Linearized Matrix June 2023 13. Transport This document specifies a wire transport which uses JSON [RFC8259] over HTTPS [RFC9110]. Servers MUST support a minimum of HTTP/2 [RFC9113] and TLS 1.3 [RFC8446]. 13.1. TLS Certificates Servers MUST provide a TLS certificate signed by a known Certificate Authority. Requesting servers are ultimately responsible for the Certificate Authorities they place trust in, however servers SHOULD trust authorities which would commonly be trusted by an operating system or web browser. 13.2. API Standards 13.2.1. Requests and Responses All HTTP POST and PUT endpoints require the sending server to supply a (potentially empty) JSON object as the request body. Requesting servers SHOULD supply a Content-Type header of application/json for such requests. All endpoints which require a server to respond with a JSON object MUST include a Content-Type header of application/json. All JSON data, in requests or responses, MUST be encoded using UTF-8 [RFC3629]. All endpoints in this document do _not_ support trailing slashes on them. When such a request is encountered, it MUST be handled as an unknown endpoint (Section 13.2.3). Examples include: * https://example.org/_matrix/path - valid. * https://example.org/_matrix/path/ - unknown/invalid. * https://example.org//_matrix/path - unknown/invalid (domain also can't have a trailing slash). * https://example.org//_matrix/path/ - doubly unknown/invalid. Servers (both hub and participants) MUST implement all endpoints unless otherwise specified. Ralston & Hodgson Expires 29 December 2023 [Page 31] Internet-Draft Linearized Matrix June 2023 Most endpoints have a version number as part of the path. This version number is that endpoint's version, allowing for breaking changes to be made to the schema of that endpoint. For clarity, the version number is _not_ representative of an API version. 13.2.2. Errors All errors are represented by an error code defined by this document and an accompanied HTTP status code. It is possible for a HTTP status code to map to multiple error codes, and it's possible for an error code to map to multiple HTTP status codes. When a server is returning an error to a caller, it MUST use the most appropriate error response defined by the endpoint. If no appropriate error response is specified, the server SHOULD use M_UNKNOWN as the error code and 500 Internal Server Error as the HTTP status code. Errors are represented as JSON objects, requiring a Content-Type: application/json response header: { "errcode": "M_UNKNOWN", "error": "Something went wrong." } errcode is required and denotes the error code. error is an optional human-readable description of the error. error can be as precise or vague as the responding server desires - the strings in this document are suggestions. Some common error codes are: * M_UNKNOWN - An unknown error has occurred. * M_FORBIDDEN - The caller is not permitted to access the resource. For example, trying to join a room the user does not have an invite for. * M_NOT_JSON - The request did not contain valid JSON. Must be accompanied by a 400 Bad Request HTTP status code. * M_BAD_JSON - The request did contain valid JSON, but it was missing required keys or was malformed in another way. Must be accompanied by a 400 Bad Request HTTP status code. * M_LIMIT_EXCEEDED - Too many requests have been sent. The caller should wait before trying the request again. Ralston & Hodgson Expires 29 December 2023 [Page 32] Internet-Draft Linearized Matrix June 2023 * M_TOO_LARGE - The request was too large for the receiver to handle. 13.2.3. Unsupported Endpoints If a server receives a request for an unsupported or otherwise unknown endpoint, the server MUST respond with an HTTP 404 Not Found status code and M_UNRECOGNIZED error code. If the request was for a known endpoint, but wrong HTTP method, a 405 Method Not Allowed HTTP status code and M_UNRECOGNIZED error code (Section 13.2.2). 13.2.4. Malformed Requests If a server is expecting JSON in the request body but receives something else, it MUST respond with an HTTP status code of 400 Bad Request and error code M_NOT_JSON (Section 13.2.2). If the request contains JSON, and is for a known endpoint, but otherwise missing required keys or is malformed, the server MUST respond with an HTTP status code of 400 Bad Request and error code M_BAD_JSON (Section 13.2.2). Where possible, error for M_BAD_JSON should describe the missing keys or other parsing error. 13.2.5. Transaction Identifiers Where endpoints use HTTP PUT, it is typical for a "transaction ID" to be specified in the path parameters. This transaction ID MUST ONLY be used for making requests idempotent - if a server receives two (or more) requests with the same transaction ID, it MUST return the same response for each and only process the request body once. It is assumed that requests using the same transaction ID also contain the same request body between calls. A transaction ID only needs to be unique per-endpoint and per-sending server. A server's transaction IDs do not affect requests made by other servers or made to other endpoints by the same server. 13.2.6. Rate Limiting Servers SHOULD implement rate limiting semantics to reduce the risk of being overloaded. Endpoints which support being rate limited are annotated in this document. If a rate limit is encountered, the server MUST respond with an HTTP 429 Too Many Requests status code and M_LIMIT_EXCEEDED error code (Section 13.2.2). If applicable, the server should additionally include a retry_after_ms integer field on the error response to denote how long the caller should wait before retrying, in milliseconds. Ralston & Hodgson Expires 29 December 2023 [Page 33] Internet-Draft Linearized Matrix June 2023 { "errcode": "M_LIMIT_EXCEEDED", "error": "Too many requests. Try again later.", "retry_after_ms": 10254 } The exact rate limit mechanics are left as an implementation detail. A potential approach may be to prevent repeated requests for the same resource at a high rate and ensuring a remote server does not request more than a defined number of resources at a time. 13.3. Resolving Server Names Before making an API request, the caller MUST resolve a server name (Section 3.1) to an IP address and port, suitable for HTTPS [RFC9110] traffic. A server MAY change the IP/port combination used for API endpoints using SRV DNS records [RFC2782]. Servers MAY additionally change which TLS certificate is presented by using .well-known delegation. .well-known delegation (step 3 below) is recommended for its ease of configuration over SRV DNS records. The target server MUST present a valid TLS certificate (Section 13.1) for the name described in each step. Similarly, the requesting server MUST use an HTTP Host header matching the description in each step. Server developers should note that many of the DNS requirements for the steps below are typically handled by the software language or library implicitly. It is rare that a DNS A record needs to be resolved manually, for example. Per Section 3.1, a server name consists of [:]. The steps to convert that server name to an IP address and port are: 1. If is an IP literal, then that IP address is to be used together with the given port number, or 8448 if no port is given. TLS certificate: (always without port) Host header: or : if a port was specified Ralston & Hodgson Expires 29 December 2023 [Page 34] Internet-Draft Linearized Matrix June 2023 2. If is not an IP literal, and an explicit is present, resolve to an IP address using CNAME [RFC1034] [RFC2181], AAAA [RFC3596], or A [RFC1035] DNS records. Requests are made to the resolved IP address and port number. TLS certificate: (always without port) Host header: : 3. If is not an IP literal, a regular (non-Matrix) HTTPS request is made to https:///.well-known/matrix/server, expecting the schema defined by Section 13.3.1. If the response is invalid (bad/not JSON, missing properties, non-200 response, etc), skip to Step 4. If the response is valid, the m.server property is parsed as [:]. 1. If is an IP literal, then that IP address is to be used together with the given port number, or 8448 if no port is given. TLS certificate: (always without port) Host header: or : if a port was specified 2. If is not an IP literal, and is present, resolve to an IP address using CNAME, AAAA, or A DNS records. Requests are made to the resolved IP address and port number. TLS certificate: (always without port) Host header: : 3. If is not an IP literal and no is present, an SRV DNS record is resolved for _matrix._tcp.. This may result in another hostname and port to be resolved using AAAA or A DNS records. Requests are made to the resolved IP address and port number. TLS certificate: Host header: (without port) Ralston & Hodgson Expires 29 December 2023 [Page 35] Internet-Draft Linearized Matrix June 2023 4. If no SRV record is found, an IP address is resolved for is resolved using CNAME, AAAA, or A DNS records. Requests are made to the resolved IP address with port number 8448. TLS certificate: Host header: (without port) 4. If the .well-known call from Step 3 resulted in an invalid response, an SRV DNS record is resolved for _matrix._tcp.. This may result in another hostname and port to be resolved using AAAA or A DNS records. Requests are made to the resolved IP address and port number. TLS certificate: (always without port) Host header: (without port) 5. If the .well-known call from Step 3 resulted in an invalid response, and the SRV record from Step 4 was not found, and IP address is resolved using CNAME, AAAA, or A DNS records. Requests are made to the resolved IP address and port 8448. TLS certificate: (always without port) Host header: (without port) We require <[delegated_]hostname> rather than in Steps 3.3 and 4 for the following reasons: 1. DNS is largely insecure (not all domains use DNSSEC [RFC9364]), so the target of the SRV record must prove it is a valid delegate/target for <[delegated_]hostname> via TLS. 2. Section 6.2.1 of [RFC6125] recommends this approach, and is consistent with other applications which use SRV records (such as Section 13.7.2.1 of [RFC6120]/XMPP). Server implementations and owners should additionally note that the target of a SRV record MUST NOT be a CNAME, as per RFC 2782 [RFC2782]: the name MUST NOT be an alias (in the sense of RFC 1034 or RFC 2181) [RFC1034] [RFC2181] Ralston & Hodgson Expires 29 December 2023 [Page 36] Internet-Draft Linearized Matrix June 2023 13.3.1. GET /.well-known/matrix/server Used by the server name resolution approach to determine a delegated hostname for a given server. 30x HTTP redirection MUST be followed, though loops SHOULD be avoided. Normal X.509 certificate validation is applied to this endpoint (not the specific validation required by the server name resolution steps) [RFC5280]. This endpoint MAY be implemented by servers (it is optional). *Rate-limited*: No. *Authentication required*: No. This HTTP endpoint does not specify any request parameters or body. 200 OK response: { "m.server": "delegated.example.org:8448" } m.server is a required response field. Responses SHOULD have a Content-Type HTTP header of application/json, however servers parsing the response should assume that the body is JSON regardless of Content-Type header. Failures in parsing the JSON or otherwise invalid data that prevents parsing MUST NOT result in discovery failure. Instead, the caller is expected to move on to the next step of the name resolution approach. Cache control headers SHOULD be respected on a 200 OK response. Callers SHOULD impose a maximum cache time of 48 hours, regardless of cache control headers. A default of 24 hours SHOULD be used when no cache control headers are present. Error responses (non-200) SHOULD be cached for no longer than 1 hour. Callers SHOULD exponentially back off (to a defined limit) upon receiving repeated error responses. 13.4. Request Authentication Most endpoints in this document require authentication to prove which server is making the request. This is done using public key digital signatures. The request method, target, and body are represented as a JSON object, signed, and appended as an HTTP Authorization header with an auth scheme of X-Matrix. Ralston & Hodgson Expires 29 December 2023 [Page 37] Internet-Draft Linearized Matrix June 2023 The object to be signed is: { "method": "GET", "uri": "/path/to/endpoint?with_qs=true", "origin": "requesting.server.name.example.org", "destination": "target.server.name.example.org", "content": {"json_request_body": true} } method is the HTTP request method, capitalized. uri is the full request path, beginning with the leading slash and containing the query string (if present). uri does not contain the https: scheme or hostname. *TODO*: Define an ordering algorithm for the query string (if we need to?). origin and destination are the sender and receiver server names (Section 3.1), respectively. content is the JSON-encoded request body. When a request doesn't contain a body, such as in GET requests, use an empty JSON object. That object is then signed (Section 7.2) by the requesting server. The resulting signature is appended as an Authentication HTTP header on the request: GET /path/to/endpoint?with_qs=true Authorization: X-Matrix origin="requesting.server.name.example.org", destination="target.server.name.example.org", key="ed25519:0", sig="" Content-Type: application/json {"json_request_body": true} Linebreaks within Authorization are for clarity and are non- normative. Ralston & Hodgson Expires 29 December 2023 [Page 38] Internet-Draft Linearized Matrix June 2023 The format of the Authorization header matches Section 11.4 of [RFC9110]. The header begins with an authorization scheme of X-Matrix, followed by one or more spaces, followed by an (unordered) comma-separated list of parameters written as name=value pairs. The names are case insensitive, though the values are. The values must be enclosed in quotes if they contain characters which are not allowed in a token, as defined by Section 5.6.2 of [RFC9110]. If a value is a valid token it may not be enclosed in quotes. Quoted values MAY contain backslash-escaped characters. When parsing the header, the recipient must unescape the characters. The exact parameters are: * origin - The name of the sending server. MUST match the origin in the signed JSON. * destination - The name of the receiving server. MUST match the destination in the signed JSON. * key - The ID, including algorithm name, of the sending server's signing key used to sign the request. * signature - The unpadded base64 (Section 11) encoded signature from step 2. Unknown parameters are ignored and MUST NOT result in authentication errors. A receiving server validates the Authorization header by composing the JSON object represented above and checking the sender's signature (Section 7.3). Note that to comply with Section 7.3 the receiver may need to append a signatures field to the JSON object manually. All signatures MUST use an unexpired key at the time of the request (Section 13.4.1.1). A server with multiple signing keys SHOULD include an Authorization header for each signing key. If an endpoint requires authentication, servers MUST: * Validate all presented Authorization headers. * Ensure at least one Authorization header is present. If either fails (lack of headers, or any of the headers fail validation), the request MUST be rejected with an HTTP 401 Unauthorized status code and M_FORBIDDEN error code (Section 13.2.2): Ralston & Hodgson Expires 29 December 2023 [Page 39] Internet-Draft Linearized Matrix June 2023 { "errcode": "M_FORBIDDEN", "error": "Signature error on request." } If an endpoint does _not_ require authentication, Authorization headers are ignored entirely. Responses from a server are authenticated using TLS and do not have additional signing requirements. 13.4.1. Retrieving Server Keys A server's signing keys are published under /_matrix/key/v2/server (Section 13.4.1.2) and can be queried through notary servers in two ways: Section 13.4.1.3 and Section 13.4.1.4. Notary servers implicitly call /_matrix/key/v2/server when queried, signing and caching the response for some time. This allows the target server to offline without affecting their previously sent events. The approach used here is borrowed from the Perspectives Project [PerspectivesProject], modified to cover the server's ed25519 keys and to use JSON instead of XML. The advantage of this system is it allows each server to pick which notaries it trusts, and can contact multiple notaries to corroborate the keys returned by any given notary. Servers SHOULD attempt to contact the target server directly before using a notary server. Note that these endpoints operate outside the context of a room: a server does not need to participate in any shared rooms to be used as a notary by another server, and does not need to use the hub as a notary. 13.4.1.1. Validity A server's keys are only valid for a short time, denoted by valid_until_ts. Around the valid_until_ts timestamp, a server would re-fetch the server's keys to discover any changes. In the vast majority of cases, only valid_until_ts changes between requests (keys are long-lived, but validated frequently). valid_until_ts MUST be handled as the lesser of valid_until_ts and 7 days into the future, preventing attackers from publishing long-lived keys that are unable to be revoked. Servers SHOULD use a timestamp approximately 12 hours into the future when responding with their keys. Ralston & Hodgson Expires 29 December 2023 [Page 40] Internet-Draft Linearized Matrix June 2023 *TODO*: What does it mean to require events have an origin_server_ts which is less than that of valid_until_ts? Do we reject the event, soft-fail it, or do something else? Do we only do this on the hub? 13.4.1.2. GET /_matrix/key/v2/server Retrieves the server's signing keys. The server can have any number of active or inactive keys at a time, but SHOULD have at least 1 active key at all times. *Rate-limited*: No. *Authentication required*: No. This HTTP endpoint does not specify any request parameters or body. 200 OK response: { "server_name": "example.org", "valid_until_ts": 1686776437176, "m.linearized": true, "verify_keys": { "ed25519:0": { "key": "" } }, "old_verify_keys": { "ed25519:bad": { "expired_ts": 1586776437176, "key": "" } }, "signatures": { "example.org": { "ed25519:0": "" } } } server_name MUST be the name of the server (Section 3.1) which is returning the keys. valid_until_ts is the integer timestamp (milliseconds since Unix epoch) for when the server's keys should be re-fetched. See Section 13.4.1.1. Ralston & Hodgson Expires 29 December 2023 [Page 41] Internet-Draft Linearized Matrix June 2023 m.linearized is an optional boolean, but SHOULD be set to true. Semantics for false and not being present apply to contexts outside of this document. verify_keys are the current signing keys for the server, keyed by key ID (Section 7). The object value for each key ID under verify_keys is simply the key, consisting of the unpadded base64 encoded public key matching that algorithm and version. old_verify_keys are similar to verify_keys, but have an additional required expired_ts property to denote when the key ceased usage. This overrides valid_until_ts for the purposes of Section 13.4.1.1 at an individual key level. *TODO*: What about events sent with old_verify_keys? For request authentication (Section 13.4), only keys listed under verify_keys are honoured. If another key is referenced by the Authorization headers, the request fails authentication. Notaries SHOULD cache a 200 OK response for half of its lifetime to avoid serving stale values. Responding servers SHOULD avoid returning responses which expire in less than an hour to avoid repeated requests. Requesting servers SHOULD limit how frequently they query for keys to avoid flooding a server with requests. If the server fails to respond to this request, notaries SHOULD continue to return the last response they received from the server so that the signatures of old events can still be checked, even if that response is no longer considered valid (Section 13.4.1.1). Servers are capable of rotating their keys without populating old_verify_keys, though this can cause reliability issues if other servers don't see both keys. Notaries SHOULD cache responses with distinct key IDs indefinitely. For example, if a server has ed25519:0 and ed25519:1 on its first response, and a later response returns ed25519:1 and ed25519:2, the notary should cache both responses. This gives servers an ability to validate ed25519:0 for old events in a room. 13.4.1.3. GET /_matrix/key/v2/query/:serverName This is one of two endpoints for querying a server's keys through another server. The notary (receiving) server will attempt to refresh its cached copy of the target server's keys through /_matrix/key/v2/server, falling back to any cached values if needed. *Rate-limited*: No. Ralston & Hodgson Expires 29 December 2023 [Page 42] Internet-Draft Linearized Matrix June 2023 *Authentication required*: No. Path parameters: * :serverName - the target server's name (Section 3.1) to retrieve keys for. Query parameters: * minimum_valid_until_ts (integer; optional) - The time in milliseconds since the Unix epoch the target server's keys will need to be valid until to be useful to the caller. If not specified the notary server's current time will be used. Request body: None applicable. 200 OK response: { "server_keys": [ {/* server key */} ] } server_keys is the array of keys (see Section 13.4.1.2 response format) for the target server. If the target server could not be reached and the notary has no cached keys, this array is empty. If the keys do not meet minimum_valid_until_ts per Section 13.4.1.1, they are not included. The notary server MUST sign each key returned in server_keys by at least one of its own signing keys. The calling server MUST validate all signatures on the objects. 13.4.1.4. POST /_matrix/key/v2/query A bulk version of /_matrix/key/v2/query/:serverName (Section 13.4.1.3). The same behaviour applies to this endpoint. *Rate-limited*: No. *Authentication required*: No. Path parameters: None applicable. Query parameters: None applicable. Request body: Ralston & Hodgson Expires 29 December 2023 [Page 43] Internet-Draft Linearized Matrix June 2023 { "server_keys": { "example.org": { "ed25519:0": { "minimum_valid_until_ts": 1686783382189 } } } } server_keys is required and is the search criteria. The object value is first keyed by server name which maps to another object keyed by Key ID, mapping to the specific criteria. If no key IDs are given in the request, all of the server's known keys are queried. If no servers are given in the request, the response MUST contain an empty server_keys array. minimum_valid_until_ts holds the same meaning as in Section 13.4.1.3. 200 OK response: Same as Section 13.4.1.3 with the following added detail: Responding servers SHOULD only return signed key objects for the key IDs requested by the caller, however servers MAY respond with more keys than requested. The caller is expected to filter the response if needed. 13.5. Sending Events Events accepted into the room by a hub server must be sent to all other servers in that room. Similarly, participant servers need a way to send partial events through the hub server, as mentioned by Section 3.5.1. A single endpoint is used for all rooms on either server, and can contain both fully-formed PDUs (Section 3.5) or Linearized PDUs (partial events; Section 3.5.1) depending on the server's role in the applicable room. A typical event send path will be: Ralston & Hodgson Expires 29 December 2023 [Page 44] Internet-Draft Linearized Matrix June 2023 +-----+ +---------------+ +---------------+ | Hub | | Participant1 | | Participant2 | +-----+ +---------------+ +---------------+ | | | | | Create LPDU | | +-----------+ | | | | | | |<----------+ | | | | | PUT /send/:txnId | | |<--------------------------+ | | | | | Append PDU fields | | +-----------------+ | | | | | | |<----------------+ | | | | | ----------------- Concurrent requests follow ----------------- | | | | PUT /send/:txnId | | +-------------------------->| | | | | | PUT /send/:txnId | | +------------------------------------------------>| | | | PUT /send/:txnId is shorthand for Section 13.5.1. Hubs which generate events would skip to the point where they create a fully-formed PDU and send it out to all other participants. When a hub is broadcasting events to participant servers, it MUST include the following targets: * The server implied by the sender for a kick or ban m.room.member (Section 3.5.3.3) event, up to the point of that kick or ban. * All servers which have at least 1 user which is joined to the room. 13.5.1. PUT /_matrix/federation/v2/send/:txnId Sends (L)PDUs (Section 3.5, Section 3.5.1) to another server. The sending server MUST wait for a 200 OK response from the receiver before sending another request with a different :txnId. Ralston & Hodgson Expires 29 December 2023 [Page 45] Internet-Draft Linearized Matrix June 2023 *Implementation note*: Currently this endpoint doesn't actually exist. Use PUT /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/send/:txnId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *TODO*: Remove implementation notes. *Rate-limited*: No. *Authentication required*: Yes. Path parameters: * :txnId - the transaction ID (Section 13.2.5) for the request. Query parameters: None applicable. Request body: { "edus": [{/* TODO: Define EDUs */}], "pdus": [ {/* Either an LPDU or PDU */} ] } *TODO*: Describe EDUs. edus are the Ephemeral Data Units to send. If no EDUs are being sent, this field MAY be excluded from the request body. There MUST NOT be more than 100 entries in edus. pdus are the events/PDUs (Section 3.5) and LPDUs (Section 3.5.1) to send to the server. Whether it's an LPDU or PDU depends on the sending server's role in that room: if they are a non-hub server, it will be an LPDU. There MUST NOT be more than 50 entries in pdus. Each event in the pdus array gets processed as such: 1. Identify the room ID for the event. The exact format of the event can differ between room versions, however currently this would be done by extracting the room_id property. 1. If that room ID is invalid/not found, the event is rejected. 2. If the server is not participating in the room, the event is dropped/skipped. Ralston & Hodgson Expires 29 December 2023 [Page 46] Internet-Draft Linearized Matrix June 2023 2. If the event is an LPDU and the receiving server is the hub, the additional PDU fields are appended before continuing. 3. If the event is an LPDU and the receiving server is not the hub, the event is dropped/skipped. 4. The checks defined by Section 6.1 are performed. 5. If the event still hasn't been dropped/rejected, it is appended to the room. For participant servers, this may mean it's queued for sending to local clients. Server implementation authors should note that these steps can be condensed, but are expanded here for specification purposes. For example, an LPDU's signature can/will fail without ever needing to append the PDU fields first - the server can skip some extra work this way. 200 OK response: { "failed_pdus": { "$eventid": { "error": "Invalid event format" }, "$eventid": { "error": "@alice:example.org cannot send m.room.power_levels" } } } The receiving server MUST NOT send a 200 OK response until all events have been processed. Servers SHOULD NOT block responding to this endpoint on sending accepted events to local clients or other participant servers, as doing so could lead to a lengthy backlog of events waiting to be sent. Sending servers SHOULD apply/expect a timeout and retry the exact same request with the same transaction ID until they see a 200 OK response. If the sending server attempts to send a different transaction ID from the one already in flight, the receiving server MUST respond with a 400 Bad Request HTTP status code and M_BAD_STATE error code (Section 13.2.2). Receiving servers SHOULD continue processing requests to this endpoint event after the sender has disconnected/timed out, but SHOULD NOT process the request multiple times due to the transaction ID (Section 13.2.5). Ralston & Hodgson Expires 29 December 2023 [Page 47] Internet-Draft Linearized Matrix June 2023 failed_pdus is an object mapping event ID (Section 3.5) to error string. Event IDs are based upon the received object, not the final/ complete object. For example, if an LPDU is sent, gets its PDU fields appended, and fails event authorization, then the error would be for the event ID of the LPDU, not the fully-formed PDU. This is to allow the sender to correlate what they sent with errors. The object for each event ID MUST contain an error string field, representing the human-readable reason for an event being rejected. Events which are dropped/ignored or accepted do _not_ appear in failed_pdus. *TODO*: Should we also return fully-formed PDUs for the LPDUs we received? 13.6. Event and State APIs When a participant in the room is missing an event, or otherwise needs a new copy of it, it can retrieve that event from the hub server. Similar mechanics apply for getting state events, current state of a room, and backfilling scrollback in a room. All servers are required to implement all endpoints (Section 13.2.1), however only hub servers are guaranteed to have the full history/ state for a room. While other participant servers might have history, they SHOULD NOT be contacted due to the high likelihood of a Not Found-style error. 13.6.1. GET /_matrix/federation/v2/event/:eventId Retrieves a single event. *Implementation note*: Currently this endpoint doesn't actually exist. Use GET /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/event/:eventId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *TODO*: Remove implementation notes. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: Ralston & Hodgson Expires 29 December 2023 [Page 48] Internet-Draft Linearized Matrix June 2023 * :eventId - the event ID (Section 3.5) to retrieve. Note that event IDs are typically reference hashes (Section 10.2) of the event itself, which includes the room ID. This makes event IDs globally unique. Query parameters: None applicable. Request body: None applicable. 200 OK response: { /* the event */ } The response body is simply the event (Section 3.5) itself, if the requesting server has reasonable visibility of the event (Section 3.5.3.5.1). When the server can see an event but not the contents, the event is served redacted (Section 9) instead. If the event isn't known to the server, or the requesting server has no reason to know that the event even exists, a 404 Not Found HTTP status code and M_NOT_FOUND error code (Section 13.2.2) is returned. The returned event MUST be checked before being used by the requesting server (Section 6.1). This endpoint MUST NOT return LPDUs (Section 3.5.1), instead treating such events as though they didn't exist. 13.6.2. GET /_matrix/federation/v1/state/:roomId Retrieves a snapshot of the room state (Section 3.5.2) at the given event. This is typically most useful when a participant server prefers to store minimal information about the room, but still needs to offer context to its clients. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :roomId - the room ID (Section 3.2) to retrieve state in. Query parameters: * event_id (string; required) - The event ID (Section 3.5) to retrieve state at. Ralston & Hodgson Expires 29 December 2023 [Page 49] Internet-Draft Linearized Matrix June 2023 Request body: None applicable. 200 OK response: { "auth_chain": [ {/* event */} ], "pdus": [ {/* event */} ] } The returned room state is in two parts: the pdus, consisting of the events which represent "current state" (Section 3.5.2) prior to considering state changes induced by the event in the original request, and auth_chain, consisting of the events which make up the auth_events (Section 6.4.1) for the pdus and the auth_events of those events, recursively. The auth_chain will eventually stop recursing when it reaches the m.room.create event, as it cannot have any auth_events. For example, if the requested event ID was an m.room.power_levels event, the returned state would be as if the new power levels were not applied. Both auth_chain and pdus contain event objects (Section 3.5). If the requesting server does not have reasonable visibility on the room (Section 3.5.3.5.1), or either the room ID or event ID don't exist, a 404 Not Found HTTP status code and M_NOT_FOUND error code (Section 13.2.2) is returned. The same error is returned if the event ID doesn't exist in the requested room ID. Note that the requesting server will generally always have visibility of the auth_chain and pdu events, but may not be able to see their contents. In this case, they are redacted (Section 9) before being served. The returned events MUST be checked before being used by the requesting server (Section 6.1). This endpoint MUST NOT return LPDUs (Section 3.5.1), instead treating such events as though they didn't exist. Ralston & Hodgson Expires 29 December 2023 [Page 50] Internet-Draft Linearized Matrix June 2023 13.6.3. GET /_matrix/federation/v1/state_ids/:roomId This performs the same function as Section 13.6.2 but returns just the event IDs instead. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :roomId - the room ID (Section 3.2) to retrieve state in. Query parameters: * event_id (string; required) - The event ID (Section 3.5) to retrieve state at. Request body: None applicable. 200 OK response: { "auth_chain_ids": ["$event1", "$event2"], "pdu_ids": ["$event3", "$event4"] } See Section 13.6.2 for behaviour. Note that auth_chain becomes auth_chain_ids when using this endpoint, and pdus becomes pdu_ids. 13.6.4. GET /_matrix/federation/v2/backfill/:roomId Retrieves a sliding window history of previous events in a given room. *Implementation note*: Currently this endpoint doesn't actually exist. Use GET /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/backfill/:roomId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *TODO*: Remove implementation notes. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: Ralston & Hodgson Expires 29 December 2023 [Page 51] Internet-Draft Linearized Matrix June 2023 * :roomId - the room ID (Section 3.2) to retrieve events from. Query parameters: * v (string; required) - The event ID (Section 3.5) to start backfilling from. * limit (integer; required) - The maximum number of events to return, including v. Request body: None applicable. 200 OK response: { "pdus": [ {/* event */} ] } The number of returned pdus MUST NOT exceed the limit provided by the caller. limit SHOULD have a maximum value imposed by the receiving server. pdus contains the events (Section 3.5) preceeding the requested event ID (v), including v. pdus is ordered from oldest to newest. If the requesting server does not have reasonable visibility on the room (Section 3.5.3.5.1), or either the room ID or event ID don't exist, a 404 Not Found HTTP status code and M_NOT_FOUND error code (Section 13.2.2) is returned. The same error is returned if the event ID doesn't exist in the requested room ID. If the requesting server does have visibility on the returned events, but not their contents, they are redacted (Section 9) before being served. The returned events MUST be checked before being used by the requesting server (Section 6.1). This endpoint MUST NOT return LPDUs (Section 3.5.1), instead treating such events as though they didn't exist. 13.7. Room Membership When a server is already participating in a room, it can simply send m.room.member (Section 3.5.3.3) events with the /send API (Section 13.5.1) to other servers/the hub directly. When a server is not already participating however, it needs to be welcomed in by the hub server. Ralston & Hodgson Expires 29 December 2023 [Page 52] Internet-Draft Linearized Matrix June 2023 A typical invite flow would be: +-------------+ +-----+ +---------------+ | Participant | | Hub | | TargetServer | +-------------+ +-----+ +---------------+ | | | | POST /invite (LPDU) | | +---------------------->| | | | | | | POST /invite (PDU) | | +----------------------->| | | | | | | Decide to process the | | | invite. Can reject due | | | to spam, or send it to | | | the recipient user. | | +----------------------+ | | | | | | |<---------------------+ | | | | | Finish POST /invite | | |<-----------------------+ | | | | Finish POST /invite | | |<----------------------+ | | | | ------------------------ User decides to accept invite ------------------------- | | | | | GET /make_join | | |<-----------------------+ | | | | | Finish GET /make_join | | +----------------------->| | | | | | | Fill event template | | +-------------------+ | | | | | | |<------------------+ | | | | | POST /send_join | | |<-----------------------+ | | | | | Finish POST /send_join | | +----------------------->| | | | Ralston & Hodgson Expires 29 December 2023 [Page 53] Internet-Draft Linearized Matrix June 2023 POST /invite is shorthand for Section 13.7.2.1. Similarly, GET /make_join is Section 13.7.3.1 and POST /send_join is Section 13.7.3.2. If the user decided to reject the invite, the TargetServer would use GET /make_leave (Section 13.7.2.2.1) and POST /send_leave (Section 13.7.2.2.2) instead of make/send_join. 13.7.1. Make and Send Handshake When a server is already participating in a room, it can use m.room.member (Section 3.5.3.3) events and the /send API (Section 13.5.1) to directly change membership. When the server is not already involved in the room, such as when being invited for the first time, the server needs to "make" an event and "send" it through the hub server to append it to the room. The different processes which use this handshake are: * Rejecting Invites (Section 13.7.2.2) * Joins (Section 13.7.3) * Knocks (Section 13.7.4) The "make" portion of the endpoints take the shape of GET /_matrix/federation/v1/make_CHANGE/:roomId/:userId, where CHANGE is leave, join, or knock (respective to the list above). This endpoint will return a partial LPDU (Section 3.5.1) which needs to be turned into a full LPDU and signed before being sent using POST /_matrix/federation/v3/send_CHANGE/:txnId. The flow for this handshake appears as such: Ralston & Hodgson Expires 29 December 2023 [Page 54] Internet-Draft Linearized Matrix June 2023 +----------------+ +-----+ | ExternalServer | | Hub | +----------------+ +-----+ | | | GET /_matrix/federation/v1/make_CHANGE/:roomId/:userId | +-------------------------------------------------------->| | | | Reject if event future event | | would not be allowed by auth rules | |<--------------------------------------------------------+ | | | Respond with partial LPDU | |<--------------------------------------------------------+ | | | Populate LPDU and sign it | +-------------------------+ | | | | |<------------------------+ | | | | POST /_matrix/federation/v3/send_CHANGE/:txnId | +-------------------------------------------------------->| | | | Validate event and append to the room | | +-------------------------------------+ | | | | +------------------------------------>| | | | Reject if event not allowed by auth rules | |<--------------------------------------------------------+ | | | Send new event to all other | | participants in the room (async) | | +-------------------------------------+ | | | | +------------------------------------>| | | | 200 OK | |<--------------------------------------------------------+ | | Note that the send_CHANGE step re-checks the event against the auth rules: any amount of time could have passed between the make_CHANGE and send_CHANGE calls. *TODO*: Describe how the external server is meant to find the hub. Invites work by (usually) trying to contact the server which sent the invite, but knocking is a guess. Ralston & Hodgson Expires 29 December 2023 [Page 55] Internet-Draft Linearized Matrix June 2023 13.7.2. Invites When inviting a user belonging to a server already in the room, senders SHOULD use m.room.member (Section 3.5.3.3) events and the /send API (Section 13.5.1). This section's endpoints SHOULD only be used when the target server is _not_ participating in the room already. Note that being invited does not count as the server "participating" in the room. This can mean that while a server has a user with a pending invite in the room, this section's endpoints are needed to send additional invites to other users on the same server. The full invite sequence is: Ralston & Hodgson Expires 29 December 2023 [Page 56] Internet-Draft Linearized Matrix June 2023 +-------------+ +-----+ +---------------+ | Participant | | Hub | | TargetServer | +-------------+ +-----+ +---------------+ | | | | POST /invite | | +--------------------->| | | | | | Reject if sender | | | cannot invite other | | | users | | |<---------------------+ | | | | | | Otherwise, append | | | PDU fields | | +------------------+ | | | | | | |<-----------------+ | | | | | | POST /invite | | +----------------------->| | | | | | Reject if room | | | version not supported | | |<-----------------------+ | | | | | Reject if target user | | | is ineligible for | | | invites | | |<-----------------------+ | | | | Proxy TargetServer | | | rejection | | |<---------------------+ | | | | | | | Otherwise, queue | | | sending the invite to | | | target user | | +----------------------+ | | | | | | |<---------------------+ | | | | | 200 OK | | |<-----------------------+ | | | | 200 OK | | |<---------------------+ | | | | Ralston & Hodgson Expires 29 December 2023 [Page 57] Internet-Draft Linearized Matrix June 2023 POST /invite is shorthand for Section 13.7.2.1. What causes a user to be considered "ineligible" for an invite is left as an implementation detail. See Section 14 and Section 15 for suggestions on handling user-level privacy controls and spam invites. 13.7.2.1. POST /_matrix/federation/v3/invite/:txnId Sends an invite event to a server. If the sender is a participant server, the receiving server (the hub) will convert the contained LPDU (Section 3.5.1) to a fully-formed event (Section 3.5) before sending that event to the intended server. *Implementation note*: Currently this endpoint doesn't actually exist. Use POST /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/invite/:txnId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *TODO*: Remove implementation notes. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :txnId - the transaction ID (Section 13.2.5) for the request. The event ID (Section 3.5) of the contained event may be a good option as a readily-available transaction ID. Query parameters: None applicable. Request body: { "event": {/* the event */}, "invite_room_state": [/* stripped state events */], "room_version": "I.1" } invite_room_state are the stripped state events (Section 3.5.2.1) for the room's current state. invite_room_state MAY be excluded from the request body. room_version is the room version identifier (Section 3.2.1) the room is currently using. This will be retrieved from the m.room.create (Section 3.5.3.1) state event. Ralston & Hodgson Expires 29 December 2023 [Page 58] Internet-Draft Linearized Matrix June 2023 event is the event (LPDU or PDU; Section 3.5) representing the invite for the user. It MUST meet the following criteria, in addition to the requirements of an event: * type MUST be m.room.member. * membership in content MUST be invite. When the hub server receives a request from a participant server, it MUST populate the event fields before sending the event to the intended recipient. This means running the event through the normal event authorization steps (Section 6.4). If the invite is not allowed under the auth rules, the server responds with a 403 Forbidden HTTP status code and M_FORBIDDEN error code (Section 13.2.2). The intended recipient of the invite can be identified by the state_key on the event. If the invite event is valid, the hub server sends its own POST /_matrix/federation/v3/invite/:txnId request to the target server (if the target server is not itself) with the fully-formed event. The transaction ID does not need to be the same as the original inbound request. All responses from the target server SHOULD be proxied verbatim to the original requesting server through the hub. The hub SHOULD discard what appears to be excess data before sending a response to the requesting server, such as extra or large fields. If the target server does not respond with JSON, an error response (Section 13.2.2) SHOULD be sent by the hub instead. The target server then ensures it can support the room version. If it can't, it responds with an HTTP status code of 400 Bad Request and error code of M_INCOMPATIBLE_ROOM_VERSION (Section 13.2.2). Then, the target server runs any implementation-specific checks as needed, such as those implied by Section 14 and Section 15, rejecting/erroring the request as needed. Finally, the target server signs the event and returns it to the hub. The hub server appends this signed event to the room and sends it out to all participants in the room. The signed event is additionally returned to the originating participant server, though it also receives the event through the /send API (Section 13.5.1). 200 OK response: Ralston & Hodgson Expires 29 December 2023 [Page 59] Internet-Draft Linearized Matrix June 2023 { "pdu": {/* signed fully-formed event */} } Note that by the time a response is received, the event is signed 2-3 times: 1. The LPDU signature from the participant server (Section 3.5.1). 2. The hub's signature on the PDU (Section 3.5). 3. The target server's signature on the PDU. These signatures are to satisfy the auth rules (Section 6.4). *TODO*: Do we ever validate the target server's signature? Do we need to? 13.7.2.2. Rejecting Invites and Leaves Rejecting an invite is done by making a membership transition of invite to leave through the user's m.room.member (Section 3.5.3.3) event. The membership event SHOULD be sent directly when it can and use the "make and send" handshake (Section 13.7.1) described here otherwise. This same approach is additionally used to retract a knock (Section 13.7.4). 13.7.2.2.1. GET /_matrix/federation/v1/make_leave/:roomId/:userId Requests an event template from the hub server for a room. The requesting server will have already been checked to ensure it supports the room version as part of the invite process prior to making a call to this endpoint. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :roomId - the room ID (Section 3.2) to get a template for. * :userId - the user ID (Section 3.3) attempting to leave. Query parameters: None applicable. Ralston & Hodgson Expires 29 December 2023 [Page 60] Internet-Draft Linearized Matrix June 2023 Request body: None applicable. 200 OK response: { "event": {/* partial LPDU */}, "room_version": "I.1" } The response body's event MUST be a partial LPDU (Section 3.5.1) with at least the following fields: * type of m.room.member. * state_key of :userId from the path parameters. * sender of :userId from the path parameters. * content of {"membership": "leave"}. The sending server SHOULD remove all other fields before using the event in a send_leave (Section 13.7.2.2.2). If the receiving server is not the hub server for the room ID, an HTTP status code of 400 Bad Request and error code M_WRONG_SERVER (Section 13.2.2) is returned. If the room ID is not known, 404 Not Found is used as an HTTP status code and M_NOT_FOUND as an error code (Section 13.2.2). If the user does not have permission to leave under the auth rules (Section 6.4), a 403 Forbidden HTTP status code is returned alongside an error code of M_FORBIDDEN (Section 13.2.2). For example, if the user does not have a pending invite, is not a member of the room, or is banned. If the sending server does not recognize the returned room_version, it SHOULD NOT attempt to populate the template or use the send_leave (Section 13.7.2.2.2) endpoint. 13.7.2.2.2. POST /_matrix/federation/v3/send_leave/:txnId Sends a leave membership event to the room through a hub server. *Implementation note*: Currently this endpoint doesn't actually exist. Use POST /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/send_leave/:txnId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. Ralston & Hodgson Expires 29 December 2023 [Page 61] Internet-Draft Linearized Matrix June 2023 *TODO*: Remove implementation notes. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :txnId - the transaction ID (Section 13.2.5) for the request. The event ID (Section 3.5) of the contained event may be a good option as a readily-available transaction ID. Query parameters: None applicable. Request body: { /* LPDU created from make_leave template */ } 200 OK response: {/* deliberately empty object */} The errors responses from /make_leave (Section 13.7.2.2.1) are copied here. Servers should note that room state MAY change between a /make_leave and /send_leave, potentially in a way which prevents the user from leaving the room suddenly. For example, the invited user may have been banned from the room. 13.7.3. Joins Joins for users SHOULD be sent directly whenever possible, and otherwise use the "make and send" handshake (Section 13.7.1) approach described here. 13.7.3.1. GET /_matrix/federation/v1/make_join/:roomId/:userId Requests an event template from the hub server for a room. This is done to ensure the requesting server supports the room's version (Section 3.2.1), as well as hint at the event format needed to participate. Note that this endpoint is extremely similar to /make_leave (Section 13.7.2.2.1). *Rate-limited*: Yes. Ralston & Hodgson Expires 29 December 2023 [Page 62] Internet-Draft Linearized Matrix June 2023 *Authentication required*: Yes. Path parameters: * :roomId - the room ID (Section 3.2) to get a template for. * :userId - the user ID (Section 3.3) attempting to join. Query parameters: * ver (string; required; repeated) - The room versions (Section 3.2.1) the sending server supports. Request body: None applicable. 200 OK response: { /* partial LPDU */ } The response body MUST be a partial LPDU (Section 3.5.1) with at least the following fields: * type of m.room.member. * state_key of :userId from the path parameters. * sender of :userId from the path parameters. * content of {"membership": "join"}. The sending server SHOULD remove all other fields before using the event in a send_join (Section 13.7.3.2). If the receiving server is not the hub server for the room ID, an HTTP status code of 400 Bad Request and error code M_WRONG_SERVER (Section 13.2.2) is returned. If the room ID is not known, 404 Not Found is used as an HTTP status code and M_NOT_FOUND as an error code (Section 13.2.2). If the user does not have permission to join under the auth rules (Section 6.4), a 403 Forbidden HTTP status code is returned alongside an error code of M_FORBIDDEN (Section 13.2.2). If the room version is not one of the ver strings the sender supplied, a 400 Bad Request HTTP status code is returned alongside M_INCOMPATIBLE_ROOM_VERSION error code (Section 13.2.2). Ralston & Hodgson Expires 29 December 2023 [Page 63] Internet-Draft Linearized Matrix June 2023 13.7.3.2. POST /_matrix/federation/v3/send_join/:txnId Sends a join membership event to the room through a hub server. Note that this endpoint is extremely similar to /send_leave (Section 13.7.2.2.2). *Implementation note*: Currently this endpoint doesn't actually exist. Use POST /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/send_join/:txnId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *TODO*: Remove implementation notes. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :txnId - the transaction ID (Section 13.2.5) for the request. The event ID (Section 3.5) of the contained event may be a good option as a readily-available transaction ID. Query parameters: None applicable. *TODO*: Incorporate faster joins work. Request body: { /* LPDU created from make_join template */ } 200 OK response: { "state": [/* events */], "auth_chain": [/* events */], "event": {/* fully-formed event */} } Ralston & Hodgson Expires 29 December 2023 [Page 64] Internet-Draft Linearized Matrix June 2023 state is the current room state, consisting of the events which represent "current state" (Section 3.5.2) prior to considering the membership state change. auth_chain consists of the events which make up the auth_events (Section 6.4.1) for the state events, and the auth_events of those events, recursively. event will be the fully- formed PDU (Section 3.5) that is sent by the hub to all other participants in the room. The errors responses from /make_join (Section 13.7.3.1) are copied here (with the exception of M_INCOMPATIBLE_ROOM_VERSION, as the server already checked for support). Servers should note that room state MAY change between a /make_join and /send_join, potentially in a way which prevents the user from joining the room suddenly. 13.7.4. Knocks To knock on a room is to request an invite to that room. It is not a join, nor is it an invite itself. "Approving" the knock is done by inviting the user, which is typically only allowed by moderators in these rooms. "Denying" the knock is done through kicking (sending a leave membership) or banning the user. If the user is kicked, they may re-send their knock. Senders should note the reason field on m.room.member events (Section 3.5.3.3) to provide context for their knock. To retract a knock, the sending server uses the same APIs as rejecting an invite (Section 13.7.2.2). Where possible, knocks from users SHOULD be sent directly, otherwise using the "make and send" handshake (Section 13.7.1) approach described here. 13.7.4.1. GET /_matrix/federation/v1/make_knock/:roomId/:userId Requests an event template from the hub server for a room. This is done to ensure the requesting server supports the room's version (Section 3.2.1), as well as hint at the event format needed to participate. Note that this endpoint is almost exactly the same as /make_join (Section 13.7.3.1). *TODO*: It's so similar to make_join that we should probably just combine the two endpoints. *Rate-limited*: Yes. Ralston & Hodgson Expires 29 December 2023 [Page 65] Internet-Draft Linearized Matrix June 2023 *Authentication required*: Yes. Path parameters: * :roomId - the room ID (Section 3.2) to get a template for. * :userId - the user ID (Section 3.3) attempting to knock. Query parameters: * ver (string; required; repeated) - The room versions (Section 3.2.1) the sending server supports. Request body: None applicable. 200 OK response: { /* partial LPDU */ } The response body MUST be a partial LPDU (Section 3.5.1) with at least the following fields: * type of m.room.member. * state_key of :userId from the path parameters. * sender of :userId from the path parameters. * content of {"membership": "knock"}. The sending server SHOULD remove all other fields before using the event in a send_knock (Section 13.7.4.2). If the receiving server is not the hub server for the room ID, an HTTP status code of 400 Bad Request and error code M_WRONG_SERVER (Section 13.2.2) is returned. If the room ID is not known, 404 Not Found is used as an HTTP status code and M_NOT_FOUND as an error code (Section 13.2.2). If the user does not have permission to knock under the auth rules (Section 6.4), a 403 Forbidden HTTP status code is returned alongside an error code of M_FORBIDDEN (Section 13.2.2). If the room version is not one of the ver strings the sender supplied, a 400 Bad Request HTTP status code is returned alongside M_INCOMPATIBLE_ROOM_VERSION error code (Section 13.2.2). Ralston & Hodgson Expires 29 December 2023 [Page 66] Internet-Draft Linearized Matrix June 2023 13.7.4.2. POST /_matrix/federation/v3/send_knock/:txnId Sends a knock membership event to the room through a hub server. *Implementation note*: Currently this endpoint doesn't actually exist. Use POST /_matrix/federation/unstable/org.matrix.i-d.ralston- mimi-linearized-matrix.02/send_knock/:txnId when testing against other Linearized Matrix implementations. This string may be updated later to account for breaking changes. *TODO*: Remove implementation notes. *Rate-limited*: Yes. *Authentication required*: Yes. Path parameters: * :txnId - the transaction ID (Section 13.2.5) for the request. The event ID (Section 3.5) of the contained event may be a good option as a readily-available transaction ID. Query parameters: None applicable. Request body: { /* LPDU created from make_knock template */ } 200 OK response: { "stripped_state": [ /* stripped state events */ ] } stripped_state are the stripped state events (Section 3.5.2.1) for the room. The errors responses from /make_knock (Section 13.7.4.1) are copied here (with the exception of M_INCOMPATIBLE_ROOM_VERSION, as the server already checked for support). Servers should note that room state MAY change between a /make_knock and /send_knock, potentially in a way which prevents the user from knocking upon the room suddenly. Ralston & Hodgson Expires 29 December 2023 [Page 67] Internet-Draft Linearized Matrix June 2023 13.8. Content Repository The content repository, sometimes called the "media repo", is where user-generated content is stored for referencing within an encrypted message. *TODO*: Complete this section. We want auth/event linking from MSC3911 and MSC3916. *TODO*: Spell out that content is images, videos, files, etc. 13.9. TODO: Remainder of Transport *TODO*: This section. Topics: * EDUs (typing notifications, receipts, presence) * Device management & to-device messaging * Query APIs (alias resolution, profiles) * Encryption APIs Notably/deliberately missing APIs are: * get_missing_events - this is used by DAG servers only * Public room directory * Timestamp-to-event API * All of 3rd party invites * All of Spaces * OpenID API 13.9.1. Open Questions * Should we include /_matrix/federation/v1/version in here? It's used by federation testers, but not really anything else. 14. User Privacy *TODO*: Fully complete this section. Ralston & Hodgson Expires 29 December 2023 [Page 68] Internet-Draft Linearized Matrix June 2023 Messaging providers may have user-level settings to prevent unexpected or unwarranted invites, such as automatically blocking invites from non-contacts. This setting can be upheld by returning an error on POST /_matrix/federation/v3/invite/:txnId (Section 13.7.2.1), and by having the server (optionally) auto- decline any invites received directly through PUT /_matrix/federation/v2/send/:txnId (Section 13.5.1). See Section 13.7.2.2 for more information on rejecting invites. 15. Spam Prevention *TODO*: Fully complete this section. Servers MAY temporarily or permanently block a room entirely by using the room ID. Typically, when a room becomes blocked, all local users will be removed from the room using m.room.member events with membership of leave (Section 3.5.3.3). Then, any time the server receives a request for that room ID it can reject it with an error response (Section 13.2.2). Blocking a room does not block it from all servers, but does prevent users on a server from accessing the content within. This is primarily useful to remove a server from rooms where abusive/illegal content is shared. 16. Security Considerations *TODO*: Expand upon this section. With the combined use of MLS and server-side enforcement, the server theoretically has an ability to add a malicious device to the MLS group and receive decryptable messages. Authenticity of devices needs to be established to ensure a user's devices are actually a user's devices. *TODO*: Should we bring Matrix's cross-signing here? Servers retain the ability to control/puppet their own users due to no strong cryptographic link between the sending device and the event which gets emitted. 17. IANA Considerations The m.* namespace likely needs formal registration in some capacity. The I.* namespace likely needs formal registration in some capacity. Port 8448 may need formal registration. Ralston & Hodgson Expires 29 December 2023 [Page 69] Internet-Draft Linearized Matrix June 2023 The SRV service name matrix may need re-registering, or a new service name assigned. The .well-known/matrix namespace is already registered for use by The Matrix.org Foundation C.I.C. 18. References 18.1. Normative References [I-D.ietf-mls-architecture] Beurdouche, B., Rescorla, E., Omara, E., Inguva, S., and A. Duric, "The Messaging Layer Security (MLS) Architecture", Work in Progress, Internet-Draft, draft- ietf-mls-architecture-10, 16 December 2022, . [I-D.ietf-mls-protocol] Barnes, R., Beurdouche, B., Robert, R., Millican, J., Omara, E., and K. Cohn-Gordon, "The Messaging Layer Security (MLS) Protocol", Work in Progress, Internet- Draft, draft-ietf-mls-protocol-20, 27 March 2023, . [I-D.ralston-mimi-terminology] Ralston, T., "MIMI Terminology", Work in Progress, Internet-Draft, draft-ralston-mimi-terminology-01, 9 June 2023, . [RFC1034] Mockapetris, P., "Domain names - concepts and facilities", STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987, . [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987, . [RFC1123] Braden, R., Ed., "Requirements for Internet Hosts - Application and Support", STD 3, RFC 1123, DOI 10.17487/RFC1123, October 1989, . Ralston & Hodgson Expires 29 December 2023 [Page 70] Internet-Draft Linearized Matrix June 2023 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS Specification", RFC 2181, DOI 10.17487/RFC2181, July 1997, . [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000, . [RFC3596] Thomson, S., Huitema, C., Ksinant, V., and M. Souissi, "DNS Extensions to Support IP Version 6", STD 88, RFC 3596, DOI 10.17487/RFC3596, October 2003, . [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, . [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", RFC 4291, DOI 10.17487/RFC4291, February 2006, . [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, . [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, . [RFC6125] Saint-Andre, P. and J. Hodges, "Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)", RFC 6125, DOI 10.17487/RFC6125, March 2011, . [RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011, . Ralston & Hodgson Expires 29 December 2023 [Page 71] Internet-Draft Linearized Matrix June 2023 [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, January 2017, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, . [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, . [RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, DOI 10.17487/RFC8785, June 2020, . [RFC9110] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022, . [RFC9113] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, DOI 10.17487/RFC9113, June 2022, . 18.2. Informative References [DMLS] Chathi, H., "Decentralised MLS", 29 May 2023, . [MSC3820] Ralston, T., "MSC3820: Room Version 11", 8 June 2023, . [MSC3995] Ralston, T., "MSC3995: [WIP] Linearized Matrix", 12 April 2023, . Ralston & Hodgson Expires 29 December 2023 [Page 72] Internet-Draft Linearized Matrix June 2023 [PerspectivesProject] "Perspectives Project", 2 July 2017, . [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008, . [RFC6120] Saint-Andre, P., "Extensible Messaging and Presence Protocol (XMPP): Core", RFC 6120, DOI 10.17487/RFC6120, March 2011, . [RFC9364] Hoffman, P., "DNS Security Extensions (DNSSEC)", BCP 237, RFC 9364, DOI 10.17487/RFC9364, February 2023, . Acknowledgments Thank you to the Matrix Spec Core Team (SCT), and in particular Richard van der Hoff, for exploring how Matrix rooms could be represented as a linear structure, leading to this document. Authors' Addresses Travis Ralston The Matrix.org Foundation C.I.C. Email: travisr@matrix.org Matthew Hodgson The Matrix.org Foundation C.I.C. Email: matthew@matrix.org Ralston & Hodgson Expires 29 December 2023 [Page 73]