Skip to main content

Linearized Matrix
draft-ralston-mimi-linearized-matrix-02

The information below is for an old version of the document.
Document Type
This is an older version of an Internet-Draft whose latest revision state is "Active".
Authors Travis Ralston , Matthew Hodgson
Last updated 2023-06-26 (Latest revision 2023-06-06)
Replaces draft-ralston-mimi-matrix-transport, draft-ralston-mimi-matrix-framework
RFC stream (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-ralston-mimi-linearized-matrix-02
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": "<unpadded base64>"
       },
       "sha256": "<unpadded base64>"
     },
     "signatures": {
       "first.example.org": {
         "ed25519:1": "<unpadded base64 signature covering whole event>"
       },
       "second.example.org": {
         "ed25519:1": "<unpadded base64 signature covering LPDU>"
       }
     },
     "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 <hostname>[:<port>].  The
   steps to convert that server name to an IP address and port are:

   1.  If <hostname> 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: <hostname> (always without port)

       Host header: <hostname> or <hostname>:<port> if a port was
       specified

Ralston & Hodgson       Expires 29 December 2023               [Page 34]
Internet-Draft              Linearized Matrix                  June 2023

   2.  If <hostname> is not an IP literal, and an explicit <port> is
       present, resolve <hostname> 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: <hostname> (always without port)

       Host header: <hostname>:<port>

   3.  If <hostname> is not an IP literal, a regular (non-Matrix) HTTPS
       request is made to https://<hostname>/.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 <delegated_hostname>[:<delegated_port>].

       1.  If <delegated_hostname> 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: <delegated_hostname> (always without port)

           Host header: <delegated_hostname> or
           <delegated_hostname>:<delegated_port> if a port was specified

       2.  If <delegated_hostname> is not an IP literal, and
           <delegated_port> is present, resolve <delegated_hostname> to
           an IP address using CNAME, AAAA, or A DNS records.  Requests
           are made to the resolved IP address and port number.

           TLS certificate: <delegated_hostname> (always without port)

           Host header: <delegated_hostname>:<delegated_port>

       3.  If <delegated_hostname> is not an IP literal and no
           <delegated_port> is present, an SRV DNS record is resolved
           for _matrix._tcp.<delegated_hostname>.  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: <delegated_hostname>

           Host header: <delegated_hostname> (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
           <delegated_hostname> is resolved using CNAME, AAAA, or A DNS
           records.  Requests are made to the resolved IP address with
           port number 8448.

           TLS certificate: <delegated_hostname>

           Host header: <delegated_hostname> (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.<hostname>.  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: <hostname> (always without port)

       Host header: <hostname> (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: <hostname> (always without port)

       Host header: <hostname> (without port)

   We require <[delegated_]hostname> rather than <srv_hostname> 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="<unpadded base64 encoded signature>"
   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": "<unpadded base64 encoded public key>"
         }
      },
      "old_verify_keys": {
         "ed25519:bad": {
            "expired_ts": 1586776437176,
            "key": "<unpadded base64 encoded public key>"
         }
      },
      "signatures": {
         "example.org": {
            "ed25519:0": "<unpadded base64 encoded signature>"
         }
      }
   }

   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,
              <https://datatracker.ietf.org/doc/html/draft-ietf-mls-
              architecture-10>.

   [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,
              <https://datatracker.ietf.org/doc/html/draft-ietf-mls-
              protocol-20>.

   [I-D.ralston-mimi-terminology]
              Ralston, T., "MIMI Terminology", Work in Progress,
              Internet-Draft, draft-ralston-mimi-terminology-01, 9 June
              2023, <https://datatracker.ietf.org/doc/html/draft-
              ralston-mimi-terminology-01>.

   [RFC1034]  Mockapetris, P., "Domain names - concepts and facilities",
              STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987,
              <https://www.rfc-editor.org/rfc/rfc1034>.

   [RFC1035]  Mockapetris, P., "Domain names - implementation and
              specification", STD 13, RFC 1035, DOI 10.17487/RFC1035,
              November 1987, <https://www.rfc-editor.org/rfc/rfc1035>.

   [RFC1123]  Braden, R., Ed., "Requirements for Internet Hosts -
              Application and Support", STD 3, RFC 1123,
              DOI 10.17487/RFC1123, October 1989,
              <https://www.rfc-editor.org/rfc/rfc1123>.

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,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC2181]  Elz, R. and R. Bush, "Clarifications to the DNS
              Specification", RFC 2181, DOI 10.17487/RFC2181, July 1997,
              <https://www.rfc-editor.org/rfc/rfc2181>.

   [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,
              <https://www.rfc-editor.org/rfc/rfc2782>.

   [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,
              <https://www.rfc-editor.org/rfc/rfc3596>.

   [RFC3629]  Yergeau, F., "UTF-8, a transformation format of ISO
              10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
              2003, <https://www.rfc-editor.org/rfc/rfc3629>.

   [RFC4291]  Hinden, R. and S. Deering, "IP Version 6 Addressing
              Architecture", RFC 4291, DOI 10.17487/RFC4291, February
              2006, <https://www.rfc-editor.org/rfc/rfc4291>.

   [RFC4648]  Josefsson, S., "The Base16, Base32, and Base64 Data
              Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
              <https://www.rfc-editor.org/rfc/rfc4648>.

   [RFC5234]  Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
              Specifications: ABNF", STD 68, RFC 5234,
              DOI 10.17487/RFC5234, January 2008,
              <https://www.rfc-editor.org/rfc/rfc5234>.

   [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, <https://www.rfc-editor.org/rfc/rfc6125>.

   [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,
              <https://www.rfc-editor.org/rfc/rfc6234>.

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,
              <https://www.rfc-editor.org/rfc/rfc8032>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [RFC8259]  Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
              Interchange Format", STD 90, RFC 8259,
              DOI 10.17487/RFC8259, December 2017,
              <https://www.rfc-editor.org/rfc/rfc8259>.

   [RFC8446]  Rescorla, E., "The Transport Layer Security (TLS) Protocol
              Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
              <https://www.rfc-editor.org/rfc/rfc8446>.

   [RFC8785]  Rundgren, A., Jordan, B., and S. Erdtman, "JSON
              Canonicalization Scheme (JCS)", RFC 8785,
              DOI 10.17487/RFC8785, June 2020,
              <https://www.rfc-editor.org/rfc/rfc8785>.

   [RFC9110]  Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
              Ed., "HTTP Semantics", STD 97, RFC 9110,
              DOI 10.17487/RFC9110, June 2022,
              <https://www.rfc-editor.org/rfc/rfc9110>.

   [RFC9113]  Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113,
              DOI 10.17487/RFC9113, June 2022,
              <https://www.rfc-editor.org/rfc/rfc9113>.

18.2.  Informative References

   [DMLS]     Chathi, H., "Decentralised MLS", 29 May 2023,
              <https://gitlab.matrix.org/matrix-org/mls-ts/-
              /blob/48efb972075233c3a0f3e3ca01c4d4f888342205/
              decentralised.org>.

   [MSC3820]  Ralston, T., "MSC3820: Room Version 11", 8 June 2023,
              <https://github.com/matrix-org/matrix-spec-proposals/
              pull/3820>.

   [MSC3995]  Ralston, T., "MSC3995: [WIP] Linearized Matrix", 12 April
              2023, <https://github.com/matrix-org/matrix-spec-
              proposals/pull/3995>.

Ralston & Hodgson       Expires 29 December 2023               [Page 72]
Internet-Draft              Linearized Matrix                  June 2023

   [PerspectivesProject]
              "Perspectives Project", 2 July 2017,
              <https://web.archive.org/web/20170702024706/
              https://perspectives-project.org/>.

   [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,
              <https://www.rfc-editor.org/rfc/rfc5280>.

   [RFC6120]  Saint-Andre, P., "Extensible Messaging and Presence
              Protocol (XMPP): Core", RFC 6120, DOI 10.17487/RFC6120,
              March 2011, <https://www.rfc-editor.org/rfc/rfc6120>.

   [RFC9364]  Hoffman, P., "DNS Security Extensions (DNSSEC)", BCP 237,
              RFC 9364, DOI 10.17487/RFC9364, February 2023,
              <https://www.rfc-editor.org/rfc/rfc9364>.

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]