<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.4 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ralston-mimi-linearized-matrix-04" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.19.0 -->
  <front>
    <title abbrev="Linearized Matrix">Linearized Matrix</title>
    <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-linearized-matrix-04"/>
    <author fullname="Travis Ralston">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>travisr@matrix.org</email>
      </address>
    </author>
    <author fullname="Matthew Hodgson">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>matthew@matrix.org</email>
      </address>
    </author>
    <date year="2024" month="January" day="11"/>
    <area>Applications and Real-Time</area>
    <workgroup>More Instant Messaging Interoperability</workgroup>
    <keyword>matrix</keyword>
    <keyword>linearized</keyword>
    <keyword>interoperability</keyword>
    <keyword>messaging</keyword>
    <keyword>mimi</keyword>
    <keyword>decentralized</keyword>
    <abstract>
      <?line 66?>

<t>This document specifies Linearized Matrix (LM). LM is an extensible protocol for interoperability
between messaging providers, using Matrix's (<eref target="https://matrix.org">matrix.org</eref>) decentralized room
model. LM simplifies the Directed Acyclic Graph (DAG) persistence of Matrix while maintaining
compatibility with non-linearized servers within a room. It does this by using a doubly-linked list
of events/messages per room with hub and spoke fanout.</t>
      <t>LM's extensibility enables a wide range of transport protocol and end-to-end encryption possibilities.
This document uses Matrix's room access control semantics supported by Messaging Layer Security (MLS),
transported via HTTPS and JSON. The details of which server-to-server transport to use and what is
put over MLS are replaceable.</t>
      <t>The threat model of LM does not place trust in a central owning server for each conversation. Instead,
it defines a hub server which handles maintaining linearized room history for other servers in the
room. This model permits transparent interconnection between LM servers and Matrix servers, in the
same room.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://turt2live.github.io/ietf-mimi-linearized-matrix/draft-ralston-mimi-linearized-matrix.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ralston-mimi-linearized-matrix/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        More Instant Messaging Interoperability Working Group mailing list (<eref target="mailto:mimi@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/mimi/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/mimi/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/turt2live/ietf-mimi-linearized-matrix"/>.</t>
    </note>
  </front>
  <middle>
    <?line 84?>

<section anchor="int-intro">
      <name>Introduction</name>
      <t>Linearized Matrix derives from Matrix (<eref target="https://matrix.org">matrix.org</eref>). Matrix is an interoperable
decentralized communications protocol with an open specification. Matrix uses a Directed Acyclic Graph
(DAG) to persist rooms, synchronizing the DAG between servers. Linearized Matrix uses an append-only
doubly-linked list. A hub server is present in each room to persist the linked list, and to handle
linearization of events (user/application messages, as well as room configuration changes) from other
servers.</t>
      <t>The hub server in a room does not act as an owner for the room. All rooms support the doubly-linked
list and a DAG at the same time. The precise details of DAG and linked list interconnection are not
covered by this document; they are out of scope for the More Instant Messaging Interoperability (MIMI)
working group. Full details are available within the Matrix specification process as <xref target="MSC3995"/>. Where
applicable, this document covers the mandatory components.</t>
      <t>As rooms support these two representations, this permits a variable threat model. Messaging providers
who want to deliver all their messages/don't trust other servers to deliver their messages would choose
the DAG representation, at the cost of implementation complexity. Providers using the Linearized Matrix
representation place trust in the hub server to deliver the messages. Those providers attach verifiable
hashes and signatures to each event as a safeguard against the hub server modifying the events.</t>
      <t>The primary exports of Linearized Matrix are the room model and the rules which govern how a room
accepts events. This document specifies a server-centric approach, where one or more servers perform
access control. With some changes, it can become client-centric too. This document also specifies a
transport for synchronizing the doubly-linked list to other servers. More efficient and scalable
transport methods should replace this example.</t>
      <t>In a similar fashion, this document specifies how Messaging Layer Security (MLS) <xref target="I-D.ietf-mls-protocol"/>
        <xref target="I-D.ietf-mls-architecture"/> could run over a Linearized Matrix room. User messages use MLS, while
state events (room configuration information) are plain-text in this iteration of the document. Clients
synchronize room and MLS group membership, while servers verify those memberships. This ensures that
users who are not in the room are unable to gain access to encrypted messages.</t>
      <t>A key component for interoperability is consistent access control semantics. Where a single server
'owns' a room, it can establish arbitrary measures. For example, an owning provider might decide that
a different kind of password is required to join a room. This diminishes the user experience on providers
who do not (or can not) support those custom measures. With decentralization, all participating servers
must use the same consistent set of access controls. Linearized Matrix uses a decentralized room model
for this reason, with linear room history for ease of implementation.</t>
      <t>Linearized Matrix also supports transferring a hub to a different server in the room. This enables
two major features: a hub server that wishes to leave the room can do so, as it is no longer responsible
for handling events for the room, and because the hub could change at any time, access control semantics
must remain consistent. As a bonus, hub transfers make it possible for a (non-linearized) Matrix server
to take hub status. When it becomes the hub, it takes responsibility for linearizing the room's DAG
for other Linearized Matrix servers in the room. The DAG linearization algorithm is not specified in
this document; it is out of scope for the MIMI working group.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<t>This document uses <xref target="I-D.ralston-mimi-terminology"/> for the majority of terminology.</t>
      <t>This document additionally defines:</t>
      <t><strong>Rejection</strong>: An event which is "rejected" is not relayed to any local clients and is not appended
to the room in any way.</t>
      <t><strong>Soft Failure</strong>: An event which is "soft-failed" <bcp14>SHOULD NOT</bcp14> be relayed to any local clients, nor be
used as in <tt>auth_events</tt> if possible. The event is otherwise appended to the room as per usual.</t>
      <t>Further terms are introduced in-context within this document.</t>
      <t><strong>TODO</strong>: We should move/copy those definitions up here anyways.</t>
    </section>
    <section anchor="architecture">
      <name>Architecture</name>
      <t>For a given conversation/room:</t>
      <artset>
        <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="400" width="552" viewBox="0 0 552 400" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
            <path d="M 8,128 L 8,192" fill="none" stroke="black"/>
            <path d="M 56,72 L 56,128" fill="none" stroke="black"/>
            <path d="M 56,192 L 56,272" fill="none" stroke="black"/>
            <path d="M 104,200 L 104,240" fill="none" stroke="black"/>
            <path d="M 112,64 L 112,120" fill="none" stroke="black"/>
            <path d="M 160,128 L 160,192" fill="none" stroke="black"/>
            <path d="M 288,224 L 288,288" fill="none" stroke="black"/>
            <path d="M 336,296 L 336,352" fill="none" stroke="black"/>
            <path d="M 392,128 L 392,192" fill="none" stroke="black"/>
            <path d="M 392,288 L 392,344" fill="none" stroke="black"/>
            <path d="M 440,72 L 440,128" fill="none" stroke="black"/>
            <path d="M 440,224 L 440,288" fill="none" stroke="black"/>
            <path d="M 496,64 L 496,120" fill="none" stroke="black"/>
            <path d="M 544,128 L 544,192" fill="none" stroke="black"/>
            <path d="M 40,32 L 128,32" fill="none" stroke="black"/>
            <path d="M 424,32 L 512,32" fill="none" stroke="black"/>
            <path d="M 40,64 L 128,64" fill="none" stroke="black"/>
            <path d="M 424,64 L 512,64" fill="none" stroke="black"/>
            <path d="M 8,128 L 160,128" fill="none" stroke="black"/>
            <path d="M 392,128 L 544,128" fill="none" stroke="black"/>
            <path d="M 160,144 L 248,144" fill="none" stroke="black"/>
            <path d="M 320,144 L 384,144" fill="none" stroke="black"/>
            <path d="M 168,176 L 248,176" fill="none" stroke="black"/>
            <path d="M 320,176 L 392,176" fill="none" stroke="black"/>
            <path d="M 8,192 L 160,192" fill="none" stroke="black"/>
            <path d="M 392,192 L 544,192" fill="none" stroke="black"/>
            <path d="M 288,224 L 440,224" fill="none" stroke="black"/>
            <path d="M 104,240 L 144,240" fill="none" stroke="black"/>
            <path d="M 216,240 L 288,240" fill="none" stroke="black"/>
            <path d="M 56,272 L 144,272" fill="none" stroke="black"/>
            <path d="M 216,272 L 280,272" fill="none" stroke="black"/>
            <path d="M 288,288 L 440,288" fill="none" stroke="black"/>
            <path d="M 320,352 L 408,352" fill="none" stroke="black"/>
            <path d="M 320,384 L 408,384" fill="none" stroke="black"/>
            <path d="M 40,32 C 31.16936,32 24,39.16936 24,48" fill="none" stroke="black"/>
            <path d="M 128,32 C 136.83064,32 144,39.16936 144,48" fill="none" stroke="black"/>
            <path d="M 424,32 C 415.16936,32 408,39.16936 408,48" fill="none" stroke="black"/>
            <path d="M 512,32 C 520.83064,32 528,39.16936 528,48" fill="none" stroke="black"/>
            <path d="M 40,64 C 31.16936,64 24,56.83064 24,48" fill="none" stroke="black"/>
            <path d="M 128,64 C 136.83064,64 144,56.83064 144,48" fill="none" stroke="black"/>
            <path d="M 424,64 C 415.16936,64 408,56.83064 408,48" fill="none" stroke="black"/>
            <path d="M 512,64 C 520.83064,64 528,56.83064 528,48" fill="none" stroke="black"/>
            <path d="M 320,352 C 311.16936,352 304,359.16936 304,368" fill="none" stroke="black"/>
            <path d="M 408,352 C 416.83064,352 424,359.16936 424,368" fill="none" stroke="black"/>
            <path d="M 320,384 C 311.16936,384 304,376.83064 304,368" fill="none" stroke="black"/>
            <path d="M 408,384 C 416.83064,384 424,376.83064 424,368" fill="none" stroke="black"/>
            <polygon class="arrowhead" points="504,120 492,114.4 492,125.6" fill="black" transform="rotate(90,496,120)"/>
            <polygon class="arrowhead" points="448,72 436,66.4 436,77.6" fill="black" transform="rotate(270,440,72)"/>
            <polygon class="arrowhead" points="400,344 388,338.4 388,349.6" fill="black" transform="rotate(90,392,344)"/>
            <polygon class="arrowhead" points="392,144 380,138.4 380,149.6" fill="black" transform="rotate(0,384,144)"/>
            <polygon class="arrowhead" points="344,296 332,290.4 332,301.6" fill="black" transform="rotate(270,336,296)"/>
            <polygon class="arrowhead" points="288,272 276,266.4 276,277.6" fill="black" transform="rotate(0,280,272)"/>
            <polygon class="arrowhead" points="176,176 164,170.4 164,181.6" fill="black" transform="rotate(180,168,176)"/>
            <polygon class="arrowhead" points="120,120 108,114.4 108,125.6" fill="black" transform="rotate(90,112,120)"/>
            <polygon class="arrowhead" points="112,200 100,194.4 100,205.6" fill="black" transform="rotate(270,104,200)"/>
            <polygon class="arrowhead" points="64,72 52,66.4 52,77.6" fill="black" transform="rotate(270,56,72)"/>
            <g class="text">
              <text x="76" y="52">Client</text>
              <text x="112" y="52">A</text>
              <text x="460" y="52">Client</text>
              <text x="496" y="52">B</text>
              <text x="184" y="100">Client-Server</text>
              <text x="256" y="100">API</text>
              <text x="284" y="148">events</text>
              <text x="80" y="164">Provider/Server</text>
              <text x="464" y="164">Provider/Server</text>
              <text x="80" y="180">A</text>
              <text x="284" y="180">events</text>
              <text x="464" y="180">B</text>
              <text x="240" y="196">Server-Server</text>
              <text x="332" y="196">Protocol</text>
              <text x="180" y="244">events</text>
              <text x="360" y="260">Provider/Server</text>
              <text x="180" y="276">events</text>
              <text x="360" y="276">C</text>
              <text x="356" y="372">Client</text>
              <text x="392" y="372">C</text>
            </g>
          </svg>
        </artwork>
        <artwork type="ascii-art"><![CDATA[
   .------------.                                  .------------.
  |   Client A   |                                |   Client B   |
   '---------+--'                                  '---------+--'
      ^      |                                        ^      |
      |      |  Client-Server API                     |      |
      |      V                                        |      V
+-----+------------+                            +-----+------------+
|                  +----------( events )------->|                  |
| Provider/Server  |                            | Provider/Server  |
|        A         |<---------( events )--------+        B         |
+-----+------------+   Server-Server Protocol   +------------------+
      |     ^
      |     |                      +------------------+
      |     +----( events )--------+                  |
      |                            | Provider/Server  |
      +----------( events )------->|        C         |
                                   +------------+-----+
                                         ^      |
                                         |      |
                                         |      V
                                      .--+---------.
                                     |   Client C   |
                                      '------------'
]]></artwork>
      </artset>
      <t>In this diagram, events (<xref target="int-pdu"/>) are objects which carry information about the room as well as messages
between users within that room.</t>
      <t>Server A is acting as a hub for the other two servers in the diagram. 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. Servers communicate
with each other using the API surface described by <xref target="int-transport"/>.</t>
      <t>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.</t>
      <t>This leads to two distinct roles:</t>
      <ul spacing="normal">
        <li>
          <t><strong>Hub server</strong>: the server responsible for holding conversation history on behalf of
other servers in the room.</t>
        </li>
        <li>
          <t><strong>Participant server</strong>: any non-hub server. This server <bcp14>MAY</bcp14> persist conversation history
or rely on the hub server instead.</t>
        </li>
      </ul>
      <t><strong>OPEN QUESTION</strong>: 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)</t>
      <t><strong>OPEN QUESTION</strong>: Should we instead require that each server persist events they create, with the hub
being responsible for purely distribution/fetching? It'd be in the hub's best interest to store all
history, but equally if it can rebuild the room by reaching out to origin servers then it might be
fine enough (it'd only be storing event IDs rather than whole events).</t>
      <section anchor="int-server-names">
        <name>Server Names</name>
        <t>Each messaging provider is referred to as a "server" and 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.</t>
        <t>A server name <bcp14>MUST</bcp14> be compliant with <xref section="2.1" sectionFormat="of" target="RFC1123"/>. Improper server names <bcp14>MUST</bcp14> be
considered "uncontactable" by a server.</t>
        <t>A server <bcp14>MUST NOT</bcp14> 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 a certificate for (required in <xref target="int-transport"/>). Additionally, servers <bcp14>SHOULD NOT</bcp14> use
an explicit port in their server name for similar portability reasons.</t>
        <t>The approximate ABNF <xref target="RFC5234"/> grammar for a server name is:</t>
        <artwork><![CDATA[
server_name = hostname [ ":" port ]
port        = 1*5DIGIT
hostname    = 1*255dns-char
dns-char    = DIGIT / ALPHA / "-" / "."
]]></artwork>
        <t>Server names <bcp14>MUST</bcp14> be treated as case sensitive (<tt>eXaMpLe.OrG</tt>, <tt>example.org</tt>, and <tt>EXAMPLE.ORG</tt>
are 3 different servers). Server names <bcp14>SHOULD</bcp14> be lower case (<tt>example.org</tt>) and <bcp14>SHOULD NOT</bcp14> 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 <xref section="2.1" sectionFormat="of" target="RFC1123"/>.</t>
        <t>Examples:</t>
        <ul spacing="normal">
          <li>
            <t><tt>example.org</tt> (DNS host name)</t>
          </li>
          <li>
            <t><tt>example.org:5678</tt> (DNS host name with explicit port)</t>
          </li>
        </ul>
      </section>
      <section anchor="int-room-id">
        <name>Rooms</name>
        <t>Rooms hold the same definition under <xref target="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.</t>
        <t>The different chat types are represented by rooms through state events (<xref target="int-state-events"/>), which
ultimately change how the different algorithms in the room version (<xref target="int-room-versions"/>) behave.</t>
        <t>Rooms have a single internal "Room ID" to identify them from another room. The ABNF <xref target="RFC5234"/>
grammar for a room ID is:</t>
        <artwork><![CDATA[
room_id = "!" room_id_localpart ":" server_name
room_id_localpart = 1*opaque
opaque = DIGIT / ALPHA / "-" / "." / "~" / "_"
]]></artwork>
        <t><tt>server_name</tt> is inherited from <xref target="int-server-names"/>.</t>
        <t><tt>room_id</tt> <bcp14>MUST NOT</bcp14> exceed 255 characters and <bcp14>MUST</bcp14> be treated as case sensitive.</t>
        <t>Example: <tt>!abc:example.org</tt>.</t>
        <t>The <tt>server_name</tt> for a room ID does <em>NOT</em> 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.</t>
        <t>The entire room ID after the <tt>!</tt> sigil <bcp14>MUST</bcp14> be treated as opaque. No part of the room ID should
be parsed, and cannot be assumed to be human-readable.</t>
        <section anchor="int-room-versions">
          <name>Room Versions</name>
          <t><strong>TODO</strong>: We should consider naming this something else.</t>
          <t>Each room declares which room version it's using, and each room version (identified by a single
string) describes the specific algorithms a server needs to follow in order to particpate in rooms
with that version. Room versions are immutable once specified, as otherwise a change in algorithms
could cause a split-brain between servers participating in affected rooms.</t>
          <t>Room versions prefixed with <tt>I.</tt> <bcp14>MUST</bcp14> only be used within the IETF specification process.
Room versions consisting solely of <tt>0-9</tt> and <tt>.</tt> <bcp14>MUST</bcp14> only be used by the Matrix protocol.</t>
          <t>This document as a whole describes <tt>I.1</tt> as a room version.</t>
          <t>Servers <bcp14>MUST</bcp14> implement support for <tt>I.1</tt> at a minimum. Servers <bcp14>SHOULD</bcp14> use <tt>I.1</tt> when creating
new rooms.</t>
          <t><strong>Implementation note</strong>: Currently <tt>I.1</tt> is not a real thing. Use
<tt>org.matrix.i-d.ralston-mimi-linearized-matrix.02</tt> when testing against other Linearized Matrix
implementations. This string may be updated later to account for breaking changes.</t>
          <t><strong>Implementation note</strong>: <tt>org.matrix.i-d.ralston-mimi-linearized-matrix.00</tt> also exists in the
wild, defining a set of algorithms which exist in a prior version of this document (00 and 01).</t>
          <t><strong>TODO</strong>: Remove implementation notes.</t>
          <t>There is no implicit ordering or hierarchy to room versions. Future room versions, such as an <tt>I.2</tt>,
can choose to build upon <tt>I.1</tt>'s algorithms or start completely from scratch if they prefer.</t>
          <t>A room version has the following algorithms defined:</t>
          <ul spacing="normal">
            <li>
              <t>Event authorization - Rules which govern when events are accepted, rejected, or soft-failed
by a server. For <tt>I.1</tt>, this is <xref target="int-auth-rules"/>.</t>
            </li>
            <li>
              <t>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.
For <tt>I.1</tt>, this is <xref target="int-redactions"/>.</t>
            </li>
            <li>
              <t>Event format - Which fields are expected to be present on an event, and the schema for each. For
<tt>I.1</tt>, this is <xref target="int-pdu"/>.</t>
            </li>
            <li>
              <t>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. For <tt>I.1</tt>, this is
<xref target="int-canonical-json"/>.</t>
            </li>
            <li>
              <t>Hub selection - Rules around picking the hub server and transferring to a new hub. For <tt>I.1</tt>,
this is <xref target="int-hub-selection"/>.</t>
            </li>
            <li>
              <t>Identifier grammar - All identifiers (room IDs, user IDs, event IDs, etc) can change grammar
within a room version. As such, they <bcp14>SHOULD</bcp14> generally be treated as opaque as possible over a
transport. For <tt>I.1</tt>, these details are described in <xref target="int-server-names"/>, <xref target="int-room-id"/>,
<xref target="int-user-id"/>, <xref target="int-device-id"/>, and <xref target="int-pdu"/>.</t>
            </li>
          </ul>
          <t>The transport between servers is decoupled from the algorithms above. For example, events are
treated as blobs with no specific format over the wire but have strict schema in the context
of a room or room version. Endpoints <bcp14>MUST</bcp14> be designed with this distinction in mind.</t>
          <t>Each room version has a "stable" or "unstable" designation. Stable room versions <bcp14>SHOULD</bcp14> be used
in production by messaging providers. Unstable room versions might contain bugs or are not yet
fully specified and <bcp14>SHOULD NOT</bcp14> be used in production by messaging providers.</t>
          <t><tt>I.1</tt> shall be considered "stable".</t>
          <t><strong>Implementation note</strong>: <tt>org.matrix.i-d.ralston-mimi-linearized-matrix.02</tt> is considered "unstable".</t>
          <t><strong>TODO</strong>: Remove implementation notes.</t>
          <t><strong>TODO</strong>: Matrix considers a version as stable once accepted through FCP. When would be the
process equivalent for the IETF?</t>
          <t>The ABNF <xref target="RFC5234"/> grammar for a room version is:</t>
          <artwork><![CDATA[
room_version = 1*128room_version_char
room_version_char = DIGIT
                  / %x61-7A         ; a-z
                  / "-" / "."
]]></artwork>
          <t>Examples:</t>
          <ul spacing="normal">
            <li>
              <t><tt>1</tt></t>
            </li>
            <li>
              <t><tt>I.1</tt></t>
            </li>
            <li>
              <t><tt>org.example.my-room-version</tt></t>
            </li>
          </ul>
          <t>Room versions not formally specified <bcp14>SHOULD</bcp14> be prefixed using reverse domain name notation,
creating a sort of namespace. <tt>org.example.my-room-version</tt> is an example of this.</t>
        </section>
      </section>
      <section anchor="int-user-id">
        <name>Users</name>
        <t>As described by <xref target="I-D.ralston-mimi-terminology"/>, a user is typically a human which operates
a client. Each user has a distinct user ID.</t>
        <t>The ABNF <xref target="RFC5234"/> grammar for a user ID is:</t>
        <artwork><![CDATA[
user_id = "@" user_id_localpart ":" server_name
user_id_localpart = 1*user_id_char
user_id_char = DIGIT
             / %x61-7A                   ; a-z
             / "-" / "." / "="
             / "_" / "/" / "+"
]]></artwork>
        <t><tt>server_name</tt> is inherited from <xref target="int-server-names"/>.</t>
        <t><tt>user_id</tt> <bcp14>MUST NOT</bcp14> exceed 255 characters and <bcp14>MUST</bcp14> be treated as case sensitive.</t>
        <t>Examples:</t>
        <ul spacing="normal">
          <li>
            <t><tt>@alice:example.org</tt></t>
          </li>
          <li>
            <t><tt>@watch/for/slashes:example.org</tt></t>
          </li>
        </ul>
        <t><tt>user_id_localpart</tt> <bcp14>SHOULD</bcp14> be human-readable and notably <bcp14>MUST NOT</bcp14> contain uppercase letters.</t>
        <t><tt>server_name</tt> denotes the domain name (<xref target="int-server-names"/>) which allocated the ID, or would allocate
the ID if the user doesn't exist yet.</t>
        <t>Identity systems and messaging providers <bcp14>SHOULD NOT</bcp14> use a phone number in a localpart. Using a phone
number would mean that when a human operator's changes their phone number then they'd lose access to
their existing chats and potentially gain access to any chats the new number is participating in.
Providers which use phone numbers <bcp14>SHOULD</bcp14> ensure the new user ID is not in chats belonging to a different
logical user. To prevent this case, a GUID (scoped to the allocating server) or an account ID is
recommended as a localpart, allowing users to change their phone number without losing chats.</t>
        <t>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.</t>
        <t>User IDs are sometimes informally referenced as "MXIDs", short for "Matrix User IDs".</t>
      </section>
      <section anchor="int-device-id">
        <name>Devices</name>
        <t>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.</t>
        <t>Because device IDs are used as "key versions" in a key ID (<xref target="int-signing"/>), they have a compatible
ABNF <xref target="RFC5234"/> grammar:</t>
        <artwork><![CDATA[
device_id = 1*key_version_char
device_id_char = ALPHA / DIGIT / "_"
]]></artwork>
      </section>
      <section anchor="int-pdu">
        <name>Events</name>
        <t>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 <tt>type</tt>
to distinguish them, and use reverse domain name notation to namespace custom events
(for example, <tt>org.example.appname.eventname</tt>).</t>
        <t>Event types using <tt>m.</tt> as a prefix <bcp14>MUST</bcp14> only be used by the protocol.</t>
        <t>When events are traversing a transport to another server they are referred to as a
<strong>Persistent Data Unit</strong> or <strong>PDU</strong>. Structurally, an event and PDU are the same.</t>
        <t>An event has the following minimum fields:</t>
        <ul spacing="normal">
          <li>
            <t><tt>room_id</tt> (string; required) - The room ID for where the event is being sent. This <bcp14>MUST</bcp14> be
a valid room ID (<xref target="int-room-id"/>).</t>
          </li>
          <li>
            <t><tt>type</tt> (string; required) - A UTF-8 <xref target="RFC3629"/> string to distinguish different data types
being carried by events. Event types are case sensitive. This <bcp14>MUST NOT</bcp14> exceed 255 characters.</t>
          </li>
          <li>
            <t><tt>state_key</tt> (string; optional) - A UTF-8 <xref target="RFC3629"/> string to further distinguish an event
as a state event (see <xref target="int-state-events"/>). Can be an empty string. This <bcp14>MUST NOT</bcp14> exceed 255
characters.  </t>
            <t>
Each event type specifies its own state key requirements. For <tt>m.room.member</tt> (<xref target="int-ev-member"/>),
the state key is the user ID (<xref target="int-user-id"/>) for which the membership applies to. For
<tt>m.room.join_rules</tt> (<xref target="int-ev-join-rules"/>), this is an empty string. For a custom event type
this may be an opaque string such as a UUID or randomly generated string.</t>
          </li>
          <li>
            <t><tt>sender</tt> (string; required) - The user ID which is sending this event. This <bcp14>MUST</bcp14> be a valid
user ID (<xref target="int-user-id"/>).</t>
          </li>
          <li>
            <t><tt>origin_server_ts</tt> (64-bit integer; required) - The milliseconds since the unix epoch for when this
event was created.</t>
          </li>
          <li>
            <t><tt>hub_server</tt> (string; optional) - When a hub server is converting an LPDU (<xref target="int-lpdu"/>) to a
formal event, it <bcp14>MUST</bcp14> specify its own server name (<xref target="int-server-names"/>) here. The value <bcp14>MUST</bcp14> be
a valid server name.  </t>
            <t>
To support interconnection with non-linearized Matrix, as discussed in <xref target="int-intro"/>, events
created outside of a hub server <bcp14>MUST NOT</bcp14> populate this field.</t>
          </li>
          <li>
            <t><tt>content</tt> (object; required) - The event content. The specific schema depends on the event
type. Clients and servers processing an event <bcp14>MUST NOT</bcp14> assume the <tt>content</tt> 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.</t>
          </li>
          <li>
            <t><tt>hashes</tt> (object; required) - The content hashes (<xref target="int-content-hashes"/>) for the event. There is
a special <tt>lpdu</tt> key to contain the LPDU (partial PDU schema; see <xref target="int-lpdu"/>) hashes, which is
itself keyed by hash algorithm and has the encoded hash as the value. The <tt>hashes</tt> object, outside
of <tt>lpdu</tt>, similarly is keyed by hash algorithm with encoded hash values.  </t>
            <t>
Events which specify a <tt>hub_server</tt> <bcp14>MUST</bcp14> additionally contain an <tt>lpdu</tt> hash. All other events <bcp14>MUST
NOT</bcp14> contain <tt>lpdu</tt> hashes. This is to support interconnection with non-linearized Matrix, as discussed
in <xref target="int-intro"/>.</t>
          </li>
          <li>
            <t><tt>signatures</tt> (object; required) - Keyed first by domain name then by key ID, the signatures for
the event.</t>
          </li>
          <li>
            <t><tt>auth_events</tt> (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 (<xref target="int-auth-selection"/>).</t>
          </li>
          <li>
            <t><tt>prev_events</tt> (array of strings; required) - This field is to support interconnection with
non-linearized Matrix, discussed in <xref target="int-intro"/>. Events which specify a <tt>hub_server</tt> are expected
to have exactly 1 entry in this array, while other events <bcp14>MAY</bcp14> have 1 or more entries.</t>
          </li>
        </ul>
        <t>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
(<xref target="int-reference-hashes"/>) then encode it using URL-safe Unpadded Base64 (<xref target="int-unpadded-base64"/>)
and prefix that with the event ID sigil, <tt>$</tt>. For example, <tt>$nKHVqt3iyLA_HEE8lT1yUaaVjjBRR-fAqpN4t7opadc</tt>.</t>
        <t>Using a reference hash in the event ID prevents other servers from changing what that event ID represents.
If an event ID was just a UUID (or similar), any server along the send or receive path could swap the
actual event payload out for a different event. The hashes and signatures in this case do nothing to
protect the actual event, as a malicious server can simply generate legal hashes/signatures as part of
their modification. If we add a namespace condition where the event ID <em>must</em> reference the same server
name as the <tt>sender</tt> (<tt>$uuid:example.org</tt>) then the sending server is free to re-assign the event ID
to a different payload during the sending of that event, though all other servers along the send/receive
path cannot change the event. This is particularly problematic if the event's sender is the hub for
the room: the hub can send one copy of an event to half the room, and a very different copy to the other
half while still maintaining the same event ID for both halves. To fix this, a hash of the event itself
would need to become part of the event ID such that any modification or reassignment of the event ID
is made obvious to receipient servers. This could be a tuple of <tt>(uuid, hash)</tt>, though for simplicity
this document uses just the reference hash on its own.</t>
        <t>With event IDs containing hashes of the events it's theoretically possible for a sufficiently motivated
person to build a database of event IDs. With that database, they could eventually determine enough
information to identify parts of the event payload itself. There is not enough anchoring information
on an event (or sent over the transport) for this to be efficient or effective, however.</t>
        <t>The ABNF <xref target="RFC5234"/> for an event ID is:</t>
        <artwork><![CDATA[
event_id = "$" reference_hash
reference_hash = 1*urlsafe_unpadded_base64_char
urlsafe_unpadded_base64_char = ALPHA / DIGIT / "-" / "_"
]]></artwork>
        <t>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 <tt>auth_events</tt>
will make sense, for example). The sender and receiver will need to review that their implementation
matches the specification in this case.</t>
        <t>Events are treated as JSON <xref target="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.</t>
        <t>An example event is:</t>
        <sourcecode type="json"><![CDATA[
{
  "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"]
}
]]></sourcecode>
        <t>An event/PDU <bcp14>MUST NOT</bcp14> exceed 65536 bytes when formatted using Canonical JSON (<xref target="int-canonical-json"/>).
Note that this includes all <tt>signatures</tt> on the event.</t>
        <t>Fields have no size limit unless specified above, other than the maximum 65536 bytes for the whole
event.</t>
        <section anchor="int-lpdu">
          <name>Linearized PDU</name>
          <t>All events generated by participant servers are routed through the hub, but the participant servers
themselves are unable to populate fields like <tt>prev_events</tt> because they can't guarantee order and
those fields contribute to the event ID, signatures, and overall validity. To fix this, participant
servers send the hub server a "Linearized PDU" or "LPDU" which does not include the fields they cannot
set while still ensuring integrity of the event contents themselves.</t>
          <t>The participant server <bcp14>MUST NOT</bcp14> populate the following fields on events (LPDUs) they are sending to
the hub:</t>
          <ul spacing="normal">
            <li>
              <t><tt>auth_events</tt> - the participant cannot reliably determine what allows it to send the event.</t>
            </li>
            <li>
              <t><tt>prev_events</tt> - the participant cannot reliably know what event precedes theirs.</t>
            </li>
            <li>
              <t><tt>hashes</tt> (except <tt>hashes.lpdu</tt>) - top-level hashes cover the above two fields.</t>
            </li>
          </ul>
          <t>The participant server <bcp14>MUST</bcp14> populate the <tt>hashes.lpdu</tt> object, covering a content hash
(<xref target="int-content-hashes"/>) 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.</t>
          <t>The participant server will receive an echo of the fully-formed event from the hub once appended
to the room.</t>
        </section>
        <section anchor="int-state-events">
          <name>State Events</name>
          <t>State events track metadata for the room, such as name, topic, and members. State is keyed by a
tuple of <tt>type</tt> and <tt>state_key</tt>. The state "at" an event is the set of state events which have
the most recent (in terms of event ordering, not timestamp) state tuple.</t>
          <t>For example, consider the following (simplified) room history:</t>
          <sourcecode type="json"><![CDATA[
[
   /* in all events, irrelevant fields are not shown for brevity */

   /* 0 */ {
      "type": "m.room.create", "state_key": ""
   },

   /* 1 */ {
      "type": "m.room.member", "state_key": "@alice:example.org"
   },

   /* 2 */ {
      "type": "m.room.encrypted"
   },

   /* 3 */ {
      "type": "m.room.member", "state_key": "@bob:example.org"
   },

   /* 4 */ {
      "type": "m.room.member", "state_key": "@alice:example.org"
   }
]
]]></sourcecode>
          <t>The state at index 2 consists of Alice's <tt>m.room.member</tt> event (<xref target="int-ev-member"/>) and the <tt>m.room.create</tt>
event (<xref target="int-ev-create"/>) from the room. The <tt>m.room.encrypted</tt> event itself is not a state event
and therefore does not get appended to the state "at" any particular event.</t>
          <t>The state at index 4 would have Alice's new <tt>m.room.member</tt> event, Bob's <tt>m.room.member</tt> event, and the
<tt>m.room.create</tt> event from before. Alice's old membership event is overridden due to having the same
<tt>type</tt> and <tt>state_key</tt> as the previous event. Note however that the state at index 3 still contains
the older membership event, as the new event happens later with respect to event ordering.</t>
          <t>"Current state" is the state at the most recent event in the room. Calculating the state at a given
event is needed for the authorization rules (<xref target="int-auth-rules"/>) and event visibility (<xref target="int-calc-event-visibility"/>)
algorithms. Clients additionally need to know current state to show accurate room names, topics,
avatars, etc.</t>
          <section anchor="int-stripped-state">
            <name>Stripped State</name>
            <t>Stripped state events are extremely simplified state events to provide context to a user for an invite
(<xref target="int-transport-invites"/>) or knock (<xref target="int-transport-knocks"/>). Servers and clients have no ability
to verify the events outside of the context for a room, so all such fields are removed. Servers and
clients <bcp14>MUST NOT</bcp14> rely on the events being accurate because they cannot independently verify them.</t>
            <t>When generating stripped state for an invite or knock, the following events <bcp14>SHOULD</bcp14> be included
if present in the current room state itself:</t>
            <ul spacing="normal">
              <li>
                <t><tt>m.room.create</tt> (<xref target="int-ev-create"/>)</t>
              </li>
              <li>
                <t><tt>m.room.name</tt> (<strong>TODO</strong>: Link)</t>
              </li>
              <li>
                <t><tt>m.room.avatar</tt> (<strong>TODO</strong>: Link)</t>
              </li>
              <li>
                <t><tt>m.room.topic</tt> (<strong>TODO</strong>: Link)</t>
              </li>
              <li>
                <t><tt>m.room.join_rules</tt> (<xref target="int-ev-join-rules"/>)</t>
              </li>
              <li>
                <t><tt>m.room.canonical_alias</tt> (<strong>TODO</strong>: Link)</t>
              </li>
            </ul>
            <t>Servers <bcp14>MAY</bcp14> 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.</t>
            <t>Stripped state events <bcp14>MUST</bcp14> only have <tt>sender</tt>, <tt>type</tt>, <tt>state_key</tt>, and <tt>content</tt> from the event
schema (<xref target="int-pdu"/>).</t>
            <t>Example:</t>
            <sourcecode type="json"><![CDATA[
{
   "type": "m.room.create",
   "sender": "@alice:example.org",
   "state_key": "",
   "content": {
      "room_version": "I.1"
   }
}
]]></sourcecode>
          </section>
        </section>
        <section anchor="event-types">
          <name>Event Types</name>
          <t>Linearized Matrix defines the following event types. The section headers are the event <tt>type</tt>.</t>
          <section anchor="int-ev-create">
            <name><tt>m.room.create</tt></name>
            <t>The very first event in the room. It <bcp14>MUST NOT</bcp14> have any <tt>auth_events</tt> or <tt>prev_events</tt>, and the
domain of the <tt>sender</tt> <bcp14>MUST</bcp14> be the same as the domain in the <tt>room_id</tt>. The <tt>state_key</tt> <bcp14>MUST</bcp14>
be an empty string.</t>
            <t>The <tt>content</tt> for a create event <bcp14>MUST</bcp14> have at least a <tt>room_version</tt> field to denote what set
of algorithms the room is using.</t>
            <t>These conditions are checked as part of the event authorization rules (<xref target="int-auth-rules"/>).</t>
          </section>
          <section anchor="int-ev-join-rules">
            <name><tt>m.room.join_rules</tt></name>
            <t>Defines whether users can join without an invite and other similar conditions. The <tt>state_key</tt>
              <bcp14>MUST</bcp14> be an empty string. Any other state key, including lack thereof, serve no meaning and
are treated as though they were a custom event.</t>
            <t>The <tt>content</tt> for a join rules event <bcp14>MUST</bcp14> have at least a <tt>join_rule</tt> field to denote the
join policy for the room. Allowable values are:</t>
            <ul spacing="normal">
              <li>
                <t><tt>public</tt> - anyone can join without an invite.</t>
              </li>
              <li>
                <t><tt>knock</tt> - users must receive an invite to join, and can request an invite (knock) too.</t>
              </li>
              <li>
                <t><tt>invite</tt> - users must receive an invite to join.</t>
              </li>
            </ul>
            <t><strong>TODO</strong>: Describe <tt>restricted</tt> (and <tt>knock_restricted</tt>) rooms?</t>
            <t><strong>TODO</strong>: What's the default?</t>
          </section>
          <section anchor="int-ev-member">
            <name><tt>m.room.member</tt></name>
            <t>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 <tt>leave</tt> state.</t>
            <t>The <tt>state_key</tt> <bcp14>MUST</bcp14> be a non-empty string denotating the user ID the membership is affecting.</t>
            <t>The <tt>content</tt> for a membership event <bcp14>MUST</bcp14> have at least a <tt>membership</tt> field to denote the
membership state for the user. Allowable values are:</t>
            <ul spacing="normal">
              <li>
                <t><tt>leave</tt> - not participating in the room. If the <tt>state_key</tt> and <tt>sender</tt> do not match, this was
a kick rather than voluntary leave.</t>
              </li>
              <li>
                <t><tt>join</tt> - participating in the room.</t>
              </li>
              <li>
                <t><tt>knock</tt> - requesting an invite to the room.</t>
              </li>
              <li>
                <t><tt>invite</tt> - invited to participate in the room.</t>
              </li>
              <li>
                <t><tt>ban</tt> - implies kicked/not participating. Cannot be invited or join the room without being
unbanned first (moderator sends a kick, essentially).</t>
              </li>
            </ul>
            <t>These conditions are checked as part of the event authorization rules (<xref target="int-auth-rules"/>),
as are the rules for moving between membership states.</t>
            <t>The <tt>content</tt> for a membership event <bcp14>MAY</bcp14> additionally have a <tt>reason</tt> 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.</t>
          </section>
          <section anchor="int-ev-power-levels">
            <name><tt>m.room.power_levels</tt></name>
            <t>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 (<xref target="int-auth-rules"/>).</t>
            <t>The <tt>state_key</tt> <bcp14>MUST</bcp14> be an empty string.</t>
            <t>The <tt>content</tt> for a power levels event <bcp14>SHOULD</bcp14> have at least the following:</t>
            <ul spacing="normal">
              <li>
                <t><tt>ban</tt> (integer) - the level required to ban a user. Defaults to <tt>50</tt> if unspecified.</t>
              </li>
              <li>
                <t><tt>kick</tt> (integer) - the level required to kick a user. Defaults to <tt>50</tt> if unspecified.</t>
              </li>
              <li>
                <t><tt>invite</tt> (integer) - the level required to invite a user. Defaults to <tt>0</tt> if unspecified.</t>
              </li>
              <li>
                <t><tt>redact</tt> (integer) - the level required to redact an event sent by another user. Defaults
to <tt>50</tt> if unspecified.</t>
              </li>
              <li>
                <t><tt>events</tt> (map) - keyed by event type string, the level required to send that event type to
the room. Defaults to an empty map if unspecified.</t>
              </li>
              <li>
                <t><tt>events_default</tt> (integer) - the level required to send events in the room. Overridden by
the <tt>events</tt> map. Defaults to <tt>0</tt> if unspecified.</t>
              </li>
              <li>
                <t><tt>state_default</tt> (integer) - the level required to send state events in the room. Overridden
by the <tt>events</tt> map. Defaults to <tt>50</tt> if unspecified.</t>
              </li>
              <li>
                <t><tt>users</tt> (map) - keyed by user ID, the level of that user. Defaults to an empty map if
unspecified.</t>
              </li>
              <li>
                <t><tt>users_default</tt> (integer) - the level for users. Overridden by the <tt>users</tt> map. Defaults to
<tt>0</tt> if unspecified.</t>
              </li>
            </ul>
            <t><strong>TODO</strong>: Include notifications for at-room here too?</t>
            <t>Note that if no power levels event is specified in the room then the room creator (<tt>sender</tt> of
the <tt>m.room.create</tt> state event) has a default power level of 100.</t>
            <t>These conditions are checked as part of the event authorization rules (<xref target="int-auth-rules"/>).</t>
          </section>
          <section anchor="mroomhistoryvisibility">
            <name><tt>m.room.history_visibility</tt></name>
            <t><strong>TODO</strong>: Describe.</t>
            <section anchor="int-calc-event-visibility">
              <name>Calculating Event Visibility</name>
              <t><strong>TODO</strong>: Describe. (when can a server see an event?). Mention that <tt>m.mls.commit</tt> is exempt.</t>
              <t><strong>TODO</strong>: This section feels like it's in the wrong place. Bring it closer to on-receive-event sections.</t>
            </section>
          </section>
          <section anchor="todo-other-events">
            <name>TODO: Other events</name>
            <t><strong>TODO</strong>: <tt>m.room.name</tt>, <tt>m.room.topic</tt>, <tt>m.room.avatar</tt>, <tt>m.room.canonical_alias</tt></t>
          </section>
        </section>
      </section>
    </section>
    <section anchor="int-mls-considerations">
      <name>MLS Considerations</name>
      <t><strong>TODO</strong>: We should consider running <xref target="I-D.robert-mimi-delivery-service"/> over LM instead.
Using something like <xref target="I-D.mahy-mimi-group-chat"/> would be good for more of a client-side
representation of the LM room model.</t>
      <t>The MIMI working group is chartered to use Messaging Layer Security (MLS) <xref target="I-D.ietf-mls-protocol"/>
        <xref target="I-D.ietf-mls-architecture"/> for encryption in chats, and this document specifies no different.
Each room has a single MLS Group associated with it, both identified by the room ID (<xref target="int-room-id"/>).</t>
      <t>Rooms additionally track membership at a per-user level while MLS tracks group membership at a
per-device level. With this consideration, commits to the MLS Group <bcp14>MUST</bcp14> use <tt>PublicMessage</tt>, giving
the hub server an ability to inspect MLS group membership changes for illegal joins and leaves.</t>
      <t>Encryption can only be enabled at the time the room is created. This prevents the room having encryption
disabled or downgraded without an entirely new room being created. The exact ciphersuite and other
algorithmic details are contained in the <tt>content</tt> for the <tt>m.room.create</tt> event (<xref target="int-ev-create"/>):</t>
      <sourcecode type="json"><![CDATA[
{
   "encryption": {
      "algorithm": "m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519"
   }
}
]]></sourcecode>
      <t><tt>algorithm</tt> denotes which specific algorithm clients <bcp14>MUST</bcp14> use for sending and receiving encrypted
events in the room. If a received event is encrypted using a different algorithm, it <bcp14>MUST</bcp14> be treated
as undecryptable (even if the client has sufficient key information to decrypt it).</t>
      <t><tt>m.mls.v1.</tt> as a prefix describes the behaviour for encrypted clients, with the remainder of the
algorithm string covering the exact ciphersuite. This document uses the same mandatory ciphersuite
as MLS: <tt>MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519</tt>. Thus, this is encoded as
<tt>m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519</tt>. Other ciphersuites can be represented similarly,
though are considered to be entirely new encryption algorithms for the purposes of this document.</t>
      <t>Custom or non-standard encryption algorithms are possible with this approach, however out of scope
for MIMI. If such an algorithm is used, it <bcp14>SHOULD</bcp14> be prefixed using reverse domain name notation.
For example, <tt>org.example.my-encryption</tt>.</t>
      <t>Mentioned in the introduction (<xref target="int-intro"/>), this document does not explore the details for what is
needed to interconnect Linearized Matrix and Matrix's existing room model. However, for interconnection
to be successful, extensions to MLS are needed to support decentralization. One possible extension
is "Decentralised MLS" <xref target="DMLS"/>.</t>
      <section anchor="int-mls-credentials">
        <name>Device Credentials</name>
        <t>Under Section 5.3 of <xref target="I-D.ietf-mls-protocol"/>, each MLS group member (a device, <xref target="int-device-id"/>)
has a "credential" or signing key associated with it. These are published to each client's local server
and available over federation (<xref target="int-transport-mls"/>).</t>
        <t>This document relies upon out-of-band verification and therefore uses basic credentials. The format
for the credential is:</t>
        <artwork><![CDATA[
struct {
    opaque user_id<V>;
    opaque device_id<V>;
    opaque signature_key<V>;
} BasicCredential;
]]></artwork>
        <t><tt>user_id</tt> is as described by <xref target="int-user-id"/>, and <tt>device_id</tt> is as described by <xref target="int-device-id"/>.
<tt>signature_key</tt> is from MLS.</t>
        <t>The device then constructs the following object, signs it using each of the listed <tt>keys</tt>, and publishes
it through its local server (<xref target="int-transport-devices"/>):</t>
        <sourcecode type="json"><![CDATA[
{
   "device_id": "ABCDEF",
   "user_id": "@alice:example.org",
   "algorithms": [
      "m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519"
   ],
   "keys": {
      "m.mls.v1.credential.ed25519:ABCDEF":
         "<unpadded base64 BasicCredential>"
   },
   "signatures": {
      "@alice:example.org": {
         "m.mls.v1.credential.ed25519:ABCDEF":
            "<unpadded base64 signature>"
      }
   }
}
]]></sourcecode>
        <t><tt>device_id</tt> is the client's device ID (<xref target="int-device-id"/>). <tt>user_id</tt> is the user ID (<xref target="int-user-id"/>)
to which the device ID belongs. <tt>algorithms</tt> are the encryption algorithms the device supports, and
<bcp14>SHOULD</bcp14> contain at least <tt>m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519</tt>.</t>
        <t>When a device supports <tt>m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519</tt>, it <bcp14>MUST</bcp14> specify its basic
credential with the <tt>m.mls.v1.credential.ed25519</tt> key algorithm.</t>
        <t><tt>keys</tt> is an object containing each algorithm-specific key (or keys) for the device. The fields for
the object form a key ID, with the device ID representing the "key version", as per <xref target="int-signing"/>.</t>
        <t>All top-level fields in the object above <bcp14>MUST</bcp14> be supplied.</t>
        <t>For each of the device's <tt>keys</tt>, a valid signature <bcp14>MUST</bcp14> be produced. If there is a missing signature
from any of the keys, or from the <tt>user_id</tt>, the device information is considered invalid. Invalid
devices <bcp14>MUST NOT</bcp14> be members of the MLS group, and are removed if already members prior to the device
information becoming invalid.</t>
      </section>
      <section anchor="group-creation">
        <name>Group Creation</name>
        <t>After the <tt>m.room.create</tt> event and other initial state events for the room are sent, the room creator
<bcp14>MUST</bcp14> establish the appropriate MLS group. This is sent as an <tt>m.mls.commit</tt> event (<xref target="int-ev-mls-commit"/>).
Afterwards, the remaining devices are added as normal (<xref target="int-mls-add-remove"/>).</t>
        <t>Ideally, the <tt>m.room.create</tt> event would also contain the initial public group state, however doing
so would mean either tracking an independent MLS group ID or allowing the client to specify the room
ID. While servers <bcp14>MAY</bcp14> allow the client to specify the room ID, servers usually have better context
for which localparts (see <xref target="int-room-id"/>) are already claimed by other rooms. Having independent
group IDs and room IDs can lead to confusion and a similar sort of namespacing issue (a room creator
can create a conflicting group ID). Instead, the server (usually) creates the room on behalf of the
client, allowing the client to then send the initial public group state to the room for other MLS
members.</t>
      </section>
      <section anchor="int-mls-add-remove">
        <name>Updating Group State</name>
        <t>This document does not provide a way to send proposals to the MLS group, meaning all commits <bcp14>MUST</bcp14> only
contain proposals which are sent by the same member (see <xref section="12" sectionFormat="of" target="I-D.ietf-mls-protocol"/>).</t>
        <t>All commits are encoded as <tt>m.mls.commit</tt> events (<xref target="int-ev-mls-commit"/>) and are sent to the room.
These commits are additionally encoded using <tt>PublicMessage</tt>, giving servers visibility on the contents
of the commits. Upon receiving the event (see <xref target="int-receiving-events"/>), the hub server <bcp14>MUST</bcp14> additionally
validate that any membership changes match what is possible with the room membership:</t>
        <ul spacing="normal">
          <li>
            <t>Devices can only be added to the group if they belong to a user which is joined to the room, or if the
room is "world readable" (<xref target="int-calc-event-visibility"/>). It is generally not enough to be invited,
knocking, etc on the room - the user ID must usually be in the <tt>join</tt> state.</t>
          </li>
          <li>
            <t>Devices can be removed in two ways:
            </t>
            <ul spacing="normal">
              <li>
                <t>A device can remove another device if they both belong to the same user ID.</t>
              </li>
              <li>
                <t>A device can be removed by anyone if the user ID to which it belongs is no longer in the <tt>join</tt> state.
This condition is required to satisfy a case in MLS where a device cannot self-remove itself from
the group.</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>If this validation fails, the hub server <bcp14>MUST</bcp14> reject the request if it's shaped as an LPDU (<xref target="int-lpdu"/>)
and soft-fail the event if it's a PDU (<xref target="int-pdu"/>).</t>
        <t>Welcome messages are sent to devices over to-device messaging (<xref target="int-transport-to-device"/>). The <tt>message_type</tt>
for the message is <tt>m.room.encrypted</tt> [<strong>TODO</strong>: Rename to avoid confusion with room event?] and <tt>message</tt>
of:</t>
        <sourcecode type="json"><![CDATA[
{
   "algorithm": "m.mls.v1.welcome.[ciphersuite]",
   "ciphertext": "<unpadded base64 encoded welcome message>",
   "commit_event_id": "<event ID of the m.mls.commit event>"
}
]]></sourcecode>
        <t><tt>algorithm</tt> is the ciphersuite, <tt>dhkemx25519-aes128gcm-sha256-ed25519</tt>, prefixed with <tt>m.mls.v1.welcome</tt>.</t>
        <t>The remaining fields are as described in the example. See <xref target="int-unpadded-base64"/> for "unpadded base64".</t>
        <t>All fields <bcp14>MUST</bcp14> be supplied. Note that the sender's user ID and device ID are made available over the
to-device messaging endpoints (<xref target="int-transport-to-device"/>).</t>
        <t>In all cases, a device remembers the event ID (either from the <tt>m.mls.commit</tt> event or <tt>commit_event_id</tt>
from a to-device message) after decryption to associate it with the MLS epoch. The device can then do
a reverse lookup of epoch to event ID to MLS group state. Note that a client <em>always</em> has access to
<tt>m.mls.commit</tt> events, even when hidden by history visibility (<xref target="int-calc-event-visibility"/>).</t>
        <t><strong>TODO</strong>: Is it correct to say all commits are visible as "shared"?</t>
        <t><strong>TODO</strong>: We may need to store the group state in the media repo if it gets to be too big, or otherwise
allow oversized events.</t>
        <t><strong>TODO</strong>: The server also likely needs to prevent devices being added to the group which don't support
the ciphersuite/algorithm.</t>
      </section>
      <section anchor="int-mls-key-packages">
        <name>Key Packages</name>
        <t>Clients "claim" another device's key package through their server (<xref target="int-transport-key-claim"/>). Clients
will typically generate several key packages and upload them to their server, making them available even
if the client goes offline.</t>
        <t>The algorithm for a key package is <tt>m.mls.v1.key_package.dhkemx25519-aes128gcm-sha256-ed25519</tt> and is
combined with a device-generated key version, forming a key ID described by <xref target="int-signing"/>. The key
version <bcp14>SHOULD</bcp14> be generated based upon the key package itself rather than using an unrelated string,
such as a hash or the public key of the key package.</t>
      </section>
      <section anchor="room-event-types">
        <name>Room Event Types</name>
        <t><strong>TODO</strong>: Should these be defined with the other event types rather than here?</t>
        <t>This document describes the following event types for use with MLS-encrypted rooms. The section headers
are the event <tt>type</tt>. See <xref target="int-pdu"/> for more information on events.</t>
        <t>These event types are non-state events, also called "room events".</t>
        <section anchor="int-ev-mls-commit">
          <name><tt>m.mls.commit</tt></name>
          <t>Represents an MLS commit, which may be rejected by the hub server.</t>
          <t><tt>content</tt> for the event <bcp14>MUST</bcp14> contain at least the following example:</t>
          <sourcecode type="json"><![CDATA[
{
   "message": "<unpadded base64 encoded PublicMessage>",
   "public_group_state": "<unpadded base64 encoded public group state>"
}
]]></sourcecode>
          <t>As mentioned, <tt>message</tt> is a <tt>PublicMessage</tt> from MLS. <tt>public_group_state</tt> is to enable external
joins.</t>
          <t>An optional field, <tt>prev_commit_event_id</tt>, <bcp14>SHOULD</bcp14> be specified when a parent commit exists. This is
to enable clients to find the commit they have keys for upon joining the room, as the most recent one
may not be decryptable to them. The client can then work forwards from where they can decrypt the
message.</t>
          <t><strong>TODO</strong>: Should we use the <tt>RatchetTree</tt> extension? It might make the group state massive...</t>
          <t><strong>TODO</strong>: Which fields from this need to be protected by <xref target="int-redactions"/>?</t>
        </section>
        <section anchor="int-ev-encrypted">
          <name><tt>m.room.encrypted</tt></name>
          <t>Represents an encrypted MLS application message. The sender first encrypts the message per the content
format then <bcp14>MUST</bcp14> send an event with <tt>content</tt> matching:</t>
          <sourcecode type="json"><![CDATA[
{
   "algorithm": "m.mls.v1.[ciphersuite]",
   "ciphertext": "<unpadded base64 encoded MLS ciphertext>",
   "commit_event_id": "<event ID of applicable m.mls.commit event>"
}
]]></sourcecode>
          <t>Within this document, <tt>algorithm</tt> will be <tt>m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519</tt>. The other
fields are as described in the example.</t>
          <t>Clients <bcp14>SHOULD</bcp14> treat <tt>m.room.encrypted</tt> events which are improperly structured as undecryptable events.</t>
          <t><strong>TODO</strong>: Which fields from this need to be protected by <xref target="int-redactions"/>?</t>
        </section>
      </section>
    </section>
    <section anchor="processing-events">
      <name>Processing Events</name>
      <t>An event has several authenticity properties:</t>
      <ul spacing="normal">
        <li>
          <t>Content hashes (<xref target="int-content-hashes"/>) to cover the LPDU (<xref target="int-lpdu"/>) and event (<xref target="int-pdu"/>)
contents.</t>
        </li>
        <li>
          <t>Reference hashes (<xref target="int-reference-hashes"/>) which double as the event ID, covering the
redacted event.</t>
        </li>
        <li>
          <t>Signatures from the direct senders (server name of the <tt>sender</tt> and the <tt>hub_server</tt> if
present), ensuring the entities did actually produce that event.</t>
        </li>
      </ul>
      <t><strong>TODO</strong>: Does the hub's signature actually guard anything?</t>
      <t>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.</t>
      <section anchor="int-receiving-events">
        <name>Receiving Events/PDUs</name>
        <t><strong>TODO</strong>: This section conflates sending and receiving a bit more than it should. Split sending
out to its own section.</t>
        <t>When a hub receives an LPDU from a participant it <bcp14>MUST</bcp14> add the missing fields to create a fully
formed PDU then <bcp14>MUST</bcp14> send that PDU back out to all participants, including the original sender.</t>
        <t>A server is considered to have "received" an event when it does not recognize the event ID. This
may be because the event has not yet been persisted, or the server is not persisting anything (in
the case of a participant server). This includes when the server asks another server for an event
it might be missing.</t>
        <t>When a server (hub or participant) receives an event, it <bcp14>MUST</bcp14>:</t>
        <ol spacing="normal" type="1"><li>
            <t>Verify the event matches the schema for the room version (<xref target="int-pdu"/>), without considering
type-specific schemas applied to <tt>content</tt>. If an event fails to meet this requirement, it is
dropped/ignored.</t>
          </li>
          <li>
            <t>Ensure the required signatures are present and that they are valid (<xref target="int-checking-signatures"/>).
If the event has a <tt>hub_server</tt> field, the event <bcp14>MUST</bcp14> be signed by that server. The event
<bcp14>MUST</bcp14> also be signed by the server implied by the <tt>sender</tt>, noting that this will be an LPDU
if <tt>hub_server</tt> is present. All other signatures <bcp14>MUST NOT</bcp14> be considered for signature
validation, regardless of their individual validity. If the event fails to meet this
requirement, it is dropped/ignored.</t>
          </li>
          <li>
            <t>Ensure the event has a valid content hashes (<xref target="int-content-hashes"/>). If the event has a
<tt>hub_server</tt> field, it <bcp14>MUST</bcp14> 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.</t>
          </li>
        </ol>
        <t>Additionally, a hub server <bcp14>MUST</bcp14> complete the following checks. Participant servers <bcp14>SHOULD</bcp14>
also perform the following checks to validate that the hub server is acting in a compliant
manner. If the hub is not acting appropriately (for example, by sending the participant an
event which never should have been accepted), the participant server <bcp14>MAY</bcp14> choose to warn its
local users that the room history may have been tampered with.</t>
        <ol spacing="normal" type="1"><li>
            <t>The constraints described by <xref target="int-mls-add-remove"/> validated, if the room is encrypted.</t>
          </li>
        </ol>
      </section>
      <section anchor="int-auth-rules">
        <name>Authorization Rules</name>
        <t>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.</t>
        <section anchor="int-auth-selection">
          <name>Auth Events Selection</name>
          <t>The <tt>auth_events</tt> on an event <bcp14>MUST</bcp14> consist of the following state events, with the exception
of an <tt>m.room.create</tt> event which has no <tt>auth_events</tt>.</t>
          <ol spacing="normal" type="1"><li>
              <t>The <tt>m.room.create</tt> state event.</t>
            </li>
            <li>
              <t>The current <tt>m.room.power_levels</tt> state event, if any.</t>
            </li>
            <li>
              <t>The sender's current <tt>m.room.member</tt> state event, if any.</t>
            </li>
            <li>
              <t>If the <tt>type</tt> is <tt>m.room.member</tt>:
              </t>
              <ol spacing="normal" type="1"><li>
                  <t>The target's (<tt>state_key</tt>) current <tt>m.room.member</tt> state event, if any.</t>
                </li>
                <li>
                  <t>If <tt>content.membership</tt> is <tt>join</tt> or <tt>invite</tt>, the current <tt>m.room.join_rules</tt> state
event, if any.</t>
                </li>
              </ol>
            </li>
          </ol>
          <t><strong>TODO</strong>: Talk about restricted room joins here?</t>
        </section>
        <section anchor="int-calc-power-levels">
          <name>Calculating Power Levels</name>
          <t>A requirement of the authorization rules is being able to determine the current/future "power level"
for a user. All power levels are calculated with reference to the <tt>content</tt> of an <tt>m.room.power_levels</tt>
state event (<xref target="int-ev-power-levels"/>).</t>
          <t>To calculate a user's current power level:</t>
          <ol spacing="normal" type="1"><li>
              <t>If <tt>users</tt> is present, use the power level for the user ID, if present.</t>
            </li>
            <li>
              <t>If <tt>users</tt> is not present, or the user ID is not present in <tt>users</tt>, use <tt>users_default</tt>.</t>
            </li>
            <li>
              <t>If <tt>users_default</tt> is not present, use <tt>0</tt>.</t>
            </li>
          </ol>
          <t>To calculate the required power level to do an action:</t>
          <ol spacing="normal" type="1"><li>
              <t>If the action (<tt>kick</tt>, <tt>ban</tt>, <tt>invite</tt>, or <tt>redact</tt>) is present, use that power level.</t>
            </li>
            <li>
              <t>If not present, use the default for the action (<tt>50</tt> for <tt>kick</tt>, <tt>ban</tt>, and <tt>redact</tt>, <tt>0</tt>
for <tt>invite</tt>).</t>
            </li>
          </ol>
          <t>To calculate the required power level to send an event:</t>
          <ol spacing="normal" type="1"><li>
              <t>If <tt>events</tt> is present, use the power level for the event <tt>type</tt>, if present.</t>
            </li>
            <li>
              <t>If <tt>events</tt> is not present, or the event <tt>type</tt> is not present in <tt>events</tt>:
              </t>
              <ol spacing="normal" type="1"><li>
                  <t>If <tt>state_key</tt> is present (including empty), use <tt>state_default</tt>.
                  </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If <tt>state_default</tt> is not specified, use <tt>50</tt>.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>If <tt>state_key</tt> is not present, use <tt>events_default</tt>.
                  </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If <tt>events_default</tt> is not specified, use <tt>0</tt>.</t>
                    </li>
                  </ol>
                </li>
              </ol>
            </li>
          </ol>
        </section>
        <section anchor="auth-rules-algorithm">
          <name>Auth Rules Algorithm</name>
          <t>With consideration for default/calculated power levels (<xref target="int-calc-power-levels"/>), each event <bcp14>MUST</bcp14>
pass the following rules. "Current state" (and "current membership", etc) are the state of the room
<em>before</em> the event being checked is applied.</t>
          <t><strong>TODO</strong>: should we reference <tt>m.federate</tt>?</t>
          <ol spacing="normal" type="1"><li>
              <t>Events must be signed (<xref target="int-checking-signatures"/>) by the server denoted by the <tt>sender</tt>
field. Note that this may be an LPDU if the <tt>hub_server</tt> is specified and not the same server.
If the event is improperly signed, reject the event.</t>
            </li>
            <li>
              <t>If <tt>hub_server</tt> is present on the event, the event must be signed (<xref target="int-checking-signatures"/>)
by that server. If it is improperly signed, reject the event.</t>
            </li>
            <li>
              <t>If the event's <tt>type</tt> is <tt>m.room.create</tt>:  </t>
              <ol spacing="normal" type="1"><li>
                  <t>If it has any <tt>prev_events</tt>, reject the event.</t>
                </li>
                <li>
                  <t>If the domain of the <tt>room_id</tt> is not the same domain as the <tt>sender</tt>, reject the event.</t>
                </li>
                <li>
                  <t>If <tt>content.room_version</tt> is not <tt>I.1</tt>, reject the event.</t>
                </li>
                <li>
                  <t>Otherwise, allow the event.</t>
                </li>
              </ol>
            </li>
            <li>
              <t>Considering the event's <tt>auth_events</tt>:  </t>
              <t><strong>TODO</strong>: Does this check make sense for Linearized Matrix? We already removed what was #3 because
it talked about rejecting events which reference rejected events.  </t>
              <ol spacing="normal" type="1"><li>
                  <t>If there are duplicate entries for a given <tt>type</tt> and <tt>state_key</tt> pair, reject the event.</t>
                </li>
                <li>
                  <t>If there are entries whose <tt>type</tt> and <tt>state_key</tt> do not match those specified by the
auth events selection algorithm (<xref target="int-auth-selection"/>), reject the event.</t>
                </li>
                <li>
                  <t>If there is no <tt>m.room.create</tt> event among the entries, reject.</t>
                </li>
              </ol>
            </li>
            <li>
              <t>If the event's <tt>type</tt> is <tt>m.room.member</tt>:  </t>
              <ol spacing="normal" type="1"><li>
                  <t>If there is no <tt>state_key</tt> property, or no <tt>membership</tt> in <tt>content</tt>, reject the event.</t>
                </li>
                <li>
                  <t>If the event <tt>content</tt>'s <tt>membership</tt> field is <tt>join</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the previous event is an <tt>m.room.create</tt> event and the <tt>state_key</tt> is the
creator, allow the event.</t>
                    </li>
                    <li>
                      <t>If <tt>sender</tt> does not match <tt>state_key</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt> is banned, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>join_rule</tt> for <tt>m.room.join_rules</tt> is <tt>invite</tt> or <tt>knock</tt>, then allow the event if
the current membership state is <tt>invite</tt> or <tt>join</tt>.</t>
                    </li>
                    <li>
                      <t>If the <tt>join_rule</tt> for <tt>m.room.join_rules</tt> is <tt>public</tt>, allow the event.</t>
                    </li>
                    <li>
                      <t>Otherwise, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>If the event <tt>content</tt>'s <tt>membership</tt> field is <tt>invite</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the <tt>sender</tt>'s current membership state is not <tt>join</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the target user's (<tt>state_key</tt>) membership is <tt>join</tt> or <tt>ban</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt>'s power level is greater than or equal to the power level needed
to send invites, allow the event.</t>
                    </li>
                    <li>
                      <t>Otherwise, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>If the event <tt>content</tt>'s <tt>membership</tt> field is <tt>leave</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the <tt>sender</tt> matches the <tt>state_key</tt>, allow the event if and only if that user's current
membership state is <tt>knock</tt>, <tt>join</tt>, or <tt>invite</tt>.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt>'s current membership state is not <tt>join</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the target user's (<tt>state_key</tt>) current membership state is <tt>ban</tt>, and the
<tt>sender</tt>'s power level is less than the power level needed to ban other users, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt>'s power level is greater than or equal to the power level needed to
kick users, and the target user's (<tt>state_key</tt>) power level is less than the <tt>sender</tt>'s,
allow the event.</t>
                    </li>
                    <li>
                      <t>Otherwise, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>If the event <tt>content</tt>'s <tt>membership</tt> field is <tt>ban</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the <tt>sender</tt>'s current membership state is not <tt>join</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt>'s power level is greater than or equal to the power level needed
to ban users, and the target user's (<tt>state_key</tt>) power level is less than the
<tt>sender</tt>'s power level, allow the event.</t>
                    </li>
                    <li>
                      <t>Otherwise, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>If the event <tt>content</tt>'s <tt>membership</tt> field is <tt>knock</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the <tt>join_rule</tt> for <tt>m.room.join_rules</tt> is anything other than <tt>knock</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt> does not match the <tt>state_key</tt>, reject the event.</t>
                    </li>
                    <li>
                      <t>If the <tt>sender</tt>'s current membership state is not <tt>ban</tt> or <tt>join</tt>, allow the event.</t>
                    </li>
                    <li>
                      <t>Otherwise, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>Otherwise, the <tt>membership</tt> is unknown. reject the event.</t>
                </li>
              </ol>
            </li>
            <li>
              <t>If the <tt>sender</tt>'s current membership state is not <tt>join</tt>, reject the event.</t>
            </li>
            <li>
              <t>If the event <tt>type</tt>'s required power level to send it is greater than the <tt>sender</tt>'s power level,
reject the event.</t>
            </li>
            <li>
              <t>If the event has a <tt>state_key</tt> which starts with an <tt>@</tt> and does not match the <tt>sender</tt>,
reject the event.  </t>
              <t><strong>TODO</strong>: Do we care? This is theoretically to allow for owned state events, but in practice nothing
which uses this concept makes it this far into the auth rules (membership events are validated above).</t>
            </li>
            <li>
              <t>If the event's <tt>type</tt> is <tt>m.room.power_levels</tt>:  </t>
              <ol spacing="normal" type="1"><li>
                  <t>If any of the fields <tt>users_default</tt>, <tt>events_default</tt>, <tt>state_default</tt>, <tt>ban</tt>, <tt>redact</tt>,
<tt>kick</tt>, or <tt>invite</tt> in <tt>content</tt> are present and not an integer, reject the event.</t>
                </li>
                <li>
                  <t>If <tt>events</tt> in <tt>content</tt> is present and not an object with values that are integers,
reject the event.</t>
                </li>
                <li>
                  <t>If the <tt>users</tt> in <tt>content</tt> is present and not an object with valid user IDs as keys and
integers as values, reject the event.</t>
                </li>
                <li>
                  <t>If there is no previous <tt>m.room.power_levels</tt> event in the room, allow the event.</t>
                </li>
                <li>
                  <t>For the fields <tt>users_default</tt>, <tt>events_default</tt>, <tt>state_default</tt>, <tt>ban</tt>, <tt>redact</tt>, <tt>kick</tt>,
and <tt>invite</tt>, check if they were added, changed, or removed. For each found alteration:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the current value is higher than the <tt>sender</tt>'s current power level, reject the event.</t>
                    </li>
                    <li>
                      <t>If the new value is higher than the <tt>sender</tt>'s current power level, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>For each entry being changed in or removed from <tt>events</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the current value is higher than the <tt>sender</tt>'s current power level, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>For each entry being added to or changed in <tt>events</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the new value is greater than the <tt>sender</tt>'s current power level, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>For each entry being changed in or removed from <tt>users</tt>, other than the <tt>sender</tt>'s own
entry:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the current value is higher than the <tt>sender</tt>'s current power level, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>For each entry being added to or changed in <tt>users</tt>:      </t>
                  <ol spacing="normal" type="1"><li>
                      <t>If the new value is greater than the <tt>sender</tt>'s current power level, reject the event.</t>
                    </li>
                  </ol>
                </li>
                <li>
                  <t>Otherwise, allow the event.</t>
                </li>
              </ol>
            </li>
            <li>
              <t>Otherwise, allow the event.</t>
            </li>
          </ol>
          <t>There are some consequences to these rules:</t>
          <ul spacing="normal">
            <li>
              <t>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.</t>
            </li>
            <li>
              <t>To unban another user, the sender must have a power level greater than or equal to both
the kick and ban power levels, <em>and</em> greater than the target user's power level.</t>
            </li>
          </ul>
          <t><strong>TODO</strong>: If we want to enforce a single hub in a room, we'd do so here with auth rules.</t>
        </section>
      </section>
    </section>
    <section anchor="int-signing">
      <name>Signing</name>
      <t>All servers, including hubs and participants, publish an ed25519 <xref target="RFC8032"/> signing key
to be used by other servers when verifying signatures. These keys can then be fetched over
the transport as needed (<xref target="int-transport-get-server-keys"/>).</t>
      <t><strong>TODO</strong>: Verify RFC reference. We might be using a slightly different ed25519 key today?
See https://hdevalence.ca/blog/2020-10-04-its-25519am</t>
      <t>Each key ID consists of an algorithm name and version. Signing keys <bcp14>MUST</bcp14> use an algorithm
of <tt>ed25519</tt> (and therefore <bcp14>MUST</bcp14> be an ed25519 key). The key version <bcp14>MUST</bcp14> be valid under
the following ABNF <xref target="RFC5234"/>:</t>
      <artwork><![CDATA[
key_version = 1*key_version_char
key_version_char = ALPHA / DIGIT / "_"
]]></artwork>
      <t>An algorithm and version combined is a "key ID", deliminated by <tt>:</tt> as per the following
ABNF <xref target="RFC5234"/>:</t>
      <artwork><![CDATA[
key_id = key_algorithm ":" key_version
key_algorithm = "ed25519"
]]></artwork>
      <t>Additional key algorithms may be supported by future documents.</t>
      <section anchor="int-signing-events">
        <name>Signing Events</name>
        <t>To sign an event:</t>
        <ol spacing="normal" type="1"><li>
            <t>Redact it (<xref target="int-redactions"/>).</t>
          </li>
          <li>
            <t>Sign the result as an arbitrary object (<xref target="int-signing-objects"/>).</t>
          </li>
        </ol>
      </section>
      <section anchor="int-signing-objects">
        <name>Signing Arbitrary Objects</name>
        <t>To sign an object:</t>
        <ol spacing="normal" type="1"><li>
            <t>Remove <tt>signatures</tt> if present.</t>
          </li>
          <li>
            <t>Encode the result with Canonical JSON (<xref target="int-canonical-json"/>).</t>
          </li>
          <li>
            <t>Using the relevant ed25519 signing key (usually the server's), sign the object.</t>
          </li>
          <li>
            <t>Encode that signature under <tt>signatures</tt> using unpadded base64 (<xref target="int-unpadded-base64"/>).</t>
          </li>
        </ol>
        <t>Note that <tt>signatures</tt> is an object with keys being the entity which did the signing and value
being the key ID to encoded signature pair. See <xref target="int-pdu"/> for details on the <tt>signatures</tt>
structure for events specifically.</t>
      </section>
      <section anchor="int-checking-signatures">
        <name>Checking Signatures</name>
        <t>If the <tt>signatures</tt> 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.</t>
        <t>If decoding the base64 fails, the check fails.</t>
        <t>If the object is an event, redact (<xref target="int-redactions"/>) it before continuing.</t>
        <t>If removing the <tt>signatures</tt> property, canonicalizing the JSON (<xref target="int-canonical-json"/>),
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 (<xref target="int-transport-get-server-keys"/>).</t>
        <t>Otherwise, the check passes.</t>
        <t><strong>TODO</strong>: 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?</t>
      </section>
    </section>
    <section anchor="int-canonical-json">
      <name>Canonical JSON</name>
      <t>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.</t>
      <t>To canonicalize a JSON object, use <xref target="RFC8785"/>.</t>
      <t><strong>TODO</strong>: Matrix currently doesn't use RFC8785, but it should (or similar).</t>
    </section>
    <section anchor="int-redactions">
      <name>Event Redactions</name>
      <t>All fields at the top level except the following are stripped from the event:</t>
      <ul spacing="normal">
        <li>
          <t><tt>type</tt></t>
        </li>
        <li>
          <t><tt>room_id</tt></t>
        </li>
        <li>
          <t><tt>sender</tt></t>
        </li>
        <li>
          <t><tt>state_key</tt></t>
        </li>
        <li>
          <t><tt>content</tt></t>
        </li>
        <li>
          <t><tt>origin_server_ts</tt></t>
        </li>
        <li>
          <t><tt>hashes</tt></t>
        </li>
        <li>
          <t><tt>signatures</tt></t>
        </li>
        <li>
          <t><tt>prev_events</tt></t>
        </li>
        <li>
          <t><tt>auth_events</tt></t>
        </li>
        <li>
          <t><tt>hub_server</tt></t>
        </li>
      </ul>
      <t>Additionally, some event types retain specific fields under the event's <tt>content</tt>. All other
fields are stripped.</t>
      <ul spacing="normal">
        <li>
          <t><tt>m.room.create</tt> retains all fields in <tt>content</tt>.</t>
        </li>
        <li>
          <t><tt>m.room.member</tt> retains <tt>membership</tt>.</t>
        </li>
        <li>
          <t><tt>m.room.join_rules</tt> retains <tt>join_rule</tt>.</t>
        </li>
        <li>
          <t><tt>m.room.power_levels</tt> retains <tt>ban</tt>, <tt>events</tt>, <tt>events_default</tt>, <tt>kick</tt>, <tt>redact</tt>, <tt>state_default</tt>,
<tt>users</tt>, <tt>users_default</tt>, and <tt>invite</tt>.</t>
        </li>
        <li>
          <t><tt>m.room.history_visibility</tt> retains <tt>history_visibility</tt>.</t>
        </li>
      </ul>
    </section>
    <section anchor="hashes">
      <name>Hashes</name>
      <t>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.</t>
      <section anchor="int-content-hashes">
        <name>Content Hash Calculation</name>
        <t><strong>TODO</strong>: Describe what this protects, and why it matters.</t>
        <ol spacing="normal" type="1"><li>
            <t>Remove any existing <tt>signatures</tt> field.
            </t>
            <ol spacing="normal" type="1"><li>
                <t>If calculating an LPDU's (<xref target="int-lpdu"/>) content hash, remove any existing <tt>hashes</tt> field as well.</t>
              </li>
              <li>
                <t>If <em>not</em> calculating an LPDU's content hash, remove any existing fields under <tt>hashes</tt> except
for <tt>lpdu</tt>.</t>
              </li>
            </ol>
          </li>
          <li>
            <t>Encode the object using canonical JSON.</t>
          </li>
          <li>
            <t>Hash the resulting bytes with SHA-256 <xref target="RFC6234"/>.</t>
          </li>
          <li>
            <t>Encode the hash using unpadded base64 (<xref target="int-unpadded-base64"/>).</t>
          </li>
        </ol>
      </section>
      <section anchor="int-reference-hashes">
        <name>Reference Hash Calculation</name>
        <t><strong>TODO</strong>: Describe what this protects, and why it matters.</t>
        <ol spacing="normal" type="1"><li>
            <t>Redact the event.</t>
          </li>
          <li>
            <t>Remove <tt>signatures</tt> field.</t>
          </li>
          <li>
            <t>Encode the object using canonical JSON.</t>
          </li>
          <li>
            <t>Hash the resulting bytes with SHA-256 <xref target="RFC6234"/>.</t>
          </li>
          <li>
            <t>Encode the hash using URL-safe unpadded base64 (<xref target="int-unpadded-base64"/>).</t>
          </li>
        </ol>
      </section>
    </section>
    <section anchor="int-unpadded-base64">
      <name>Unpadded Base64</name>
      <t>Throughout this document, "unpadded base64" is used to represent binary values as strings. Base64 is
as specified by <xref section="4" sectionFormat="of" target="RFC4648"/>, and "unpadded base64" simply removes any <tt>=</tt> padding from
the resulting string.</t>
      <t>Implementations <bcp14>SHOULD</bcp14> accept input with or without padding on base64 values, where possible.</t>
      <t><xref section="5" sectionFormat="of" target="RFC4648"/> describes <em>URL-safe</em> base64. The same changes are adopted here. Namely, the
62nd and 63rd characters are replaced with <tt>-</tt> and <tt>_</tt> respectively. The unpadded behaviour is as
described above.</t>
    </section>
    <section anchor="int-hub-selection">
      <name>Hub Selection</name>
      <t><strong>TODO</strong>: Describe impacts of hub transfers</t>
      <t>The hub server for a room is the server denoted by the <tt>sender</tt> of the <tt>m.room.create</tt> event
(<xref target="int-ev-create"/>). Note that this is effectively the same as the server name contained in the
room ID (<xref target="int-room-id"/>) currently, however is deliberately not defined as such. In a future
scenario where hub transfers are possible, the room ID does not change when the hub server does.</t>
      <section anchor="hub-transfers">
        <name>Hub Transfers</name>
        <t><strong>TODO</strong>: 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 <em>sends</em> the transfer event? how does a transfer start?</t>
        <t><strong>TODO</strong>: Likely to be done with an <tt>m.room.hub</tt> state event in the room, where the "current hub" is
either the sender of <tt>m.room.hub</tt> or <tt>m.room.create</tt> if no hub state event is present. Auth rules
would govern what makes for a legal <tt>m.room.hub</tt> event.</t>
        <t><strong>TODO</strong>: <xref target="I-D.kohbrok-mimi-portability"/> may be of help here.</t>
      </section>
    </section>
    <section anchor="int-transport">
      <name>Transport</name>
      <t>This document specifies a wire transport which uses JSON <xref target="RFC8259"/> over HTTPS <xref target="RFC9110"/>. Servers
<bcp14>MUST</bcp14> support a minimum of HTTP/2 <xref target="RFC9113"/> and TLS 1.3 <xref target="RFC8446"/>.</t>
      <t><strong>TODO</strong>: This transport doesn't scale, and doesn't use RESTful endpoints. This example transport is
heavily inspired by Matrix's existing Server-Server API, largely acting as a starting point for testing
interoperability of the access control semantics. A better option might be gRPC, which might change how
events are structured but keep the overall semantics the same. <xref target="I-D.rosenberg-mimi-protocol"/> might
have ideas here as well for REST APIs.</t>
      <section anchor="int-tls">
        <name>TLS Certificates</name>
        <t>Servers <bcp14>MUST</bcp14> 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
<bcp14>SHOULD</bcp14> trust authorities which would commonly be trusted by an operating system or web browser.</t>
      </section>
      <section anchor="api-standards">
        <name>API Standards</name>
        <section anchor="int-transport-requests-responses">
          <name>Requests and Responses</name>
          <t>All HTTP <tt>POST</tt> and <tt>PUT</tt> endpoints require the sending server to supply a (potentially empty) JSON
object as the request body. Requesting servers <bcp14>SHOULD</bcp14> supply a <tt>Content-Type</tt> header of <tt>application/json</tt>
for such requests.</t>
          <t>All endpoints which require a server to respond with a JSON object <bcp14>MUST</bcp14> include a <tt>Content-Type</tt> header
of <tt>application/json</tt>.</t>
          <t>All JSON data, in requests or responses, <bcp14>MUST</bcp14> be encoded using UTF-8 <xref target="RFC3629"/>.</t>
          <t>All endpoints in this document do <em>not</em> support trailing slashes on them. When such a request is
encountered, it <bcp14>MUST</bcp14> be handled as an unknown endpoint (<xref target="int-unknown-endpoints"/>). Examples include:</t>
          <ul spacing="normal">
            <li>
              <t><tt>https://example.org/_matrix/path</tt> - valid.</t>
            </li>
            <li>
              <t><tt>https://example.org/_matrix/path/</tt> - unknown/invalid.</t>
            </li>
            <li>
              <t><tt>https://example.org//_matrix/path</tt> - unknown/invalid (domain also can't have a trailing slash).</t>
            </li>
            <li>
              <t><tt>https://example.org//_matrix/path/</tt> - doubly unknown/invalid.</t>
            </li>
          </ul>
          <t>Servers (both hub and participants) <bcp14>MUST</bcp14> implement all endpoints unless otherwise specified.</t>
          <t>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 <em>not</em> representative of an API version.</t>
        </section>
        <section anchor="int-transport-errors">
          <name>Errors</name>
          <t>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.</t>
          <t>When a server is returning an error to a caller, it <bcp14>MUST</bcp14> use the most appropriate error response defined
by the endpoint. If no appropriate error response is specified, the server <bcp14>SHOULD</bcp14> use <tt>M_UNKNOWN</tt> as the
error code and <tt>500 Internal Server Error</tt> as the HTTP status code.</t>
          <t>Errors are represented as JSON objects, requiring a <tt>Content-Type: application/json</tt> response header:</t>
          <sourcecode type="json"><![CDATA[
{
  "errcode": "M_UNKNOWN",
  "error": "Something went wrong."
}
]]></sourcecode>
          <t><tt>errcode</tt> is required and denotes the error code. <tt>error</tt> is an optional human-readable description of
the error. <tt>error</tt> can be as precise or vague as the responding server desires - the strings in this
document are suggestions.</t>
          <t>Some common error codes are:</t>
          <ul spacing="normal">
            <li>
              <t><tt>M_UNKNOWN</tt> - An unknown error has occurred.</t>
            </li>
            <li>
              <t><tt>M_FORBIDDEN</tt> - The caller is not permitted to access the resource. For example, trying to join a room
the user does not have an invite for.</t>
            </li>
            <li>
              <t><tt>M_NOT_JSON</tt> - The request did not contain valid JSON. Must be accompanied by a <tt>400 Bad Request</tt> HTTP
status code.</t>
            </li>
            <li>
              <t><tt>M_BAD_JSON</tt> - The request did contain valid JSON, but it was missing required keys or was malformed in
 another way. Must be accompanied by a <tt>400 Bad Request</tt> HTTP status code.</t>
            </li>
            <li>
              <t><tt>M_LIMIT_EXCEEDED</tt> - Too many requests have been sent. The caller should wait before trying the request
again.</t>
            </li>
            <li>
              <t><tt>M_TOO_LARGE</tt> - The request was too large for the receiver to handle.</t>
            </li>
          </ul>
        </section>
        <section anchor="int-unknown-endpoints">
          <name>Unsupported Endpoints</name>
          <t>If a server receives a request for an unsupported or otherwise unknown endpoint, the server <bcp14>MUST</bcp14> respond
with an HTTP <tt>404 Not Found</tt> status code and <tt>M_UNRECOGNIZED</tt> error code. If the request was for a known
endpoint, but wrong HTTP method, a <tt>405 Method Not Allowed</tt> HTTP status code and <tt>M_UNRECOGNIZED</tt> error
code (<xref target="int-transport-errors"/>).</t>
        </section>
        <section anchor="malformed-requests">
          <name>Malformed Requests</name>
          <t>If a server is expecting JSON in the request body but receives something else, it <bcp14>MUST</bcp14> respond with an
HTTP status code of <tt>400 Bad Request</tt> and error code <tt>M_NOT_JSON</tt> (<xref target="int-transport-errors"/>). If the
request contains JSON, and is for a known endpoint, but otherwise missing required keys or is malformed,
the server <bcp14>MUST</bcp14> respond with an HTTP status code of <tt>400 Bad Request</tt> and error code <tt>M_BAD_JSON</tt>
(<xref target="int-transport-errors"/>). Where possible, <tt>error</tt> for <tt>M_BAD_JSON</tt> should describe the missing keys
or other parsing error.</t>
        </section>
        <section anchor="int-txn-ids">
          <name>Transaction Identifiers</name>
          <t>Where endpoints use HTTP <tt>PUT</tt>, it is typical for a "transaction ID" to be specified in the path
parameters. This transaction ID <bcp14>MUST</bcp14> ONLY be used for making requests idempotent - if a server receives
two (or more) requests with the same transaction ID, it <bcp14>MUST</bcp14> 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.</t>
          <t>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.</t>
        </section>
        <section anchor="rate-limiting">
          <name>Rate Limiting</name>
          <t>Servers <bcp14>SHOULD</bcp14> implement rate limiting semantics to reduce the risk of being overloaded. Endpoints which
support being rate limited are annotated in this document.</t>
          <t>If a rate limit is encountered, the server <bcp14>MUST</bcp14> respond with an HTTP <tt>429 Too Many Requests</tt> status code
and <tt>M_LIMIT_EXCEEDED</tt> error code (<xref target="int-transport-errors"/>). If applicable, the server should additionally
include a <tt>retry_after_ms</tt> integer field on the error response to denote how long the caller should
wait before retrying, in milliseconds.</t>
          <sourcecode type="json"><![CDATA[
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests. Try again later.",
  "retry_after_ms": 10254
}
]]></sourcecode>
          <t>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.</t>
        </section>
      </section>
      <section anchor="int-resolve-domain">
        <name>Resolving Server Names</name>
        <t>Before making an API request, the caller <bcp14>MUST</bcp14> resolve a server name (<xref target="int-server-names"/>) to an IP
address and port, suitable for HTTPS <xref target="RFC9110"/> traffic.</t>
        <t>A server <bcp14>MAY</bcp14> change the IP/port combination used for API endpoints using SRV DNS records <xref target="RFC2782"/>.
Servers <bcp14>MAY</bcp14> additionally change which TLS certificate is presented by using <tt>.well-known</tt> delegation.</t>
        <t><tt>.well-known</tt> delegation (step 3 below) is recommended for its ease of configuration over SRV DNS records.</t>
        <t>The target server <bcp14>MUST</bcp14> present a valid TLS certificate (<xref target="int-tls"/>) for the name described in each
step. Similarly, the requesting server <bcp14>MUST</bcp14> use an HTTP <tt>Host</tt> header matching the description in each
step.</t>
        <t>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.</t>
        <t>Per <xref target="int-server-names"/>, a server name consists of <tt>&lt;hostname&gt;[:&lt;port&gt;]</tt>. The steps to convert that
server name to an IP address and port are:</t>
        <ol spacing="normal" type="1"><li>
            <t>If <tt>&lt;hostname&gt;</tt> has an explicit <tt>&lt;port&gt;</tt> is present, resolve <tt>&lt;hostname&gt;</tt> to
an IP address using CNAME <xref target="RFC1034"/> <xref target="RFC2181"/>, AAAA <xref target="RFC3596"/>, or A <xref target="RFC1035"/> DNS
records. Requests are made to the resolved IP address and port number.  </t>
            <t>
TLS certificate: <tt>&lt;hostname&gt;</tt> (always without port)  </t>
            <t>
Host header: <tt>&lt;hostname&gt;:&lt;port&gt;</tt></t>
          </li>
          <li>
            <t>A regular (non-Matrix) HTTPS request is made to <tt>https://&lt;hostname&gt;/.well-known/matrix/server</tt>,
expecting the schema defined by <xref target="int-wellknown"/>. If the response is invalid (bad/not JSON, missing
properties, non-200 response, etc), skip to Step 4. If the response is valid, the <tt>m.server</tt> property
is parsed as <tt>&lt;delegated_hostname&gt;[:&lt;delegated_port&gt;]</tt>.  </t>
            <ol spacing="normal" type="1"><li>
                <t>If <tt>&lt;delegated_hostname&gt;</tt> has an explicit <tt>&lt;delegated_port&gt;</tt> is present, resolve
<tt>&lt;delegated_hostname&gt;</tt> to an IP address using CNAME, AAAA, or A DNS records. Requests are made to the
resolved IP address and port number.      </t>
                <t>
TLS certificate: <tt>&lt;delegated_hostname&gt;</tt> (always without port)      </t>
                <t>
Host header: <tt>&lt;delegated_hostname&gt;:&lt;delegated_port&gt;</tt></t>
              </li>
              <li>
                <t>An SRV DNS record is resolved for <tt>_matrix._tcp.&lt;delegated_hostname&gt;</tt>. 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.      </t>
                <t>
TLS certificate: <tt>&lt;delegated_hostname&gt;</tt>      </t>
                <t>
Host header: <tt>&lt;delegated_hostname&gt;</tt> (without port)</t>
              </li>
              <li>
                <t>If no SRV record is found, an IP address is resolved for <tt>&lt;delegated_hostname&gt;</tt> is resolved using
CNAME, AAAA, or A DNS records. Requests are made to the resolved IP address with port number 8448.      </t>
                <t>
TLS certificate: <tt>&lt;delegated_hostname&gt;</tt>      </t>
                <t>
Host header: <tt>&lt;delegated_hostname&gt;</tt> (without port)</t>
              </li>
            </ol>
          </li>
          <li>
            <t>If the <tt>.well-known</tt> call from Step 2 resulted in an invalid response, an SRV DNS record is resolved
for <tt>_matrix._tcp.&lt;hostname&gt;</tt>. 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.  </t>
            <t>
TLS certificate: <tt>&lt;hostname&gt;</tt> (always without port)  </t>
            <t>
Host header: <tt>&lt;hostname&gt;</tt> (without port)</t>
          </li>
          <li>
            <t>If the <tt>.well-known</tt> 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.  </t>
            <t>
TLS certificate: <tt>&lt;hostname&gt;</tt> (always without port)  </t>
            <t>
Host header: <tt>&lt;hostname&gt;</tt> (without port)</t>
          </li>
        </ol>
        <t>We require <tt>&lt;[delegated_]hostname&gt;</tt> rather than <tt>&lt;srv_hostname&gt;</tt> in Steps 2.3 and 3 for the following reasons:</t>
        <ol spacing="normal" type="1"><li>
            <t>DNS is largely insecure (not all domains use DNSSEC <xref target="RFC9364"/>), so the target of the SRV record must
prove it is a valid delegate/target for <tt>&lt;[delegated_]hostname&gt;</tt> via TLS.</t>
          </li>
          <li>
            <t><xref section="6.2.1" sectionFormat="of" target="RFC6125"/> recommends this approach, and is consistent with other applications
which use SRV records (such as <xref section="13.7.2.1" sectionFormat="of" target="RFC6120"/>/XMPP).</t>
          </li>
        </ol>
        <t>Server implementations and owners should additionally note that the target of a SRV record <bcp14>MUST NOT</bcp14> be a CNAME,
as per RFC 2782 <xref target="RFC2782"/>:</t>
        <ul empty="true">
          <li>
            <t>the name <bcp14>MUST NOT</bcp14> be an alias (in the sense of RFC 1034 or RFC 2181)</t>
          </li>
        </ul>
        <t><xref target="RFC1034"/> <xref target="RFC2181"/></t>
        <section anchor="int-wellknown">
          <name><tt>GET /.well-known/matrix/server</tt></name>
          <t>Used by the server name resolution approach to determine a delegated hostname for a given server. 30x HTTP
redirection <bcp14>MUST</bcp14> be followed, though loops <bcp14>SHOULD</bcp14> be avoided. Normal X.509 certificate validation is applied
to this endpoint (not the specific validation required by the server name resolution steps) <xref target="RFC5280"/>.</t>
          <t>This endpoint <bcp14>MAY</bcp14> be implemented by servers (it is optional).</t>
          <t><strong>Rate-limited</strong>: No.</t>
          <t><strong>Authentication required</strong>: No.</t>
          <t>This HTTP endpoint does not specify any request parameters or body.</t>
          <t><tt>200 OK</tt> response:</t>
          <sourcecode type="json"><![CDATA[
{
   "m.server": "delegated.example.org:8448"
}
]]></sourcecode>
          <t><tt>m.server</tt> is a required response field. Responses <bcp14>SHOULD</bcp14> have a <tt>Content-Type</tt> HTTP header of
<tt>application/json</tt>, however servers parsing the response should assume that the body is JSON regardless
of <tt>Content-Type</tt> header. Failures in parsing the JSON or otherwise invalid data that prevents parsing
<bcp14>MUST NOT</bcp14> result in discovery failure. Instead, the caller is expected to move on to the next step of
the name resolution approach.</t>
          <t>Cache control headers <bcp14>SHOULD</bcp14> be respected on a <tt>200 OK</tt> response. Callers <bcp14>SHOULD</bcp14> impose a maximum
cache time of 48 hours, regardless of cache control headers. A default of 24 hours <bcp14>SHOULD</bcp14> be used
when no cache control headers are present.</t>
          <t>Error responses (non-200) <bcp14>SHOULD</bcp14> be cached for no longer than 1 hour. Callers <bcp14>SHOULD</bcp14> exponentially
back off (to a defined limit) upon receiving repeated error responses.</t>
        </section>
      </section>
      <section anchor="int-transport-auth">
        <name>Request Authentication</name>
        <t>Most endpoints in this document require authentication to prove which server is making the request.
This is done using public key digital signatures.</t>
        <t>The request method, target, and body are represented as a JSON object, signed, and appended as an HTTP
<tt>Authorization</tt> header with an auth scheme of <tt>X-Matrix</tt>.</t>
        <t>The object to be signed is:</t>
        <sourcecode type="json"><![CDATA[
{
   "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}
}
]]></sourcecode>
        <t><tt>method</tt> is the HTTP request method, capitalized. <tt>uri</tt> is the full request path, beginning with the
leading slash and containing the query string (if present). <tt>uri</tt> does not contain the <tt>https:</tt> scheme
or hostname.</t>
        <t><strong>TODO</strong>: Define an ordering algorithm for the query string (if we need to?).</t>
        <t><tt>origin</tt> and <tt>destination</tt> are the sender and receiver server names (<xref target="int-server-names"/>), respectively.</t>
        <t><tt>content</tt> is the JSON-encoded request body. When a request doesn't contain a body, such as in <tt>GET</tt>
requests, use an empty JSON object.</t>
        <t>That object is then signed (<xref target="int-signing-objects"/>) by the requesting server. The resulting signature
is appended as an <tt>Authentication</tt> HTTP header on the request:</t>
        <artwork><![CDATA[
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}
]]></artwork>
        <t>Linebreaks within <tt>Authorization</tt> are for clarity and are non-normative.</t>
        <t>The format of the Authorization header matches <xref section="11.4" sectionFormat="of" target="RFC9110"/>. The header begins with an
authorization scheme of <tt>X-Matrix</tt>, 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 <tt>token</tt>, as defined by <xref section="5.6.2" sectionFormat="of" target="RFC9110"/>. If a value is a valid <tt>token</tt> it may not be
enclosed in quotes. Quoted values <bcp14>MAY</bcp14> contain backslash-escaped characters. When parsing the header,
the recipient must unescape the characters.</t>
        <t>The exact parameters are:</t>
        <ul spacing="normal">
          <li>
            <t><tt>origin</tt> - The name of the sending server. <bcp14>MUST</bcp14> match the <tt>origin</tt> in the signed JSON.</t>
          </li>
          <li>
            <t><tt>destination</tt> - The name of the receiving server. <bcp14>MUST</bcp14> match the <tt>destination</tt> in the signed JSON.</t>
          </li>
          <li>
            <t><tt>key</tt> - The ID, including algorithm name, of the sending server's signing key used to sign the request.</t>
          </li>
          <li>
            <t><tt>signature</tt> - The unpadded base64 (<xref target="int-unpadded-base64"/>) encoded signature from step 2.</t>
          </li>
        </ul>
        <t>Unknown parameters are ignored and <bcp14>MUST NOT</bcp14> result in authentication errors.</t>
        <t>A receiving server validates the Authorization header by composing the JSON object represented above
and checking the sender's signature (<xref target="int-checking-signatures"/>). Note that to comply with
<xref target="int-checking-signatures"/> the receiver may need to append a <tt>signatures</tt> field to the JSON object
manually. All signatures <bcp14>MUST</bcp14> use an unexpired key at the time of the request
(<xref target="int-transport-keys-validity"/>).</t>
        <t>A server with multiple signing keys <bcp14>SHOULD</bcp14> include an <tt>Authorization</tt> header for each signing key.</t>
        <t>If an endpoint requires authentication, servers <bcp14>MUST</bcp14>:</t>
        <ul spacing="normal">
          <li>
            <t>Validate all presented <tt>Authorization</tt> headers.</t>
          </li>
          <li>
            <t>Ensure at least one <tt>Authorization</tt> header is present.</t>
          </li>
        </ul>
        <t>If either fails (lack of headers, or any of the headers fail validation), the request <bcp14>MUST</bcp14> be rejected
with an HTTP <tt>401 Unauthorized</tt> status code and <tt>M_FORBIDDEN</tt> error code (<xref target="int-transport-errors"/>):</t>
        <sourcecode type="json"><![CDATA[
{
   "errcode": "M_FORBIDDEN",
   "error": "Signature error on request."
}
]]></sourcecode>
        <t>If an endpoint does <em>not</em> require authentication, <tt>Authorization</tt> headers are ignored entirely.</t>
        <t>Responses from a server are authenticated using TLS and do not have additional signing requirements.</t>
        <section anchor="int-transport-get-server-keys">
          <name>Retrieving Server Keys</name>
          <t><strong>TODO</strong>: Explain what notaries are and what they do, if we keep this section at all.</t>
          <t>A server's signing keys are published under <tt>/_matrix/key/v2/server</tt> (<xref target="int-api-self-key"/>) and can
be queried through notary servers in two ways: <xref target="int-api-notary-query"/> and <xref target="int-api-notary-query-bulk"/>.
Notary servers implicitly call <tt>/_matrix/key/v2/server</tt> when queried, signing and caching the response
for some time. This allows the target server to be offline without affecting their previously sent events.</t>
          <t>The approach used here is borrowed from the Perspectives Project <xref target="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.</t>
          <t>Servers <bcp14>SHOULD</bcp14> attempt to contact the target server directly before using a notary server.</t>
          <t>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.</t>
          <section anchor="int-transport-keys-validity">
            <name>Validity</name>
            <t>A server's keys are only valid for a short time, denoted by <tt>valid_until_ts</tt>. Around the <tt>valid_until_ts</tt>
timestamp, a server would re-fetch the server's keys to discover any changes. In the vast majority of
cases, only <tt>valid_until_ts</tt> changes between requests (keys are long-lived, but validated frequently).</t>
            <t><tt>valid_until_ts</tt> <bcp14>MUST</bcp14> be handled as the lesser of <tt>valid_until_ts</tt> and 7 days into the future, preventing
attackers from publishing long-lived keys that are unable to be revoked. Servers <bcp14>SHOULD</bcp14> use a timestamp
approximately 12 hours into the future when responding with their keys.</t>
            <t><strong>TODO</strong>: What does it mean to require events have an <tt>origin_server_ts</tt> which is less than that of
<tt>valid_until_ts</tt>? Do we reject the event, soft-fail it, or do something else? Do we only do this on the
hub?</t>
          </section>
          <section anchor="int-api-self-key">
            <name><tt>GET /_matrix/key/v2/server</tt></name>
            <t>Retrieves the server's signing keys. The server can have any number of active or inactive keys at a
time, but <bcp14>SHOULD</bcp14> have at least 1 active key at all times.</t>
            <t><strong>Rate-limited</strong>: No.</t>
            <t><strong>Authentication required</strong>: No.</t>
            <t>This HTTP endpoint does not specify any request parameters or body.</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   "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>"
      }
   }
}
]]></sourcecode>
            <t><tt>server_name</tt> <bcp14>MUST</bcp14> be the name of the server (<xref target="int-server-names"/>) which is returning the keys.</t>
            <t><tt>valid_until_ts</tt> is the integer timestamp (milliseconds since Unix epoch) for when the server's keys
should be re-fetched. See <xref target="int-transport-keys-validity"/>.</t>
            <t><tt>m.linearized</tt> is an optional boolean, but <bcp14>SHOULD</bcp14> be set to <tt>true</tt>. Semantics for <tt>false</tt> and not
being present apply to contexts outside of this document.</t>
            <t><tt>verify_keys</tt> are the current signing keys for the server, keyed by key ID (<xref target="int-signing"/>). The
object value for each key ID under <tt>verify_keys</tt> is simply the <tt>key</tt>, consisting of the unpadded
base64 encoded public key matching that algorithm and version.</t>
            <t><tt>old_verify_keys</tt> are similar to <tt>verify_keys</tt>, but have an additional required <tt>expired_ts</tt> property
to denote when the key ceased usage. This overrides <tt>valid_until_ts</tt> for the purposes of
<xref target="int-transport-keys-validity"/> at an individual key level.</t>
            <t><strong>TODO</strong>: What about events sent with <tt>old_verify_keys</tt>?</t>
            <t>For request authentication (<xref target="int-transport-auth"/>), only keys listed under <tt>verify_keys</tt> are honoured.
If another key is referenced by the <tt>Authorization</tt> headers, the request fails authentication.</t>
            <t>Notaries <bcp14>SHOULD</bcp14> cache a 200 OK response for half of its lifetime to avoid serving stale values.
Responding servers <bcp14>SHOULD</bcp14> avoid returning responses which expire in less than an hour to avoid
repeated requests. Requesting servers <bcp14>SHOULD</bcp14> limit how frequently they query for keys to avoid
flooding a server with requests.</t>
            <t>If the server fails to respond to this request, notaries <bcp14>SHOULD</bcp14> 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 (<xref target="int-transport-keys-validity"/>).</t>
            <t>Servers are capable of rotating their keys without populating <tt>old_verify_keys</tt>, though this can cause
reliability issues if other servers don't see both keys. Notaries <bcp14>SHOULD</bcp14> cache responses with distinct
key IDs indefinitely. For example, if a server has <tt>ed25519:0</tt> and <tt>ed25519:1</tt> on its first response,
and a later response returns <tt>ed25519:1</tt> and <tt>ed25519:2</tt>, the notary should cache both responses. This
gives servers an ability to validate <tt>ed25519:0</tt> for old events in a room.</t>
          </section>
          <section anchor="int-api-notary-query">
            <name><tt>GET /_matrix/key/v2/query/:serverName</tt></name>
            <t>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 <tt>/_matrix/key/v2/server</tt>,
falling back to any cached values if needed.</t>
            <t><strong>Rate-limited</strong>: No.</t>
            <t><strong>Authentication required</strong>: No.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:serverName</tt> - the target server's name (<xref target="int-server-names"/>) to retrieve keys for.</t>
              </li>
            </ul>
            <t>Query parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>minimum_valid_until_ts</tt> (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.</t>
              </li>
            </ul>
            <t>Request body: None applicable.</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   "server_keys": [
      {/* server key */}
   ]
}
]]></sourcecode>
            <t><tt>server_keys</tt> is the array of keys (see <xref target="int-api-self-key"/> 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 <tt>minimum_valid_until_ts</tt> per <xref target="int-transport-keys-validity"/>, they are not included.</t>
            <t>The notary server <bcp14>MUST</bcp14> sign each key returned in <tt>server_keys</tt> by at least one of its own signing keys.
The calling server <bcp14>MUST</bcp14> validate all signatures on the objects.</t>
          </section>
          <section anchor="int-api-notary-query-bulk">
            <name><tt>POST /_matrix/key/v2/query</tt></name>
            <t>A bulk version of <tt>/_matrix/key/v2/query/:serverName</tt> (<xref target="int-api-notary-query"/>). The same behaviour
applies to this endpoint.</t>
            <t><strong>Rate-limited</strong>: No.</t>
            <t><strong>Authentication required</strong>: No.</t>
            <t>Path parameters: None applicable.</t>
            <t>Query parameters: None applicable.</t>
            <t>Request body:</t>
            <sourcecode type="json"><![CDATA[
{
   "server_keys": {
      "example.org": {
         "ed25519:0": {
            "minimum_valid_until_ts": 1686783382189
         }
      }
   }
}
]]></sourcecode>
            <t><tt>server_keys</tt> 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 <bcp14>MUST</bcp14> contain an empty <tt>server_keys</tt> array.</t>
            <t><tt>minimum_valid_until_ts</tt> holds the same meaning as in <xref target="int-api-notary-query"/>.</t>
            <t><tt>200 OK</tt> response:</t>
            <t>Same as <xref target="int-api-notary-query"/> with the following added detail:</t>
            <t>Responding servers <bcp14>SHOULD</bcp14> only return signed key objects for the key IDs requested by the caller, however
servers <bcp14>MAY</bcp14> respond with more keys than requested. The caller is expected to filter the response if
needed.</t>
          </section>
        </section>
      </section>
      <section anchor="int-transport-send-events">
        <name>Sending Events</name>
        <t>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 <xref target="int-lpdu"/>.</t>
        <t>A single endpoint is used for all rooms on either server, and can contain both fully-formed PDUs
(<xref target="int-pdu"/>) or Linearized PDUs (partial events; <xref target="int-lpdu"/>) depending on the server's role in the
applicable room.</t>
        <t>A typical event send path will be:</t>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="432" width="504" viewBox="0 0 504 432" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
              <path d="M 32,72 L 32,296" fill="none" stroke="black"/>
              <path d="M 32,312 L 32,416" fill="none" stroke="black"/>
              <path d="M 56,32 L 56,64" fill="none" stroke="black"/>
              <path d="M 176,240 L 176,272" fill="none" stroke="black"/>
              <path d="M 192,32 L 192,64" fill="none" stroke="black"/>
              <path d="M 256,72 L 256,288" fill="none" stroke="black"/>
              <path d="M 256,320 L 256,392" fill="none" stroke="black"/>
              <path d="M 320,32 L 320,64" fill="none" stroke="black"/>
              <path d="M 352,112 L 352,144" fill="none" stroke="black"/>
              <path d="M 368,32 L 368,64" fill="none" stroke="black"/>
              <path d="M 432,72 L 432,296" fill="none" stroke="black"/>
              <path d="M 432,312 L 432,416" fill="none" stroke="black"/>
              <path d="M 496,32 L 496,64" fill="none" stroke="black"/>
              <path d="M 8,32 L 56,32" fill="none" stroke="black"/>
              <path d="M 192,32 L 320,32" fill="none" stroke="black"/>
              <path d="M 368,32 L 496,32" fill="none" stroke="black"/>
              <path d="M 8,64 L 56,64" fill="none" stroke="black"/>
              <path d="M 192,64 L 320,64" fill="none" stroke="black"/>
              <path d="M 368,64 L 496,64" fill="none" stroke="black"/>
              <path d="M 256,112 L 352,112" fill="none" stroke="black"/>
              <path d="M 264,144 L 352,144" fill="none" stroke="black"/>
              <path d="M 40,192 L 256,192" fill="none" stroke="black"/>
              <path d="M 32,240 L 176,240" fill="none" stroke="black"/>
              <path d="M 40,272 L 176,272" fill="none" stroke="black"/>
              <path d="M 8,304 L 136,304" fill="none" stroke="black"/>
              <path d="M 368,304 L 496,304" fill="none" stroke="black"/>
              <path d="M 32,352 L 248,352" fill="none" stroke="black"/>
              <path d="M 32,400 L 424,400" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="432,400 420,394.4 420,405.6" fill="black" transform="rotate(0,424,400)"/>
              <polygon class="arrowhead" points="272,144 260,138.4 260,149.6" fill="black" transform="rotate(180,264,144)"/>
              <polygon class="arrowhead" points="256,352 244,346.4 244,357.6" fill="black" transform="rotate(0,248,352)"/>
              <polygon class="arrowhead" points="48,272 36,266.4 36,277.6" fill="black" transform="rotate(180,40,272)"/>
              <polygon class="arrowhead" points="48,192 36,186.4 36,197.6" fill="black" transform="rotate(180,40,192)"/>
              <g class="text">
                <text x="32" y="52">Hub</text>
                <text x="252" y="52">Participant1</text>
                <text x="428" y="52">Participant2</text>
                <text x="292" y="100">Create</text>
                <text x="340" y="100">LPDU</text>
                <text x="128" y="180">PUT</text>
                <text x="196" y="180">/send/:txnId</text>
                <text x="68" y="228">Append</text>
                <text x="112" y="228">PDU</text>
                <text x="156" y="228">fields</text>
                <text x="188" y="308">Concurrent</text>
                <text x="268" y="308">requests</text>
                <text x="332" y="308">follow</text>
                <text x="56" y="340">PUT</text>
                <text x="124" y="340">/send/:txnId</text>
                <text x="56" y="388">PUT</text>
                <text x="124" y="388">/send/:txnId</text>
                <text x="256" y="420">|</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
+-----+                +---------------+     +---------------+
| Hub |                | Participant1  |     | Participant2  |
+-----+                +---------------+     +---------------+
   |                           |                     |
   |                           | Create LPDU         |
   |                           +-----------+         |
   |                           |           |         |
   |                           |<----------+         |
   |                           |                     |
   |          PUT /send/:txnId |                     |
   |<--------------------------+                     |
   |                           |                     |
   | Append PDU fields         |                     |
   +-----------------+         |                     |
   |                 |         |                     |
   |<----------------+         |                     |
   |                           |                     |
----------------- Concurrent requests follow -----------------
   |                           |                     |
   | PUT /send/:txnId          |                     |
   +-------------------------->|                     |
   |                           |                     |
   | PUT /send/:txnId          |                     |
   +------------------------------------------------>|
   |                           |                     |
]]></artwork>
        </artset>
        <t><tt>PUT /send/:txnId</tt> is shorthand for <xref target="int-api-send-txn"/>.</t>
        <t>Hubs which generate events would skip to the point where they create a fully-formed PDU and send it
out to all other participants.</t>
        <t>When a hub is broadcasting events to participant servers, it <bcp14>MUST</bcp14> include the following targets:</t>
        <ul spacing="normal">
          <li>
            <t>The server implied by the <tt>sender</tt> for a kick or ban <tt>m.room.member</tt> (<xref target="int-ev-member"/>) event, up
to the point of that kick or ban.</t>
          </li>
          <li>
            <t>All servers which have at least 1 user which is joined to the room.</t>
          </li>
        </ul>
        <section anchor="int-api-send-txn">
          <name><tt>PUT /_matrix/federation/v2/send/:txnId</tt></name>
          <t>Sends (L)PDUs (<xref target="int-pdu"/>, <xref target="int-lpdu"/>) to another server. The sending server <bcp14>MUST</bcp14> wait for a
<tt>200 OK</tt> response from the receiver before sending another request with a different <tt>:txnId</tt>.</t>
          <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>PUT /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/send/:txnId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
          <t><strong>TODO</strong>: Remove implementation notes.</t>
          <t><strong>Rate-limited</strong>: No.</t>
          <t><strong>Authentication required</strong>: Yes.</t>
          <t>Path parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>:txnId</tt> - the transaction ID (<xref target="int-txn-ids"/>) for the request.</t>
            </li>
          </ul>
          <t>Query parameters: None applicable.</t>
          <t>Request body:</t>
          <sourcecode type="json"><![CDATA[
{
   "edus": [
      {/* EDU */}
   ],
   "pdus": [
      {/* Either an LPDU or PDU */}
   ]
}
]]></sourcecode>
          <t><tt>edus</tt> are the Ephemeral Data Units (<xref target="int-transport-edus"/>) to send. If no EDUs are being sent, this
field <bcp14>MAY</bcp14> be excluded from the request body. There <bcp14>MUST NOT</bcp14> be more than 100 entries in <tt>edus</tt>.</t>
          <t><tt>pdus</tt> are the events/PDUs (<xref target="int-pdu"/>) and LPDUs (<xref target="int-lpdu"/>) 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 <bcp14>MUST NOT</bcp14> be more than 50 entries in <tt>pdus</tt>.</t>
          <t>Each event in the <tt>pdus</tt> array gets processed as such:</t>
          <ol spacing="normal" type="1"><li>
              <t>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 <tt>room_id</tt> property.  </t>
              <ol spacing="normal" type="1"><li>
                  <t>If that room ID is invalid/not found, the event is rejected.</t>
                </li>
                <li>
                  <t>If the server is not participating in the room, the event is dropped/skipped.</t>
                </li>
              </ol>
            </li>
            <li>
              <t>If the event is an LPDU and the receiving server is the hub, the additional PDU fields are appended
before continuing.</t>
            </li>
            <li>
              <t>If the event is an LPDU and the receiving server is not the hub, the event is dropped/skipped.</t>
            </li>
            <li>
              <t>The checks defined by <xref target="int-receiving-events"/> are performed.</t>
            </li>
            <li>
              <t>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.</t>
            </li>
          </ol>
          <t>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.</t>
          <t><tt>200 OK</tt> response:</t>
          <sourcecode type="json"><![CDATA[
{
   "failed_pdus": {
      "$eventid": {
         "error": "Invalid event format"
      },
      "$eventid": {
         "error":
            "@alice:example.org cannot send m.room.power_levels"
      }
   }
}
]]></sourcecode>
          <t>The receiving server <bcp14>MUST NOT</bcp14> send a <tt>200 OK</tt> response until all events have been processed. Servers
<bcp14>SHOULD NOT</bcp14> 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.</t>
          <t>Sending servers <bcp14>SHOULD</bcp14> apply/expect a timeout and retry the exact same request with the same transaction
ID until they see a <tt>200 OK</tt> response. If the sending server attempts to send a different transaction
ID from the one already in flight, the receiving server <bcp14>MUST</bcp14> respond with a <tt>400 Bad Request</tt> HTTP
status code and <tt>M_BAD_STATE</tt> error code (<xref target="int-transport-errors"/>). Receiving servers <bcp14>SHOULD</bcp14> continue
processing requests to this endpoint even after the sender has disconnected/timed out, but <bcp14>SHOULD NOT</bcp14>
process the request multiple times due to the transaction ID (<xref target="int-txn-ids"/>).</t>
          <t><tt>failed_pdus</tt> is an object mapping event ID (<xref target="int-pdu"/>) 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.</t>
          <t>The object for each event ID <bcp14>MUST</bcp14> contain an <tt>error</tt> string field, representing the human-readable
reason for an event being rejected.</t>
          <t>Events which are dropped/ignored or accepted do <em>not</em> appear in <tt>failed_pdus</tt>.</t>
          <t><strong>TODO</strong>: Should we also return fully-formed PDUs for the LPDUs we received?</t>
        </section>
      </section>
      <section anchor="event-and-state-apis">
        <name>Event and State APIs</name>
        <t>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.</t>
        <t>All servers are required to implement all endpoints (<xref target="int-transport-requests-responses"/>), however
only hub servers are guaranteed to have the full history/state for a room. While other participant
servers might have history, they <bcp14>SHOULD NOT</bcp14> be contacted due to the high likelihood of a Not Found-style
error.</t>
        <section anchor="get-matrixfederationv2eventeventid">
          <name><tt>GET /_matrix/federation/v2/event/:eventId</tt></name>
          <t>Retrieves a single event.</t>
          <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>GET /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/event/:eventId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
          <t><strong>TODO</strong>: Remove implementation notes.</t>
          <t><strong>Rate-limited</strong>: Yes.</t>
          <t><strong>Authentication required</strong>: Yes.</t>
          <t>Path parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>:eventId</tt> - the event ID (<xref target="int-pdu"/>) to retrieve. Note that event IDs are typically reference
hashes (<xref target="int-reference-hashes"/>) of the event itself, which includes the room ID. This makes
event IDs globally unique.</t>
            </li>
          </ul>
          <t>Query parameters: None applicable.</t>
          <t>Request body: None applicable.</t>
          <t><tt>200 OK</tt> response:</t>
          <sourcecode type="json"><![CDATA[
{
   /* the event */
}
]]></sourcecode>
          <t>The response body is simply the event (<xref target="int-pdu"/>) itself, if the requesting server has reasonable
visibility of the event (<xref target="int-calc-event-visibility"/>). When the server can see an event but not the
contents, the event is served redacted (<xref target="int-redactions"/>) instead.</t>
          <t>If the event isn't known to the server, or the requesting server has no reason to know that the event
even exists, a <tt>404 Not Found</tt> HTTP status code and <tt>M_NOT_FOUND</tt> error code (<xref target="int-transport-errors"/>)
is returned.</t>
          <t>The returned event <bcp14>MUST</bcp14> be checked before being used by the requesting server (<xref target="int-receiving-events"/>).
This endpoint <bcp14>MUST NOT</bcp14> return LPDUs (<xref target="int-lpdu"/>), instead treating such events as though they didn't
exist.</t>
        </section>
        <section anchor="int-api-get-state">
          <name><tt>GET /_matrix/federation/v1/state/:roomId</tt></name>
          <t>Retrieves a snapshot of the room state (<xref target="int-state-events"/>) 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.</t>
          <t><strong>Rate-limited</strong>: Yes.</t>
          <t><strong>Authentication required</strong>: Yes.</t>
          <t>Path parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>:roomId</tt> - the room ID (<xref target="int-room-id"/>) to retrieve state in.</t>
            </li>
          </ul>
          <t>Query parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>event_id</tt> (string; required) - The event ID (<xref target="int-pdu"/>) to retrieve state at.</t>
            </li>
          </ul>
          <t>Request body: None applicable.</t>
          <t><tt>200 OK</tt> response:</t>
          <sourcecode type="json"><![CDATA[
{
   "auth_chain": [
      {/* event */}
   ],
   "pdus": [
      {/* event */}
   ]
}
]]></sourcecode>
          <t>The returned room state is in two parts: the <tt>pdus</tt>, consisting of the events which represent "current
state" (<xref target="int-state-events"/>) prior to considering state changes induced by the event in the original
request, and <tt>auth_chain</tt>, consisting of the events which make up the <tt>auth_events</tt> (<xref target="int-auth-selection"/>)
for the <tt>pdus</tt> and the <tt>auth_events</tt> of those events, recursively.</t>
          <t>The <tt>auth_chain</tt> will eventually stop recursing when it reaches the <tt>m.room.create</tt> event, as it cannot
have any <tt>auth_events</tt>.</t>
          <t><strong>TODO</strong>: Do we actually need to recurse auth events to get the full auth chain here? What are participant
servers expected to do with this information? (Do they even care about it?)</t>
          <t>For example, if the requested event ID was an <tt>m.room.power_levels</tt> event, the returned state would be
as if the new power levels were not applied.</t>
          <t>Both <tt>auth_chain</tt> and <tt>pdus</tt> contain event objects (<xref target="int-pdu"/>).</t>
          <t>If the requesting server does not have reasonable visibility on the room (<xref target="int-calc-event-visibility"/>),
or either the room ID or event ID don't exist, a <tt>404 Not Found</tt> HTTP status code and <tt>M_NOT_FOUND</tt>
error code (<xref target="int-transport-errors"/>) is returned. The same error is returned if the event ID doesn't
exist in the requested room ID.</t>
          <t>Note that the requesting server will generally always have visibility of the <tt>auth_chain</tt> and <tt>pdu</tt>
events, but may not be able to see their contents. In this case, they are redacted (<xref target="int-redactions"/>)
before being served.</t>
          <t>The returned events <bcp14>MUST</bcp14> be checked before being used by the requesting server (<xref target="int-receiving-events"/>).
This endpoint <bcp14>MUST NOT</bcp14> return LPDUs (<xref target="int-lpdu"/>), instead treating such events as though they didn't
exist.</t>
          <t>If the receiving server is not the hub server for the room ID, an HTTP status code of <tt>400 Bad Request</tt>
and error code <tt>M_WRONG_SERVER</tt> (<xref target="int-transport-errors"/>) is returned.</t>
        </section>
        <section anchor="get-matrixfederationv1stateidsroomid">
          <name><tt>GET /_matrix/federation/v1/state_ids/:roomId</tt></name>
          <t>This performs the same function as <xref target="int-api-get-state"/> but returns just the event IDs instead.</t>
          <t><strong>Rate-limited</strong>: Yes.</t>
          <t><strong>Authentication required</strong>: Yes.</t>
          <t>Path parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>:roomId</tt> - the room ID (<xref target="int-room-id"/>) to retrieve state in.</t>
            </li>
          </ul>
          <t>Query parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>event_id</tt> (string; required) - The event ID (<xref target="int-pdu"/>) to retrieve state at.</t>
            </li>
          </ul>
          <t>Request body: None applicable.</t>
          <t><tt>200 OK</tt> response:</t>
          <sourcecode type="json"><![CDATA[
{
   "auth_chain_ids": ["$event1", "$event2"],
   "pdu_ids": ["$event3", "$event4"]
}
]]></sourcecode>
          <t>See <xref target="int-api-get-state"/> for behaviour. Note that <tt>auth_chain</tt> becomes <tt>auth_chain_ids</tt> when using
this endpoint, and <tt>pdus</tt> becomes <tt>pdu_ids</tt>.</t>
        </section>
        <section anchor="get-matrixfederationv2backfillroomid">
          <name><tt>GET /_matrix/federation/v2/backfill/:roomId</tt></name>
          <t>Retrieves a sliding window history of previous events in a given room.</t>
          <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>GET /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/backfill/:roomId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
          <t><strong>TODO</strong>: Remove implementation notes.</t>
          <t><strong>Rate-limited</strong>: Yes.</t>
          <t><strong>Authentication required</strong>: Yes.</t>
          <t>Path parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>:roomId</tt> - the room ID (<xref target="int-room-id"/>) to retrieve events from.</t>
            </li>
          </ul>
          <t>Query parameters:</t>
          <ul spacing="normal">
            <li>
              <t><tt>v</tt> (string; required) - The event ID (<xref target="int-pdu"/>) to start backfilling from.</t>
            </li>
            <li>
              <t><tt>limit</tt> (integer; required) - The maximum number of events to return, including <tt>v</tt>.</t>
            </li>
          </ul>
          <t>Request body: None applicable.</t>
          <t><tt>200 OK</tt> response:</t>
          <sourcecode type="json"><![CDATA[
{
   "pdus": [
      {/* event */}
   ]
}
]]></sourcecode>
          <t>The number of returned <tt>pdus</tt> <bcp14>MUST NOT</bcp14> exceed the <tt>limit</tt> provided by the caller. <tt>limit</tt> <bcp14>SHOULD</bcp14> have
a maximum value imposed by the receiving server. <tt>pdus</tt> contains the events (<xref target="int-pdu"/>) preceeding
the requested event ID (<tt>v</tt>), including <tt>v</tt>. <tt>pdus</tt> is ordered from oldest to newest.</t>
          <t>If the requesting server does not have reasonable visibility on the room (<xref target="int-calc-event-visibility"/>),
or either the room ID or event ID don't exist, a <tt>404 Not Found</tt> HTTP status code and <tt>M_NOT_FOUND</tt>
error code (<xref target="int-transport-errors"/>) is returned. The same error is returned if the event ID doesn't
exist in the requested room ID.</t>
          <t>If the requesting server does have visibility on the returned events, but not their contents, they
are redacted (<xref target="int-redactions"/>) before being served.</t>
          <t>The returned events <bcp14>MUST</bcp14> be checked before being used by the requesting server (<xref target="int-receiving-events"/>).
This endpoint <bcp14>MUST NOT</bcp14> return LPDUs (<xref target="int-lpdu"/>), instead treating such events as though they didn't
exist.</t>
        </section>
      </section>
      <section anchor="int-transport-room-membership">
        <name>Room Membership</name>
        <t>When a server is already participating in a room, it can simply send <tt>m.room.member</tt> (<xref target="int-ev-member"/>)
events with the <tt>/send</tt> API (<xref target="int-api-send-txn"/>) to other servers/the hub directly. When a server is
not already participating however, it needs to be welcomed in by the hub server.</t>
        <t>A typical invite flow would be:</t>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="720" width="584" viewBox="0 0 584 720" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
              <path d="M 64,72 L 64,408" fill="none" stroke="black"/>
              <path d="M 64,424 L 64,704" fill="none" stroke="black"/>
              <path d="M 120,32 L 120,64" fill="none" stroke="black"/>
              <path d="M 232,32 L 232,64" fill="none" stroke="black"/>
              <path d="M 256,72 L 256,400" fill="none" stroke="black"/>
              <path d="M 256,432 L 256,704" fill="none" stroke="black"/>
              <path d="M 272,256 L 272,288" fill="none" stroke="black"/>
              <path d="M 280,32 L 280,64" fill="none" stroke="black"/>
              <path d="M 296,560 L 296,592" fill="none" stroke="black"/>
              <path d="M 392,32 L 392,64" fill="none" stroke="black"/>
              <path d="M 456,72 L 456,408" fill="none" stroke="black"/>
              <path d="M 456,424 L 456,704" fill="none" stroke="black"/>
              <path d="M 520,32 L 520,64" fill="none" stroke="black"/>
              <path d="M 8,32 L 120,32" fill="none" stroke="black"/>
              <path d="M 232,32 L 280,32" fill="none" stroke="black"/>
              <path d="M 392,32 L 520,32" fill="none" stroke="black"/>
              <path d="M 8,64 L 120,64" fill="none" stroke="black"/>
              <path d="M 232,64 L 280,64" fill="none" stroke="black"/>
              <path d="M 392,64 L 520,64" fill="none" stroke="black"/>
              <path d="M 64,112 L 248,112" fill="none" stroke="black"/>
              <path d="M 256,160 L 448,160" fill="none" stroke="black"/>
              <path d="M 272,256 L 456,256" fill="none" stroke="black"/>
              <path d="M 272,288 L 448,288" fill="none" stroke="black"/>
              <path d="M 264,336 L 456,336" fill="none" stroke="black"/>
              <path d="M 72,384 L 256,384" fill="none" stroke="black"/>
              <path d="M 8,416 L 160,416" fill="none" stroke="black"/>
              <path d="M 416,416 L 576,416" fill="none" stroke="black"/>
              <path d="M 264,464 L 456,464" fill="none" stroke="black"/>
              <path d="M 256,512 L 448,512" fill="none" stroke="black"/>
              <path d="M 296,560 L 456,560" fill="none" stroke="black"/>
              <path d="M 296,592 L 448,592" fill="none" stroke="black"/>
              <path d="M 264,640 L 456,640" fill="none" stroke="black"/>
              <path d="M 256,688 L 448,688" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="456,688 444,682.4 444,693.6" fill="black" transform="rotate(0,448,688)"/>
              <polygon class="arrowhead" points="456,592 444,586.4 444,597.6" fill="black" transform="rotate(0,448,592)"/>
              <polygon class="arrowhead" points="456,512 444,506.4 444,517.6" fill="black" transform="rotate(0,448,512)"/>
              <polygon class="arrowhead" points="456,288 444,282.4 444,293.6" fill="black" transform="rotate(0,448,288)"/>
              <polygon class="arrowhead" points="456,160 444,154.4 444,165.6" fill="black" transform="rotate(0,448,160)"/>
              <polygon class="arrowhead" points="272,640 260,634.4 260,645.6" fill="black" transform="rotate(180,264,640)"/>
              <polygon class="arrowhead" points="272,464 260,458.4 260,469.6" fill="black" transform="rotate(180,264,464)"/>
              <polygon class="arrowhead" points="272,336 260,330.4 260,341.6" fill="black" transform="rotate(180,264,336)"/>
              <polygon class="arrowhead" points="256,112 244,106.4 244,117.6" fill="black" transform="rotate(0,248,112)"/>
              <polygon class="arrowhead" points="80,384 68,378.4 68,389.6" fill="black" transform="rotate(180,72,384)"/>
              <g class="text">
                <text x="64" y="52">Participant</text>
                <text x="256" y="52">Hub</text>
                <text x="452" y="52">TargetServer</text>
                <text x="92" y="100">POST</text>
                <text x="144" y="100">/invite</text>
                <text x="204" y="100">(LPDU)</text>
                <text x="284" y="148">POST</text>
                <text x="336" y="148">/invite</text>
                <text x="392" y="148">(PDU)</text>
                <text x="300" y="196">Decide</text>
                <text x="340" y="196">to</text>
                <text x="384" y="196">process</text>
                <text x="432" y="196">the</text>
                <text x="296" y="212">invite.</text>
                <text x="344" y="212">Can</text>
                <text x="388" y="212">reject</text>
                <text x="432" y="212">due</text>
                <text x="276" y="228">to</text>
                <text x="312" y="228">spam,</text>
                <text x="348" y="228">or</text>
                <text x="380" y="228">send</text>
                <text x="412" y="228">it</text>
                <text x="436" y="228">to</text>
                <text x="304" y="244">the</text>
                <text x="360" y="244">recipient</text>
                <text x="424" y="244">user.</text>
                <text x="316" y="324">Finish</text>
                <text x="364" y="324">POST</text>
                <text x="416" y="324">/invite</text>
                <text x="116" y="372">Finish</text>
                <text x="164" y="372">POST</text>
                <text x="216" y="372">/invite</text>
                <text x="188" y="420">User</text>
                <text x="240" y="420">decides</text>
                <text x="284" y="420">to</text>
                <text x="324" y="420">accept</text>
                <text x="380" y="420">invite</text>
                <text x="344" y="452">GET</text>
                <text x="404" y="452">/make_join</text>
                <text x="292" y="500">Finish</text>
                <text x="336" y="500">GET</text>
                <text x="396" y="500">/make_join</text>
                <text x="308" y="548">Fill</text>
                <text x="352" y="548">event</text>
                <text x="412" y="548">template</text>
                <text x="340" y="628">POST</text>
                <text x="404" y="628">/send_join</text>
                <text x="292" y="676">Finish</text>
                <text x="340" y="676">POST</text>
                <text x="404" y="676">/send_join</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
+-------------+             +-----+             +---------------+
| 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 |
       |                       +----------------------->|
       |                       |                        |
]]></artwork>
        </artset>
        <t><tt>POST /invite</tt> is shorthand for <xref target="int-api-invite"/>. Similarly, <tt>GET /make_join</tt> is <xref target="int-api-make-join"/>
and <tt>POST /send_join</tt> is <xref target="int-api-send-join"/>.</t>
        <t>If the user decided to reject the invite, the TargetServer would use <tt>GET /make_leave</tt> (<xref target="int-api-make-leave"/>)
and <tt>POST /send_leave</tt> (<xref target="int-api-send-leave"/>) instead of make/send_join.</t>
        <section anchor="int-transport-make-and-send">
          <name>Make and Send Handshake</name>
          <t>When a server is already participating in a room, it can use <tt>m.room.member</tt> (<xref target="int-ev-member"/>) events
and the <tt>/send</tt> API (<xref target="int-api-send-txn"/>) 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.</t>
          <t>The different processes which use this handshake are:</t>
          <ul spacing="normal">
            <li>
              <t>Rejecting Invites (<xref target="int-transport-leaves"/>)</t>
            </li>
            <li>
              <t>Joins (<xref target="int-transport-joins"/>)</t>
            </li>
            <li>
              <t>Knocks (<xref target="int-transport-knocks"/>)</t>
            </li>
          </ul>
          <t>The "make" portion of the endpoints take the shape of <tt>GET /_matrix/federation/v1/make_CHANGE/:roomId/:userId</tt>,
where <tt>CHANGE</tt> is <tt>leave</tt>, <tt>join</tt>, or <tt>knock</tt> (respective to the list above). This endpoint will
return a partial LPDU (<xref target="int-lpdu"/>) which needs to be turned into a full LPDU and signed before being
sent using <tt>POST /_matrix/federation/v3/send_CHANGE/:txnId</tt>.</t>
          <t>The flow for this handshake appears as such:</t>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="656" width="568" viewBox="0 0 568 656" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
                <path d="M 72,72 L 72,640" fill="none" stroke="black"/>
                <path d="M 144,32 L 144,64" fill="none" stroke="black"/>
                <path d="M 232,400 L 232,432" fill="none" stroke="black"/>
                <path d="M 232,544 L 232,576" fill="none" stroke="black"/>
                <path d="M 280,272 L 280,304" fill="none" stroke="black"/>
                <path d="M 512,32 L 512,64" fill="none" stroke="black"/>
                <path d="M 536,72 L 536,640" fill="none" stroke="black"/>
                <path d="M 560,32 L 560,64" fill="none" stroke="black"/>
                <path d="M 8,32 L 144,32" fill="none" stroke="black"/>
                <path d="M 512,32 L 560,32" fill="none" stroke="black"/>
                <path d="M 8,64 L 144,64" fill="none" stroke="black"/>
                <path d="M 512,64 L 560,64" fill="none" stroke="black"/>
                <path d="M 72,112 L 528,112" fill="none" stroke="black"/>
                <path d="M 80,176 L 536,176" fill="none" stroke="black"/>
                <path d="M 80,224 L 536,224" fill="none" stroke="black"/>
                <path d="M 72,272 L 280,272" fill="none" stroke="black"/>
                <path d="M 80,304 L 280,304" fill="none" stroke="black"/>
                <path d="M 72,352 L 528,352" fill="none" stroke="black"/>
                <path d="M 232,400 L 536,400" fill="none" stroke="black"/>
                <path d="M 232,432 L 528,432" fill="none" stroke="black"/>
                <path d="M 80,480 L 536,480" fill="none" stroke="black"/>
                <path d="M 232,544 L 536,544" fill="none" stroke="black"/>
                <path d="M 232,576 L 528,576" fill="none" stroke="black"/>
                <path d="M 80,624 L 536,624" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="536,576 524,570.4 524,581.6" fill="black" transform="rotate(0,528,576)"/>
                <polygon class="arrowhead" points="536,432 524,426.4 524,437.6" fill="black" transform="rotate(0,528,432)"/>
                <polygon class="arrowhead" points="536,352 524,346.4 524,357.6" fill="black" transform="rotate(0,528,352)"/>
                <polygon class="arrowhead" points="536,112 524,106.4 524,117.6" fill="black" transform="rotate(0,528,112)"/>
                <polygon class="arrowhead" points="88,624 76,618.4 76,629.6" fill="black" transform="rotate(180,80,624)"/>
                <polygon class="arrowhead" points="88,480 76,474.4 76,485.6" fill="black" transform="rotate(180,80,480)"/>
                <polygon class="arrowhead" points="88,304 76,298.4 76,309.6" fill="black" transform="rotate(180,80,304)"/>
                <polygon class="arrowhead" points="88,224 76,218.4 76,229.6" fill="black" transform="rotate(180,80,224)"/>
                <polygon class="arrowhead" points="88,176 76,170.4 76,181.6" fill="black" transform="rotate(180,80,176)"/>
                <g class="text">
                  <text x="76" y="52">ExternalServer</text>
                  <text x="536" y="52">Hub</text>
                  <text x="96" y="100">GET</text>
                  <text x="316" y="100">/_matrix/federation/v1/make_CHANGE/:roomId/:userId</text>
                  <text x="324" y="148">Reject</text>
                  <text x="364" y="148">if</text>
                  <text x="400" y="148">event</text>
                  <text x="452" y="148">future</text>
                  <text x="504" y="148">event</text>
                  <text x="272" y="164">would</text>
                  <text x="312" y="164">not</text>
                  <text x="340" y="164">be</text>
                  <text x="384" y="164">allowed</text>
                  <text x="428" y="164">by</text>
                  <text x="460" y="164">auth</text>
                  <text x="504" y="164">rules</text>
                  <text x="352" y="212">Respond</text>
                  <text x="404" y="212">with</text>
                  <text x="456" y="212">partial</text>
                  <text x="508" y="212">LPDU</text>
                  <text x="116" y="260">Populate</text>
                  <text x="172" y="260">LPDU</text>
                  <text x="208" y="260">and</text>
                  <text x="244" y="260">sign</text>
                  <text x="276" y="260">it</text>
                  <text x="100" y="340">POST</text>
                  <text x="288" y="340">/_matrix/federation/v3/send_CHANGE/:txnId</text>
                  <text x="260" y="388">Validate</text>
                  <text x="320" y="388">event</text>
                  <text x="360" y="388">and</text>
                  <text x="404" y="388">append</text>
                  <text x="444" y="388">to</text>
                  <text x="472" y="388">the</text>
                  <text x="508" y="388">room</text>
                  <text x="220" y="468">Reject</text>
                  <text x="260" y="468">if</text>
                  <text x="296" y="468">event</text>
                  <text x="336" y="468">not</text>
                  <text x="384" y="468">allowed</text>
                  <text x="428" y="468">by</text>
                  <text x="460" y="468">auth</text>
                  <text x="504" y="468">rules</text>
                  <text x="324" y="516">Send</text>
                  <text x="360" y="516">new</text>
                  <text x="400" y="516">event</text>
                  <text x="436" y="516">to</text>
                  <text x="464" y="516">all</text>
                  <text x="504" y="516">other</text>
                  <text x="316" y="532">participants</text>
                  <text x="380" y="532">in</text>
                  <text x="408" y="532">the</text>
                  <text x="444" y="532">room</text>
                  <text x="496" y="532">(async)</text>
                  <text x="488" y="612">200</text>
                  <text x="516" y="612">OK</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
+----------------+                                             +-----+
| 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 |
        |<--------------------------------------------------------+
        |                                                         |
]]></artwork>
          </artset>
          <t>Note that the <tt>send_CHANGE</tt> step re-checks the event against the auth rules: any amount of time
could have passed between the <tt>make_CHANGE</tt> and <tt>send_CHANGE</tt> calls.</t>
          <t><strong>TODO</strong>: 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.</t>
        </section>
        <section anchor="int-transport-invites">
          <name>Invites</name>
          <t>When inviting a user belonging to a server already in the room, senders <bcp14>SHOULD</bcp14> use <tt>m.room.member</tt>
(<xref target="int-ev-member"/>) events and the <tt>/send</tt> API (<xref target="int-api-send-txn"/>). This section's endpoints <bcp14>SHOULD</bcp14>
only be used when the target server is <em>not</em> participating in the room already.</t>
          <t>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.</t>
          <t>The full invite sequence is:</t>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="784" width="520" viewBox="0 0 520 784" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
                <path d="M 64,72 L 64,768" fill="none" stroke="black"/>
                <path d="M 120,32 L 120,64" fill="none" stroke="black"/>
                <path d="M 224,32 L 224,64" fill="none" stroke="black"/>
                <path d="M 248,72 L 248,768" fill="none" stroke="black"/>
                <path d="M 272,32 L 272,64" fill="none" stroke="black"/>
                <path d="M 272,624 L 272,656" fill="none" stroke="black"/>
                <path d="M 384,32 L 384,64" fill="none" stroke="black"/>
                <path d="M 400,256 L 400,288" fill="none" stroke="black"/>
                <path d="M 448,72 L 448,768" fill="none" stroke="black"/>
                <path d="M 512,32 L 512,64" fill="none" stroke="black"/>
                <path d="M 8,32 L 120,32" fill="none" stroke="black"/>
                <path d="M 224,32 L 272,32" fill="none" stroke="black"/>
                <path d="M 384,32 L 512,32" fill="none" stroke="black"/>
                <path d="M 8,64 L 120,64" fill="none" stroke="black"/>
                <path d="M 224,64 L 272,64" fill="none" stroke="black"/>
                <path d="M 384,64 L 512,64" fill="none" stroke="black"/>
                <path d="M 64,112 L 240,112" fill="none" stroke="black"/>
                <path d="M 72,192 L 248,192" fill="none" stroke="black"/>
                <path d="M 248,256 L 400,256" fill="none" stroke="black"/>
                <path d="M 256,288 L 400,288" fill="none" stroke="black"/>
                <path d="M 248,336 L 440,336" fill="none" stroke="black"/>
                <path d="M 256,400 L 448,400" fill="none" stroke="black"/>
                <path d="M 256,480 L 448,480" fill="none" stroke="black"/>
                <path d="M 72,544 L 248,544" fill="none" stroke="black"/>
                <path d="M 272,624 L 448,624" fill="none" stroke="black"/>
                <path d="M 272,656 L 440,656" fill="none" stroke="black"/>
                <path d="M 256,704 L 448,704" fill="none" stroke="black"/>
                <path d="M 72,752 L 248,752" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="448,656 436,650.4 436,661.6" fill="black" transform="rotate(0,440,656)"/>
                <polygon class="arrowhead" points="448,336 436,330.4 436,341.6" fill="black" transform="rotate(0,440,336)"/>
                <polygon class="arrowhead" points="264,704 252,698.4 252,709.6" fill="black" transform="rotate(180,256,704)"/>
                <polygon class="arrowhead" points="264,480 252,474.4 252,485.6" fill="black" transform="rotate(180,256,480)"/>
                <polygon class="arrowhead" points="264,400 252,394.4 252,405.6" fill="black" transform="rotate(180,256,400)"/>
                <polygon class="arrowhead" points="264,288 252,282.4 252,293.6" fill="black" transform="rotate(180,256,288)"/>
                <polygon class="arrowhead" points="248,112 236,106.4 236,117.6" fill="black" transform="rotate(0,240,112)"/>
                <polygon class="arrowhead" points="80,752 68,746.4 68,757.6" fill="black" transform="rotate(180,72,752)"/>
                <polygon class="arrowhead" points="80,544 68,538.4 68,549.6" fill="black" transform="rotate(180,72,544)"/>
                <polygon class="arrowhead" points="80,192 68,186.4 68,197.6" fill="black" transform="rotate(180,72,192)"/>
                <g class="text">
                  <text x="64" y="52">Participant</text>
                  <text x="248" y="52">Hub</text>
                  <text x="444" y="52">TargetServer</text>
                  <text x="92" y="100">POST</text>
                  <text x="144" y="100">/invite</text>
                  <text x="132" y="148">Reject</text>
                  <text x="172" y="148">if</text>
                  <text x="212" y="148">sender</text>
                  <text x="108" y="164">cannot</text>
                  <text x="164" y="164">invite</text>
                  <text x="216" y="164">other</text>
                  <text x="216" y="180">users</text>
                  <text x="300" y="228">Otherwise,</text>
                  <text x="372" y="228">append</text>
                  <text x="272" y="244">PDU</text>
                  <text x="316" y="244">fields</text>
                  <text x="276" y="324">POST</text>
                  <text x="328" y="324">/invite</text>
                  <text x="348" y="372">Reject</text>
                  <text x="388" y="372">if</text>
                  <text x="420" y="372">room</text>
                  <text x="296" y="388">version</text>
                  <text x="344" y="388">not</text>
                  <text x="400" y="388">supported</text>
                  <text x="292" y="436">Reject</text>
                  <text x="332" y="436">if</text>
                  <text x="372" y="436">target</text>
                  <text x="420" y="436">user</text>
                  <text x="308" y="452">is</text>
                  <text x="364" y="452">ineligible</text>
                  <text x="424" y="452">for</text>
                  <text x="408" y="468">invites</text>
                  <text x="112" y="516">Proxy</text>
                  <text x="188" y="516">TargetServer</text>
                  <text x="200" y="532">rejection</text>
                  <text x="348" y="580">Otherwise,</text>
                  <text x="416" y="580">queue</text>
                  <text x="296" y="596">sending</text>
                  <text x="344" y="596">the</text>
                  <text x="388" y="596">invite</text>
                  <text x="428" y="596">to</text>
                  <text x="372" y="612">target</text>
                  <text x="420" y="612">user</text>
                  <text x="400" y="692">200</text>
                  <text x="428" y="692">OK</text>
                  <text x="200" y="740">200</text>
                  <text x="228" y="740">OK</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
+-------------+            +-----+             +---------------+
| 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 |                        |
       |<---------------------+                        |
       |                      |                        |
]]></artwork>
          </artset>
          <t><tt>POST /invite</tt> is shorthand for <xref target="int-api-invite"/>.</t>
          <t>What causes a user to be considered "ineligible" for an invite is left as an implementation detail.
See <xref target="int-user-privacy"/> and <xref target="int-spam"/> for suggestions on handling user-level privacy controls and
spam invites.</t>
          <section anchor="int-api-invite">
            <name><tt>POST /_matrix/federation/v3/invite/:txnId</tt></name>
            <t>Sends an invite event to a server. If the sender is a participant server, the receiving server (the
hub) will convert the contained LPDU (<xref target="int-lpdu"/>) to a fully-formed event (<xref target="int-pdu"/>) before sending
that event to the intended server.</t>
            <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>POST /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/invite/:txnId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
            <t><strong>TODO</strong>: Remove implementation notes.</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:txnId</tt> - the transaction ID (<xref target="int-txn-ids"/>) for the request. The event ID (<xref target="int-pdu"/>) of the
contained event may be a good option as a readily-available transaction ID.</t>
              </li>
            </ul>
            <t>Query parameters: None applicable.</t>
            <t>Request body:</t>
            <sourcecode type="json"><![CDATA[
{
   "event": {/* the event */},
   "invite_room_state": [/* stripped state events */],
   "room_version": "I.1"
}
]]></sourcecode>
            <t><tt>invite_room_state</tt> are the stripped state events (<xref target="int-stripped-state"/>) for the room's current
state. <tt>invite_room_state</tt> <bcp14>MAY</bcp14> be excluded from the request body.</t>
            <t><tt>room_version</tt> is the room version identifier (<xref target="int-room-versions"/>) the room is currently using. This
will be retrieved from the <tt>m.room.create</tt> (<xref target="int-ev-create"/>) state event.</t>
            <t><tt>event</tt> is the event (LPDU or PDU; <xref target="int-pdu"/>) representing the invite for the user. It <bcp14>MUST</bcp14> meet
the following criteria, in addition to the requirements of an event:</t>
            <ul spacing="normal">
              <li>
                <t><tt>type</tt> <bcp14>MUST</bcp14> be <tt>m.room.member</tt>.</t>
              </li>
              <li>
                <t><tt>membership</tt> in <tt>content</tt> <bcp14>MUST</bcp14> be <tt>invite</tt>.</t>
              </li>
            </ul>
            <t>When the hub server receives a request from a participant server, it <bcp14>MUST</bcp14> populate the event fields
before sending the event to the intended recipient. This means running the event through the normal
event authorization steps (<xref target="int-auth-rules"/>). If the invite is not allowed under the auth rules,
the server responds with a <tt>403 Forbidden</tt> HTTP status code and <tt>M_FORBIDDEN</tt> error code (<xref target="int-transport-errors"/>).</t>
            <t>The intended recipient of the invite can be identified by the <tt>state_key</tt> on the event.</t>
            <t>If the invite event is valid, the hub server sends its own <tt>POST /_matrix/federation/v3/invite/:txnId</tt>
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.</t>
            <t>All responses from the target server <bcp14>SHOULD</bcp14> be proxied verbatim to the original requesting server
through the hub. The hub <bcp14>SHOULD</bcp14> 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 (<xref target="int-transport-errors"/>) <bcp14>SHOULD</bcp14> be sent by the hub instead.</t>
            <t>The target server then ensures it can support the room version. If it can't, it responds with an HTTP
status code of <tt>400 Bad Request</tt> and error code of <tt>M_INCOMPATIBLE_ROOM_VERSION</tt> (<xref target="int-transport-errors"/>).</t>
            <t>Then, the target server runs any implementation-specific checks as needed, such as those implied by
<xref target="int-user-privacy"/> and <xref target="int-spam"/>, rejecting/erroring the request as needed.</t>
            <t>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 <tt>/send</tt>
API (<xref target="int-api-send-txn"/>).</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   "pdu": {/* signed fully-formed event */}
}
]]></sourcecode>
            <t>Note that by the time a response is received, the event is signed 2-3 times:</t>
            <ol spacing="normal" type="1"><li>
                <t>The LPDU signature from the participant server (<xref target="int-lpdu"/>).</t>
              </li>
              <li>
                <t>The hub's signature on the PDU (<xref target="int-pdu"/>).</t>
              </li>
              <li>
                <t>The target server's signature on the PDU.</t>
              </li>
            </ol>
            <t>These signatures are to satisfy the auth rules (<xref target="int-auth-rules"/>).</t>
            <t><strong>TODO</strong>: Do we ever validate the target server's signature? Do we need to?</t>
          </section>
          <section anchor="int-transport-leaves">
            <name>Rejecting Invites and Leaves</name>
            <t>Rejecting an invite is done by making a membership transition of <tt>invite</tt> to <tt>leave</tt> through the user's
<tt>m.room.member</tt> (<xref target="int-ev-member"/>) event. The membership event <bcp14>SHOULD</bcp14> be sent directly when it can and
use the "make and send" handshake (<xref target="int-transport-make-and-send"/>) described here otherwise.</t>
            <t>This same approach is additionally used to retract a knock (<xref target="int-transport-knocks"/>).</t>
            <section anchor="int-api-make-leave">
              <name><tt>GET /_matrix/federation/v1/make_leave/:roomId/:userId</tt></name>
              <t>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.</t>
              <t><strong>Rate-limited</strong>: Yes.</t>
              <t><strong>Authentication required</strong>: Yes.</t>
              <t>Path parameters:</t>
              <ul spacing="normal">
                <li>
                  <t><tt>:roomId</tt> - the room ID (<xref target="int-room-id"/>) to get a template for.</t>
                </li>
                <li>
                  <t><tt>:userId</tt> - the user ID (<xref target="int-user-id"/>) attempting to leave.</t>
                </li>
              </ul>
              <t>Query parameters: None applicable.</t>
              <t>Request body: None applicable.</t>
              <t><tt>200 OK</tt> response:</t>
              <sourcecode type="json"><![CDATA[
{
   "event": {/* partial LPDU */},
   "room_version": "I.1"
}
]]></sourcecode>
              <t>The response body's <tt>event</tt> <bcp14>MUST</bcp14> be a partial LPDU (<xref target="int-lpdu"/>) with at least the following fields:</t>
              <ul spacing="normal">
                <li>
                  <t><tt>type</tt> of <tt>m.room.member</tt>.</t>
                </li>
                <li>
                  <t><tt>state_key</tt> of <tt>:userId</tt> from the path parameters.</t>
                </li>
                <li>
                  <t><tt>sender</tt> of <tt>:userId</tt> from the path parameters.</t>
                </li>
                <li>
                  <t><tt>content</tt> of <tt>{"membership": "leave"}</tt>.</t>
                </li>
              </ul>
              <t>The sending server <bcp14>SHOULD</bcp14> remove all other fields before using the event in a <tt>send_leave</tt> (<xref target="int-api-send-leave"/>).</t>
              <t>If the receiving server is not the hub server for the room ID, an HTTP status code of <tt>400 Bad Request</tt>
and error code <tt>M_WRONG_SERVER</tt> (<xref target="int-transport-errors"/>) is returned. If the room ID is not known,
<tt>404 Not Found</tt> is used as an HTTP status code and <tt>M_NOT_FOUND</tt> as an error code (<xref target="int-transport-errors"/>).</t>
              <t>If the user does not have permission to leave under the auth rules (<xref target="int-auth-rules"/>), a <tt>403 Forbidden</tt>
HTTP status code is returned alongside an error code of <tt>M_FORBIDDEN</tt> (<xref target="int-transport-errors"/>). For example,
if the user does not have a pending invite, is not a member of the room, or is banned.</t>
              <t>If the sending server does not recognize the returned <tt>room_version</tt>, it <bcp14>SHOULD NOT</bcp14> attempt to populate
the template or use the <tt>send_leave</tt> (<xref target="int-api-send-leave"/>) endpoint.</t>
            </section>
            <section anchor="int-api-send-leave">
              <name><tt>POST /_matrix/federation/v3/send_leave/:txnId</tt></name>
              <t>Sends a leave membership event to the room through a hub server.</t>
              <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>POST /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/send_leave/:txnId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
              <t><strong>TODO</strong>: Remove implementation notes.</t>
              <t><strong>Rate-limited</strong>: Yes.</t>
              <t><strong>Authentication required</strong>: Yes.</t>
              <t>Path parameters:</t>
              <ul spacing="normal">
                <li>
                  <t><tt>:txnId</tt> - the transaction ID (<xref target="int-txn-ids"/>) for the request. The event ID (<xref target="int-pdu"/>) of the
contained event may be a good option as a readily-available transaction ID.</t>
                </li>
              </ul>
              <t>Query parameters: None applicable.</t>
              <t>Request body:</t>
              <sourcecode type="json"><![CDATA[
{
   /* LPDU created from make_leave template */
}
]]></sourcecode>
              <t><tt>200 OK</tt> response:</t>
              <sourcecode type="json"><![CDATA[
{/* deliberately empty object */}
]]></sourcecode>
              <t>The errors responses from <tt>/make_leave</tt> (<xref target="int-api-make-leave"/>) are copied here. Servers should note
that room state <bcp14>MAY</bcp14> change between a <tt>/make_leave</tt> and <tt>/send_leave</tt>, 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.</t>
            </section>
          </section>
        </section>
        <section anchor="int-transport-joins">
          <name>Joins</name>
          <t>Joins for users <bcp14>SHOULD</bcp14> be sent directly whenever possible, and otherwise use the "make and send" handshake
(<xref target="int-transport-make-and-send"/>) approach described here.</t>
          <section anchor="int-api-make-join">
            <name><tt>GET /_matrix/federation/v1/make_join/:roomId/:userId</tt></name>
            <t>Requests an event template from the hub server for a room. This is done to ensure the requesting
server supports the room's version (<xref target="int-room-versions"/>), as well as hint at the event format
needed to participate.</t>
            <t>Note that this endpoint is extremely similar to <tt>/make_leave</tt> (<xref target="int-api-make-leave"/>).</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:roomId</tt> - the room ID (<xref target="int-room-id"/>) to get a template for.</t>
              </li>
              <li>
                <t><tt>:userId</tt> - the user ID (<xref target="int-user-id"/>) attempting to join.</t>
              </li>
            </ul>
            <t>Query parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>ver</tt> (string; required; repeated) - The room versions (<xref target="int-room-versions"/>) the sending server
supports.</t>
              </li>
            </ul>
            <t>Request body: None applicable.</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   /* partial LPDU */
}
]]></sourcecode>
            <t>The response body <bcp14>MUST</bcp14> be a partial LPDU (<xref target="int-lpdu"/>) with at least the following fields:</t>
            <ul spacing="normal">
              <li>
                <t><tt>type</tt> of <tt>m.room.member</tt>.</t>
              </li>
              <li>
                <t><tt>state_key</tt> of <tt>:userId</tt> from the path parameters.</t>
              </li>
              <li>
                <t><tt>sender</tt> of <tt>:userId</tt> from the path parameters.</t>
              </li>
              <li>
                <t><tt>content</tt> of <tt>{"membership": "join"}</tt>.</t>
              </li>
            </ul>
            <t>The sending server <bcp14>SHOULD</bcp14> remove all other fields before using the event in a <tt>send_join</tt> (<xref target="int-api-send-join"/>).</t>
            <t>If the receiving server is not the hub server for the room ID, an HTTP status code of <tt>400 Bad Request</tt>
and error code <tt>M_WRONG_SERVER</tt> (<xref target="int-transport-errors"/>) is returned. If the room ID is not known,
<tt>404 Not Found</tt> is used as an HTTP status code and <tt>M_NOT_FOUND</tt> as an error code (<xref target="int-transport-errors"/>).</t>
            <t>If the user does not have permission to join under the auth rules (<xref target="int-auth-rules"/>), a <tt>403 Forbidden</tt>
HTTP status code is returned alongside an error code of <tt>M_FORBIDDEN</tt> (<xref target="int-transport-errors"/>).</t>
            <t>If the room version is not one of the <tt>ver</tt> strings the sender supplied, a <tt>400 Bad Request</tt> HTTP status
code is returned alongside <tt>M_INCOMPATIBLE_ROOM_VERSION</tt> error code (<xref target="int-transport-errors"/>).</t>
          </section>
          <section anchor="int-api-send-join">
            <name><tt>POST /_matrix/federation/v3/send_join/:txnId</tt></name>
            <t>Sends a join membership event to the room through a hub server.</t>
            <t>Note that this endpoint is extremely similar to <tt>/send_leave</tt> (<xref target="int-api-send-leave"/>).</t>
            <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>POST /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/send_join/:txnId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
            <t><strong>TODO</strong>: Remove implementation notes.</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:txnId</tt> - the transaction ID (<xref target="int-txn-ids"/>) for the request. The event ID (<xref target="int-pdu"/>) of the
contained event may be a good option as a readily-available transaction ID.</t>
              </li>
            </ul>
            <t>Query parameters: None applicable.</t>
            <t><strong>TODO</strong>: Incorporate faster joins work.</t>
            <t>Request body:</t>
            <sourcecode type="json"><![CDATA[
{
   /* LPDU created from make_join template */
}
]]></sourcecode>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   "state": [/* events */],
   "auth_chain": [/* events */],
   "event": {/* fully-formed event */}
}
]]></sourcecode>
            <t><tt>state</tt> is the current room state, consisting of the events which represent "current state" (<xref target="int-state-events"/>)
prior to considering the membership state change. <tt>auth_chain</tt> consists of the events which make up
the <tt>auth_events</tt> (<xref target="int-auth-selection"/>) for the <tt>state</tt> events, and the <tt>auth_events</tt> of those events,
recursively. <tt>event</tt> will be the fully-formed PDU (<xref target="int-pdu"/>) that is sent by the hub to all other
participants in the room.</t>
            <t>The errors responses from <tt>/make_join</tt> (<xref target="int-api-make-join"/>) are copied here (with the exception
of <tt>M_INCOMPATIBLE_ROOM_VERSION</tt>, as the server already checked for support). Servers should note
that room state <bcp14>MAY</bcp14> change between a <tt>/make_join</tt> and <tt>/send_join</tt>, potentially in a way which
prevents the user from joining the room suddenly.</t>
          </section>
        </section>
        <section anchor="int-transport-knocks">
          <name>Knocks</name>
          <t>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 <tt>leave</tt> membership) or banning the
user. If the user is kicked, they may re-send their knock.</t>
          <t>Senders should note the <tt>reason</tt> field on <tt>m.room.member</tt> events (<xref target="int-ev-member"/>) to provide context
for their knock.</t>
          <t>To retract a knock, the sending server uses the same APIs as rejecting an invite (<xref target="int-transport-leaves"/>).</t>
          <t>Where possible, knocks from users <bcp14>SHOULD</bcp14> be sent directly, otherwise using the "make and send" handshake
(<xref target="int-transport-make-and-send"/>) approach described here.</t>
          <section anchor="int-api-make-knock">
            <name><tt>GET /_matrix/federation/v1/make_knock/:roomId/:userId</tt></name>
            <t>Requests an event template from the hub server for a room. This is done to ensure the requesting
server supports the room's version (<xref target="int-room-versions"/>), as well as hint at the event format
needed to participate.</t>
            <t>Note that this endpoint is almost exactly the same as <tt>/make_join</tt> (<xref target="int-api-make-join"/>).</t>
            <t><strong>TODO</strong>: It's so similar to make_join that we should probably just combine the two endpoints.</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:roomId</tt> - the room ID (<xref target="int-room-id"/>) to get a template for.</t>
              </li>
              <li>
                <t><tt>:userId</tt> - the user ID (<xref target="int-user-id"/>) attempting to knock.</t>
              </li>
            </ul>
            <t>Query parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>ver</tt> (string; required; repeated) - The room versions (<xref target="int-room-versions"/>) the sending server
supports.</t>
              </li>
            </ul>
            <t>Request body: None applicable.</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   /* partial LPDU */
}
]]></sourcecode>
            <t>The response body <bcp14>MUST</bcp14> be a partial LPDU (<xref target="int-lpdu"/>) with at least the following fields:</t>
            <ul spacing="normal">
              <li>
                <t><tt>type</tt> of <tt>m.room.member</tt>.</t>
              </li>
              <li>
                <t><tt>state_key</tt> of <tt>:userId</tt> from the path parameters.</t>
              </li>
              <li>
                <t><tt>sender</tt> of <tt>:userId</tt> from the path parameters.</t>
              </li>
              <li>
                <t><tt>content</tt> of <tt>{"membership": "knock"}</tt>.</t>
              </li>
            </ul>
            <t>The sending server <bcp14>SHOULD</bcp14> remove all other fields before using the event in a <tt>send_knock</tt> (<xref target="int-api-send-knock"/>).</t>
            <t>If the receiving server is not the hub server for the room ID, an HTTP status code of <tt>400 Bad Request</tt>
and error code <tt>M_WRONG_SERVER</tt> (<xref target="int-transport-errors"/>) is returned. If the room ID is not known,
<tt>404 Not Found</tt> is used as an HTTP status code and <tt>M_NOT_FOUND</tt> as an error code (<xref target="int-transport-errors"/>).</t>
            <t>If the user does not have permission to knock under the auth rules (<xref target="int-auth-rules"/>), a <tt>403 Forbidden</tt>
HTTP status code is returned alongside an error code of <tt>M_FORBIDDEN</tt> (<xref target="int-transport-errors"/>).</t>
            <t>If the room version is not one of the <tt>ver</tt> strings the sender supplied, a <tt>400 Bad Request</tt> HTTP status
code is returned alongside <tt>M_INCOMPATIBLE_ROOM_VERSION</tt> error code (<xref target="int-transport-errors"/>).</t>
          </section>
          <section anchor="int-api-send-knock">
            <name><tt>POST /_matrix/federation/v3/send_knock/:txnId</tt></name>
            <t>Sends a knock membership event to the room through a hub server.</t>
            <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>POST /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/send_knock/:txnId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
            <t><strong>TODO</strong>: Remove implementation notes.</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:txnId</tt> - the transaction ID (<xref target="int-txn-ids"/>) for the request. The event ID (<xref target="int-pdu"/>) of the
contained event may be a good option as a readily-available transaction ID.</t>
              </li>
            </ul>
            <t>Query parameters: None applicable.</t>
            <t>Request body:</t>
            <sourcecode type="json"><![CDATA[
{
   /* LPDU created from make_knock template */
}
]]></sourcecode>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   "stripped_state": [
      /* stripped state events */
   ]
}
]]></sourcecode>
            <t><tt>stripped_state</tt> are the stripped state events (<xref target="int-stripped-state"/>) for the room.</t>
            <t>The errors responses from <tt>/make_knock</tt> (<xref target="int-api-make-knock"/>) are copied here (with the exception
of <tt>M_INCOMPATIBLE_ROOM_VERSION</tt>, as the server already checked for support). Servers should note
that room state <bcp14>MAY</bcp14> change between a <tt>/make_knock</tt> and <tt>/send_knock</tt>, potentially in a way which
prevents the user from knocking upon the room suddenly.</t>
          </section>
        </section>
      </section>
      <section anchor="content-repository">
        <name>Content Repository</name>
        <t>The content repository, sometimes called the "media repo", is where user-generated content is stored
for referencing within an encrypted message.</t>
        <t><strong>TODO</strong>: Complete this section. We want auth/event linking from MSC3911 and MSC3916.</t>
        <t><strong>TODO</strong>: Spell out that content is images, videos, files, etc.</t>
      </section>
      <section anchor="int-transport-edus">
        <name>Ephemeral Data Units (EDUs)</name>
        <t>EDUs are sent out of band from rooms and are only persisted for exactly as long as they are needed.
For example, once a to-device (<xref target="int-transport-to-device"/>) message is delivered to a client, the
server may easily be able to delete its copy of the message.</t>
        <t>EDUs contain the following mandatory fields:</t>
        <sourcecode type="json"><![CDATA[
{
   "type": "m.room.encrypted",
   "sender": "@alice:example.org",
   "content": {
      /* type-specific content */
   }
}
]]></sourcecode>
        <t>The <tt>type</tt> is similar to an event type (<xref target="int-pdu"/>) and ultimately describes the schema for the
<tt>content</tt>.</t>
        <t><tt>sender_id</tt> is the user ID (<xref target="int-user-id"/>) which is sending the EDU. Typically, clients will not
generate EDUs directly. Instead, the server will convert a client's request into an EDU for sending
to a remote server, where that server then unpacks the EDU before delivering it to local devices.</t>
        <t>Because EDUs are not sent in the context of a room, even if an MLS <tt>Welcome</tt> message is being sent
for a room, servers <bcp14>MUST</bcp14> send the EDUs directly to the target server with the send API (<xref target="int-api-send-txn"/>).</t>
        <t>In this document, EDUs are only used for to-device messages (<xref target="int-transport-to-device"/>) and device
list changes (<xref target="int-transport-devices"/>), but could be used for read/delivery receipts, typing notifications,
and more in future. This may necessitate routing EDUs through the hub rather than using full-mesh fanout.</t>
        <t><strong>TODO</strong>: Address EDU fanout; Document the implied missing features (receipts, typing notifs).</t>
      </section>
      <section anchor="int-transport-mls">
        <name>MLS</name>
        <t><strong>TODO</strong>: This section. Talk about to-device messaging, device management/querying/key claiming, etc.</t>
        <t>There are several endpoints required by this document's MLS implementation (<xref target="int-mls-considerations"/>),
largely around device management for each device's signing key, claiming key packages for those devices,
and sending messages (<tt>Welcome</tt> in particular) after using a key package.</t>
        <section anchor="int-transport-devices">
          <name>Device Info Publishing</name>
          <t>When a user creates a new encryption-capable device, or removes one, a "device list update" is sent
to all servers the user shares a room with. The receiving servers then determine which local clients
need to be made aware of the device list change and sends the information to them. This is primarily
used by this document's MLS implementation (<xref target="int-mls-considerations"/>) to indicate to other devices
that either a new possible device has come online or that another needs to be removed from some MLS
groups due to being deleted.</t>
          <t>Typically, a device is created by a user when they log in to a new session. Similarly, a device is
deleted/removed when they log out of that client.</t>
          <t>The device list update takes the shape of an EDU (<xref target="int-transport-edus"/>), as such:</t>
          <sourcecode type="json"><![CDATA[
{
   "type": "m.device_list_update",
   "sender_id": "@alice:example.org",
   "content": {
      "changed": [/* Device Objects */],
      "removed": [/* Device IDs */]
   }
}
]]></sourcecode>
          <t>The device objects are the same as in the response for <tt>/user/:userId/device/:deviceId</tt> (<xref target="int-api-get-device"/>),
indicating that either a new device was created or that information about a previous device has changed.</t>
          <t><strong>TODO</strong>: Matrix's <tt>m.device_list_update</tt> EDU is <em>very</em> different from this, and relatively complicated.
Do we actually need a <tt>stream_id</tt>, like in Matrix? Do we then need the <tt>/devices</tt> endpoint?</t>
          <section anchor="int-api-get-device">
            <name><tt>GET /_matrix/federation/v1/user/:userId/device/:deviceId</tt></name>
            <t>Retrieves information about a specific device for a user. This request does not go via a hub, instead
going directly to the server which owns the <tt>:userId</tt>.</t>
            <t><strong>Implementation note</strong>: Currently this endpoint doesn't actually exist. Use
<tt>PUT /_matrix/federation/unstable/org.matrix.i-d.ralston-mimi-linearized-matrix.02/user/:userId/device/:deviceId</tt>
when testing against other Linearized Matrix implementations. This string may be updated later to
account for breaking changes.</t>
            <t><strong>TODO</strong>: Remove implementation notes.</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters:</t>
            <ul spacing="normal">
              <li>
                <t><tt>:userId</tt> - the user ID (<xref target="int-user-id"/>) who owns the device.</t>
              </li>
              <li>
                <t><tt>:deviceId</tt> - the device ID (<xref target="int-device-id"/>) to get information about.</t>
              </li>
            </ul>
            <t>Query parameters: None applicable.</t>
            <t>Request body: None applicable.</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
   "device_id": "ABCDEF",
   "user_id": "@alice:example.org",
   "algorithms": [
      "m.mls.v1.dhkemx25519-aes128gcm-sha256-ed25519"
   ],
   "keys": {
      "m.mls.v1.credential.ed25519:ABCDEF":
         "<unpadded base64 BasicCredential>"
   },
   "signatures": {
      "@alice:example.org": {
         "m.mls.v1.credential.ed25519:ABCDEF":
            "<unpadded base64 signature>"
      }
   }
}
]]></sourcecode>
            <t>Note that the response is the same object the device itself signed/created in <xref target="int-mls-credentials"/>.</t>
            <t>If the user ID does not belong the receiving server, a <tt>404 Not Found</tt> HTTP status code is returned
with error code <tt>M_NOT_FOUND</tt> (<xref target="int-transport-errors"/>). The same applies if the user ID does not
exist, or the user does not have the device ID requested.</t>
          </section>
        </section>
        <section anchor="int-transport-to-device">
          <name>To-Device Messaging</name>
          <t>To-device messaging is an ability to send information directly to another device, typically to carry
MLS <tt>Welcome</tt> messages and similar. They are sent as EDUs (<xref target="int-transport-edus"/>), one per receipient
device and payload:</t>
          <sourcecode type="json"><![CDATA[
{
   "type": "m.direct_to_device",
   "sender": "@alice:example.org",
   "content": {
      "target": "@bob:example.org",
      "target_device": "ABCD",
      "message_type": "m.room.encrypted",
      "message": {
         /* message_type-specific schema */
      }
   }
}
]]></sourcecode>
          <t><tt>target</tt> and <tt>target_device</tt> denote the destination user ID (<xref target="int-user-id"/>) and device ID (<xref target="int-device-id"/>)
for that user. This EDU <bcp14>MUST</bcp14> be sent to the server denoted by the target user ID. If the target user
doesn't exist or doesn't have a device with the ID described, the receiving server drops/ignores the
EDU.</t>
          <t>See <xref target="int-mls-add-remove"/> for an example of a to-device message being used.</t>
        </section>
        <section anchor="int-transport-key-claim">
          <name>One Time Key Claiming</name>
          <t>To enable two devices to communicate, they need to claim a key package (<xref target="int-mls-key-packages"/>)
for the other device. These key packages are also called "one time keys". This is done through the
following endpoint.</t>
          <section anchor="post-matrixfederationv1userkeysclaim">
            <name><tt>POST /_matrix/federation/v1/user/keys/claim</tt></name>
            <t>Claims one time keys for devices. This request does not go via a hub, instead going directly to the
server which owns the given user IDs.</t>
            <t><strong>Rate-limited</strong>: Yes.</t>
            <t><strong>Authentication required</strong>: Yes.</t>
            <t>Path parameters: None applicable.</t>
            <t>Query parameters: None applicable.</t>
            <t>Request body:</t>
            <sourcecode type="json"><![CDATA[
{
  "one_time_keys": {
    "@alice:example.org": {
      "ABCD":
        "m.mls.v1.key_package.dhkemx25519-aes128gcm-sha256-ed25519"
    }
  }
}
]]></sourcecode>
            <t><tt>one_time_keys</tt> <bcp14>MUST</bcp14> be specified and is a map of user ID (<xref target="int-user-id"/>) to device ID (<xref target="int-device-id"/>)
to algorithm for the key package to claim. Currently the only expected algorithm is defined by <xref target="int-mls-key-packages"/>.</t>
            <t>Any user IDs which don't belong to the receiving server, or which don't exist, are ignored. The same
applies for device IDs for which the user doesn't have.</t>
            <t><tt>200 OK</tt> response:</t>
            <sourcecode type="json"><![CDATA[
{
  "one_time_keys": {
    "@alice:example.org": {
      "ABCD": {
        "m.mls.v1.key_package.dhkemx25519-aes128gcm-sha256-ed25519":
          "<unpadded base64 encoded key package>"
      }
    }
  }
}
]]></sourcecode>
            <t>Like the request body, <tt>one_time_keys</tt> <bcp14>MUST</bcp14> be specified (but <bcp14>MAY</bcp14> be empty) and is a map of requested
user ID to requested device ID to algorithm name. The value for the algorithm name is dependent on the
algorithm itself. For <tt>m.mls.v1.key_package.dhkemx25519-aes128gcm-sha256-ed25519</tt>, this is an unpadded
base64 (<xref target="int-unpadded-base64"/>) string representing the key package itself.</t>
            <t>Servers <bcp14>MUST NOT</bcp14> reuse a device's one time key, unless that key permits it. For example, MLS's "last
resort" key <bcp14>MAY</bcp14> be used multiple times, but <bcp14>SHOULD</bcp14> only be used if no other one time keys remain for
the device. Servers <bcp14>MUST NOT</bcp14> use an expired key.</t>
            <t>Typically, the server will inform the device that a key was used so the device can upload additional
keys. See <xref target="int-mls-key-packages"/> for further implementation-related concerns.</t>
          </section>
        </section>
      </section>
      <section anchor="todo-remainder-of-transport">
        <name>TODO: Remainder of Transport</name>
        <t><strong>TODO</strong>: This section.</t>
        <t>Topics:</t>
        <ul spacing="normal">
          <li>
            <t>More EDUs (typing notifications, receipts, presence)</t>
          </li>
          <li>
            <t>Query APIs (alias resolution, profiles)</t>
          </li>
          <li>
            <t>Other Encryption APIs??</t>
          </li>
          <li>
            <t>Server ACLs? (this probably should become part of the auth rules)</t>
          </li>
        </ul>
        <t>Notably/deliberately missing APIs are:</t>
        <ul spacing="normal">
          <li>
            <t><tt>get_missing_events</tt> - this is used by DAG servers only</t>
          </li>
          <li>
            <t>Public room directory</t>
          </li>
          <li>
            <t>Timestamp-to-event API</t>
          </li>
          <li>
            <t>All of 3rd party invites</t>
          </li>
          <li>
            <t>All of Spaces</t>
          </li>
          <li>
            <t>OpenID API</t>
          </li>
        </ul>
        <section anchor="open-questions">
          <name>Open Questions</name>
          <ul spacing="normal">
            <li>
              <t>Should we include <tt>/_matrix/federation/v1/version</tt> in here? It's used by federation testers, but not
really anything else.</t>
            </li>
          </ul>
        </section>
      </section>
    </section>
    <section anchor="int-user-privacy">
      <name>User Privacy</name>
      <t><strong>TODO</strong>: Fully complete this section.</t>
      <t>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 <tt>POST /_matrix/federation/v3/invite/:txnId</tt> (<xref target="int-api-invite"/>), and by having the server (optionally)
auto-decline any invites received directly through <tt>PUT /_matrix/federation/v2/send/:txnId</tt> (<xref target="int-api-send-txn"/>).
See <xref target="int-transport-leaves"/> for more information on rejecting invites.</t>
    </section>
    <section anchor="int-spam">
      <name>Spam Prevention</name>
      <t><strong>TODO</strong>: Fully complete this section.</t>
      <t><strong>TODO</strong>: Talk about how to deal with spammy/unwanted invites.</t>
      <t>Servers <bcp14>MAY</bcp14> 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 <tt>m.room.member</tt> events with
<tt>membership</tt> of <tt>leave</tt> (<xref target="int-ev-member"/>). Then, any time the server receives a request for that
room ID it can reject it with an error response (<xref target="int-transport-errors"/>).</t>
      <t>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.</t>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t><strong>TODO</strong>: Expand upon this section.</t>
      <t>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.</t>
      <t><strong>TODO</strong>: Should we bring Matrix's cross-signing here?</t>
      <t>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.</t>
    </section>
    <section anchor="mimi-protocol-comparison">
      <name>MIMI Protocol Comparison</name>
      <t><xref target="I-D.barnes-mimi-arch"/>, <xref target="I-D.ralston-mimi-protocol"/>, and <xref target="I-D.robert-mimi-delivery-service"/>
collectively define a protocol with similar capabilities to Linearized Matrix, leaning more heavily
into the MLS layering to accomplish interoperable messaging. Linearized Matrix in contrast provides
a signaling layer for which encryption can operate, using existing open standards as the foundational
piece.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>The <tt>m.*</tt> namespace likely needs formal registration in some capacity.</t>
      <t>The <tt>I.*</tt> namespace likely needs formal registration in some capacity.</t>
      <t>Port 8448 may need formal registration.</t>
      <t>The SRV service name <tt>matrix</tt> may need re-registering, or a new service name assigned.</t>
      <t>The <tt>.well-known/matrix</tt> namespace is already registered for use by The Matrix.org Foundation C.I.C.</t>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC6125">
          <front>
            <title>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)</title>
            <author fullname="P. Saint-Andre" initials="P." surname="Saint-Andre"/>
            <author fullname="J. Hodges" initials="J." surname="Hodges"/>
            <date month="March" year="2011"/>
            <abstract>
              <t>Many application technologies enable secure communication between two entities by means of Internet Public Key Infrastructure Using X.509 (PKIX) certificates in the context of Transport Layer Security (TLS). This document specifies procedures for representing and verifying the identity of application services in such interactions. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6125"/>
          <seriesInfo name="DOI" value="10.17487/RFC6125"/>
        </reference>
        <reference anchor="RFC4648">
          <front>
            <title>The Base16, Base32, and Base64 Data Encodings</title>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <date month="October" year="2006"/>
            <abstract>
              <t>This document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets, and canonical encodings. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="4648"/>
          <seriesInfo name="DOI" value="10.17487/RFC4648"/>
        </reference>
        <reference anchor="RFC1123">
          <front>
            <title>Requirements for Internet Hosts - Application and Support</title>
            <author fullname="R. Braden" initials="R." role="editor" surname="Braden"/>
            <date month="October" year="1989"/>
            <abstract>
              <t>This RFC is an official specification for the Internet community. It incorporates by reference, amends, corrects, and supplements the primary protocol standards documents relating to hosts. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="3"/>
          <seriesInfo name="RFC" value="1123"/>
          <seriesInfo name="DOI" value="10.17487/RFC1123"/>
        </reference>
        <reference anchor="I-D.ietf-mls-protocol">
          <front>
            <title>The Messaging Layer Security (MLS) Protocol</title>
            <author fullname="Richard Barnes" initials="R." surname="Barnes">
              <organization>Cisco</organization>
            </author>
            <author fullname="Benjamin Beurdouche" initials="B." surname="Beurdouche">
              <organization>Inria &amp; Mozilla</organization>
            </author>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Jon Millican" initials="J." surname="Millican">
              <organization>Meta Platforms</organization>
            </author>
            <author fullname="Emad Omara" initials="E." surname="Omara">
              <organization>Google</organization>
            </author>
            <author fullname="Katriel Cohn-Gordon" initials="K." surname="Cohn-Gordon">
              <organization>University of Oxford</organization>
            </author>
            <date day="27" month="March" year="2023"/>
            <abstract>
              <t>Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that messages are only accessible to the communicating endpoints, and not to any servers involved in delivering messages.  Establishing keys to provide such protections is challenging for group chat settings, in which more than two clients need to agree on a key but may not be online at the same time.  In this document, we specify a key establishment protocol that provides efficient asynchronous group key establishment with forward secrecy (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.
              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mls-protocol-20"/>
        </reference>
        <reference anchor="I-D.ietf-mls-architecture">
          <front>
            <title>The Messaging Layer Security (MLS) Architecture</title>
            <author fullname="Benjamin Beurdouche" initials="B." surname="Beurdouche">
              <organization>Inria &amp; Mozilla</organization>
            </author>
            <author fullname="Eric Rescorla" initials="E." surname="Rescorla">
              <organization>Mozilla</organization>
            </author>
            <author fullname="Emad Omara" initials="E." surname="Omara">
              <organization>Google</organization>
            </author>
            <author fullname="Srinivas Inguva" initials="S." surname="Inguva">
         </author>
            <author fullname="Alan Duric" initials="A." surname="Duric">
              <organization>Wire</organization>
            </author>
            <date day="26" month="July" year="2023"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol (I-D.ietf-mls-protocol)
   provides a Group Key Agreement protocol for messaging applications.
   MLS is meant to protect against eavesdropping, tampering, message
   forgery, and provide Forward Secrecy (FS) and Post-Compromise
   Security (PCS).

   This document describes the architecture for using MLS in a general
   secure group messaging infrastructure and defines the security goals
   for MLS.  It provides guidance on building a group messaging system
   and discusses security and privacy tradeoffs offered by multiple
   security mechanisms that are part of the MLS protocol (e.g.,
   frequency of public encryption key rotation).  The document also
   provides guidance for parts of the infrastructure that are not
   standardized by MLS and are instead left to the application.

   While the recommendations of this document are not mandatory to
   follow in order to interoperate at the protocol level, they affect
   the overall security guarantees that are achieved by a messaging
   application.  This is especially true in the case of active
   adversaries that are able to compromise clients, the delivery
   service, or the authentication service.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mls-architecture-11"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="I-D.ralston-mimi-terminology">
          <front>
            <title>MIMI Terminology</title>
            <author fullname="Travis Ralston" initials="T." surname="Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date day="23" month="October" year="2023"/>
            <abstract>
              <t>   This document introduces a set of terminology to use when discussing
   or describing concepts within MIMI.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-terminology-03"/>
        </reference>
        <reference anchor="RFC5234">
          <front>
            <title>Augmented BNF for Syntax Specifications: ABNF</title>
            <author fullname="D. Crocker" initials="D." role="editor" surname="Crocker"/>
            <author fullname="P. Overell" initials="P." surname="Overell"/>
            <date month="January" year="2008"/>
            <abstract>
              <t>Internet technical specifications often need to define a formal syntax. Over the years, a modified version of Backus-Naur Form (BNF), called Augmented BNF (ABNF), has been popular among many Internet specifications. The current specification documents ABNF. It balances compactness and simplicity with reasonable representational power. The differences between standard BNF and ABNF involve naming rules, repetition, alternatives, order-independence, and value ranges. This specification also supplies additional rule definitions and encoding for a core lexical analyzer of the type common to several Internet specifications. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="68"/>
          <seriesInfo name="RFC" value="5234"/>
          <seriesInfo name="DOI" value="10.17487/RFC5234"/>
        </reference>
        <reference anchor="RFC3629">
          <front>
            <title>UTF-8, a transformation format of ISO 10646</title>
            <author fullname="F. Yergeau" initials="F." surname="Yergeau"/>
            <date month="November" year="2003"/>
            <abstract>
              <t>ISO/IEC 10646-1 defines a large character set called the Universal Character Set (UCS) which encompasses most of the world's writing systems. The originally proposed encodings of the UCS, however, were not compatible with many current applications and protocols, and this has led to the development of UTF-8, the object of this memo. UTF-8 has the characteristic of preserving the full US-ASCII range, providing compatibility with file systems, parsers and other software that rely on US-ASCII values but are transparent to other values. This memo obsoletes and replaces RFC 2279.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="63"/>
          <seriesInfo name="RFC" value="3629"/>
          <seriesInfo name="DOI" value="10.17487/RFC3629"/>
        </reference>
        <reference anchor="RFC8259">
          <front>
            <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
            <author fullname="T. Bray" initials="T." role="editor" surname="Bray"/>
            <date month="December" year="2017"/>
            <abstract>
              <t>JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format. It was derived from the ECMAScript Programming Language Standard. JSON defines a small set of formatting rules for the portable representation of structured data.</t>
              <t>This document removes inconsistencies with other specifications of JSON, repairs specification errors, and offers experience-based interoperability guidance.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="90"/>
          <seriesInfo name="RFC" value="8259"/>
          <seriesInfo name="DOI" value="10.17487/RFC8259"/>
        </reference>
        <reference anchor="I-D.robert-mimi-delivery-service">
          <front>
            <title>MIMI Delivery Service</title>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="6" month="November" year="2023"/>
            <abstract>
              <t>   This document describes the MIMI Delivery Service.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-robert-mimi-delivery-service-06"/>
        </reference>
        <reference anchor="RFC8032">
          <front>
            <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
            <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
            <author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/>
            <date month="January" year="2017"/>
            <abstract>
              <t>This document describes elliptic curve signature scheme Edwards-curve Digital Signature Algorithm (EdDSA). The algorithm is instantiated with recommended parameters for the edwards25519 and edwards448 curves. An example implementation and test vectors are provided.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8032"/>
          <seriesInfo name="DOI" value="10.17487/RFC8032"/>
        </reference>
        <reference anchor="RFC8785">
          <front>
            <title>JSON Canonicalization Scheme (JCS)</title>
            <author fullname="A. Rundgren" initials="A." surname="Rundgren"/>
            <author fullname="B. Jordan" initials="B." surname="Jordan"/>
            <author fullname="S. Erdtman" initials="S." surname="Erdtman"/>
            <date month="June" year="2020"/>
            <abstract>
              <t>Cryptographic operations like hashing and signing need the data to be expressed in an invariant format so that the operations are reliably repeatable. One way to address this is to create a canonical representation of the data. Canonicalization also permits data to be exchanged in its original form on the "wire" while cryptographic operations performed on the canonicalized counterpart of the data in the producer and consumer endpoints generate consistent results.</t>
              <t>This document describes the JSON Canonicalization Scheme (JCS). This specification defines how to create a canonical representation of JSON data by building on the strict serialization methods for JSON primitives defined by ECMAScript, constraining JSON data to the Internet JSON (I-JSON) subset, and by using deterministic property sorting.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8785"/>
          <seriesInfo name="DOI" value="10.17487/RFC8785"/>
        </reference>
        <reference anchor="RFC6234">
          <front>
            <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
            <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake 3rd"/>
            <author fullname="T. Hansen" initials="T." surname="Hansen"/>
            <date month="May" year="2011"/>
            <abstract>
              <t>Federal Information Processing Standard, FIPS</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6234"/>
          <seriesInfo name="DOI" value="10.17487/RFC6234"/>
        </reference>
        <reference anchor="RFC9110">
          <front>
            <title>HTTP Semantics</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2022"/>
            <abstract>
              <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of the protocol that are shared by all versions. In this definition are core protocol elements, extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes.</t>
              <t>This document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="97"/>
          <seriesInfo name="RFC" value="9110"/>
          <seriesInfo name="DOI" value="10.17487/RFC9110"/>
        </reference>
        <reference anchor="RFC9113">
          <front>
            <title>HTTP/2</title>
            <author fullname="M. Thomson" initials="M." role="editor" surname="Thomson"/>
            <author fullname="C. Benfield" initials="C." role="editor" surname="Benfield"/>
            <date month="June" year="2022"/>
            <abstract>
              <t>This specification describes an optimized expression of the semantics of the Hypertext Transfer Protocol (HTTP), referred to as HTTP version 2 (HTTP/2). HTTP/2 enables a more efficient use of network resources and a reduced latency by introducing field compression and allowing multiple concurrent exchanges on the same connection.</t>
              <t>This document obsoletes RFCs 7540 and 8740.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9113"/>
          <seriesInfo name="DOI" value="10.17487/RFC9113"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="RFC2782">
          <front>
            <title>A DNS RR for specifying the location of services (DNS SRV)</title>
            <author fullname="A. Gulbrandsen" initials="A." surname="Gulbrandsen"/>
            <author fullname="P. Vixie" initials="P." surname="Vixie"/>
            <author fullname="L. Esibov" initials="L." surname="Esibov"/>
            <date month="February" year="2000"/>
            <abstract>
              <t>This document describes a DNS RR which specifies the location of the server(s) for a specific protocol and domain. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="2782"/>
          <seriesInfo name="DOI" value="10.17487/RFC2782"/>
        </reference>
        <reference anchor="RFC1034">
          <front>
            <title>Domain names - concepts and facilities</title>
            <author fullname="P. Mockapetris" initials="P." surname="Mockapetris"/>
            <date month="November" year="1987"/>
            <abstract>
              <t>This RFC is the revised basic definition of The Domain Name System. It obsoletes RFC-882. This memo describes the domain style names and their used for host address look up and electronic mail forwarding. It discusses the clients and servers in the domain name system and the protocol used between them.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="13"/>
          <seriesInfo name="RFC" value="1034"/>
          <seriesInfo name="DOI" value="10.17487/RFC1034"/>
        </reference>
        <reference anchor="RFC2181">
          <front>
            <title>Clarifications to the DNS Specification</title>
            <author fullname="R. Elz" initials="R." surname="Elz"/>
            <author fullname="R. Bush" initials="R." surname="Bush"/>
            <date month="July" year="1997"/>
            <abstract>
              <t>This document considers some areas that have been identified as problems with the specification of the Domain Name System, and proposes remedies for the defects identified. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="2181"/>
          <seriesInfo name="DOI" value="10.17487/RFC2181"/>
        </reference>
        <reference anchor="RFC3596">
          <front>
            <title>DNS Extensions to Support IP Version 6</title>
            <author fullname="S. Thomson" initials="S." surname="Thomson"/>
            <author fullname="C. Huitema" initials="C." surname="Huitema"/>
            <author fullname="V. Ksinant" initials="V." surname="Ksinant"/>
            <author fullname="M. Souissi" initials="M." surname="Souissi"/>
            <date month="October" year="2003"/>
            <abstract>
              <t>This document defines the changes that need to be made to the Domain Name System (DNS) to support hosts running IP version 6 (IPv6). The changes include a resource record type to store an IPv6 address, a domain to support lookups based on an IPv6 address, and updated definitions of existing query types that return Internet addresses as part of additional section processing. The extensions are designed to be compatible with existing applications and, in particular, DNS implementations themselves. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="88"/>
          <seriesInfo name="RFC" value="3596"/>
          <seriesInfo name="DOI" value="10.17487/RFC3596"/>
        </reference>
        <reference anchor="RFC1035">
          <front>
            <title>Domain names - implementation and specification</title>
            <author fullname="P. Mockapetris" initials="P." surname="Mockapetris"/>
            <date month="November" year="1987"/>
            <abstract>
              <t>This RFC is the revised specification of the protocol and format used in the implementation of the Domain Name System. It obsoletes RFC-883. This memo documents the details of the domain name client - server communication.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="13"/>
          <seriesInfo name="RFC" value="1035"/>
          <seriesInfo name="DOI" value="10.17487/RFC1035"/>
        </reference>
        <reference anchor="I-D.barnes-mimi-arch">
          <front>
            <title>An Architecture for More Instant Messaging Interoperability (MIMI)</title>
            <author fullname="Richard Barnes" initials="R." surname="Barnes">
              <organization>Cisco</organization>
            </author>
            <date day="23" month="October" year="2023"/>
            <abstract>
              <t>   The More Instant Messaging Interoperability (MIMI) working group is
   defining a suite of protocols that allow messaging providers to
   interoperate with one another.  This document lays out an overall
   architecture enumerating the MIMI protocols and how they work
   together to enable an overall messaging experience.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-barnes-mimi-arch-02"/>
        </reference>
        <reference anchor="I-D.ralston-mimi-protocol">
          <front>
            <title>More Instant Messaging Interoperability (MIMI) using HTTPS and MLS</title>
            <author fullname="Travis Ralston" initials="T." surname="Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Matthew Hodgson" initials="M." surname="Hodgson">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date day="6" month="November" year="2023"/>
            <abstract>
              <t>   This document specifies the More Instant Messaging Interoperability
   (MIMI) protocol, which allows users of different messaging providers
   to share membership in rooms and send messages to one-another.

   More specifically, the MIMI protocol defines message formats and
   conventions that allows the servers of different providers to
   interoperate, leaving the provider-internal client-server
   communication up to the provider.

   To ensure that communications between users are confidential and
   authentic, the MIMI protocol relies on MLS ([RFC9420], through the
   MIMI DS protocol [I-D.robert-mimi-delivery-service]) to protect
   messages end-to-end.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-protocol-01"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="RFC6120">
          <front>
            <title>Extensible Messaging and Presence Protocol (XMPP): Core</title>
            <author fullname="P. Saint-Andre" initials="P." surname="Saint-Andre"/>
            <date month="March" year="2011"/>
            <abstract>
              <t>The Extensible Messaging and Presence Protocol (XMPP) is an application profile of the Extensible Markup Language (XML) that enables the near-real-time exchange of structured yet extensible data between any two or more network entities. This document defines XMPP's core protocol methods: setup and teardown of XML streams, channel encryption, authentication, error handling, and communication primitives for messaging, network availability ("presence"), and request-response interactions. This document obsoletes RFC 3920. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6120"/>
          <seriesInfo name="DOI" value="10.17487/RFC6120"/>
        </reference>
        <reference anchor="MSC3995" target="https://github.com/matrix-org/matrix-spec-proposals/pull/3995">
          <front>
            <title>MSC3995: [WIP] Linearized Matrix</title>
            <author fullname="Travis Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023" month="April" day="12"/>
          </front>
        </reference>
        <reference anchor="DMLS" target="https://gitlab.matrix.org/matrix-org/mls-ts/-/blob/48efb972075233c3a0f3e3ca01c4d4f888342205/decentralised.org">
          <front>
            <title>Decentralised MLS</title>
            <author fullname="Hubert Chathi">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023" month="May" day="29"/>
          </front>
        </reference>
        <reference anchor="PerspectivesProject" target="https://web.archive.org/web/20170702024706/https://perspectives-project.org/">
          <front>
            <title>Perspectives Project</title>
            <author>
              <organization/>
            </author>
            <date year="2017" month="July" day="02"/>
          </front>
        </reference>
        <reference anchor="I-D.mahy-mimi-group-chat">
          <front>
            <title>Group Chat Framework for More Instant Messaging Interoperability (MIMI)</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Wire</organization>
            </author>
            <date day="10" month="July" year="2023"/>
            <abstract>
              <t>   This document describes a group instant messaging ("group chat")
   semantic framework for the More Instant Messaging Interoperability
   (MIMI) Working Group.  It describes several properties and policy
   options which can be combined to model a wide range of chat and
   multimedia conference types.  It also describes how to build these
   options as an overlay to Messaging Layer Security (MLS) groups and to
   authorize MLS primitives.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mimi-group-chat-00"/>
        </reference>
        <reference anchor="I-D.kohbrok-mimi-portability">
          <front>
            <title>MIMI Portability</title>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="4" month="January" year="2024"/>
            <abstract>
              <t>   This document describes MIMI Portability mechanisms.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-kohbrok-mimi-portability-01"/>
        </reference>
        <reference anchor="I-D.rosenberg-mimi-protocol">
          <front>
            <title>More Instant Messaging Interop (MIMI) Transport Protocol</title>
            <author fullname="Jonathan Rosenberg" initials="J." surname="Rosenberg">
              <organization>Five9</organization>
            </author>
            <author fullname="Cullen Fluffy Jennings" initials="C. F." surname="Jennings">
              <organization>Cisco</organization>
            </author>
            <author fullname="Suhas Nandakumar" initials="S." surname="Nandakumar">
              <organization>Cisco</organization>
            </author>
            <date day="13" month="March" year="2023"/>
            <abstract>
              <t>   This document specifies the More Instant Messaging Interop (mimi)
   Transport Protocol (MTP)- a protocol for inter-provider persistent
   group chat.  MIMI utilizes Messaging Layer Security (MLS) for end-to-
   end encryption of content.  The MIMI Transport Protocol plays the
   role of the Delivery Service (DS) defined by the MLS protocol.  MTP
   is meant to represent the minimal protocol required to enable
   provider to provider federation for messaging exchange using MLS.  It
   is not suitable for client to provider communications.  MTP is based
   on a pull architecture, wherein message delivery from provider A to
   provider B is accomplished by having provider B pull messages from
   provider A.  This provides better scalability and reliability and is
   amenable to implementation in modern cloud software architectures,
   while also reducing spam risk.  MTP serves as a transfer protocol for
   opaque message content, the format of which is specified in a
   separate document.  MTP is also designed to prevent spam, and does so
   by introducing a layer of authorization for the establishment of
   connections and addition to group chats.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-rosenberg-mimi-protocol-00"/>
        </reference>
        <reference anchor="RFC9364">
          <front>
            <title>DNS Security Extensions (DNSSEC)</title>
            <author fullname="P. Hoffman" initials="P." surname="Hoffman"/>
            <date month="February" year="2023"/>
            <abstract>
              <t>This document describes the DNS Security Extensions (commonly called "DNSSEC") that are specified in RFCs 4033, 4034, and 4035, as well as a handful of others. One purpose is to introduce all of the RFCs in one place so that the reader can understand the many aspects of DNSSEC. This document does not update any of those RFCs. A second purpose is to state that using DNSSEC for origin authentication of DNS data is the best current practice. A third purpose is to provide a single reference for other documents that want to refer to DNSSEC.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="237"/>
          <seriesInfo name="RFC" value="9364"/>
          <seriesInfo name="DOI" value="10.17487/RFC9364"/>
        </reference>
        <reference anchor="RFC5280">
          <front>
            <title>Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile</title>
            <author fullname="D. Cooper" initials="D." surname="Cooper"/>
            <author fullname="S. Santesson" initials="S." surname="Santesson"/>
            <author fullname="S. Farrell" initials="S." surname="Farrell"/>
            <author fullname="S. Boeyen" initials="S." surname="Boeyen"/>
            <author fullname="R. Housley" initials="R." surname="Housley"/>
            <author fullname="W. Polk" initials="W." surname="Polk"/>
            <date month="May" year="2008"/>
            <abstract>
              <t>This memo profiles the X.509 v3 certificate and X.509 v2 certificate revocation list (CRL) for use in the Internet. An overview of this approach and model is provided as an introduction. The X.509 v3 certificate format is described in detail, with additional information regarding the format and semantics of Internet name forms. Standard certificate extensions are described and two Internet-specific extensions are defined. A set of required certificate extensions is specified. The X.509 v2 CRL format is described in detail along with standard and Internet-specific extensions. An algorithm for X.509 certification path validation is described. An ASN.1 module and examples are provided in the appendices. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="5280"/>
          <seriesInfo name="DOI" value="10.17487/RFC5280"/>
        </reference>
      </references>
    </references>
    <?line 3247?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to the Matrix Spec Core Team (SCT) for exploring methods of linearizing Matrix's DAG room model,
especially Richard van der Hoff and Erik Johnston. Additional thanks to the Matrix core team as a whole
for general review and input on this document, especially Patrick Cloke and Jim Mackenzie.</t>
      <t>Matrix's crypto team graciously allowed their work-in-progress MLS considerations to be incorporated
in this document. Thanks to Hubert Chathi for reviewing the MLS work for plausibility.</t>
      <t>Thanks are also extended to the wider MIMI working group for continous review and input on this document.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
R1M4BA4NW2dXixIR+HKcGBoGiwovoKK5WTaeTFRDsfjAi2y5WTk1gYOoqPPK
lkECx5gR0N6Yn8ojGcg2UGPVe5VIbel3XGB0ytivxh8Eq+WavdLlShXURclY
nw7lqXFQt1O8p+yRZULmzaXjMsYpGjNHhvaltgR8JUeNNVN6D/+Q5flD6q8i
O4LS58BxLOqCDly+mKNhuYBjX6ALtObxraYltAV5RZ7x0RM6dAsi6zGwc4BU
g7lOYGDhtAu+Wbb1KpJs2B33o5egyHgKKqd8I4v5FpNvlKtrSwantKwl2hXh
WMRBlR3xKfUSmmyCD/LaO/qaX89OsAEthqKXj0P/2UJgf+SlmxcVHIlXkZTO
BhF6JvrTwLkhFU1ozqfWExz3F6X07pI8lnFsi7D/ehsfghYn+wCjkAq6fG3y
zS3HmzrjA+5vxRht4KdgI4mLBSI8MAAlSbfKzXNvkj8G7Fmvd3h6ItoNPOyB
i1JvWJhPbj5hY9M32HYazZaN336JjG5E1KFPHDtYijpnGt8Bwu04I06Wmudk
iDYxiR//RT49cEYDfMoIksmLssmdlcW2uQv5oGxVeI3J66bVT7PFlG+4mcDb
sOlL7onpVcLheub4nl518fbeAkBLrPa5mjPFfu7c/q4D5e1qY+EjmpgiY08D
VstHQxgLRA9RN9+9fjbk6+zdak08gwb9HWkb9+864UwfDyf8mNrhKahuqtAm
mgXkFoyjG0n//d245Xgd/271xx//9PfmqLh6dnz649OnDxZvD67eZdmf/va3
716/Hs6P/75+cbf5kqTX2XTMNibRYeNZ2hlyHao9sG4llLGtnc0RHK7O0dCc
32TfuTubNv9kHm06RMO/IVJBZeZdnw6xN2BDqcUPwGjpTr9klkmQ9zprzhV/
pb7M1uyfI3LdmARo1z6nJomPxKuK/kJM+4HRjNRZOxTkn3NR3OAERCa/8Iqg
w4HoAC4g1qYAWxqD0np1IF3kZ9lCu94Pus1qC0xVCzODrTlISlrFyxy3TxSh
C8FcIurbajqt7G0EhNwOtthF4itODDN2vXO9ZjL+3WZTzB7G2RFmD3fqiBfS
51XOAleVD0muowlFo0hasD+2NRpXFDbJJkKjItww7I/N3F3qpLyIMPYtel+o
QiJ2vSU5UpmctX0j0gLtJ10nSPSdmgODX79VBzeOhbXgirML5qF7ylvM9LnC
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

-->

</rfc>
