<?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.8 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-mimi-protocol-00" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.20.1 -->
  <front>
    <title abbrev="MIMI+MLS Protocol">More Instant Messaging Interoperability (MIMI) using HTTPS and MLS</title>
    <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-protocol-00"/>
    <author fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author fullname="Matthew Hodgson">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>matthew@matrix.org</email>
      </address>
    </author>
    <author fullname="Konrad Kohbrok">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>konrad.kohbrok@datashrine.de</email>
      </address>
    </author>
    <author fullname="Rohan Mahy">
      <organization>Unaffiliated</organization>
      <address>
        <email>rohan.ietf@gmail.com</email>
      </address>
    </author>
    <author fullname="Travis Ralston">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>travisr@matrix.org</email>
      </address>
    </author>
    <author fullname="Raphael Robert">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>ietf@raphaelrobert.com</email>
      </address>
    </author>
    <date year="2024" month="April" day="02"/>
    <area>Applications and Real-Time</area>
    <workgroup>More Instant Messaging Interoperability</workgroup>
    <keyword>mimi</keyword>
    <keyword>interoperable messaging</keyword>
    <keyword>chat</keyword>
    <keyword>secure messaging</keyword>
    <abstract>
      <?line 57?>

<t>This document specifies the More Instant Messaging Interoperability (MIMI)
transport protocol, which allows users of different messaging providers to
interoperate in group chats (rooms), including to send and receive messages,
share room policy, and add participants to and remove participants from rooms.
MIMI describes messages between providers, leaving most aspects of the
provider-internal client-server communication up to the provider.  MIMI
integrates the Messaging Layer Security (MLS) protocol to provide end-to-end security
assurances, including authentication of protocol participants, confidentiality
of messages exchanged within a room, and agreement on the state of the 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://bifurcation.github.io/ietf-mimi-protocol/draft-ralston-mimi-protocol.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ietf-mimi-protocol/"/>.
      </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/bifurcation/ietf-mimi-protocol"/>.</t>
    </note>
  </front>
  <middle>
    <?line 69?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>The More Instant Messaging Interoperability (MIMI) transport protocol enables providers of
end-to-end encrypted instant messaging to interoperate. As described in the MIMI
architecture <xref target="I-D.barnes-mimi-arch"/>, group chats and direct messages are
described in terms of "rooms".  Each MIMI protocol room is hosted at a single
provider (the "hub" provider"), but allows users from different providers to
become participants in the room. The hub provider is responsible for ordering
and distributing messages, enforcing policy, and authorizing messages. It also
keeps a copy of the room state, which includes the room policy and participant
list, which it can provide to new joiners. Each provider also
stores initial keying material for its own users (who may be offline).</t>
      <t>This document describes the communication among different providers necessary to
support messaging application functionality, for example:</t>
      <ul spacing="normal">
        <li>
          <t>Sharing room policy</t>
        </li>
        <li>
          <t>Adding and removing participants in a room</t>
        </li>
        <li>
          <t>Exchanging secure messages</t>
        </li>
      </ul>
      <t>In support of these functions, the protocol also has primitives to fetch initial
keying material and fetch the current state of the underlying end-to-end encryption
protocol for the room.</t>
      <t>Messages sent inside each room are end-to-end encrypted using the Messaging
Layer Security (MLS) protocol <xref target="RFC9420"/>, and each room is associated with an
MLS group. MLS also ensures that clients in a room agree on the room policy and
participation.  MLS is integrated into MIMI in such a way as to ensure that a
client is joined to a room's MLS group only if the client's user is a
participant in the room, and that all clients in the group agree on the state
of the room (including, for example, the room's participant list).</t>
      <section anchor="known-gaps">
        <name>Known Gaps</name>
        <t>In this version of the document, we have tried to capture enough concrete
functionality to enable basic application functionality, while defining enough
of a protocol framework to indicate how to add other necessary functionality.  The
following functions are likely to be needed by the complete protocol, but are
not covered here:</t>
        <dl>
          <dt>Authorization policy:</dt>
          <dd>
            <t>In this document, we introduce a notional concept of roles for
participants, and permissions for roles. Actual messaging systems have more
complex and well-specified authorization policies about which clients can
take which actions in a room.</t>
          </dd>
          <dt>Advanced join/leave flows:</dt>
          <dd>
            <t>In this document, all adds / removes / joins / leaves are initiated from
within the group, or by a new joiner who already has permission to join,
as this aligns well with MLS.  Messaging applications
support a variety of other flows, some of which this protocol will need to
support.</t>
          </dd>
          <dt>Consent:</dt>
          <dd>
            <t>In this document, we assume that any required consent has already been
obtained, e.g., a user consenting to be added to a room by another user.  The
full protocol will need some mechanisms for establishing this consent.</t>
          </dd>
          <dt>Identifiers:</dt>
          <dd>
            <t>Certain entities in the MIMI system need to be identified in the protocol.  In
this document, we define a notional syntax for identifiers, but a more
concrete one should be defined.</t>
          </dd>
          <dt>Abuse reporting:</dt>
          <dd>
            <t>There is no mechanism in this document for reporting abusive behavior to a
messaging provider.</t>
          </dd>
          <dt>Identifier resolution:</dt>
          <dd>
            <t>In some cases, the identifier used to initiate communications with a user
might be different from the identifier that should be used internally.  For
example, a user-visible handle might need to be mapped to a durable internal
identifier.  This document provides no mechanism for such resolution.</t>
          </dd>
          <dt>Authentication</dt>
          <dd>
            <t>While MLS provides basic message authentication, users should also be able
to (cryptographically) tie the identity of other users to their respective
providers. Further authentication such as tying clients to their users (or the
user's other clients) may also be desirable.</t>
          </dd>
        </dl>
      </section>
    </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>Terms and definitions are inherited from <xref target="I-D.barnes-mimi-arch"/>.  We also
make use of terms from the MLS protocol <xref target="RFC9420"/>.</t>
      <t>Throughout this document, the examples use the TLS Presentation Language
<xref target="RFC8446"/> and the semantics of HTTP <xref target="RFC7231"/> respectively as
placeholder a set of binary encoding mechanism and transport semantics.</t>
      <t>The protocol layering of the MIMI transport protocol is as follows:</t>
      <ol spacing="normal" type="1"><li>
          <t>An application layer that enables messaging functionality</t>
        </li>
        <li>
          <t>A security layer that provides end-to-end security guarantees:
          </t>
          <ul spacing="normal">
            <li>
              <t>Confidentiality for messages</t>
            </li>
            <li>
              <t>Authentication of actors making changes to rooms</t>
            </li>
            <li>
              <t>Agreement on room state across the clients involved in a room</t>
            </li>
          </ul>
        </li>
        <li>
          <t>A transport layer that provides secure delivery of protocol objects between
servers.</t>
        </li>
      </ol>
      <figure anchor="fig-layers">
        <name>MIMI protocol layering</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="144" width="216" viewBox="0 0 216 144" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 8,32 L 8,128" fill="none" stroke="black"/>
              <path d="M 72,64 L 72,96" fill="none" stroke="black"/>
              <path d="M 208,32 L 208,128" fill="none" stroke="black"/>
              <path d="M 8,32 L 208,32" fill="none" stroke="black"/>
              <path d="M 72,64 L 208,64" fill="none" stroke="black"/>
              <path d="M 8,96 L 208,96" fill="none" stroke="black"/>
              <path d="M 8,128 L 208,128" fill="none" stroke="black"/>
              <g class="text">
                <text x="112" y="52">Application</text>
                <text x="104" y="84">E2E</text>
                <text x="156" y="84">Security</text>
                <text x="112" y="116">Transport</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
+------------------------+
|       Application      |
|       +----------------+
|       |  E2E Security  |
+-------+----------------+
|        Transport       |
+------------------------+
]]></artwork>
        </artset>
      </figure>
      <t>MIMI uses MLS <xref target="RFC9420"/> for end-to-end security, using the MLS AppSync
proposal type to efficiently synchronize room state across the clients involved
in a room. The MIMI transport is based on HTTPS over mutually-authenticated
TLS.</t>
    </section>
    <section anchor="example-protocol-flow">
      <name>Example protocol flow</name>
      <t>This section walks through a basic scenario that illustrates how a room works
in the MIMI protocol.  The scenario involves the following actors:</t>
      <ul spacing="normal">
        <li>
          <t>Service providers <tt>a.example</tt>, <tt>b.example</tt>, and <tt>c.example</tt> represented by
servers <tt>ServerA</tt>, <tt>ServerB</tt>, and <tt>ServerC</tt> respectively</t>
        </li>
        <li>
          <t>Users Alice (<tt>alice</tt>), Bob (<tt>bob</tt>) and Cathy (<tt>cathy</tt>) of the service providers <tt>a.example</tt>, <tt>b.example</tt>, and <tt>c.example</tt> respectively.</t>
        </li>
        <li>
          <t>Clients <tt>ClientA1</tt>, <tt>ClientA2</tt>, <tt>ClientB1</tt>, etc. belonging to these users</t>
        </li>
        <li>
          <t>A room <tt>clubhouse</tt> hosted by hub provider <tt>a.example</tt> where the three users interact.</t>
        </li>
      </ul>
      <t>Inside the protocol, each provider is represented by a domain name in the
<tt>host</tt> production of the <tt>authority</tt> of a MIMI URI <xref target="RFC3986"/>. Specific
hosts or servers are represented by domain names, but not by MIMI URIs.
Examples of different types of identifiers represented in a MIMI URI are
shown in the table below:</t>
      <table anchor="mimi-uri-examples">
        <name>MIMI URI examples</name>
        <thead>
          <tr>
            <th align="left">Identifier type</th>
            <th align="left">Example URI</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">Provider</td>
            <td align="left">
              <tt>mimi://a.example</tt></td>
          </tr>
          <tr>
            <td align="left">User</td>
            <td align="left">
              <tt>mimi://a.example/u/alice</tt></td>
          </tr>
          <tr>
            <td align="left">Client</td>
            <td align="left">
              <tt>mimi://a.example/d/ClientA1</tt></td>
          </tr>
          <tr>
            <td align="left">Room</td>
            <td align="left">
              <tt>mimi://a.example/r/clubhouse</tt></td>
          </tr>
          <tr>
            <td align="left">MLS group</td>
            <td align="left">
              <tt>mimi://a.example/g/clubhouse</tt></td>
          </tr>
        </tbody>
      </table>
      <t>As noted in <xref target="I-D.barnes-mimi-arch"/>, the MIMI protocol only defines interactions
between service providers' servers.  Interactions between clients and servers
within a service provider domain are shown here for completeness, but
surrounded by <tt>[[ double brackets ]]</tt>.</t>
      <section anchor="alice-creates-a-room">
        <name>Alice Creates a Room</name>
        <t>The first step in the lifetime of a MIMI room is its creation on the hub server.
This operation is local to the service provider, and does not entail any MIMI
protocol operations.  However, it must establish the initial state of the room,
which is then the basis for protocol operations related to the room.</t>
        <t>For authorization purposes, MIMI uses permissions based on room-defined roles.
For example, a room might have a role named "admin", which has <tt>canAddUser</tt>,
<tt>canRemoveUser</tt>, and <tt>canSetUserRole</tt> permisions.</t>
        <t>Here, we assume that Alice uses ClientA1 to create a room with the following
base policy properties:</t>
        <ul spacing="normal">
          <li>
            <t>Room Identifier: <tt>mimi://a.example/r/clubhouse</tt></t>
          </li>
          <li>
            <t>Roles: <tt>admin = [canAddUser, canRemoveUser, canSetUserRole]</tt></t>
          </li>
        </ul>
        <t>And the following participant list:</t>
        <ul spacing="normal">
          <li>
            <t>Participants: <tt>[[mimi://a.example/u/alice, "admin"]]</tt></t>
          </li>
        </ul>
        <t>ClientA1 also creates an MLS group with group ID <tt>mimi://a.example/g/clubhouse</tt> and
ensures via provider-local operations that Alice's other clients are members of
this MLS group.</t>
      </section>
      <section anchor="alice-adds-bob-to-the-room">
        <name>Alice adds Bob to the Room</name>
        <t>Adding Bob to the room entails operations at two levels.  First, Bob's user
identity must be added to the room's participant list.  Second, Bob's clients
must be added to the room's MLS group.</t>
        <t>The process of adding Bob to the room thus begins by Alice fetching key material
for Bob's clients.  Alice then updates the room by sending an MLS Commit over
the following proposals:</t>
        <ul spacing="normal">
          <li>
            <t>An AppSync proposal updating the room state by adding Bob to the
participant list</t>
          </li>
          <li>
            <t>Add proposals for Bob's clients</t>
          </li>
        </ul>
        <t>The MIMI protocol interactions are between Alice's server ServerA and Bob's
server ServerB.  ServerB stores KeyPackages on behalf of Bob's devices.  ServerA
performs the key material fetch on Alice's behalf, and delivers the resulting
KeyPackages to Alice's clients.  Both ServerA and ServerB remember the sources
of the KeyPackages they handle, so that they can route a Welcome message for
those KeyPackages to the proper recipients -- ServerA to ServerB, and ServerB to
Bob's clients.</t>
        <ul empty="true">
          <li>
            <t><strong>NOTE:</strong> In the full protocol, it will be necessary to have consent and access
control on these operations.  We have elided that step here in the interest of
simplicity.</t>
          </li>
        </ul>
        <figure anchor="fig-ab-kp-fetch">
          <name>Alice Fetches KeyPackages for Bob's Clients</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="368" width="496" viewBox="0 0 496 368" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,208" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,208" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,208" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,208" fill="none" stroke="black"/>
                <path d="M 288,80 Q 290,76.8 292,80 Q 294,83.2 296,80 Q 298,76.8 300,80 Q 302,83.2 304,80 Q 306,76.8 308,80 Q 310,83.2 312,80 Q 314,76.8 316,80 Q 318,83.2 320,80 Q 322,76.8 324,80 Q 326,83.2 328,80 Q 330,76.8 332,80 Q 334,83.2 336,80 Q 338,76.8 340,80 Q 342,83.2 344,80 Q 346,76.8 348,80 Q 350,83.2 352,80 Q 354,76.8 356,80 Q 358,83.2 360,80 Q 362,76.8 364,80 Q 366,83.2 368,80 Q 370,76.8 372,80 Q 374,83.2 376,80 Q 378,76.8 380,80 Q 382,83.2 384,80 Q 386,76.8 388,80 Q 390,83.2 392,80 Q 394,76.8 396,80 Q 398,83.2 400,80 Q 402,76.8 404,80 Q 406,83.2 408,80 " fill="none" stroke="black"/>
                <path d="M 288,96 Q 290,92.8 292,96 Q 294,99.2 296,96 Q 298,92.8 300,96 Q 302,99.2 304,96 Q 306,92.8 308,96 Q 310,99.2 312,96 Q 314,92.8 316,96 Q 318,99.2 320,96 Q 322,92.8 324,96 Q 326,99.2 328,96 Q 330,92.8 332,96 Q 334,99.2 336,96 Q 338,92.8 340,96 Q 342,99.2 344,96 Q 346,92.8 348,96 Q 350,99.2 352,96 Q 354,92.8 356,96 Q 358,99.2 360,96 Q 362,92.8 364,96 Q 366,99.2 368,96 Q 370,92.8 372,96 Q 374,99.2 376,96 Q 378,92.8 380,96 Q 382,99.2 384,96 Q 386,92.8 388,96 Q 390,99.2 392,96 Q 394,92.8 396,96 Q 398,99.2 400,96 Q 402,92.8 404,96 Q 406,99.2 408,96 " fill="none" stroke="black"/>
                <path d="M 24,128 Q 26,124.8 28,128 Q 30,131.2 32,128 Q 34,124.8 36,128 Q 38,131.2 40,128 Q 42,124.8 44,128 Q 46,131.2 48,128 Q 50,124.8 52,128 Q 54,131.2 56,128 Q 58,124.8 60,128 Q 62,131.2 64,128 Q 66,124.8 68,128 Q 70,131.2 72,128 Q 74,124.8 76,128 Q 78,131.2 80,128 Q 82,124.8 84,128 Q 86,131.2 88,128 Q 90,124.8 92,128 Q 94,131.2 96,128 Q 98,124.8 100,128 Q 102,131.2 104,128 Q 106,124.8 108,128 Q 110,131.2 112,128 Q 114,124.8 116,128 Q 118,131.2 120,128 Q 122,124.8 124,128 Q 126,131.2 128,128 Q 130,124.8 132,128 Q 134,131.2 136,128 Q 138,124.8 140,128 Q 142,131.2 144,128 " fill="none" stroke="black"/>
                <path d="M 152,144 L 272,144" fill="none" stroke="black"/>
                <path d="M 160,176 L 280,176" fill="none" stroke="black"/>
                <path d="M 32,192 Q 34,188.8 36,192 Q 38,195.2 40,192 Q 42,188.8 44,192 Q 46,195.2 48,192 Q 50,188.8 52,192 Q 54,195.2 56,192 Q 58,188.8 60,192 Q 62,195.2 64,192 Q 66,188.8 68,192 Q 70,195.2 72,192 Q 74,188.8 76,192 Q 78,195.2 80,192 Q 82,188.8 84,192 Q 86,195.2 88,192 Q 90,188.8 92,192 Q 94,195.2 96,192 Q 98,188.8 100,192 Q 102,195.2 104,192 Q 106,188.8 108,192 Q 110,195.2 112,192 Q 114,188.8 116,192 Q 118,195.2 120,192 Q 122,188.8 124,192 Q 126,195.2 128,192 Q 130,188.8 132,192 Q 134,195.2 136,192 Q 138,188.8 140,192 Q 142,195.2 144,192 Q 146,188.8 148,192 Q 150,195.2 152,192 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="296,96 284,90.4 284,101.6" fill="black" transform="rotate(180,288,96)"/>
                <polygon class="arrowhead" points="296,80 284,74.4 284,85.6" fill="black" transform="rotate(180,288,80)"/>
                <polygon class="arrowhead" points="280,144 268,138.4 268,149.6" fill="black" transform="rotate(0,272,144)"/>
                <polygon class="arrowhead" points="168,176 156,170.4 156,181.6" fill="black" transform="rotate(180,160,176)"/>
                <polygon class="arrowhead" points="152,128 140,122.4 140,133.6" fill="black" transform="rotate(0,144,128)"/>
                <polygon class="arrowhead" points="40,192 28,186.4 28,197.6" fill="black" transform="rotate(180,32,192)"/>
                <g class="text">
                  <text x="36" y="36">ClientA1</text>
                  <text x="152" y="36">ServerA</text>
                  <text x="280" y="36">ServerB</text>
                  <text x="412" y="36">ClientB*</text>
                  <text x="344" y="68">Store</text>
                  <text x="384" y="68">KPs</text>
                  <text x="64" y="116">Request</text>
                  <text x="112" y="116">KPs</text>
                  <text x="212" y="132">/keyMaterial</text>
                  <text x="232" y="164">200</text>
                  <text x="260" y="164">OK</text>
                  <text x="128" y="180">KPs</text>
                  <text x="76" y="244">ClientB*-&gt;ServerB:</text>
                  <text x="164" y="244">[[</text>
                  <text x="200" y="244">Store</text>
                  <text x="272" y="244">KeyPackages</text>
                  <text x="332" y="244">]]</text>
                  <text x="76" y="260">ClientA1-&gt;ServerA:</text>
                  <text x="164" y="260">[[</text>
                  <text x="208" y="260">request</text>
                  <text x="256" y="260">KPs</text>
                  <text x="288" y="260">for</text>
                  <text x="320" y="260">Bob</text>
                  <text x="348" y="260">]]</text>
                  <text x="72" y="276">ServerA-&gt;ServerB:</text>
                  <text x="164" y="276">POST</text>
                  <text x="236" y="276">/keyMaterial</text>
                  <text x="364" y="276">KeyMaterialRequest</text>
                  <text x="36" y="292">ServerB:</text>
                  <text x="100" y="292">Verify</text>
                  <text x="148" y="292">that</text>
                  <text x="192" y="292">Alice</text>
                  <text x="228" y="292">is</text>
                  <text x="284" y="292">authorized</text>
                  <text x="340" y="292">to</text>
                  <text x="376" y="292">fetch</text>
                  <text x="448" y="292">KeyPackages</text>
                  <text x="36" y="308">ServerB:</text>
                  <text x="92" y="308">Mark</text>
                  <text x="148" y="308">returned</text>
                  <text x="200" y="308">KPs</text>
                  <text x="228" y="308">as</text>
                  <text x="276" y="308">reserved</text>
                  <text x="328" y="308">for</text>
                  <text x="376" y="308">Alice's</text>
                  <text x="424" y="308">use</text>
                  <text x="72" y="324">ServerB-&gt;ServerA:</text>
                  <text x="160" y="324">200</text>
                  <text x="188" y="324">OK</text>
                  <text x="280" y="324">KeyMaterialResponse</text>
                  <text x="36" y="340">ServerA:</text>
                  <text x="108" y="340">Remember</text>
                  <text x="164" y="340">that</text>
                  <text x="208" y="340">these</text>
                  <text x="248" y="340">KPs</text>
                  <text x="276" y="340">go</text>
                  <text x="300" y="340">to</text>
                  <text x="352" y="340">b.example</text>
                  <text x="76" y="356">ServerA-&gt;ClientA1:</text>
                  <text x="164" y="356">[[</text>
                  <text x="192" y="356">KPs</text>
                  <text x="220" y="356">]]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientA1       ServerA         ServerB         ClientB*
  |               |               |               |
  |               |               |     Store KPs |
  |               |               |<~~~~~~~~~~~~~~+
  |               |               |<~~~~~~~~~~~~~~+
  | Request KPs   |               |               |
  +~~~~~~~~~~~~~~>| /keyMaterial  |               |
  |               +-------------->|               |
  |               |        200 OK |               |
  |           KPs |<--------------+               |
  |<~~~~~~~~~~~~~~+               |               |
  |               |               |               |

ClientB*->ServerB: [[ Store KeyPackages ]]
ClientA1->ServerA: [[ request KPs for Bob ]]
ServerA->ServerB: POST /keyMaterial KeyMaterialRequest
ServerB: Verify that Alice is authorized to fetch KeyPackages
ServerB: Mark returned KPs as reserved for Alice's use
ServerB->ServerA: 200 OK KeyMaterialResponse
ServerA: Remember that these KPs go to b.example
ServerA->ClientA1: [[ KPs ]]
]]></artwork>
          </artset>
        </figure>
        <figure anchor="fig-ab-add">
          <name>Alice Adds Bob to the Room and Bob's Clients to the MLS Group</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="672" viewBox="0 0 672 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,176" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,176" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,176" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,176" fill="none" stroke="black"/>
                <path d="M 24,80 Q 26,76.8 28,80 Q 30,83.2 32,80 Q 34,76.8 36,80 Q 38,83.2 40,80 Q 42,76.8 44,80 Q 46,83.2 48,80 Q 50,76.8 52,80 Q 54,83.2 56,80 Q 58,76.8 60,80 Q 62,83.2 64,80 Q 66,76.8 68,80 Q 70,83.2 72,80 Q 74,76.8 76,80 Q 78,83.2 80,80 Q 82,76.8 84,80 Q 86,83.2 88,80 Q 90,76.8 92,80 Q 94,83.2 96,80 Q 98,76.8 100,80 Q 102,83.2 104,80 Q 106,76.8 108,80 Q 110,83.2 112,80 Q 114,76.8 116,80 Q 118,83.2 120,80 Q 122,76.8 124,80 Q 126,83.2 128,80 Q 130,76.8 132,80 Q 134,83.2 136,80 Q 138,76.8 140,80 Q 142,83.2 144,80 " fill="none" stroke="black"/>
                <path d="M 32,112 Q 34,108.8 36,112 Q 38,115.2 40,112 Q 42,108.8 44,112 Q 46,115.2 48,112 Q 50,108.8 52,112 Q 54,115.2 56,112 Q 58,108.8 60,112 Q 62,115.2 64,112 Q 66,108.8 68,112 Q 70,115.2 72,112 Q 74,108.8 76,112 Q 78,115.2 80,112 Q 82,108.8 84,112 Q 86,115.2 88,112 Q 90,108.8 92,112 Q 94,115.2 96,112 Q 98,108.8 100,112 Q 102,115.2 104,112 Q 106,108.8 108,112 Q 110,115.2 112,112 Q 114,108.8 116,112 Q 118,115.2 120,112 Q 122,108.8 124,112 Q 126,115.2 128,112 Q 130,108.8 132,112 Q 134,115.2 136,112 Q 138,108.8 140,112 Q 142,115.2 144,112 Q 146,108.8 148,112 Q 150,115.2 152,112 " fill="none" stroke="black"/>
                <path d="M 152,112 L 272,112" fill="none" stroke="black"/>
                <path d="M 160,144 L 280,144" fill="none" stroke="black"/>
                <path d="M 280,144 Q 282,140.8 284,144 Q 286,147.2 288,144 Q 290,140.8 292,144 Q 294,147.2 296,144 Q 298,140.8 300,144 Q 302,147.2 304,144 Q 306,140.8 308,144 Q 310,147.2 312,144 Q 314,140.8 316,144 Q 318,147.2 320,144 Q 322,140.8 324,144 Q 326,147.2 328,144 Q 330,140.8 332,144 Q 334,147.2 336,144 Q 338,140.8 340,144 Q 342,147.2 344,144 Q 346,140.8 348,144 Q 350,147.2 352,144 Q 354,140.8 356,144 Q 358,147.2 360,144 Q 362,140.8 364,144 Q 366,147.2 368,144 Q 370,140.8 372,144 Q 374,147.2 376,144 Q 378,140.8 380,144 Q 382,147.2 384,144 Q 386,140.8 388,144 Q 390,147.2 392,144 Q 394,140.8 396,144 Q 398,147.2 400,144 " fill="none" stroke="black"/>
                <path d="M 280,160 Q 282,156.8 284,160 Q 286,163.2 288,160 Q 290,156.8 292,160 Q 294,163.2 296,160 Q 298,156.8 300,160 Q 302,163.2 304,160 Q 306,156.8 308,160 Q 310,163.2 312,160 Q 314,156.8 316,160 Q 318,163.2 320,160 Q 322,156.8 324,160 Q 326,163.2 328,160 Q 330,156.8 332,160 Q 334,163.2 336,160 Q 338,156.8 340,160 Q 342,163.2 344,160 Q 346,156.8 348,160 Q 350,163.2 352,160 Q 354,156.8 356,160 Q 358,163.2 360,160 Q 362,156.8 364,160 Q 366,163.2 368,160 Q 370,156.8 372,160 Q 374,163.2 376,160 Q 378,156.8 380,160 Q 382,163.2 384,160 Q 386,156.8 388,160 Q 390,163.2 392,160 Q 394,156.8 396,160 Q 398,163.2 400,160 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="408,160 396,154.4 396,165.6" fill="black" transform="rotate(0,400,160)"/>
                <polygon class="arrowhead" points="408,144 396,138.4 396,149.6" fill="black" transform="rotate(0,400,144)"/>
                <polygon class="arrowhead" points="280,112 268,106.4 268,117.6" fill="black" transform="rotate(0,272,112)"/>
                <polygon class="arrowhead" points="168,144 156,138.4 156,149.6" fill="black" transform="rotate(180,160,144)"/>
                <polygon class="arrowhead" points="152,80 140,74.4 140,85.6" fill="black" transform="rotate(0,144,80)"/>
                <polygon class="arrowhead" points="40,112 28,106.4 28,117.6" fill="black" transform="rotate(180,32,112)"/>
                <g class="text">
                  <text x="36" y="36">ClientA1</text>
                  <text x="152" y="36">ServerA</text>
                  <text x="280" y="36">ServerB</text>
                  <text x="412" y="36">ClientB*</text>
                  <text x="64" y="68">Commit,</text>
                  <text x="116" y="68">etc.</text>
                  <text x="108" y="100">Accepted</text>
                  <text x="192" y="100">/notify</text>
                  <text x="232" y="132">200</text>
                  <text x="260" y="132">OK</text>
                  <text x="324" y="132">Welcome,</text>
                  <text x="380" y="132">Tree</text>
                  <text x="40" y="228">ClientA1:</text>
                  <text x="112" y="228">Prepare</text>
                  <text x="172" y="228">Commit</text>
                  <text x="220" y="228">over</text>
                  <text x="300" y="228">AppSync(+Bob),</text>
                  <text x="380" y="228">Add*</text>
                  <text x="76" y="244">ClientA1-&gt;ServerA:</text>
                  <text x="164" y="244">[[</text>
                  <text x="208" y="244">Commit,</text>
                  <text x="276" y="244">Welcome,</text>
                  <text x="360" y="244">GroupInfo?,</text>
                  <text x="460" y="244">RatchetTree?</text>
                  <text x="524" y="244">]]</text>
                  <text x="36" y="260">ServerA:</text>
                  <text x="100" y="260">Verify</text>
                  <text x="148" y="260">that</text>
                  <text x="204" y="260">AppSync,</text>
                  <text x="260" y="260">Adds</text>
                  <text x="296" y="260">are</text>
                  <text x="344" y="260">allowed</text>
                  <text x="388" y="260">by</text>
                  <text x="428" y="260">policy</text>
                  <text x="36" y="276">ServerA:</text>
                  <text x="116" y="276">Identifies</text>
                  <text x="192" y="276">Welcome</text>
                  <text x="256" y="276">domains</text>
                  <text x="312" y="276">based</text>
                  <text x="348" y="276">on</text>
                  <text x="372" y="276">KP</text>
                  <text x="404" y="276">hash</text>
                  <text x="436" y="276">in</text>
                  <text x="480" y="276">Welcome</text>
                  <text x="72" y="292">ServerA-&gt;ServerB:</text>
                  <text x="164" y="292">POST</text>
                  <text x="304" y="292">/notify/a.example/r/clubhouse</text>
                  <text x="452" y="292">Intro{</text>
                  <text x="516" y="292">Welcome,</text>
                  <text x="604" y="292">RatchetTree?</text>
                  <text x="664" y="292">}</text>
                  <text x="36" y="308">ServerB:</text>
                  <text x="116" y="308">Recognizes</text>
                  <text x="180" y="308">that</text>
                  <text x="232" y="308">Welcome</text>
                  <text x="276" y="308">is</text>
                  <text x="316" y="308">adding</text>
                  <text x="360" y="308">Bob</text>
                  <text x="388" y="308">to</text>
                  <text x="420" y="308">room</text>
                  <text x="480" y="308">clubhouse</text>
                  <text x="76" y="324">ServerB-&gt;ClientB*:</text>
                  <text x="164" y="324">[[</text>
                  <text x="212" y="324">Welcome,</text>
                  <text x="300" y="324">RatchetTree?</text>
                  <text x="364" y="324">]]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientA1       ServerA         ServerB         ClientB*
  |               |               |               |
  | Commit, etc.  |               |               |
  +~~~~~~~~~~~~~~>|               |               |
  |      Accepted | /notify       |               |
  |<~~~~~~~~~~~~~~+-------------->|               |
  |               |        200 OK | Welcome, Tree |
  |               |<--------------+~~~~~~~~~~~~~~>|
  |               |               +~~~~~~~~~~~~~~>|
  |               |               |               |


ClientA1: Prepare Commit over AppSync(+Bob), Add*
ClientA1->ServerA: [[ Commit, Welcome, GroupInfo?, RatchetTree? ]]
ServerA: Verify that AppSync, Adds are allowed by policy
ServerA: Identifies Welcome domains based on KP hash in Welcome
ServerA->ServerB: POST /notify/a.example/r/clubhouse Intro{ Welcome, RatchetTree? }
ServerB: Recognizes that Welcome is adding Bob to room clubhouse
ServerB->ClientB*: [[ Welcome, RatchetTree? ]]
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="bob-adds-cathy-to-the-room">
        <name>Bob adds Cathy to the Room</name>
        <t>The process of adding Bob was a bit abbreviated because Alice is a user of the
hub service provider.  When Bob adds Cathy, we see the full process, involving
the same two steps (KeyPackage fetch followed by Add), but this time indirected via the
hub server ServerA.  Also, now that there are users on ServerB involved in the
room, the hub ServerA will have to distribute the Commit adding Cathy and
Cathy's clients to ServerB as well as forwarding the Welcome to ServerC.</t>
        <figure anchor="fig-bc-kp-fetch">
          <name>Bob Fetches KeyPackages for Cathy's Clients</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="400" width="576" viewBox="0 0 576 400" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,208" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,208" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,208" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,208" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,208" fill="none" stroke="black"/>
                <path d="M 416,80 Q 418,76.8 420,80 Q 422,83.2 424,80 Q 426,76.8 428,80 Q 430,83.2 432,80 Q 434,76.8 436,80 Q 438,83.2 440,80 Q 442,76.8 444,80 Q 446,83.2 448,80 Q 450,76.8 452,80 Q 454,83.2 456,80 Q 458,76.8 460,80 Q 462,83.2 464,80 Q 466,76.8 468,80 Q 470,83.2 472,80 Q 474,76.8 476,80 Q 478,83.2 480,80 Q 482,76.8 484,80 Q 486,83.2 488,80 Q 490,76.8 492,80 Q 494,83.2 496,80 Q 498,76.8 500,80 Q 502,83.2 504,80 Q 506,76.8 508,80 Q 510,83.2 512,80 Q 514,76.8 516,80 Q 518,83.2 520,80 Q 522,76.8 524,80 Q 526,83.2 528,80 Q 530,76.8 532,80 Q 534,83.2 536,80 " fill="none" stroke="black"/>
                <path d="M 416,96 Q 418,92.8 420,96 Q 422,99.2 424,96 Q 426,92.8 428,96 Q 430,99.2 432,96 Q 434,92.8 436,96 Q 438,99.2 440,96 Q 442,92.8 444,96 Q 446,99.2 448,96 Q 450,92.8 452,96 Q 454,99.2 456,96 Q 458,92.8 460,96 Q 462,99.2 464,96 Q 466,92.8 468,96 Q 470,99.2 472,96 Q 474,92.8 476,96 Q 478,99.2 480,96 Q 482,92.8 484,96 Q 486,99.2 488,96 Q 490,92.8 492,96 Q 494,99.2 496,96 Q 498,92.8 500,96 Q 502,99.2 504,96 Q 506,92.8 508,96 Q 510,99.2 512,96 Q 514,92.8 516,96 Q 518,99.2 520,96 Q 522,92.8 524,96 Q 526,99.2 528,96 Q 530,92.8 532,96 Q 534,99.2 536,96 " fill="none" stroke="black"/>
                <path d="M 24,128 Q 26,124.8 28,128 Q 30,131.2 32,128 Q 34,124.8 36,128 Q 38,131.2 40,128 Q 42,124.8 44,128 Q 46,131.2 48,128 Q 50,124.8 52,128 Q 54,131.2 56,128 Q 58,124.8 60,128 Q 62,131.2 64,128 Q 66,124.8 68,128 Q 70,131.2 72,128 Q 74,124.8 76,128 Q 78,131.2 80,128 Q 82,124.8 84,128 Q 86,131.2 88,128 Q 90,124.8 92,128 Q 94,131.2 96,128 Q 98,124.8 100,128 Q 102,131.2 104,128 Q 106,124.8 108,128 Q 110,131.2 112,128 Q 114,124.8 116,128 Q 118,131.2 120,128 Q 122,124.8 124,128 Q 126,131.2 128,128 Q 130,124.8 132,128 Q 134,131.2 136,128 Q 138,124.8 140,128 Q 142,131.2 144,128 " fill="none" stroke="black"/>
                <path d="M 152,144 L 400,144" fill="none" stroke="black"/>
                <path d="M 160,176 L 408,176" fill="none" stroke="black"/>
                <path d="M 32,192 Q 34,188.8 36,192 Q 38,195.2 40,192 Q 42,188.8 44,192 Q 46,195.2 48,192 Q 50,188.8 52,192 Q 54,195.2 56,192 Q 58,188.8 60,192 Q 62,195.2 64,192 Q 66,188.8 68,192 Q 70,195.2 72,192 Q 74,188.8 76,192 Q 78,195.2 80,192 Q 82,188.8 84,192 Q 86,195.2 88,192 Q 90,188.8 92,192 Q 94,195.2 96,192 Q 98,188.8 100,192 Q 102,195.2 104,192 Q 106,188.8 108,192 Q 110,195.2 112,192 Q 114,188.8 116,192 Q 118,195.2 120,192 Q 122,188.8 124,192 Q 126,195.2 128,192 Q 130,188.8 132,192 Q 134,195.2 136,192 Q 138,188.8 140,192 Q 142,195.2 144,192 Q 146,188.8 148,192 Q 150,195.2 152,192 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="424,96 412,90.4 412,101.6" fill="black" transform="rotate(180,416,96)"/>
                <polygon class="arrowhead" points="424,80 412,74.4 412,85.6" fill="black" transform="rotate(180,416,80)"/>
                <polygon class="arrowhead" points="408,144 396,138.4 396,149.6" fill="black" transform="rotate(0,400,144)"/>
                <polygon class="arrowhead" points="296,176 284,170.4 284,181.6" fill="black" transform="rotate(180,288,176)"/>
                <polygon class="arrowhead" points="280,144 268,138.4 268,149.6" fill="black" transform="rotate(0,272,144)"/>
                <polygon class="arrowhead" points="168,176 156,170.4 156,181.6" fill="black" transform="rotate(180,160,176)"/>
                <polygon class="arrowhead" points="152,128 140,122.4 140,133.6" fill="black" transform="rotate(0,144,128)"/>
                <polygon class="arrowhead" points="40,192 28,186.4 28,197.6" fill="black" transform="rotate(180,32,192)"/>
                <g class="text">
                  <text x="36" y="36">ClientB1</text>
                  <text x="152" y="36">ServerB</text>
                  <text x="280" y="36">ServerA</text>
                  <text x="408" y="36">ServerC</text>
                  <text x="540" y="36">ClientC*</text>
                  <text x="472" y="68">Store</text>
                  <text x="512" y="68">KPs</text>
                  <text x="64" y="116">Request</text>
                  <text x="112" y="116">KPs</text>
                  <text x="212" y="132">/keyMaterial</text>
                  <text x="340" y="132">/keyMaterial</text>
                  <text x="232" y="164">200</text>
                  <text x="260" y="164">OK</text>
                  <text x="360" y="164">200</text>
                  <text x="388" y="164">OK</text>
                  <text x="128" y="180">KPs</text>
                  <text x="76" y="244">ClientC*-&gt;ServerC:</text>
                  <text x="164" y="244">[[</text>
                  <text x="200" y="244">Store</text>
                  <text x="272" y="244">KeyPackages</text>
                  <text x="332" y="244">]]</text>
                  <text x="76" y="260">ClientB1-&gt;ServerB:</text>
                  <text x="164" y="260">[[</text>
                  <text x="208" y="260">request</text>
                  <text x="256" y="260">KPs</text>
                  <text x="288" y="260">for</text>
                  <text x="320" y="260">Bob</text>
                  <text x="348" y="260">]]</text>
                  <text x="72" y="276">ServerB-&gt;ServerA:</text>
                  <text x="164" y="276">POST</text>
                  <text x="236" y="276">/keyMaterial</text>
                  <text x="364" y="276">KeyMaterialRequest</text>
                  <text x="72" y="292">ServerA-&gt;ServerC:</text>
                  <text x="164" y="292">POST</text>
                  <text x="236" y="292">/keyMaterial</text>
                  <text x="364" y="292">KeyMaterialRequest</text>
                  <text x="36" y="308">ServerB:</text>
                  <text x="100" y="308">Verify</text>
                  <text x="148" y="308">that</text>
                  <text x="184" y="308">Bob</text>
                  <text x="212" y="308">is</text>
                  <text x="268" y="308">authorized</text>
                  <text x="324" y="308">to</text>
                  <text x="360" y="308">fetch</text>
                  <text x="432" y="308">KeyPackages</text>
                  <text x="36" y="324">ServerB:</text>
                  <text x="92" y="324">Mark</text>
                  <text x="148" y="324">returned</text>
                  <text x="200" y="324">KPs</text>
                  <text x="228" y="324">as</text>
                  <text x="276" y="324">reserved</text>
                  <text x="328" y="324">for</text>
                  <text x="368" y="324">Bob's</text>
                  <text x="408" y="324">use</text>
                  <text x="72" y="340">ServerC-&gt;ServerA:</text>
                  <text x="160" y="340">200</text>
                  <text x="188" y="340">OK</text>
                  <text x="280" y="340">KeyMaterialResponse</text>
                  <text x="36" y="356">ServerA:</text>
                  <text x="108" y="356">Remember</text>
                  <text x="164" y="356">that</text>
                  <text x="208" y="356">these</text>
                  <text x="248" y="356">KPs</text>
                  <text x="276" y="356">go</text>
                  <text x="300" y="356">to</text>
                  <text x="352" y="356">b.example</text>
                  <text x="72" y="372">ServerA-&gt;ServerB:</text>
                  <text x="160" y="372">200</text>
                  <text x="188" y="372">OK</text>
                  <text x="280" y="372">KeyMaterialResponse</text>
                  <text x="76" y="388">ServerB-&gt;ClientB1:</text>
                  <text x="164" y="388">[[</text>
                  <text x="192" y="388">KPs</text>
                  <text x="220" y="388">]]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientB1       ServerB         ServerA         ServerC         ClientC*
  |               |               |               |               |
  |               |               |               |     Store KPs |
  |               |               |               |<~~~~~~~~~~~~~~+
  |               |               |               |<~~~~~~~~~~~~~~+
  | Request KPs   |               |               |               |
  +~~~~~~~~~~~~~~>| /keyMaterial  | /keyMaterial  |               |
  |               +-------------->+-------------->|               |
  |               |        200 OK |        200 OK |               |
  |           KPs |<--------------+<--------------+               |
  |<~~~~~~~~~~~~~~+               |               |               |
  |               |               |               |               |

ClientC*->ServerC: [[ Store KeyPackages ]]
ClientB1->ServerB: [[ request KPs for Bob ]]
ServerB->ServerA: POST /keyMaterial KeyMaterialRequest
ServerA->ServerC: POST /keyMaterial KeyMaterialRequest
ServerB: Verify that Bob is authorized to fetch KeyPackages
ServerB: Mark returned KPs as reserved for Bob's use
ServerC->ServerA: 200 OK KeyMaterialResponse
ServerA: Remember that these KPs go to b.example
ServerA->ServerB: 200 OK KeyMaterialResponse
ServerB->ClientB1: [[ KPs ]]
]]></artwork>
          </artset>
        </figure>
        <figure anchor="fig-bc-add">
          <name>Bob Adds Cathy to the Room and Cathy's Clients to the MLS Group</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="496" width="576" viewBox="0 0 576 496" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,64 L 8,272" fill="none" stroke="black"/>
                <path d="M 120,64 L 120,272" fill="none" stroke="black"/>
                <path d="M 216,64 L 216,240" fill="none" stroke="black"/>
                <path d="M 312,64 L 312,208" fill="none" stroke="black"/>
                <path d="M 408,64 L 408,208" fill="none" stroke="black"/>
                <path d="M 488,64 L 488,208" fill="none" stroke="black"/>
                <path d="M 488,240 L 488,272" fill="none" stroke="black"/>
                <path d="M 568,64 L 568,272" fill="none" stroke="black"/>
                <path d="M 8,96 Q 10,92.8 12,96 Q 14,99.2 16,96 Q 18,92.8 20,96 Q 22,99.2 24,96 Q 26,92.8 28,96 Q 30,99.2 32,96 Q 34,92.8 36,96 Q 38,99.2 40,96 Q 42,92.8 44,96 Q 46,99.2 48,96 Q 50,92.8 52,96 Q 54,99.2 56,96 Q 58,92.8 60,96 Q 62,99.2 64,96 Q 66,92.8 68,96 Q 70,99.2 72,96 Q 74,92.8 76,96 Q 78,99.2 80,96 Q 82,92.8 84,96 Q 86,99.2 88,96 Q 90,92.8 92,96 Q 94,99.2 96,96 Q 98,92.8 100,96 Q 102,99.2 104,96 Q 106,92.8 108,96 Q 110,99.2 112,96 " fill="none" stroke="black"/>
                <path d="M 120,112 L 208,112" fill="none" stroke="black"/>
                <path d="M 128,144 L 216,144" fill="none" stroke="black"/>
                <path d="M 16,176 Q 18,172.8 20,176 Q 22,179.2 24,176 Q 26,172.8 28,176 Q 30,179.2 32,176 Q 34,172.8 36,176 Q 38,179.2 40,176 Q 42,172.8 44,176 Q 46,179.2 48,176 Q 50,172.8 52,176 Q 54,179.2 56,176 Q 58,172.8 60,176 Q 62,179.2 64,176 Q 66,172.8 68,176 Q 70,179.2 72,176 Q 74,172.8 76,176 Q 78,179.2 80,176 Q 82,172.8 84,176 Q 86,179.2 88,176 Q 90,172.8 92,176 Q 94,179.2 96,176 Q 98,172.8 100,176 Q 102,179.2 104,176 Q 106,172.8 108,176 Q 110,179.2 112,176 Q 114,172.8 116,176 Q 118,179.2 120,176 " fill="none" stroke="black"/>
                <path d="M 216,176 L 304,176" fill="none" stroke="black"/>
                <path d="M 312,192 Q 314,188.8 316,192 Q 318,195.2 320,192 Q 322,188.8 324,192 Q 326,195.2 328,192 Q 330,188.8 332,192 Q 334,195.2 336,192 Q 338,188.8 340,192 Q 342,195.2 344,192 Q 346,188.8 348,192 Q 350,195.2 352,192 Q 354,188.8 356,192 Q 358,195.2 360,192 Q 362,188.8 364,192 Q 366,195.2 368,192 Q 370,188.8 372,192 Q 374,195.2 376,192 Q 378,188.8 380,192 Q 382,195.2 384,192 Q 386,188.8 388,192 Q 390,195.2 392,192 Q 394,188.8 396,192 Q 398,195.2 400,192 " fill="none" stroke="black"/>
                <path d="M 312,208 Q 314,204.8 316,208 Q 318,211.2 320,208 Q 322,204.8 324,208 Q 326,211.2 328,208 Q 330,204.8 332,208 Q 334,211.2 336,208 Q 338,204.8 340,208 Q 342,211.2 344,208 Q 346,204.8 348,208 Q 350,211.2 352,208 Q 354,204.8 356,208 Q 358,211.2 360,208 Q 362,204.8 364,208 Q 366,211.2 368,208 Q 370,204.8 372,208 Q 374,211.2 376,208 Q 378,204.8 380,208 Q 382,211.2 384,208 Q 386,204.8 388,208 Q 390,211.2 392,208 Q 394,204.8 396,208 Q 398,211.2 400,208 " fill="none" stroke="black"/>
                <path d="M 128,224 L 216,224" fill="none" stroke="black"/>
                <path d="M 216,224 Q 218,220.8 220,224 Q 222,227.2 224,224 Q 226,220.8 228,224 Q 230,227.2 232,224 Q 234,220.8 236,224 Q 238,227.2 240,224 Q 242,220.8 244,224 Q 246,227.2 248,224 Q 250,220.8 252,224 Q 254,227.2 256,224 Q 258,220.8 260,224 Q 262,227.2 264,224 Q 266,220.8 268,224 Q 270,227.2 272,224 Q 274,220.8 276,224 Q 278,227.2 280,224 Q 282,220.8 284,224 Q 286,227.2 288,224 Q 290,220.8 292,224 Q 294,227.2 296,224 Q 298,220.8 300,224 Q 302,227.2 304,224 Q 306,220.8 308,224 Q 310,227.2 312,224 Q 314,220.8 316,224 Q 318,227.2 320,224 Q 322,220.8 324,224 Q 326,227.2 328,224 Q 330,220.8 332,224 Q 334,227.2 336,224 Q 338,220.8 340,224 Q 342,227.2 344,224 Q 346,220.8 348,224 Q 350,227.2 352,224 Q 354,220.8 356,224 Q 358,227.2 360,224 Q 362,220.8 364,224 Q 366,227.2 368,224 Q 370,220.8 372,224 Q 374,227.2 376,224 Q 378,220.8 380,224 Q 382,227.2 384,224 Q 386,220.8 388,224 Q 390,227.2 392,224 Q 394,220.8 396,224 Q 398,227.2 400,224 Q 402,220.8 404,224 Q 406,227.2 408,224 Q 410,220.8 412,224 Q 414,227.2 416,224 Q 418,220.8 420,224 Q 422,227.2 424,224 Q 426,220.8 428,224 Q 430,227.2 432,224 Q 434,220.8 436,224 Q 438,227.2 440,224 Q 442,220.8 444,224 Q 446,227.2 448,224 Q 450,220.8 452,224 Q 454,227.2 456,224 Q 458,220.8 460,224 Q 462,227.2 464,224 Q 466,220.8 468,224 Q 470,227.2 472,224 Q 474,220.8 476,224 Q 478,227.2 480,224 Q 482,220.8 484,224 Q 486,227.2 488,224 Q 490,220.8 492,224 Q 494,227.2 496,224 Q 498,220.8 500,224 Q 502,227.2 504,224 Q 506,220.8 508,224 Q 510,227.2 512,224 Q 514,220.8 516,224 Q 518,227.2 520,224 Q 522,220.8 524,224 Q 526,227.2 528,224 Q 530,220.8 532,224 Q 534,227.2 536,224 Q 538,220.8 540,224 Q 542,227.2 544,224 Q 546,220.8 548,224 Q 550,227.2 552,224 Q 554,220.8 556,224 Q 558,227.2 560,224 " fill="none" stroke="black"/>
                <path d="M 120,256 Q 122,252.8 124,256 Q 126,259.2 128,256 Q 130,252.8 132,256 Q 134,259.2 136,256 Q 138,252.8 140,256 Q 142,259.2 144,256 Q 146,252.8 148,256 Q 150,259.2 152,256 Q 154,252.8 156,256 Q 158,259.2 160,256 Q 162,252.8 164,256 Q 166,259.2 168,256 Q 170,252.8 172,256 Q 174,259.2 176,256 Q 178,252.8 180,256 Q 182,259.2 184,256 Q 186,252.8 188,256 Q 190,259.2 192,256 Q 194,252.8 196,256 Q 198,259.2 200,256 Q 202,252.8 204,256 Q 206,259.2 208,256 Q 210,252.8 212,256 Q 214,259.2 216,256 Q 218,252.8 220,256 Q 222,259.2 224,256 Q 226,252.8 228,256 Q 230,259.2 232,256 Q 234,252.8 236,256 Q 238,259.2 240,256 Q 242,252.8 244,256 Q 246,259.2 248,256 Q 250,252.8 252,256 Q 254,259.2 256,256 Q 258,252.8 260,256 Q 262,259.2 264,256 Q 266,252.8 268,256 Q 270,259.2 272,256 Q 274,252.8 276,256 Q 278,259.2 280,256 Q 282,252.8 284,256 Q 286,259.2 288,256 Q 290,252.8 292,256 Q 294,259.2 296,256 Q 298,252.8 300,256 Q 302,259.2 304,256 Q 306,252.8 308,256 Q 310,259.2 312,256 Q 314,252.8 316,256 Q 318,259.2 320,256 Q 322,252.8 324,256 Q 326,259.2 328,256 Q 330,252.8 332,256 Q 334,259.2 336,256 Q 338,252.8 340,256 Q 342,259.2 344,256 Q 346,252.8 348,256 Q 350,259.2 352,256 Q 354,252.8 356,256 Q 358,259.2 360,256 Q 362,252.8 364,256 Q 366,259.2 368,256 Q 370,252.8 372,256 Q 374,259.2 376,256 Q 378,252.8 380,256 Q 382,259.2 384,256 Q 386,252.8 388,256 Q 390,259.2 392,256 Q 394,252.8 396,256 Q 398,259.2 400,256 Q 402,252.8 404,256 Q 406,259.2 408,256 Q 410,252.8 412,256 Q 414,259.2 416,256 Q 418,252.8 420,256 Q 422,259.2 424,256 Q 426,252.8 428,256 Q 430,259.2 432,256 Q 434,252.8 436,256 Q 438,259.2 440,256 Q 442,252.8 444,256 Q 446,259.2 448,256 Q 450,252.8 452,256 Q 454,259.2 456,256 Q 458,252.8 460,256 Q 462,259.2 464,256 Q 466,252.8 468,256 Q 470,259.2 472,256 Q 474,252.8 476,256 Q 478,259.2 480,256 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="568,224 556,218.4 556,229.6" fill="black" transform="rotate(0,560,224)"/>
                <polygon class="arrowhead" points="488,256 476,250.4 476,261.6" fill="black" transform="rotate(0,480,256)"/>
                <polygon class="arrowhead" points="408,208 396,202.4 396,213.6" fill="black" transform="rotate(0,400,208)"/>
                <polygon class="arrowhead" points="408,192 396,186.4 396,197.6" fill="black" transform="rotate(0,400,192)"/>
                <polygon class="arrowhead" points="312,176 300,170.4 300,181.6" fill="black" transform="rotate(0,304,176)"/>
                <polygon class="arrowhead" points="216,112 204,106.4 204,117.6" fill="black" transform="rotate(0,208,112)"/>
                <polygon class="arrowhead" points="136,224 124,218.4 124,229.6" fill="black" transform="rotate(180,128,224)"/>
                <polygon class="arrowhead" points="136,144 124,138.4 124,149.6" fill="black" transform="rotate(180,128,144)"/>
                <polygon class="arrowhead" points="120,96 108,90.4 108,101.6" fill="black" transform="rotate(0,112,96)"/>
                <polygon class="arrowhead" points="24,176 12,170.4 12,181.6" fill="black" transform="rotate(180,16,176)"/>
                <g class="text">
                  <text x="28" y="36">Client</text>
                  <text x="404" y="36">Client</text>
                  <text x="484" y="36">Client</text>
                  <text x="548" y="36">Client</text>
                  <text x="12" y="52">B1</text>
                  <text x="120" y="52">ServerB</text>
                  <text x="216" y="52">ServerA</text>
                  <text x="312" y="52">ServerC</text>
                  <text x="396" y="52">C*</text>
                  <text x="476" y="52">B*</text>
                  <text x="556" y="52">A*</text>
                  <text x="48" y="84">Commit,</text>
                  <text x="96" y="84">etc</text>
                  <text x="160" y="100">/update</text>
                  <text x="168" y="132">200</text>
                  <text x="196" y="132">OK</text>
                  <text x="76" y="164">Accepted</text>
                  <text x="256" y="164">/notify</text>
                  <text x="356" y="164">Welcome,</text>
                  <text x="340" y="180">Tree</text>
                  <text x="176" y="212">/notify</text>
                  <text x="252" y="212">Commit</text>
                  <text x="156" y="244">Commit</text>
                  <text x="312" y="244">|</text>
                  <text x="408" y="244">|</text>
                  <text x="216" y="276">|</text>
                  <text x="312" y="276">|</text>
                  <text x="408" y="276">|</text>
                  <text x="40" y="308">ClientB1:</text>
                  <text x="112" y="308">Prepare</text>
                  <text x="172" y="308">Commit</text>
                  <text x="220" y="308">over</text>
                  <text x="308" y="308">AppSync(+Cathy),</text>
                  <text x="396" y="308">Add*</text>
                  <text x="76" y="324">ClientB1-&gt;ServerB:</text>
                  <text x="164" y="324">[[</text>
                  <text x="208" y="324">Commit,</text>
                  <text x="276" y="324">Welcome,</text>
                  <text x="360" y="324">GroupInfo?,</text>
                  <text x="460" y="324">RatchetTree?</text>
                  <text x="524" y="324">]]</text>
                  <text x="72" y="340">ServerB-&gt;ServerA:</text>
                  <text x="164" y="340">POST</text>
                  <text x="304" y="340">/update/a.example/r/clubhouse</text>
                  <text x="476" y="340">CommitBundle</text>
                  <text x="36" y="356">ServerA:</text>
                  <text x="100" y="356">Verify</text>
                  <text x="148" y="356">that</text>
                  <text x="188" y="356">Adds</text>
                  <text x="224" y="356">are</text>
                  <text x="272" y="356">allowed</text>
                  <text x="316" y="356">by</text>
                  <text x="356" y="356">policy</text>
                  <text x="72" y="372">ServerA-&gt;ServerB:</text>
                  <text x="160" y="372">200</text>
                  <text x="188" y="372">OK</text>
                  <text x="72" y="388">ServerA-&gt;ServerC:</text>
                  <text x="164" y="388">POST</text>
                  <text x="304" y="388">/notify/a.example/r/clubhouse</text>
                  <text x="212" y="404">Intro{</text>
                  <text x="276" y="404">Welcome,</text>
                  <text x="364" y="404">RatchetTree?</text>
                  <text x="424" y="404">}</text>
                  <text x="36" y="420">ServerC:</text>
                  <text x="116" y="420">Recognizes</text>
                  <text x="180" y="420">that</text>
                  <text x="232" y="420">Welcome</text>
                  <text x="276" y="420">is</text>
                  <text x="316" y="420">adding</text>
                  <text x="368" y="420">Cathy</text>
                  <text x="404" y="420">to</text>
                  <text x="456" y="420">clubhouse</text>
                  <text x="76" y="436">ServerC-&gt;ClientC*:</text>
                  <text x="164" y="436">[[</text>
                  <text x="212" y="436">Welcome,</text>
                  <text x="300" y="436">RatchetTree?</text>
                  <text x="364" y="436">]]</text>
                  <text x="72" y="452">ServerA-&gt;ServerB:</text>
                  <text x="164" y="452">POST</text>
                  <text x="304" y="452">/notify/a.example/r/clubhouse</text>
                  <text x="452" y="452">Commit</text>
                  <text x="76" y="468">ServerB-&gt;ClientB*:</text>
                  <text x="164" y="468">[[</text>
                  <text x="204" y="468">Commit</text>
                  <text x="244" y="468">]]</text>
                  <text x="76" y="484">ServerA-&gt;ClientA*:</text>
                  <text x="164" y="484">[[</text>
                  <text x="204" y="484">Commit</text>
                  <text x="244" y="484">]]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
Client                                         Client    Client  Client
B1         ServerB     ServerA     ServerC      C*        B*        A*
|             |           |           |           |         |         |
| Commit, etc |           |           |           |         |         |
+~~~~~~~~~~~~>| /update   |           |           |         |         |
|             +---------->|           |           |         |         |
|             |    200 OK |           |           |         |         |
|             |<----------+           |           |         |         |
|    Accepted |           | /notify   | Welcome,  |         |         |
|<~~~~~~~~~~~~+           +---------->| Tree      |         |         |
|             |           |           +~~~~~~~~~~>|         |         |
|             |   /notify | Commit    +~~~~~~~~~~>|         |         |
|             |<----------+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
|             | Commit    |           |           |         |         |
|             +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|         |
|             |           |           |           |         |         |

ClientB1: Prepare Commit over AppSync(+Cathy), Add*
ClientB1->ServerB: [[ Commit, Welcome, GroupInfo?, RatchetTree? ]]
ServerB->ServerA: POST /update/a.example/r/clubhouse CommitBundle
ServerA: Verify that Adds are allowed by policy
ServerA->ServerB: 200 OK
ServerA->ServerC: POST /notify/a.example/r/clubhouse
                       Intro{ Welcome, RatchetTree? }
ServerC: Recognizes that Welcome is adding Cathy to clubhouse
ServerC->ClientC*: [[ Welcome, RatchetTree? ]]
ServerA->ServerB: POST /notify/a.example/r/clubhouse Commit
ServerB->ClientB*: [[ Commit ]]
ServerA->ClientA*: [[ Commit ]]
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="cathy-sends-a-message">
        <name>Cathy Sends a Message</name>
        <t>Now that Alice, Bob, and Cathy are all in the room, Cathy wants to say hello to
everyone.  Cathy's client encapsulates the message in an MLS PrivateMessage and
sends it to ServerC, who forwards it to the hub ServerA on Cathy's behalf.
Assuming Cathy is allowed to speak in the room, ServerA will forward Cathy's
message to the other servers involved in the room, who distribute it to their
clients.</t>
        <figure anchor="fig-c-msg">
          <name>Cathy Sends a Message to the Room</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="448" width="736" viewBox="0 0 736 448" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,288" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,288" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,224" fill="none" stroke="black"/>
                <path d="M 280,256 L 280,288" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,224" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,224" fill="none" stroke="black"/>
                <path d="M 616,48 L 616,256" fill="none" stroke="black"/>
                <path d="M 696,48 L 696,288" fill="none" stroke="black"/>
                <path d="M 24,80 Q 26,76.8 28,80 Q 30,83.2 32,80 Q 34,76.8 36,80 Q 38,83.2 40,80 Q 42,76.8 44,80 Q 46,83.2 48,80 Q 50,76.8 52,80 Q 54,83.2 56,80 Q 58,76.8 60,80 Q 62,83.2 64,80 Q 66,76.8 68,80 Q 70,83.2 72,80 Q 74,76.8 76,80 Q 78,83.2 80,80 Q 82,76.8 84,80 Q 86,83.2 88,80 Q 90,76.8 92,80 Q 94,83.2 96,80 Q 98,76.8 100,80 Q 102,83.2 104,80 Q 106,76.8 108,80 Q 110,83.2 112,80 Q 114,76.8 116,80 Q 118,83.2 120,80 Q 122,76.8 124,80 Q 126,83.2 128,80 Q 130,76.8 132,80 Q 134,83.2 136,80 Q 138,76.8 140,80 Q 142,83.2 144,80 " fill="none" stroke="black"/>
                <path d="M 152,96 L 272,96" fill="none" stroke="black"/>
                <path d="M 160,128 L 280,128" fill="none" stroke="black"/>
                <path d="M 32,160 Q 34,156.8 36,160 Q 38,163.2 40,160 Q 42,156.8 44,160 Q 46,163.2 48,160 Q 50,156.8 52,160 Q 54,163.2 56,160 Q 58,156.8 60,160 Q 62,163.2 64,160 Q 66,156.8 68,160 Q 70,163.2 72,160 Q 74,156.8 76,160 Q 78,163.2 80,160 Q 82,156.8 84,160 Q 86,163.2 88,160 Q 90,156.8 92,160 Q 94,163.2 96,160 Q 98,156.8 100,160 Q 102,163.2 104,160 Q 106,156.8 108,160 Q 110,163.2 112,160 Q 114,156.8 116,160 Q 118,163.2 120,160 Q 122,156.8 124,160 Q 126,163.2 128,160 Q 130,156.8 132,160 Q 134,163.2 136,160 Q 138,156.8 140,160 Q 142,163.2 144,160 Q 146,156.8 148,160 Q 150,163.2 152,160 " fill="none" stroke="black"/>
                <path d="M 280,160 L 400,160" fill="none" stroke="black"/>
                <path d="M 408,176 Q 410,172.8 412,176 Q 414,179.2 416,176 Q 418,172.8 420,176 Q 422,179.2 424,176 Q 426,172.8 428,176 Q 430,179.2 432,176 Q 434,172.8 436,176 Q 438,179.2 440,176 Q 442,172.8 444,176 Q 446,179.2 448,176 Q 450,172.8 452,176 Q 454,179.2 456,176 Q 458,172.8 460,176 Q 462,179.2 464,176 Q 466,172.8 468,176 Q 470,179.2 472,176 Q 474,172.8 476,176 Q 478,179.2 480,176 Q 482,172.8 484,176 Q 486,179.2 488,176 Q 490,172.8 492,176 Q 494,179.2 496,176 Q 498,172.8 500,176 Q 502,179.2 504,176 Q 506,172.8 508,176 Q 510,179.2 512,176 Q 514,172.8 516,176 Q 518,179.2 520,176 Q 522,172.8 524,176 Q 526,179.2 528,176 " fill="none" stroke="black"/>
                <path d="M 160,208 L 280,208" fill="none" stroke="black"/>
                <path d="M 152,240 Q 154,236.8 156,240 Q 158,243.2 160,240 Q 162,236.8 164,240 Q 166,243.2 168,240 Q 170,236.8 172,240 Q 174,243.2 176,240 Q 178,236.8 180,240 Q 182,243.2 184,240 Q 186,236.8 188,240 Q 190,243.2 192,240 Q 194,236.8 196,240 Q 198,243.2 200,240 Q 202,236.8 204,240 Q 206,243.2 208,240 Q 210,236.8 212,240 Q 214,243.2 216,240 Q 218,236.8 220,240 Q 222,243.2 224,240 Q 226,236.8 228,240 Q 230,243.2 232,240 Q 234,236.8 236,240 Q 238,243.2 240,240 Q 242,236.8 244,240 Q 246,243.2 248,240 Q 250,236.8 252,240 Q 254,243.2 256,240 Q 258,236.8 260,240 Q 262,243.2 264,240 Q 266,236.8 268,240 Q 270,243.2 272,240 Q 274,236.8 276,240 Q 278,243.2 280,240 Q 282,236.8 284,240 Q 286,243.2 288,240 Q 290,236.8 292,240 Q 294,243.2 296,240 Q 298,236.8 300,240 Q 302,243.2 304,240 Q 306,236.8 308,240 Q 310,243.2 312,240 Q 314,236.8 316,240 Q 318,243.2 320,240 Q 322,236.8 324,240 Q 326,243.2 328,240 Q 330,236.8 332,240 Q 334,243.2 336,240 Q 338,236.8 340,240 Q 342,243.2 344,240 Q 346,236.8 348,240 Q 350,243.2 352,240 Q 354,236.8 356,240 Q 358,243.2 360,240 Q 362,236.8 364,240 Q 366,243.2 368,240 Q 370,236.8 372,240 Q 374,243.2 376,240 Q 378,236.8 380,240 Q 382,243.2 384,240 Q 386,236.8 388,240 Q 390,243.2 392,240 Q 394,236.8 396,240 Q 398,243.2 400,240 Q 402,236.8 404,240 Q 406,243.2 408,240 Q 410,236.8 412,240 Q 414,243.2 416,240 Q 418,236.8 420,240 Q 422,243.2 424,240 Q 426,236.8 428,240 Q 430,243.2 432,240 Q 434,236.8 436,240 Q 438,243.2 440,240 Q 442,236.8 444,240 Q 446,243.2 448,240 Q 450,236.8 452,240 Q 454,243.2 456,240 Q 458,236.8 460,240 Q 462,243.2 464,240 Q 466,236.8 468,240 Q 470,243.2 472,240 Q 474,236.8 476,240 Q 478,243.2 480,240 Q 482,236.8 484,240 Q 486,243.2 488,240 Q 490,236.8 492,240 Q 494,243.2 496,240 Q 498,236.8 500,240 Q 502,243.2 504,240 Q 506,236.8 508,240 Q 510,243.2 512,240 Q 514,236.8 516,240 Q 518,243.2 520,240 Q 522,236.8 524,240 Q 526,243.2 528,240 Q 530,236.8 532,240 Q 534,243.2 536,240 Q 538,236.8 540,240 Q 542,243.2 544,240 Q 546,236.8 548,240 Q 550,243.2 552,240 Q 554,236.8 556,240 Q 558,243.2 560,240 Q 562,236.8 564,240 Q 566,243.2 568,240 Q 570,236.8 572,240 Q 574,243.2 576,240 Q 578,236.8 580,240 Q 582,243.2 584,240 Q 586,236.8 588,240 Q 590,243.2 592,240 Q 594,236.8 596,240 Q 598,243.2 600,240 Q 602,236.8 604,240 Q 606,243.2 608,240 " fill="none" stroke="black"/>
                <path d="M 280,272 Q 282,268.8 284,272 Q 286,275.2 288,272 Q 290,268.8 292,272 Q 294,275.2 296,272 Q 298,268.8 300,272 Q 302,275.2 304,272 Q 306,268.8 308,272 Q 310,275.2 312,272 Q 314,268.8 316,272 Q 318,275.2 320,272 Q 322,268.8 324,272 Q 326,275.2 328,272 Q 330,268.8 332,272 Q 334,275.2 336,272 Q 338,268.8 340,272 Q 342,275.2 344,272 Q 346,268.8 348,272 Q 350,275.2 352,272 Q 354,268.8 356,272 Q 358,275.2 360,272 Q 362,268.8 364,272 Q 366,275.2 368,272 Q 370,268.8 372,272 Q 374,275.2 376,272 Q 378,268.8 380,272 Q 382,275.2 384,272 Q 386,268.8 388,272 Q 390,275.2 392,272 Q 394,268.8 396,272 Q 398,275.2 400,272 Q 402,268.8 404,272 Q 406,275.2 408,272 Q 410,268.8 412,272 Q 414,275.2 416,272 Q 418,268.8 420,272 Q 422,275.2 424,272 Q 426,268.8 428,272 Q 430,275.2 432,272 Q 434,268.8 436,272 Q 438,275.2 440,272 Q 442,268.8 444,272 Q 446,275.2 448,272 Q 450,268.8 452,272 Q 454,275.2 456,272 Q 458,268.8 460,272 Q 462,275.2 464,272 Q 466,268.8 468,272 Q 470,275.2 472,272 Q 474,268.8 476,272 Q 478,275.2 480,272 Q 482,268.8 484,272 Q 486,275.2 488,272 Q 490,268.8 492,272 Q 494,275.2 496,272 Q 498,268.8 500,272 Q 502,275.2 504,272 Q 506,268.8 508,272 Q 510,275.2 512,272 Q 514,268.8 516,272 Q 518,275.2 520,272 Q 522,268.8 524,272 Q 526,275.2 528,272 Q 530,268.8 532,272 Q 534,275.2 536,272 Q 538,268.8 540,272 Q 542,275.2 544,272 Q 546,268.8 548,272 Q 550,275.2 552,272 Q 554,268.8 556,272 Q 558,275.2 560,272 Q 562,268.8 564,272 Q 566,275.2 568,272 Q 570,268.8 572,272 Q 574,275.2 576,272 Q 578,268.8 580,272 Q 582,275.2 584,272 Q 586,268.8 588,272 Q 590,275.2 592,272 Q 594,268.8 596,272 Q 598,275.2 600,272 Q 602,268.8 604,272 Q 606,275.2 608,272 Q 610,268.8 612,272 Q 614,275.2 616,272 Q 618,268.8 620,272 Q 622,275.2 624,272 Q 626,268.8 628,272 Q 630,275.2 632,272 Q 634,268.8 636,272 Q 638,275.2 640,272 Q 642,268.8 644,272 Q 646,275.2 648,272 Q 650,268.8 652,272 Q 654,275.2 656,272 Q 658,268.8 660,272 Q 662,275.2 664,272 Q 666,268.8 668,272 Q 670,275.2 672,272 Q 674,268.8 676,272 Q 678,275.2 680,272 Q 682,268.8 684,272 Q 686,275.2 688,272 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="696,272 684,266.4 684,277.6" fill="black" transform="rotate(0,688,272)"/>
                <polygon class="arrowhead" points="616,240 604,234.4 604,245.6" fill="black" transform="rotate(0,608,240)"/>
                <polygon class="arrowhead" points="536,176 524,170.4 524,181.6" fill="black" transform="rotate(0,528,176)"/>
                <polygon class="arrowhead" points="408,160 396,154.4 396,165.6" fill="black" transform="rotate(0,400,160)"/>
                <polygon class="arrowhead" points="280,96 268,90.4 268,101.6" fill="black" transform="rotate(0,272,96)"/>
                <polygon class="arrowhead" points="168,208 156,202.4 156,213.6" fill="black" transform="rotate(180,160,208)"/>
                <polygon class="arrowhead" points="168,128 156,122.4 156,133.6" fill="black" transform="rotate(180,160,128)"/>
                <polygon class="arrowhead" points="152,80 140,74.4 140,85.6" fill="black" transform="rotate(0,144,80)"/>
                <polygon class="arrowhead" points="40,160 28,154.4 28,165.6" fill="black" transform="rotate(180,32,160)"/>
                <g class="text">
                  <text x="36" y="36">ClientC1</text>
                  <text x="152" y="36">ServerC</text>
                  <text x="280" y="36">ServerA</text>
                  <text x="408" y="36">ServerB</text>
                  <text x="540" y="36">ClientB*</text>
                  <text x="620" y="36">ClientC*</text>
                  <text x="700" y="36">ClientA*</text>
                  <text x="64" y="68">Message</text>
                  <text x="192" y="84">/submit</text>
                  <text x="232" y="116">200</text>
                  <text x="260" y="116">OK</text>
                  <text x="108" y="148">Accepted</text>
                  <text x="320" y="148">/notify</text>
                  <text x="448" y="164">Message</text>
                  <text x="240" y="196">/notify</text>
                  <text x="192" y="228">Message</text>
                  <text x="320" y="260">Message</text>
                  <text x="408" y="260">|</text>
                  <text x="536" y="260">|</text>
                  <text x="408" y="292">|</text>
                  <text x="536" y="292">|</text>
                  <text x="616" y="292">|</text>
                  <text x="76" y="324">ClientC1-&gt;ServerC:</text>
                  <text x="164" y="324">[[</text>
                  <text x="284" y="324">MLSMessage(PrivateMessage)</text>
                  <text x="404" y="324">]]</text>
                  <text x="72" y="340">ServerC-&gt;ServerA:</text>
                  <text x="164" y="340">POST</text>
                  <text x="304" y="340">/submit/a.example/r/clubhouse</text>
                  <text x="532" y="340">MLSMessage(PrivateMessage)</text>
                  <text x="36" y="356">ServerA:</text>
                  <text x="108" y="356">Verifies</text>
                  <text x="164" y="356">that</text>
                  <text x="216" y="356">message</text>
                  <text x="260" y="356">is</text>
                  <text x="304" y="356">allowed</text>
                  <text x="72" y="372">ServerA-&gt;ServerC:</text>
                  <text x="164" y="372">POST</text>
                  <text x="304" y="372">/notify/a.example/r/clubhouse</text>
                  <text x="460" y="372">Message{</text>
                  <text x="604" y="372">MLSMessage(PrivateMessage)</text>
                  <text x="720" y="372">}</text>
                  <text x="72" y="388">ServerA-&gt;ServerB:</text>
                  <text x="164" y="388">POST</text>
                  <text x="304" y="388">/notify/a.example/r/clubhouse</text>
                  <text x="460" y="388">Message{</text>
                  <text x="604" y="388">MLSMessage(PrivateMessage)</text>
                  <text x="720" y="388">}</text>
                  <text x="76" y="404">ServerA-&gt;ClientA*:</text>
                  <text x="164" y="404">[[</text>
                  <text x="284" y="404">MLSMessage(PrivateMessage)</text>
                  <text x="404" y="404">]]</text>
                  <text x="76" y="420">ServerB-&gt;ClientB*:</text>
                  <text x="164" y="420">[[</text>
                  <text x="284" y="420">MLSMessage(PrivateMessage)</text>
                  <text x="404" y="420">]]</text>
                  <text x="76" y="436">ServerC-&gt;ClientC*:</text>
                  <text x="164" y="436">[[</text>
                  <text x="284" y="436">MLSMessage(PrivateMessage)</text>
                  <text x="404" y="436">]]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientC1       ServerC         ServerA         ServerB         ClientB*  ClientC*  ClientA*
  |               |               |               |               |         |         |
  | Message       |               |               |               |         |         |
  +~~~~~~~~~~~~~~>| /submit       |               |               |         |         |
  |               +-------------->|               |               |         |         |
  |               |        200 OK |               |               |         |         |
  |               |<--------------+               |               |         |         |
  |      Accepted |               | /notify       |               |         |         |
  |<~~~~~~~~~~~~~~+               +-------------->| Message       |         |         |
  |               |               |               +~~~~~~~~~~~~~~>|         |         |
  |               |       /notify |               |               |         |         |
  |               |<--------------+               |               |         |         |
  |               | Message       |               |               |         |         |
  |               +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|         |
  |               |               | Message       |               |         |         |
  |               |               +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
  |               |               |               |               |         |         |

ClientC1->ServerC: [[ MLSMessage(PrivateMessage) ]]
ServerC->ServerA: POST /submit/a.example/r/clubhouse MLSMessage(PrivateMessage)
ServerA: Verifies that message is allowed
ServerA->ServerC: POST /notify/a.example/r/clubhouse Message{ MLSMessage(PrivateMessage) }
ServerA->ServerB: POST /notify/a.example/r/clubhouse Message{ MLSMessage(PrivateMessage) }
ServerA->ClientA*: [[ MLSMessage(PrivateMessage) ]]
ServerB->ClientB*: [[ MLSMessage(PrivateMessage) ]]
ServerC->ClientC*: [[ MLSMessage(PrivateMessage) ]]
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="bob-leaves-the-room">
        <name>Bob Leaves the Room</name>
        <t>A user removing another user follows the same flow as adding the user.  The
user performing the removal creates an MLS commit covering Remove proposals for
all of the removed user's devices, and an AppSync proposal updating the room
state to remove the removed user from the room's participant list.</t>
        <t>One's own user leaving is slightly more complicated than removing another user,
because the leaving user cannot remove all of their devices from the MLS group.
Instead, the leave happens in three steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>The leaving client constructs MLS Remove proposals for all of the user's
devices (including the leaving client), and an AppSync proposal that removes
its user from the participant list.</t>
          </li>
          <li>
            <t>The leaving client sends these proposals to the hub.  The hub caches the proposals.</t>
          </li>
          <li>
            <t>The next time a client attempts to commit, the hub requires the client to
include the cached proposals.</t>
          </li>
        </ol>
        <t>The hub thus guarantees the leaving client that they will be removed as soon as
possible.</t>
        <figure anchor="fig-b-leave">
          <name>Bob Leaves the Room</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="704" width="608" viewBox="0 0 608 704" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,416" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,416" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,416" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,416" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,368" fill="none" stroke="black"/>
                <path d="M 536,400 L 536,416" fill="none" stroke="black"/>
                <path d="M 600,48 L 600,416" fill="none" stroke="black"/>
                <path d="M 24,80 Q 26,76.8 28,80 Q 30,83.2 32,80 Q 34,76.8 36,80 Q 38,83.2 40,80 Q 42,76.8 44,80 Q 46,83.2 48,80 Q 50,76.8 52,80 Q 54,83.2 56,80 Q 58,76.8 60,80 Q 62,83.2 64,80 Q 66,76.8 68,80 Q 70,83.2 72,80 Q 74,76.8 76,80 Q 78,83.2 80,80 Q 82,76.8 84,80 Q 86,83.2 88,80 Q 90,76.8 92,80 Q 94,83.2 96,80 Q 98,76.8 100,80 Q 102,83.2 104,80 Q 106,76.8 108,80 Q 110,83.2 112,80 Q 114,76.8 116,80 Q 118,83.2 120,80 Q 122,76.8 124,80 Q 126,83.2 128,80 Q 130,76.8 132,80 Q 134,83.2 136,80 Q 138,76.8 140,80 Q 142,83.2 144,80 " fill="none" stroke="black"/>
                <path d="M 152,96 L 272,96" fill="none" stroke="black"/>
                <path d="M 160,128 L 280,128" fill="none" stroke="black"/>
                <path d="M 32,160 Q 34,156.8 36,160 Q 38,163.2 40,160 Q 42,156.8 44,160 Q 46,163.2 48,160 Q 50,156.8 52,160 Q 54,163.2 56,160 Q 58,156.8 60,160 Q 62,163.2 64,160 Q 66,156.8 68,160 Q 70,163.2 72,160 Q 74,156.8 76,160 Q 78,163.2 80,160 Q 82,156.8 84,160 Q 86,163.2 88,160 Q 90,156.8 92,160 Q 94,163.2 96,160 Q 98,156.8 100,160 Q 102,163.2 104,160 Q 106,156.8 108,160 Q 110,163.2 112,160 Q 114,156.8 116,160 Q 118,163.2 120,160 Q 122,156.8 124,160 Q 126,163.2 128,160 Q 130,156.8 132,160 Q 134,163.2 136,160 Q 138,156.8 140,160 Q 142,163.2 144,160 Q 146,156.8 148,160 Q 150,163.2 152,160 " fill="none" stroke="black"/>
                <path d="M 280,160 L 400,160" fill="none" stroke="black"/>
                <path d="M 408,192 Q 410,188.8 412,192 Q 414,195.2 416,192 Q 418,188.8 420,192 Q 422,195.2 424,192 Q 426,188.8 428,192 Q 430,195.2 432,192 Q 434,188.8 436,192 Q 438,195.2 440,192 Q 442,188.8 444,192 Q 446,195.2 448,192 Q 450,188.8 452,192 Q 454,195.2 456,192 Q 458,188.8 460,192 Q 462,195.2 464,192 Q 466,188.8 468,192 Q 470,195.2 472,192 Q 474,188.8 476,192 Q 478,195.2 480,192 Q 482,188.8 484,192 Q 486,195.2 488,192 Q 490,188.8 492,192 Q 494,195.2 496,192 Q 498,188.8 500,192 Q 502,195.2 504,192 Q 506,188.8 508,192 Q 510,195.2 512,192 Q 514,188.8 516,192 Q 518,195.2 520,192 Q 522,188.8 524,192 Q 526,195.2 528,192 " fill="none" stroke="black"/>
                <path d="M 416,240 Q 418,236.8 420,240 Q 422,243.2 424,240 Q 426,236.8 428,240 Q 430,243.2 432,240 Q 434,236.8 436,240 Q 438,243.2 440,240 Q 442,236.8 444,240 Q 446,243.2 448,240 Q 450,236.8 452,240 Q 454,243.2 456,240 Q 458,236.8 460,240 Q 462,243.2 464,240 Q 466,236.8 468,240 Q 470,243.2 472,240 Q 474,236.8 476,240 Q 478,243.2 480,240 Q 482,236.8 484,240 Q 486,243.2 488,240 Q 490,236.8 492,240 Q 494,243.2 496,240 Q 498,236.8 500,240 Q 502,243.2 504,240 Q 506,236.8 508,240 Q 510,243.2 512,240 Q 514,236.8 516,240 Q 518,243.2 520,240 Q 522,236.8 524,240 Q 526,243.2 528,240 Q 530,236.8 532,240 Q 534,243.2 536,240 " fill="none" stroke="black"/>
                <path d="M 288,272 L 408,272" fill="none" stroke="black"/>
                <path d="M 280,304 L 400,304" fill="none" stroke="black"/>
                <path d="M 408,336 Q 410,332.8 412,336 Q 414,339.2 416,336 Q 418,332.8 420,336 Q 422,339.2 424,336 Q 426,332.8 428,336 Q 430,339.2 432,336 Q 434,332.8 436,336 Q 438,339.2 440,336 Q 442,332.8 444,336 Q 446,339.2 448,336 Q 450,332.8 452,336 Q 454,339.2 456,336 Q 458,332.8 460,336 Q 462,339.2 464,336 Q 466,332.8 468,336 Q 470,339.2 472,336 Q 474,332.8 476,336 Q 478,339.2 480,336 Q 482,332.8 484,336 Q 486,339.2 488,336 Q 490,332.8 492,336 Q 494,339.2 496,336 Q 498,332.8 500,336 Q 502,339.2 504,336 Q 506,332.8 508,336 Q 510,339.2 512,336 Q 514,332.8 516,336 Q 518,339.2 520,336 Q 522,332.8 524,336 Q 526,339.2 528,336 " fill="none" stroke="black"/>
                <path d="M 160,368 L 400,368" fill="none" stroke="black"/>
                <path d="M 32,384 Q 34,380.8 36,384 Q 38,387.2 40,384 Q 42,380.8 44,384 Q 46,387.2 48,384 Q 50,380.8 52,384 Q 54,387.2 56,384 Q 58,380.8 60,384 Q 62,387.2 64,384 Q 66,380.8 68,384 Q 70,387.2 72,384 Q 74,380.8 76,384 Q 78,387.2 80,384 Q 82,380.8 84,384 Q 86,387.2 88,384 Q 90,380.8 92,384 Q 94,387.2 96,384 Q 98,380.8 100,384 Q 102,387.2 104,384 Q 106,380.8 108,384 Q 110,387.2 112,384 Q 114,380.8 116,384 Q 118,387.2 120,384 Q 122,380.8 124,384 Q 126,387.2 128,384 Q 130,380.8 132,384 Q 134,387.2 136,384 Q 138,380.8 140,384 Q 142,387.2 144,384 Q 146,380.8 148,384 Q 150,387.2 152,384 " fill="none" stroke="black"/>
                <path d="M 408,384 Q 410,380.8 412,384 Q 414,387.2 416,384 Q 418,380.8 420,384 Q 422,387.2 424,384 Q 426,380.8 428,384 Q 430,387.2 432,384 Q 434,380.8 436,384 Q 438,387.2 440,384 Q 442,380.8 444,384 Q 446,387.2 448,384 Q 450,380.8 452,384 Q 454,387.2 456,384 Q 458,380.8 460,384 Q 462,387.2 464,384 Q 466,380.8 468,384 Q 470,387.2 472,384 Q 474,380.8 476,384 Q 478,387.2 480,384 Q 482,380.8 484,384 Q 486,387.2 488,384 Q 490,380.8 492,384 Q 494,387.2 496,384 Q 498,380.8 500,384 Q 502,387.2 504,384 Q 506,380.8 508,384 Q 510,387.2 512,384 Q 514,380.8 516,384 Q 518,387.2 520,384 Q 522,380.8 524,384 Q 526,387.2 528,384 Q 530,380.8 532,384 Q 534,387.2 536,384 Q 538,380.8 540,384 Q 542,387.2 544,384 Q 546,380.8 548,384 Q 550,387.2 552,384 Q 554,380.8 556,384 Q 558,387.2 560,384 Q 562,380.8 564,384 Q 566,387.2 568,384 Q 570,380.8 572,384 Q 574,387.2 576,384 Q 578,380.8 580,384 Q 582,387.2 584,384 Q 586,380.8 588,384 Q 590,387.2 592,384 " fill="none" stroke="black"/>
                <path d="M 408,400 Q 410,396.8 412,400 Q 414,403.2 416,400 Q 418,396.8 420,400 Q 422,403.2 424,400 Q 426,396.8 428,400 Q 430,403.2 432,400 Q 434,396.8 436,400 Q 438,403.2 440,400 Q 442,396.8 444,400 Q 446,403.2 448,400 Q 450,396.8 452,400 Q 454,403.2 456,400 Q 458,396.8 460,400 Q 462,403.2 464,400 Q 466,396.8 468,400 Q 470,403.2 472,400 Q 474,396.8 476,400 Q 478,403.2 480,400 Q 482,396.8 484,400 Q 486,403.2 488,400 Q 490,396.8 492,400 Q 494,403.2 496,400 Q 498,396.8 500,400 Q 502,403.2 504,400 Q 506,396.8 508,400 Q 510,403.2 512,400 Q 514,396.8 516,400 Q 518,403.2 520,400 Q 522,396.8 524,400 Q 526,403.2 528,400 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="600,384 588,378.4 588,389.6" fill="black" transform="rotate(0,592,384)"/>
                <polygon class="arrowhead" points="536,400 524,394.4 524,405.6" fill="black" transform="rotate(0,528,400)"/>
                <polygon class="arrowhead" points="536,336 524,330.4 524,341.6" fill="black" transform="rotate(0,528,336)"/>
                <polygon class="arrowhead" points="536,192 524,186.4 524,197.6" fill="black" transform="rotate(0,528,192)"/>
                <polygon class="arrowhead" points="424,240 412,234.4 412,245.6" fill="black" transform="rotate(180,416,240)"/>
                <polygon class="arrowhead" points="408,368 396,362.4 396,373.6" fill="black" transform="rotate(0,400,368)"/>
                <polygon class="arrowhead" points="408,304 396,298.4 396,309.6" fill="black" transform="rotate(0,400,304)"/>
                <polygon class="arrowhead" points="408,160 396,154.4 396,165.6" fill="black" transform="rotate(0,400,160)"/>
                <polygon class="arrowhead" points="296,272 284,266.4 284,277.6" fill="black" transform="rotate(180,288,272)"/>
                <polygon class="arrowhead" points="280,96 268,90.4 268,101.6" fill="black" transform="rotate(0,272,96)"/>
                <polygon class="arrowhead" points="168,368 156,362.4 156,373.6" fill="black" transform="rotate(180,160,368)"/>
                <polygon class="arrowhead" points="168,128 156,122.4 156,133.6" fill="black" transform="rotate(180,160,128)"/>
                <polygon class="arrowhead" points="152,80 140,74.4 140,85.6" fill="black" transform="rotate(0,144,80)"/>
                <polygon class="arrowhead" points="40,384 28,378.4 28,389.6" fill="black" transform="rotate(180,32,384)"/>
                <polygon class="arrowhead" points="40,160 28,154.4 28,165.6" fill="black" transform="rotate(180,32,160)"/>
                <g class="text">
                  <text x="36" y="36">ClientB1</text>
                  <text x="152" y="36">ServerB</text>
                  <text x="280" y="36">ServerA</text>
                  <text x="408" y="36">ServerC</text>
                  <text x="540" y="36">ClientC1</text>
                  <text x="596" y="36">C2</text>
                  <text x="72" y="68">Proposals</text>
                  <text x="192" y="84">/update</text>
                  <text x="232" y="116">200</text>
                  <text x="260" y="116">OK</text>
                  <text x="108" y="148">Accepted</text>
                  <text x="328" y="148">/notify</text>
                  <text x="456" y="180">Proposals</text>
                  <text x="472" y="228">Commit(Props)</text>
                  <text x="368" y="260">/update</text>
                  <text x="304" y="292">200</text>
                  <text x="332" y="292">OK</text>
                  <text x="452" y="324">Accepted</text>
                  <text x="240" y="356">/notify</text>
                  <text x="320" y="356">/notify</text>
                  <text x="116" y="372">Commit</text>
                  <text x="444" y="372">Commit</text>
                  <text x="40" y="452">ClientB1:</text>
                  <text x="112" y="452">Prepare</text>
                  <text x="180" y="452">Remove*,</text>
                  <text x="272" y="452">AppSync(-Bob)</text>
                  <text x="76" y="468">ClientB1-&gt;ServerB:</text>
                  <text x="164" y="468">[[</text>
                  <text x="212" y="468">Remove*,</text>
                  <text x="280" y="468">AppSync</text>
                  <text x="324" y="468">]]</text>
                  <text x="72" y="484">ServerB-&gt;ServerA:</text>
                  <text x="164" y="484">POST</text>
                  <text x="304" y="484">/update/a.example/r/clubhouse</text>
                  <text x="460" y="484">Remove*,</text>
                  <text x="528" y="484">AppSync</text>
                  <text x="36" y="500">ServerA:</text>
                  <text x="100" y="500">Verify</text>
                  <text x="148" y="500">that</text>
                  <text x="204" y="500">Removes,</text>
                  <text x="272" y="500">AppSync</text>
                  <text x="320" y="500">are</text>
                  <text x="368" y="500">allowed</text>
                  <text x="412" y="500">by</text>
                  <text x="456" y="500">policy;</text>
                  <text x="512" y="500">cache</text>
                  <text x="72" y="516">ServerA-&gt;ServerB:</text>
                  <text x="160" y="516">200</text>
                  <text x="188" y="516">OK</text>
                  <text x="72" y="532">ServerA-&gt;ServerC:</text>
                  <text x="164" y="532">POST</text>
                  <text x="304" y="532">/notify/a.example/r/clubhouse</text>
                  <text x="464" y="532">Proposals</text>
                  <text x="80" y="548">ServerC1-&gt;ClientC1:</text>
                  <text x="172" y="548">[[</text>
                  <text x="224" y="548">Proposals</text>
                  <text x="276" y="548">]]</text>
                  <text x="76" y="564">ClientC1-&gt;ServerC:</text>
                  <text x="164" y="564">[[</text>
                  <text x="236" y="564">Commit(Props),</text>
                  <text x="332" y="564">Welcome,</text>
                  <text x="416" y="564">GroupInfo?,</text>
                  <text x="516" y="564">RatchetTree?</text>
                  <text x="580" y="564">]]</text>
                  <text x="72" y="580">ServerC-&gt;ServerA:</text>
                  <text x="164" y="580">POST</text>
                  <text x="308" y="580">/update/a.example/r/clubhousee</text>
                  <text x="484" y="580">CommitBundle</text>
                  <text x="36" y="596">ServerA:</text>
                  <text x="96" y="596">Check</text>
                  <text x="152" y="596">whether</text>
                  <text x="212" y="596">Commit</text>
                  <text x="276" y="596">includes</text>
                  <text x="340" y="596">queued</text>
                  <text x="412" y="596">proposals;</text>
                  <text x="484" y="596">accept</text>
                  <text x="72" y="612">ServerA-&gt;ServerC:</text>
                  <text x="160" y="612">200</text>
                  <text x="188" y="612">OK</text>
                  <text x="72" y="628">ServerA-&gt;ServerB:</text>
                  <text x="164" y="628">POST</text>
                  <text x="304" y="628">/notify/a.example/r/clubhouse</text>
                  <text x="452" y="628">Commit</text>
                  <text x="72" y="644">ServerA-&gt;ServerC:</text>
                  <text x="164" y="644">POST</text>
                  <text x="304" y="644">/notify/a.example/r/clubhouse</text>
                  <text x="452" y="644">Commit</text>
                  <text x="76" y="660">ServerB-&gt;ClientB1:</text>
                  <text x="164" y="660">[[</text>
                  <text x="204" y="660">Commit</text>
                  <text x="244" y="660">]]</text>
                  <text x="76" y="676">ServerC-&gt;ClientC2:</text>
                  <text x="164" y="676">[[</text>
                  <text x="204" y="676">Commit</text>
                  <text x="244" y="676">]]</text>
                  <text x="76" y="692">ServerC-&gt;ClientC1:</text>
                  <text x="164" y="692">[[</text>
                  <text x="204" y="692">Commit</text>
                  <text x="244" y="692">]]</text>
                  <text x="272" y="692">(up</text>
                  <text x="300" y="692">to</text>
                  <text x="352" y="692">provider)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientB1       ServerB         ServerA         ServerC         ClientC1  C2
  |               |               |               |               |       |
  | Proposals     |               |               |               |       |
  +~~~~~~~~~~~~~~>| /update       |               |               |       |
  |               +-------------->|               |               |       |
  |               |        200 OK |               |               |       |
  |               |<--------------+               |               |       |
  |      Accepted |               |  /notify      |               |       |
  |<~~~~~~~~~~~~~~+               +-------------->|               |       |
  |               |               |               | Proposals     |       |
  |               |               |               +~~~~~~~~~~~~~~>|       |
  |               |               |               |               |       |
  |               |               |               | Commit(Props) |       |
  |               |               |               |<~~~~~~~~~~~~~~+       |
  |               |               |       /update |               |       |
  |               |               |<--------------+               |       |
  |               |               | 200 OK        |               |       |
  |               |               +-------------->|               |       |
  |               |               |               | Accepted      |       |
  |               |               |               +~~~~~~~~~~~~~~>|       |
  |               |       /notify | /notify       |               |       |
  |        Commit |<--------------+-------------->| Commit        |       |
  |<~~~~~~~~~~~~~~+               |               +~~~~~~~~~~~~~~~~~~~~~~>|
  |               |               |               +~~~~~~~~~~~~~~>|       |
  |               |               |               |               |       |

ClientB1: Prepare Remove*, AppSync(-Bob)
ClientB1->ServerB: [[ Remove*, AppSync ]]
ServerB->ServerA: POST /update/a.example/r/clubhouse Remove*, AppSync
ServerA: Verify that Removes, AppSync are allowed by policy; cache
ServerA->ServerB: 200 OK
ServerA->ServerC: POST /notify/a.example/r/clubhouse Proposals
ServerC1->ClientC1: [[ Proposals ]]
ClientC1->ServerC: [[ Commit(Props), Welcome, GroupInfo?, RatchetTree? ]]
ServerC->ServerA: POST /update/a.example/r/clubhousee CommitBundle
ServerA: Check whether Commit includes queued proposals; accept
ServerA->ServerC: 200 OK
ServerA->ServerB: POST /notify/a.example/r/clubhouse Commit
ServerA->ServerC: POST /notify/a.example/r/clubhouse Commit
ServerB->ClientB1: [[ Commit ]]
ServerC->ClientC2: [[ Commit ]]
ServerC->ClientC1: [[ Commit ]] (up to provider)
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="cathy-adds-a-new-device">
        <name>Cathy adds a new device</name>
        <t>Many users have multiple clients often running on different devices
(for example a phone, a tablet, and a computer). When a user creates a new
client, that client needs to be able to join all the MLS groups associated
with the rooms in which the user is a participant.</t>
        <t>In MLS in order to initiate joining a group the joining client needs to get the current GroupInfo
and <tt>ratchet_tree</tt>, and then send an External Commit to the hub. In MIMI,
the hub keeps or reconstructs a copy of the GroupInfo, assuming that other
clients may not be available to assist the client with joining.</t>
        <t>For Cathy's new client (ClientC3) to join the MLS group and therefore fully participate
in the room with Alice, ClientC3 needs to fetch the MLS GroupInfo, and then
generate an External Commit adding ClientC3.</t>
        <t>Cathy's new client sends the External Commit to the room's MLS group by sending
an /update to the room.</t>
        <figure anchor="fig-c3-new-client">
          <name>Cathy Adds a new Client</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="736" width="736" viewBox="0 0 736 736" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,448" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,448" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,416" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,288" fill="none" stroke="black"/>
                <path d="M 408,320 L 408,416" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,288" fill="none" stroke="black"/>
                <path d="M 536,320 L 536,416" fill="none" stroke="black"/>
                <path d="M 616,48 L 616,288" fill="none" stroke="black"/>
                <path d="M 616,320 L 616,448" fill="none" stroke="black"/>
                <path d="M 696,48 L 696,448" fill="none" stroke="black"/>
                <path d="M 32,96 Q 34,92.8 36,96 Q 38,99.2 40,96 Q 42,92.8 44,96 Q 46,99.2 48,96 Q 50,92.8 52,96 Q 54,99.2 56,96 Q 58,92.8 60,96 Q 62,99.2 64,96 Q 66,92.8 68,96 Q 70,99.2 72,96 Q 74,92.8 76,96 Q 78,99.2 80,96 Q 82,92.8 84,96 Q 86,99.2 88,96 Q 90,92.8 92,96 Q 94,99.2 96,96 Q 98,92.8 100,96 Q 102,99.2 104,96 Q 106,92.8 108,96 Q 110,99.2 112,96 Q 114,92.8 116,96 Q 118,99.2 120,96 Q 122,92.8 124,96 Q 126,99.2 128,96 Q 130,92.8 132,96 Q 134,99.2 136,96 Q 138,92.8 140,96 Q 142,99.2 144,96 " fill="none" stroke="black"/>
                <path d="M 160,112 L 272,112" fill="none" stroke="black"/>
                <path d="M 160,144 L 272,144" fill="none" stroke="black"/>
                <path d="M 32,160 Q 34,156.8 36,160 Q 38,163.2 40,160 Q 42,156.8 44,160 Q 46,163.2 48,160 Q 50,156.8 52,160 Q 54,163.2 56,160 Q 58,156.8 60,160 Q 62,163.2 64,160 Q 66,156.8 68,160 Q 70,163.2 72,160 Q 74,156.8 76,160 Q 78,163.2 80,160 Q 82,156.8 84,160 Q 86,163.2 88,160 Q 90,156.8 92,160 Q 94,163.2 96,160 Q 98,156.8 100,160 Q 102,163.2 104,160 Q 106,156.8 108,160 Q 110,163.2 112,160 Q 114,156.8 116,160 Q 118,163.2 120,160 Q 122,156.8 124,160 Q 126,163.2 128,160 Q 130,156.8 132,160 Q 134,163.2 136,160 Q 138,156.8 140,160 Q 142,163.2 144,160 " fill="none" stroke="black"/>
                <path d="M 24,224 Q 26,220.8 28,224 Q 30,227.2 32,224 Q 34,220.8 36,224 Q 38,227.2 40,224 Q 42,220.8 44,224 Q 46,227.2 48,224 Q 50,220.8 52,224 Q 54,227.2 56,224 Q 58,220.8 60,224 Q 62,227.2 64,224 Q 66,220.8 68,224 Q 70,227.2 72,224 Q 74,220.8 76,224 Q 78,227.2 80,224 Q 82,220.8 84,224 Q 86,227.2 88,224 Q 90,220.8 92,224 Q 94,227.2 96,224 Q 98,220.8 100,224 Q 102,227.2 104,224 Q 106,220.8 108,224 Q 110,227.2 112,224 Q 114,220.8 116,224 Q 118,227.2 120,224 Q 122,220.8 124,224 Q 126,227.2 128,224 Q 130,220.8 132,224 Q 134,227.2 136,224 Q 138,220.8 140,224 Q 142,227.2 144,224 " fill="none" stroke="black"/>
                <path d="M 152,240 L 272,240" fill="none" stroke="black"/>
                <path d="M 160,272 L 280,272" fill="none" stroke="black"/>
                <path d="M 32,304 Q 34,300.8 36,304 Q 38,307.2 40,304 Q 42,300.8 44,304 Q 46,307.2 48,304 Q 50,300.8 52,304 Q 54,307.2 56,304 Q 58,300.8 60,304 Q 62,307.2 64,304 Q 66,300.8 68,304 Q 70,307.2 72,304 Q 74,300.8 76,304 Q 78,307.2 80,304 Q 82,300.8 84,304 Q 86,307.2 88,304 Q 90,300.8 92,304 Q 94,307.2 96,304 Q 98,300.8 100,304 Q 102,307.2 104,304 Q 106,300.8 108,304 Q 110,307.2 112,304 Q 114,300.8 116,304 Q 118,307.2 120,304 Q 122,300.8 124,304 Q 126,307.2 128,304 Q 130,300.8 132,304 Q 134,307.2 136,304 Q 138,300.8 140,304 Q 142,307.2 144,304 " fill="none" stroke="black"/>
                <path d="M 280,304 Q 282,300.8 284,304 Q 286,307.2 288,304 Q 290,300.8 292,304 Q 294,307.2 296,304 Q 298,300.8 300,304 Q 302,307.2 304,304 Q 306,300.8 308,304 Q 310,307.2 312,304 Q 314,300.8 316,304 Q 318,307.2 320,304 Q 322,300.8 324,304 Q 326,307.2 328,304 Q 330,300.8 332,304 Q 334,307.2 336,304 Q 338,300.8 340,304 Q 342,307.2 344,304 Q 346,300.8 348,304 Q 350,307.2 352,304 Q 354,300.8 356,304 Q 358,307.2 360,304 Q 362,300.8 364,304 Q 366,307.2 368,304 Q 370,300.8 372,304 Q 374,307.2 376,304 Q 378,300.8 380,304 Q 382,307.2 384,304 Q 386,300.8 388,304 Q 390,307.2 392,304 Q 394,300.8 396,304 Q 398,307.2 400,304 Q 402,300.8 404,304 Q 406,307.2 408,304 Q 410,300.8 412,304 Q 414,307.2 416,304 Q 418,300.8 420,304 Q 422,307.2 424,304 Q 426,300.8 428,304 Q 430,307.2 432,304 Q 434,300.8 436,304 Q 438,307.2 440,304 Q 442,300.8 444,304 Q 446,307.2 448,304 Q 450,300.8 452,304 Q 454,307.2 456,304 Q 458,300.8 460,304 Q 462,307.2 464,304 Q 466,300.8 468,304 Q 470,307.2 472,304 Q 474,300.8 476,304 Q 478,307.2 480,304 Q 482,300.8 484,304 Q 486,307.2 488,304 Q 490,300.8 492,304 Q 494,307.2 496,304 Q 498,300.8 500,304 Q 502,307.2 504,304 Q 506,300.8 508,304 Q 510,307.2 512,304 Q 514,300.8 516,304 Q 518,307.2 520,304 Q 522,300.8 524,304 Q 526,307.2 528,304 Q 530,300.8 532,304 Q 534,307.2 536,304 Q 538,300.8 540,304 Q 542,307.2 544,304 Q 546,300.8 548,304 Q 550,307.2 552,304 Q 554,300.8 556,304 Q 558,307.2 560,304 Q 562,300.8 564,304 Q 566,307.2 568,304 Q 570,300.8 572,304 Q 574,307.2 576,304 Q 578,300.8 580,304 Q 582,307.2 584,304 Q 586,300.8 588,304 Q 590,307.2 592,304 Q 594,300.8 596,304 Q 598,307.2 600,304 Q 602,300.8 604,304 Q 606,307.2 608,304 Q 610,300.8 612,304 Q 614,307.2 616,304 Q 618,300.8 620,304 Q 622,307.2 624,304 Q 626,300.8 628,304 Q 630,307.2 632,304 Q 634,300.8 636,304 Q 638,307.2 640,304 Q 642,300.8 644,304 Q 646,307.2 648,304 Q 650,300.8 652,304 Q 654,307.2 656,304 Q 658,300.8 660,304 Q 662,307.2 664,304 Q 666,300.8 668,304 Q 670,307.2 672,304 Q 674,300.8 676,304 Q 678,307.2 680,304 Q 682,300.8 684,304 Q 686,307.2 688,304 " fill="none" stroke="black"/>
                <path d="M 280,352 L 400,352" fill="none" stroke="black"/>
                <path d="M 408,368 Q 410,364.8 412,368 Q 414,371.2 416,368 Q 418,364.8 420,368 Q 422,371.2 424,368 Q 426,364.8 428,368 Q 430,371.2 432,368 Q 434,364.8 436,368 Q 438,371.2 440,368 Q 442,364.8 444,368 Q 446,371.2 448,368 Q 450,364.8 452,368 Q 454,371.2 456,368 Q 458,364.8 460,368 Q 462,371.2 464,368 Q 466,364.8 468,368 Q 470,371.2 472,368 Q 474,364.8 476,368 Q 478,371.2 480,368 Q 482,364.8 484,368 Q 486,371.2 488,368 Q 490,364.8 492,368 Q 494,371.2 496,368 Q 498,364.8 500,368 Q 502,371.2 504,368 Q 506,364.8 508,368 Q 510,371.2 512,368 Q 514,364.8 516,368 Q 518,371.2 520,368 Q 522,364.8 524,368 Q 526,371.2 528,368 " fill="none" stroke="black"/>
                <path d="M 160,400 L 280,400" fill="none" stroke="black"/>
                <path d="M 152,432 Q 154,428.8 156,432 Q 158,435.2 160,432 Q 162,428.8 164,432 Q 166,435.2 168,432 Q 170,428.8 172,432 Q 174,435.2 176,432 Q 178,428.8 180,432 Q 182,435.2 184,432 Q 186,428.8 188,432 Q 190,435.2 192,432 Q 194,428.8 196,432 Q 198,435.2 200,432 Q 202,428.8 204,432 Q 206,435.2 208,432 Q 210,428.8 212,432 Q 214,435.2 216,432 Q 218,428.8 220,432 Q 222,435.2 224,432 Q 226,428.8 228,432 Q 230,435.2 232,432 Q 234,428.8 236,432 Q 238,435.2 240,432 Q 242,428.8 244,432 Q 246,435.2 248,432 Q 250,428.8 252,432 Q 254,435.2 256,432 Q 258,428.8 260,432 Q 262,435.2 264,432 Q 266,428.8 268,432 Q 270,435.2 272,432 Q 274,428.8 276,432 Q 278,435.2 280,432 Q 282,428.8 284,432 Q 286,435.2 288,432 Q 290,428.8 292,432 Q 294,435.2 296,432 Q 298,428.8 300,432 Q 302,435.2 304,432 Q 306,428.8 308,432 Q 310,435.2 312,432 Q 314,428.8 316,432 Q 318,435.2 320,432 Q 322,428.8 324,432 Q 326,435.2 328,432 Q 330,428.8 332,432 Q 334,435.2 336,432 Q 338,428.8 340,432 Q 342,435.2 344,432 Q 346,428.8 348,432 Q 350,435.2 352,432 Q 354,428.8 356,432 Q 358,435.2 360,432 Q 362,428.8 364,432 Q 366,435.2 368,432 Q 370,428.8 372,432 Q 374,435.2 376,432 Q 378,428.8 380,432 Q 382,435.2 384,432 Q 386,428.8 388,432 Q 390,435.2 392,432 Q 394,428.8 396,432 Q 398,435.2 400,432 Q 402,428.8 404,432 Q 406,435.2 408,432 Q 410,428.8 412,432 Q 414,435.2 416,432 Q 418,428.8 420,432 Q 422,435.2 424,432 Q 426,428.8 428,432 Q 430,435.2 432,432 Q 434,428.8 436,432 Q 438,435.2 440,432 Q 442,428.8 444,432 Q 446,435.2 448,432 Q 450,428.8 452,432 Q 454,435.2 456,432 Q 458,428.8 460,432 Q 462,435.2 464,432 Q 466,428.8 468,432 Q 470,435.2 472,432 Q 474,428.8 476,432 Q 478,435.2 480,432 Q 482,428.8 484,432 Q 486,435.2 488,432 Q 490,428.8 492,432 Q 494,435.2 496,432 Q 498,428.8 500,432 Q 502,435.2 504,432 Q 506,428.8 508,432 Q 510,435.2 512,432 Q 514,428.8 516,432 Q 518,435.2 520,432 Q 522,428.8 524,432 Q 526,435.2 528,432 Q 530,428.8 532,432 Q 534,435.2 536,432 Q 538,428.8 540,432 Q 542,435.2 544,432 Q 546,428.8 548,432 Q 550,435.2 552,432 Q 554,428.8 556,432 Q 558,435.2 560,432 Q 562,428.8 564,432 Q 566,435.2 568,432 Q 570,428.8 572,432 Q 574,435.2 576,432 Q 578,428.8 580,432 Q 582,435.2 584,432 Q 586,428.8 588,432 Q 590,435.2 592,432 Q 594,428.8 596,432 Q 598,435.2 600,432 Q 602,428.8 604,432 Q 606,435.2 608,432 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="696,304 684,298.4 684,309.6" fill="black" transform="rotate(0,688,304)"/>
                <polygon class="arrowhead" points="616,432 604,426.4 604,437.6" fill="black" transform="rotate(0,608,432)"/>
                <polygon class="arrowhead" points="536,368 524,362.4 524,373.6" fill="black" transform="rotate(0,528,368)"/>
                <polygon class="arrowhead" points="408,352 396,346.4 396,357.6" fill="black" transform="rotate(0,400,352)"/>
                <polygon class="arrowhead" points="280,240 268,234.4 268,245.6" fill="black" transform="rotate(0,272,240)"/>
                <polygon class="arrowhead" points="280,112 268,106.4 268,117.6" fill="black" transform="rotate(0,272,112)"/>
                <polygon class="arrowhead" points="168,400 156,394.4 156,405.6" fill="black" transform="rotate(180,160,400)"/>
                <polygon class="arrowhead" points="168,272 156,266.4 156,277.6" fill="black" transform="rotate(180,160,272)"/>
                <polygon class="arrowhead" points="168,144 156,138.4 156,149.6" fill="black" transform="rotate(180,160,144)"/>
                <polygon class="arrowhead" points="152,224 140,218.4 140,229.6" fill="black" transform="rotate(0,144,224)"/>
                <polygon class="arrowhead" points="152,96 140,90.4 140,101.6" fill="black" transform="rotate(0,144,96)"/>
                <polygon class="arrowhead" points="40,304 28,298.4 28,309.6" fill="black" transform="rotate(180,32,304)"/>
                <polygon class="arrowhead" points="40,160 28,154.4 28,165.6" fill="black" transform="rotate(180,32,160)"/>
                <g class="text">
                  <text x="36" y="36">ClientC3</text>
                  <text x="152" y="36">ServerC</text>
                  <text x="280" y="36">ServerA</text>
                  <text x="408" y="36">ServerB</text>
                  <text x="540" y="36">ClientB*</text>
                  <text x="620" y="36">ClientC*</text>
                  <text x="700" y="36">ClientA*</text>
                  <text x="56" y="68">Fetch</text>
                  <text x="72" y="84">GroupInfo</text>
                  <text x="204" y="100">/groupInfo</text>
                  <text x="72" y="132">GroupInfo</text>
                  <text x="120" y="132">+</text>
                  <text x="232" y="132">200</text>
                  <text x="260" y="132">OK</text>
                  <text x="52" y="148">tree</text>
                  <text x="68" y="196">External</text>
                  <text x="64" y="212">Commit,</text>
                  <text x="116" y="212">etc.</text>
                  <text x="192" y="228">/update</text>
                  <text x="232" y="260">200</text>
                  <text x="260" y="260">OK</text>
                  <text x="108" y="292">Accepted</text>
                  <text x="316" y="292">Commit</text>
                  <text x="320" y="340">/notify</text>
                  <text x="444" y="356">Commit</text>
                  <text x="240" y="388">/notify</text>
                  <text x="188" y="420">Commit</text>
                  <text x="280" y="452">|</text>
                  <text x="408" y="452">|</text>
                  <text x="536" y="452">|</text>
                  <text x="76" y="484">ClientC3-&gt;ServerC:</text>
                  <text x="164" y="484">[[</text>
                  <text x="208" y="484">request</text>
                  <text x="272" y="484">current</text>
                  <text x="344" y="484">GroupInfo</text>
                  <text x="396" y="484">]]</text>
                  <text x="72" y="500">ServerC-&gt;ServerA:</text>
                  <text x="164" y="500">POST</text>
                  <text x="308" y="500">/groupInfo/a.example/clubhouse</text>
                  <text x="36" y="516">ServerA:</text>
                  <text x="100" y="516">Verify</text>
                  <text x="148" y="516">that</text>
                  <text x="204" y="516">ClientC3</text>
                  <text x="256" y="516">has</text>
                  <text x="328" y="516">authorization</text>
                  <text x="396" y="516">to</text>
                  <text x="428" y="516">join</text>
                  <text x="464" y="516">the</text>
                  <text x="500" y="516">room</text>
                  <text x="72" y="532">ServerA-&gt;ServerC:</text>
                  <text x="160" y="532">200</text>
                  <text x="188" y="532">OK</text>
                  <text x="212" y="532">w/</text>
                  <text x="256" y="532">current</text>
                  <text x="328" y="532">GroupInfo</text>
                  <text x="384" y="532">and</text>
                  <text x="432" y="532">ratchet</text>
                  <text x="484" y="532">tree</text>
                  <text x="76" y="548">ServerC-&gt;ClientC3:</text>
                  <text x="164" y="548">[[</text>
                  <text x="220" y="548">GroupInfo,</text>
                  <text x="284" y="548">tree</text>
                  <text x="316" y="548">]]</text>
                  <text x="40" y="564">ClientC3:</text>
                  <text x="112" y="564">Prepare</text>
                  <text x="180" y="564">External</text>
                  <text x="244" y="564">Commit</text>
                  <text x="292" y="564">Add*</text>
                  <text x="76" y="580">ClientC3-&gt;ServerC:</text>
                  <text x="164" y="580">[[</text>
                  <text x="208" y="580">Commit,</text>
                  <text x="288" y="580">GroupInfo?,</text>
                  <text x="388" y="580">RatchetTree?</text>
                  <text x="452" y="580">]]</text>
                  <text x="72" y="596">ServerC-&gt;ServerA:</text>
                  <text x="164" y="596">POST</text>
                  <text x="296" y="596">/update/a.example/clubhouse</text>
                  <text x="460" y="596">CommitBundle</text>
                  <text x="36" y="612">ServerA:</text>
                  <text x="100" y="612">Verify</text>
                  <text x="148" y="612">that</text>
                  <text x="196" y="612">Commit</text>
                  <text x="236" y="612">is</text>
                  <text x="272" y="612">valid</text>
                  <text x="312" y="612">and</text>
                  <text x="364" y="612">ClientC3</text>
                  <text x="412" y="612">is</text>
                  <text x="468" y="612">authorized</text>
                  <text x="72" y="628">ServerA-&gt;ServerC:</text>
                  <text x="160" y="628">200</text>
                  <text x="188" y="628">OK</text>
                  <text x="76" y="644">ServerC-&gt;ClientC3:</text>
                  <text x="164" y="644">[[</text>
                  <text x="212" y="644">External</text>
                  <text x="276" y="644">Commit</text>
                  <text x="320" y="644">was</text>
                  <text x="372" y="644">accepted</text>
                  <text x="420" y="644">]]</text>
                  <text x="76" y="660">ServerA-&gt;ClientA*:</text>
                  <text x="164" y="660">[[</text>
                  <text x="204" y="660">Commit</text>
                  <text x="244" y="660">]]</text>
                  <text x="72" y="676">ServerA-&gt;ServerB:</text>
                  <text x="164" y="676">POST</text>
                  <text x="296" y="676">/notify/a.example/clubhouse</text>
                  <text x="436" y="676">Commit</text>
                  <text x="76" y="692">ServerB-&gt;ClientB*:</text>
                  <text x="164" y="692">[[</text>
                  <text x="204" y="692">Commit</text>
                  <text x="244" y="692">]]</text>
                  <text x="72" y="708">ServerA-&gt;ServerC:</text>
                  <text x="164" y="708">POST</text>
                  <text x="296" y="708">/notify/a.example/clubhouse</text>
                  <text x="436" y="708">Commit</text>
                  <text x="76" y="724">ServerC-&gt;ClientC*:</text>
                  <text x="164" y="724">[[</text>
                  <text x="204" y="724">Commit</text>
                  <text x="244" y="724">]]</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientC3       ServerC         ServerA         ServerB         ClientB*  ClientC*  ClientA*
  |               |               |               |               |         |         |
  | Fetch         |               |               |               |         |         |
  | GroupInfo     |               |               |               |         |         |
  |~~~~~~~~~~~~~~>| /groupInfo    |               |               |         |         |
  |               |-------------->|               |               |         |         |
  | GroupInfo +   |        200 OK |               |               |         |         |
  | tree          |<--------------|               |               |         |         |
  |<~~~~~~~~~~~~~~|               |               |               |         |         |
  |               |               |               |               |         |         |
  | External      |               |               |               |         |         |
  | Commit, etc.  |               |               |               |         |         |
  +~~~~~~~~~~~~~~>| /update       |               |               |         |         |
  |               +-------------->|               |               |         |         |
  |               |        200 OK |               |               |         |         |
  |               |<--------------+               |               |         |         |
  |      Accepted |               | Commit        |               |         |         |
  |<~~~~~~~~~~~~~~|               +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
  |               |               |               |               |         |         |
  |               |               | /notify       |               |         |         |
  |               +               +-------------->| Commit        |         |         |
  |               |               |               +~~~~~~~~~~~~~~>|         |         |
  |               |       /notify |               |               |         |         |
  |               |<--------------+               |               |         |         |
  |               | Commit        |               |               |         |         |
  |               +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|         |
  |               |               |               |               |         |         |

ClientC3->ServerC: [[ request current GroupInfo ]]
ServerC->ServerA: POST /groupInfo/a.example/clubhouse
ServerA: Verify that ClientC3 has authorization to join the room
ServerA->ServerC: 200 OK w/ current GroupInfo and ratchet tree
ServerC->ClientC3: [[ GroupInfo, tree ]]
ClientC3: Prepare External Commit Add*
ClientC3->ServerC: [[ Commit, GroupInfo?, RatchetTree? ]]
ServerC->ServerA: POST /update/a.example/clubhouse CommitBundle
ServerA: Verify that Commit is valid and ClientC3 is authorized
ServerA->ServerC: 200 OK
ServerC->ClientC3: [[ External Commit was accepted ]]
ServerA->ClientA*: [[ Commit ]]
ServerA->ServerB: POST /notify/a.example/clubhouse Commit
ServerB->ClientB*: [[ Commit ]]
ServerA->ServerC: POST /notify/a.example/clubhouse Commit
ServerC->ClientC*: [[ Commit ]]
]]></artwork>
          </artset>
        </figure>
      </section>
    </section>
    <section anchor="services-required-at-each-layer">
      <name>Services required at each layer</name>
      <section anchor="transport-layer">
        <name>Transport layer</name>
        <t>MIMI servers communicate using HTTPS.  The HTTP request <bcp14>MUST</bcp14> identify the
source and target providers for the request, in the following way:</t>
        <ul spacing="normal">
          <li>
            <t>The target provider is indicated using a Host header <xref target="RFC9110"/>.  If the
provider is using a non-standard port, then the port component of the Host
header is ignored.</t>
          </li>
          <li>
            <t>The source provider is indicated using a From header <xref target="RFC9110"/>.  The
<tt>mailbox</tt> production in the From header <bcp14>MUST</bcp14> use the <tt>addr-spec</tt> variant, and
the <tt>local-part</tt> of the address <bcp14>MUST</bcp14> contain the fixed string <tt>mimi</tt>.  Thus,
the content of the From header will be <tt>mimi@a.example</tt>, where <tt>a.example</tt> is
the domain name of the source provider.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>NOTE</strong>: The use of the From header field here is not really well-aligned with its
  intended use.  The WG should consider whether this is correct, or whether a new
  header field would be better.  Perhaps something like "From-Host" to match Host?</t>
          </li>
        </ul>
        <t>The TLS connection underlying the HTTPS connection <bcp14>MUST</bcp14> be mutually
authenticated.  The certificates presented in the TLS handshake <bcp14>MUST</bcp14>
authenticate the source and target provider domains, according to <xref target="RFC6125"/>.</t>
        <t>The bodies of HTTP requests and responses are defined by the individual
endpoints defined in <xref target="application-layer"/>.</t>
      </section>
      <section anchor="end-to-end-security-layer">
        <name>End-to-End Security Layer</name>
        <t>Every MIMI room has an MLS group associated to it, which provides end-to-end
security guarantees.  The clients participating in the room manage the MLS-level
membership by sending Commit messages covering Add and Remove proposals.</t>
        <t>Every application message sent within a room is authenticated and confidentiality-protected
by virtue of being encapsulated in an MLS PrivateMessage object.</t>
        <t>MIMI uses the MLS application state synchronization mechanism
(<xref target="mls-application-state-synchronization"/>) to ensure that the clients involved
in a MIMI room agree on the state of the room.  Each MIMI message that changes
the state of the room is encapsulated in an AppSync proposal and transmitted
inside an MLS PublicMessage object.</t>
        <t>The PublicMessage encapsulation provides sender authentication, including the
ability for actors outside the group (e.g., servers involved in the room) to
originate AppSync proposals.  Encoding room state changes in MLS proposals
ensures that a client will not process a commit that confirms a state change
before processing the state change itself.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: A little more needs to be said here about how MLS is used.  For
example: What types of credential are required / allowed?  If servers are going
to be allowed to introduce room changes, how are their keys provisioned as
external signers? Need to maintain the membership and the list of queued proposals.</t>
          </li>
        </ul>
      </section>
      <section anchor="application-layer">
        <name>Application Layer</name>
        <t>Servers in MIMI provide a few functions that enable messaging applications.
All servers act as publication points for key material used to add their users
to rooms. The hub server for a room tracks the state of the room, and controls
how the room's state evolves, e.g., by ensuring that changes are compliant with
the room's policy. Non-hub servers facilitate interactions between their clients
and the hub server.</t>
        <t>In this section, we describe the state that servers keep. The following top
level section describes the HTTP endpoints exposed to enable these functions.</t>
        <section anchor="server-state">
          <name>Server State</name>
          <t>Every MIMI server is a publication point for users' key material, via the
<tt>keyMaterial</tt> endpoint discussed in <xref target="fetch-key-material"/>.  To support this
endpoint, the server stores a set of KeyPackages, where each KeyPackage belongs
to a specific user and device.</t>
          <t>Each KeyPackage includes a list of its MLS client's capabilities (MLS
protocol versions, cipher suites, extensions, proposal types, and credential
types). When claiming KeyPackages, the requester includes the list of
<tt>RequiredCapabilites</tt> to ensure the new joiner is compatible with and
capable of participating in the corresponding room.</t>
          <t>The hub server for the room stores the state of the room, comprising:</t>
          <ul spacing="normal">
            <li>
              <t>The <em>base policy</em> of the room, which does not depend on the specific
participants in the room. For example, this includes the room roles
and their permissions.</t>
            </li>
            <li>
              <t>The <em>participant list</em>: a list of the users who are participants of the
room, and each user's role in the room.</t>
            </li>
          </ul>
          <ul empty="true">
            <li>
              <t><strong>TODO</strong>: We need a more full description of the room, room state syntax.</t>
            </li>
          </ul>
          <t>When a client requests key material via the hub, the hub records the
KeyPackageRef values for the returned KeyPackages, and the identity of the
provider from which they were received.  This information is then used to route
Welcome message to the proper provider.</t>
        </section>
        <section anchor="participant-list-changes">
          <name>Participant List Changes</name>
          <t>The participant list can be changed by adding or removing users, or changing
a user's role.  These changes are described without a specific syntax as a
list of adds, removes, and role changes:</t>
          <figure anchor="fig-room-state-change">
            <name>Changing the state of the room</name>
            <artwork type="ascii-art"><![CDATA[
Add: ["mimi://d.example/u/diana", "admin"],
     ["mimi://e.example/u/eric", "admin"],
Remove: ["mimi://b.example/u/bob"],
SetRole: [["mimi://c.example/u/cathy", "admin"]]
]]></artwork>
          </figure>
          <t>To put these changes into effect, a client or server encodes them in an AppSync
proposal, signs the proposal as a PublicMessage, and submits them to the
<tt>update</tt> endpoint on the hub.</t>
        </section>
      </section>
    </section>
    <section anchor="mimi-endpoints-and-framing">
      <name>MIMI Endpoints and Framing</name>
      <t>This section describes the specific endpoints necessary to provide the
functionality in the example flow. The framing for each endpoint includes a
protocol so that different variations of the end-to-end encryption can be used.</t>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Determine the what needs to be included in the protocol. MIMI
  version, e2e protocol version, etc.</t>
        </li>
      </ul>
      <t>The syntax of the MIMI protocol messages are described using the TLS
presentation language format (<xref section="3" sectionFormat="of" target="RFC8446"/>).</t>
      <sourcecode type="tls"><![CDATA[
enum {
    reserved(0),
    mls10(1),
    (255)
} Protocol;
]]></sourcecode>
      <section anchor="directory">
        <name>Directory</name>
        <t>Like the ACME protocol (See <xref section="7.1.1" sectionFormat="of" target="RFC8555"/>), the MIMI protocol uses a directory document
to convey the HTTPS URLs used to reach certain endpoints (as opposed to hard
coding the endpoints).</t>
        <t>The directory URL is discovered using the <tt>mimi-protocol-directory</tt> well-known
URI. The response is a JSON document with URIs for each type of endpoint.</t>
        <artwork><![CDATA[
GET /.well-known/mimi-protocol-directory
]]></artwork>
        <artwork><![CDATA[
{
  "keyMaterial":
     "https://mimi.example.com/v1/keyMaterial/{targetUser}",
  "update": "https://mimi.example.com/v1/update{roomId}",
  "notify": "https://mimi.example.com/v1/notify/{roomId}",
  "submitMessage":
     "https://mimi.example.com/v1/submitMessage/{roomId}",
  "groupInfo":
     "https://mimi.example.com/v1/groupInfo/{roomId}"
}
]]></artwork>
      </section>
      <section anchor="fetch-key-material">
        <name>Fetch Key Material</name>
        <t>This action attempts to claim initial keying material for all the clients
of a single user at a specific provider. The keying material is designed
for use in a single room and may not be reused. It uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /keyMaterial/{targetUser}
]]></artwork>
        <t>The target user's URI is listed in the request path. KeyPackages
requested using this primitive <bcp14>MUST</bcp14> be sent via the hub provider of whatever
room they will be used in. (If this is not the case, the hub provider will be
unable to forward a Welcome message to the target provider).</t>
        <t>The path includes the target user. The request body includes the protocol
(currently just MLS 1.0), and the requesting user. When the request is being
made in the context of adding the target user to a room, the request <bcp14>MUST</bcp14> include
the room ID for which the KeyPackage is intended, as the target may have only
granted consent for a specific room.</t>
        <t>For MLS, the request includes a non-empty list of acceptable MLS ciphersuites,
and an MLS <tt>RequiredCapabilities</tt> object (which contains credential types,
non-default proposal types, and extensions) required by the requesting provider
(these lists can be an empty).</t>
        <t>The request body has the following form.</t>
        <sourcecode type="tls"><![CDATA[
struct {
    opaque uri<V>;
} IdentifierUri;

struct {
    Protocol protocol;
    IdentifierUri requestingUser;
    IdentifierUri targetUser;
    IdentifierUri roomId;
    select (protocol) {
        case mls10:
            CipherSuite acceptableCiphersuites<V>;
            RequiredCapabilities requiredCapabilities;
    };
} KeyMaterialRequest;
]]></sourcecode>
        <t>The response contains a user status code that indicates keying material was
returned for all the user's clients (<tt>success</tt>), that keying material was
returned for some of their clients (<tt>partialSuccess</tt>), or a specific user code
indicating failure. If the user code is success or partialSuccess, each client
is enumerated in the response. Then for each client with a <em>client</em> success
code, the structure includes initial keying material (a KeyPackage for MLS 1.0).
If the client's code is <tt>nothingCompatible</tt>, the client's capabilities are
optionally included (The client's capabilities could be omitted for privacy
reasons.)</t>
        <t>If the <em>user</em> code is <tt>noCompatibleMaterial</tt>, the provider <bcp14>MAY</bcp14> populate the
<tt>clients</tt> list. For any other user code, the provider <bcp14>MUST NOT</bcp14> populate the
<tt>clients</tt> list.</t>
        <t>Keying material provided from one response <bcp14>MUST NOT</bcp14> be provided in any other
response.
The target provider <bcp14>MUST NOT</bcp14> provide expired keying material (ex: an MLS
KeyPackage containing a LeafNode with a <tt>notAfter</tt> time past the current date
and time).</t>
        <sourcecode type="tls"><![CDATA[
enum {
    success(0);
    partialSuccess(1);
    incompatibleProtocol(2);
    noCompatibleMaterial(3);
    userUnknown(4);
    noConsent(5);
    noConsentForThisRoom(6);
    userDeleted(7);
    (255)
} KeyMaterialUserCode;

enum {
    success(0);
    keyMaterialExhausted(1),
    nothingCompatible(2),
    (255)
} KeyMaterialClientCode;


struct {
    KeyMaterialClientCode clientStatus;
    IdentifierUri clientUri;
    select (protocol) {
        case mls10:
            select (clientStatus) {
                case success:
                    KeyPackage keyPackage;
                case nothingCompatible:
                    optional<Capabilities> clientCapabilities;
            };
    };
} ClientKeyMaterial;

struct {
    Protocol protocol;
    KeyMaterialUserCode userStatus;
    IdentifierUri userUri;
    ClientKeyMaterial clients<V>;
} KeyMaterialResponse;
]]></sourcecode>
        <t>The semantics of the <tt>KeyMaterialUserCode</tt> are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>success</tt> indicates that key material was provided for every client of the
target user.</t>
          </li>
          <li>
            <t><tt>partialSuccess</tt> indicates that key material was provided for at least one
client of the target user.</t>
          </li>
          <li>
            <t><tt>incompatibleProtocol</tt> indicates that either one of providers supports the
protocol requested, or none of the clients of the target user support the
protocol requested.</t>
          </li>
          <li>
            <t><tt>noCompatibleMaterial</tt> indicates that none of the clients was able to
supply key material compatible with the <tt>requiredCapabilities</tt> field in the
request.</t>
          </li>
          <li>
            <t><tt>userUnknown</tt> indicates that the target user is not known to the target
provider.</t>
          </li>
          <li>
            <t><tt>noConsent</tt> indicates that the requester does not have consent to fetch
key material for the target user. The target provider can use this response
as a catch all and in place of other status codes such as <tt>userUnknown</tt> if
desired to preserve the privacy of its users.</t>
          </li>
          <li>
            <t><tt>noConsentForThisRoom</tt> indicates that the target user might have allowed
a request for another room, but does not for this room. If the provider
does not wish to make this distinction, it can return <tt>noConsent</tt> instead.</t>
          </li>
          <li>
            <t><tt>userDeleted</tt> indicates that the target provider wishes the requester to
know that the target user was previously a valid user of the system and has
been deleted. A target provider can of course use <tt>userUnknown</tt> if the
provider does wish to keep or specify this distinction.</t>
          </li>
        </ul>
        <t>The semantics of the <tt>KeyMaterialClientCode</tt> are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>success</tt> indicates that key material was provided for the specified
client.</t>
          </li>
          <li>
            <t><tt>keyMaterialExhausted</tt> indicates that there was no keying material
available for the specified client.</t>
          </li>
          <li>
            <t><tt>nothingCompatible</tt> indicates that the specified clients had no key
material compatible with the <tt>requiredCapabilities</tt> field in the request.</t>
          </li>
        </ul>
        <t>At minimum, as each MLS KeyPackage is returned to a requesting provider (on
behalf of a requesting IM client), the target provider needs to associate its
<tt>KeyPackageRef</tt> with the target client and the hub provider needs to associate
its <tt>KeyPackageRef</tt> with the target provider. This ensures that Welcome messages
can be correctly routed to the target provider and client. These associations
can be deleted after a Welcome message is forwarded or after the KeyPackage
<tt>leaf_node.lifetime.not_after</tt> time has passed.</t>
      </section>
      <section anchor="update-room-state">
        <name>Update Room State</name>
        <t>Adds, removes, and policy changes to the room are all forms of updating the
room state. They are accomplished using the update transaction which is used to
update the room base policy, participation list, or its underlying MLS group.
It uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /update/{roomId}
]]></artwork>
        <t>Any change to the participant list or room policy (including
authorization policy) is communicated via an <tt>AppSync</tt> proposal type
with the <tt>applicationId</tt> of <tt>mimiParticipantList</tt> or <tt>mimiRoomPolicy</tt>
respectively. When adding a user, the proposal containing the participant list
change <bcp14>MUST</bcp14> be committed either before or simultaneously with the corresponding
MLS operation.</t>
        <t>Removing an active user from a participant list or banning an active participant
likewise also happen simultaneously with any MLS changes made to the commit removing
the participant.</t>
        <t>A hub provider which observes that an active participant has been removed or
banned from the room, <bcp14>MUST</bcp14> prevent any of its clients from sending or
receiving any additional application messages in the corresponding MLS group;
<bcp14>MUST</bcp14> prevent any of those clients from sending Commit messages in that group;
and <bcp14>MUST</bcp14> prevent it from sending any proposals except for <tt>Remove</tt> and
<tt>SelfRemove</tt> <xref target="I-D.ietf-mls-extensions"/> proposals for its users in that group.</t>
        <t>The update request body is described below:</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  full(1),
  (255)
} RatchetTreeRepresentation;

struct {
  RatchetTreeRepresentation representation;
  select (representation) {
    case full:
      Node ratchet_tree<V>;
  };
} RatchetTreeOption;

struct {
  select (room.protocol) {
    case mls10:
      PublicMessage proposalOrCommit;
      select (proposalOrCommit.content.content_type) {
        case commit:
          /* Both the Welcome and GroupInfo omit the ratchet_tree */
          optional<Welcome> welcome;
          GroupInfo groupInfo;
          RatchetTreeOption ratchetTreeOption;
        case proposal:
          PublicMessage moreProposals<V>; /* a list of additional proposals */
      };
  };
} UpdateRequest;
]]></sourcecode>
        <t>For example, in the first use case described in the Protocol Overview, Alice creates a Commit
containing an AppSync proposal adding Bob (<tt>mimi://b.example/b/bob</tt>), and Add proposals for all
Bob's MLS clients.  Alice includes the Welcome message which will be sent for
Bob, a GroupInfo object for the hub provider, and complete <tt>ratchet_tree</tt>
extension.</t>
        <t>The response body is described below:</t>
        <sourcecode type="tls"><![CDATA[
enum {
  success(0),
  wrongEpoch(1),
  notAllowed(2),
  invalidProposal(3),
  (255)
} UpdateResponseCode;

struct {
  UpdateResponseCode responseCode;
  string errorDescription;
  select (responseCode) {
    case success:
      /* the hub acceptance time (in milliseconds from the UNIX epoch) */
      uint64 acceptedTimestamp;
    case wrongEpoch:
      /* current MLS epoch for the MLS group */
      uint64 currentEpoch;
    case invalidProposal:
      ProposalRef invalidProposals<V>;
  };
} UpdateRoomResponse
]]></sourcecode>
        <t>The semantics of the <tt>UpdatedResponseCode</tt> values are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>success</tt> indicates the <tt>UpdateRequest</tt> was accepted and will be distributed.</t>
          </li>
          <li>
            <t><tt>wrongEpoch</tt> indicates that the hub provider is using a different epoch. The
<tt>currentEpoch</tt> is provided in the response.</t>
          </li>
          <li>
            <t><tt>notAllowed</tt> indicates that some type of policy or authorization prevented the
hub provider from accepting the <tt>UpdateRequest</tt>.</t>
          </li>
          <li>
            <t><tt>invalidProposal</tt> indicates that at least one proposal is invalid. A list of
invalidProposals is provided in the response.</t>
          </li>
        </ul>
      </section>
      <section anchor="submit-a-message">
        <name>Submit a Message</name>
        <t>End-to-end encrypted (application) messages are submitted to the hub for
authorization and eventual fanout using an HTTP POST request.</t>
        <artwork><![CDATA[
POST /submitMessage/{roomId}
]]></artwork>
        <t>The request body is as follows:</t>
        <sourcecode type="tls"><![CDATA[
struct {
  Protocol protocol;
  select(protocol) {
    case mls10:
      /* PrivateMessage containing an application message */
      MLSMessage appMessage;
  };
} SubmitMessageRequest;
]]></sourcecode>
        <t>If the protocol is MLS 1.0, the request body is an MLSMessage with a WireFormat
of PrivateMessage (an application message).</t>
        <t>The response merely indicates if the message was accepted by the hub provider.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  accepted(0),
  notAllowed(1),
  epochTooOld(2),
  (255)
} SubmitResponseCode;

struct {
  Protocol protocol;
  select(protocol) {
    case mls10:
      SubmitResponseCode statusCode;
      select (statusCode) {
        case success:
          /* the hub acceptance time
             (in milliseconds from the UNIX epoch) */
          uint64 acceptedTimestamp;
        case epochTooOld:
          /* current MLS epoch for the MLS group */
          uint64 currentEpoch;
      };
  };
} SubmitMessageResponse;
]]></sourcecode>
        <t>The semantics of the <tt>SubmitResponseCode</tt> values are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>success</tt> indicates the <tt>SubmitMessageRequest</tt> was accepted and will be distributed.</t>
          </li>
          <li>
            <t><tt>notAllowed</tt> indicates that some type of policy or authorization prevented the
hub provider from accepting the <tt>UpdateRequest</tt>. This could include
nonsensical inputs such as an MLS epoch more recent than the hub's.</t>
          </li>
          <li>
            <t><tt>epochTooOld</tt> indicates that the hub provider is using a new MLS epoch
for the group. The <tt>currentEpoch</tt> is provided in the response.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>ISSUE:</strong> Do we want to offer a distinction between regular application
messages and ephemeral applications messages (for example "is typing"
notifications), which do not need to be queued at the target provider.</t>
          </li>
        </ul>
      </section>
      <section anchor="fanout-messages-and-room-events">
        <name>Fanout Messages and Room Events</name>
        <t>If the hub provider accepts an application or handshake message (proposal or
commit) message, it forwards that message to all other providers with active
participants in the room and all local clients which are active members.
This is described as fanning the message out. One can think of fanning a
message out as presenting an ordered list of MLS-protected events to the next
"hop" toward the receiving client.</t>
        <t>An MLS Welcome message is sent to the providers and local users associated with
the <tt>KeyPackageRef</tt> values in the <tt>secrets</tt> array of the Welcome. In the case
of a Welcome message, a <tt>RatchetTreeOption</tt> is also included in the
FanoutMessage.</t>
        <t>The hub provider also fans out any messages which originate from itself (ex: MLS
External Proposals).</t>
        <t>The hub can include multiple concatenated <tt>FanoutMessage</tt> objects relevant to
the same room. This endpoint uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /notify/{roomId}
]]></artwork>
        <sourcecode type="tls"><![CDATA[
struct {
  /* the hub acceptance time (in milliseconds from the UNIX epoch) */
  uint64 timestamp;
  select (protocol) {
    case mls10:
      /* A PrivateMessage containing an application message,
         a PublicMessage containing a proposal or commit,
         or a Welcome message.                               */
      MLSMessage message;
      select (message.wire_format) {
        case welcome:
          RatchetTreeOption ratchetTreeOption;
      };
  };
} FanoutMessage;
]]></sourcecode>
        <ul empty="true">
          <li>
            <t><strong>NOTE:</strong> Correctly fanning out Welcome messages relies on the hub and target
providers storing the <tt>KeyPackageRef</tt> of claimed KeyPackages.</t>
          </li>
        </ul>
        <t>A client which receives a <tt>success</tt> to either an <tt>UpdateRoomResponse</tt> or a
<tt>SubmitMessageResponse</tt> can view this a commitment from the hub provider that
the message will eventually be distributed to the group. The hub is not
expected to forward the client's own message to the client or its provider.
However, the client and its provider need to be prepared to receive the
client's (effectively duplicate) message. This situation can occur during
failover in high availability recovery scenarios.</t>
        <t>Clients that are being removed <bcp14>SHOULD</bcp14> receive the corresponding
Commit message, so they can recognize that they have been removed and clean up
their internal state. A removed client might not receive a commit if it was
removed as a malicious or abusive client, or if it obviously deleted.</t>
        <t>The response to a FanoutMessage contains no body. The HTTP response code
indicates if the messages in the request were accepted (201 response code), or
if there was an error. The hub need not wait for a response before sending the
next fanout message.</t>
        <t>If the hub server does not contain an HTTP 201 response code, then it <bcp14>SHOULD</bcp14>
retry the request, respecting any guidance provided by the server in HTTP header
fields such as Retry-After.  If a follower server receives a duplicate request
to the <tt>/notify</tt> endpoint, in the sense of a request from the same hub server
with the same request body as a previous <tt>/notify</tt> request, then the follower
server <bcp14>MUST</bcp14> return a 201 Accepted response.  In such cases, the follower server
<bcp14>SHOULD</bcp14> process only the first request; subsequent duplicate requests <bcp14>SHOULD</bcp14> be
ignored (despite the success response).</t>
        <ul empty="true">
          <li>
            <t><strong>NOTE:</strong> These deduplication provisions require follower servers to track
which request bodies they have received from which hub servers.  Since the
matching here is byte-exact, it can be done by keeping a rolling list of
hashes of recent messages.</t>
            <t>This byte-exact replay criterion might not be the right deduplication
strategy.  There might be situations where it is valid for the same hub server
to send the same payload multiple times, e.g., due to accidental collisions.</t>
            <t>If this is a concern, then an explicit transaction ID could be introduced.
The follower server would still have to keep a list of recently seen
transaction IDs, but deduplication could be done irrespective of the content
of request bodies.</t>
          </li>
        </ul>
      </section>
      <section anchor="claim-group-key-information">
        <name>Claim group key information</name>
        <t>When a client joins an MLS group without an existing member adding the
client to the MLS group, that is called an external join. This is useful
a) when a new client of an existing user needs to join the groups of all the
user's rooms. It can also be used b) when a client did not have key packages
available but their user is already in the participation list for the
corresponding room, c) when joining an open room, or d) when joining using
an external authentication joining code. In MIMI, external joins are
accomplished by fetching the MLS GroupInfo for a room's MLS group, and then
sending an external commit incorporating the GroupInfo.</t>
        <t>The GroupInfoRequest uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /groupInfo/{roomId}
]]></artwork>
        <t>The request provides an MLS credential proving the requesting client's real or
pseudonymous identity. This user identity is used by the hub to correlate this
request with the subsequent external commit. The credential may constitute
sufficient permission to authorize providing the GroupInfo and later joining
the group. Alternatively, the request can include an optional opaque joining
code, which the requester could use to prove permission to fetch the GroupInfo,
even if it is not yet a participant.</t>
        <t>The request also
provides a signature public key
corresponding to the requester's credential. It also specifies a CipherSuite
which merely needs to be one ciphersuite in common with the hub. It is
needed only to specify the algorithms used to sign the
GroupInfoRequest and GroupInfoResponse.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  Protocol protocol;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      SignaturePublicKey requestingSignatureKey;
      Credential requestingCredential;
      optional opaque joiningCode<V>;
  };
} GroupInfoRequestTBS;

struct {
  Protocol protocol;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      SignaturePublicKey requestingSignatureKey;
      Credential requestingCredential;
      opaque joiningCode<V>;
      /* SignWithLabel(., "GroupInfoRequestTBS", GroupInfoRequestTBS) */
      opaque signature<V>;
  };
} GroupInfoRequest;
]]></sourcecode>
        <t>If successful, the response body contains the GroupInfo and a way
to get the ratchet_tree.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  success(1),
  notAuthorized(2),
  noSuchRoom(3),
  (255)
} GroupInfoCode;

struct {
  Protocol version;
  GroupInfoCode status;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      opaque room_id<V>;
      ExternalSender hub_sender;
      GroupInfo groupInfo;   /* without embedded ratchet_tree */
      RatchetTreeOption ratchetTreeOption;
  };
} GroupInfoResponseTBS;

struct {
  Protocol version;
  GroupInfoCode status;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      opaque room_id<V>;
      ExternalSender hub_sender;
      GroupInfo groupInfo;   /* without embedded ratchet_tree */
      RatchetTreeOption ratchetTreeOption;
      /* SignWithLabel(., "GroupInfoResponseTBS", GroupInfoResponseTBS) */
      opaque signature<V>;
  };
} GroupInfoResponse;
]]></sourcecode>
        <t>The semantics of the <tt>GroupInfoCode</tt> are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>success</tt> indicates that GroupInfo and ratchet tree was provided as
requested.</t>
          </li>
          <li>
            <t><tt>notAuthorized</tt> indicates that the requester was not authorized to access
the GroupInfo.</t>
          </li>
          <li>
            <t><tt>noSuchRoom</tt> indicates that the requested room does not exist. If the hub
does not want to reveal if a room ID does not exist it can use
<tt>notAuthorized</tt> instead.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Consider adding additional failure codes/semantics for joining
codes (ex: code expired, already used, invalid)</t>
          </li>
        </ul>
        <t><strong>ISSUE</strong>: What security properties are needed to protect a
GroupInfo object in the MIMI context are still under discussion. It is
possible that the requester only needs to prove possession of their private
key. The GroupInfo in another context might be sufficiently sensitive that
it should be encrypted from the end client to the hub provider (unreadable
by the local provider).</t>
      </section>
    </section>
    <section anchor="relation-between-mimi-state-and-cryptographic-state">
      <name>Relation between MIMI state and cryptographic state</name>
      <section anchor="room-state">
        <name>Room state</name>
        <t>The state of a room consists of its room ID, its base policy, its
participant list (including the role and participation state of each
participant), and the associated end-to-end protocol state (its MLS group
state) that anchors the room state cryptographically.</t>
        <t>While all parties involved in a room agree on the room's state during a
specific epoch, the Hub is the arbiter that decides if a state change is valid,
consistent with the room's then-current policy. All state-changing events are
sent to the Hub and checked for their validity and policy conformance, before
they are forwarded to any follower servers or local clients.</t>
        <t>As soon as the Hub accepts an event that changes the room state, its effect is
applied to the room state and future events are validated in the context of that
new state.</t>
        <t>The room state is thus changed based on events, even if the MLS proposal
implementing the event was not yet committed by a client. Note that this only
applies to events changing the room state.</t>
      </section>
      <section anchor="cryptographic-room-representation">
        <name>Cryptographic room representation</name>
        <t>Each room is represented cryptographically by an MLS group. The Hub that
manages the room also manages the list of group members, i.e. the
list of clients belonging to users currently in the room.</t>
      </section>
      <section anchor="proposal-commit-paradigm">
        <name>Proposal-commit paradigm</name>
        <t>The MLS protocol follows a proposal-commit paradigm. Any
party involved in a room (follower server, Hub or clients) can send proposals
(e.g. to add/remove/update clients of a user or to re-initialize the group with
different parameters). However, only clients can send commits, which contain all
valid previously sent proposals and apply them to the MLS group state.</t>
        <t>The MIMI usage of MLS ensures that the Hub, all follower servers and the clients
of all active participants agree on the group state, which includes the client
list and the key material used for message encryption (although the latter is
only available to clients). Since the group state also includes a copy of the
room state at the time of the most recent commit, it is also covered by the
agreement.</t>
      </section>
      <section anchor="authenticating-proposals">
        <name>Authenticating proposals</name>
        <t>MLS requires that MLS proposals from the Hub and
from follower servers (external senders in MLS terminology) be authenticated
using key material contained in the <tt>external_senders</tt> extension of the MLS
group. Each MLS group associated with a MIMI room <bcp14>MUST</bcp14> therefore contain an
<tt>external_senders</tt> extension. That extension <bcp14>MUST</bcp14> contain at least the
Certificate of the Hub.</t>
        <t>When a user from a follower server becomes a participant in the room, the
Certificate of the follower server <bcp14>MAY</bcp14> be added to the extension. When the last
participant belonging to a follower server leaves the room, the certificate of
that user <bcp14>MUST</bcp14> be removed from the list. Changes to the <tt>external_senders</tt>
extension only take effect when the MLS proposal containing the event is
committed by a MIMI commit.</t>
      </section>
    </section>
    <section anchor="mls-application-state-synchronization">
      <name>MLS Application State Synchronization</name>
      <t><strong>TODO:</strong> This section should be moved to its own document in the MLS working group.</t>
      <t>One of the primary security benefits of MLS is that the MLS key schedule
confirms that the group agrees on certain metadata, such as the membership of
the group. Members that disagree on the relevant metadata will arrive at
different keys and be unable to communicate. Applications based on MLS can
integrate their state into this metadata in order to confirm that the members of
an MLS group agree on application state as well as MLS metadata.</t>
      <t>Here, we define two extensions to MLS to facilitate this application design:</t>
      <ol spacing="normal" type="1"><li>
          <t>A GroupContext extension <tt>application_states</tt> that confirms agreement on
application state from potentially multiple sources.</t>
        </li>
        <li>
          <t>A new proposal type AppSync that allows MLS group members to propose changes
to the agreed application state.</t>
        </li>
      </ol>
      <t>The <tt>application_states</tt> extension allows the application to inject state
objects into the MLS key schedule. Changes to this state can be made out of
band, or using the AppSync proposal. Using the AppSync proposal ensures that
members of the MLS group have received the relevant state changes before they
are reflected in the group's <tt>application_states</tt>.</t>
      <ul empty="true">
        <li>
          <t><strong>NOTE:</strong> This design exposes the high-level structure of the application state
to MLS.  An alternative design would be to have the application state be opaque
to MLS.  There is a trade-off between generality and the complexity of the API
between the MLS implementation and the application.  An opaque design would give
the application more freedom, but require the MLS stack to call out to the
application to get the updated state as part of Commit processing.  This design
allows the updates to happen within the MLS stack, so that no callback is
needed, at the cost of forcing the application state to fit a certain structure.
It also potentially can result in smaller state updates in large groups.</t>
        </li>
      </ul>
      <t>The state for Each <tt>applicationId</tt> in the <tt>application_states</tt> needs to conform
to one of four basic types: an ordered array, an unordered array, a map, or an
irreducible blob. This allows the AppSync proposal to efficiently modify a large
application state object.</t>
      <t>The content of the <tt>application_states</tt> extension and the <tt>AppSync</tt> proposal are
structured as follows:</t>
      <figure anchor="fig-app-state">
        <name>The `application_state` extension</name>
        <sourcecode type="tls"><![CDATA[
enum {
    irreducible(0),
    map(1),
    unorderedList(2),
    orderedArray(3),
    (255)
} StateType;

struct {
  opaque element<V>;
} OpaqueElement;

struct {
  opaque elementName<V>;
  opaque elementValue<V>;
} OpaqueMapElement;

struct {
  uint32 applicationId;
  StateType stateType;
  select (stateType) {
    case irreducible:
      OpaqueElement state;
    case map:
      OpaqueMapElement mapEntries<V>;
    case unorderedList:
      OpaqueElement unorderedEntries<V>;
    case orderedArray:
      OpaqueElement orderedEntries<V>;
  };
} ApplicationState;

struct {
  ApplicationState applicationStates<V>;
} ApplicationStatesExtension;
]]></sourcecode>
      </figure>
      <figure anchor="fig-app-sync">
        <name>The AppSync proposal type</name>
        <sourcecode type="tls"><![CDATA[
struct {
  uint32 index;
  opaque element<V>;
} ElementWithIndex;


struct {
  uint32 applicationId;
  StateType stateType;
  select (stateType) {
    case irreducible:
      OpaqueElement newState;
    case map:
      OpaqueElement removedKeys<V>;
      OpaqueMapElement newOrUpdatedElements<V>;
    case unorderedList:
      uint32 removedIndices<V>;
      OpaqueElement addedEntries<V>;
    case orderedArray:
      ElementWithIndex replacedElements<V>;
      uint32 removedIndices<V>;
      ElementWithIndex insertedElements<V>;
      OpaqueElement appenededEntries<V>;
  };
} AppSync;
]]></sourcecode>
      </figure>
      <t>The <tt>applicationId</tt> determines the structure and interpretation of the contents.
of an ApplicationState object. AppSync proposals
contain changes to this state, which the client uses to update the
representation of the state in <tt>application_states</tt>.</t>
      <t>A client receiving an AppSync proposal applies it in the following way:</t>
      <ul spacing="normal">
        <li>
          <t>Identify an <tt>application_states</tt> GroupContext extension which contains the
same <tt>application_id</tt> state as the AppSync proposal</t>
        </li>
        <li>
          <t>Apply the relevant operations (replace, remove, update, append, insert)
according to the <tt>stateType</tt> to the relevant parts of the ApplicationState
object in <tt>application_states</tt> extension.</t>
        </li>
      </ul>
      <t>An AppSync for an irreducible state replaces its <tt>state</tt> element with a new
(possibly empty) <tt>newState</tt>. An AppSync for a map-based ApplicationState first
removes all the keys in <tt>removedKeys</tt> and than replaces or adds the elements in
<tt>newOrUpdatedElements</tt>. An AppSync for an unorderedList ApplicationState first
removes all the indexes in <tt>removedIndices</tt>, then adds the elements in
<tt>addedEntries</tt>. Finally an AppSync for an orderedArray, replaces all the
elements (index-by-index) in <tt>replacedElements</tt>, the removes the elements in
<tt>removedIndices</tt> according to the then order of the array, then inserts all the
elements in <tt>insertedElements</tt> according to the then order of the array, then
finally appends the <tt>appendedEntries</tt> (in order). All indices are zero-based.</t>
      <t>Note that the <tt>application_states</tt> extension is updated directly by AppSync
proposals; a GroupContextExtensions proposal is not necessary. A proposal list
that contains both an AppSync proposal and a GroupContextExtensions proposal
is invalid.</t>
      <t>Likewise a proposal list in a Commit <bcp14>MAY</bcp14> contain more than one AppSync proposal,
but no more than one AppSync proposal per <tt>applicationId</tt>. The proposals are
applied in the order that they are sent in the Commit.</t>
      <t>AppSync proposals do not need to contain an UpdatePath. An AppSync proposal can
be sent by an authorized external sender.</t>
      <ul empty="true">
        <li>
          <t><strong>TODO:</strong> IANA registry for <tt>application_id</tt>; register extension and proposal types
as safe extensions</t>
        </li>
      </ul>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>The MIMI protocol incorporates several layers of security.</t>
      <t>Individual protocol actions are protected against network attackers with
mutually-authenticated TLS, where the TLS certificates authenticate the
identities that the protocol actors assert at the application layer.</t>
      <t>Messages and room state changes are protected end-to-end using MLS.  The
protection is "end-to-end" in the sense that messages sent within the group are
confidentiality-protected against all servers involved in the delivery of those
messages, and in the sense that the authenticity of room state changes is
verified by the end clients involved in the room.  The usage of MLS ensures that
the servers facilitating the exchange cannot read messages in the room or
falsify room state changes, even though they can read the room state change
messages.</t>
      <t>Each room has an authorization policy that dictates which protocol actors can
perform which actions in the room.  This policy is enforced by the hub server
for the room.  The actors for whom the policy is being evaluated authenticate
their identities to the hub server using the MLS PublicMessage signed object
format, together with the identity credentials presented in MLS.  This design
means that the hub is trusted to correctly enforce the room's policy, but this
cost is offset by the simplicity of not having multiple policy enforcement points.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <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="4" month="March" year="2024"/>
            <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-03"/>
        </reference>
        <reference anchor="RFC9420">
          <front>
            <title>The Messaging Layer Security (MLS) Protocol</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="B. Beurdouche" initials="B." surname="Beurdouche"/>
            <author fullname="R. Robert" initials="R." surname="Robert"/>
            <author fullname="J. Millican" initials="J." surname="Millican"/>
            <author fullname="E. Omara" initials="E." surname="Omara"/>
            <author fullname="K. Cohn-Gordon" initials="K." surname="Cohn-Gordon"/>
            <date month="July" 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="RFC" value="9420"/>
          <seriesInfo name="DOI" value="10.17487/RFC9420"/>
        </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="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="RFC7231">
          <front>
            <title>Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2014"/>
            <abstract>
              <t>The Hypertext Transfer Protocol (HTTP) is a stateless \%application- level protocol for distributed, collaborative, hypertext information systems. This document defines the semantics of HTTP/1.1 messages, as expressed by request methods, request header fields, response status codes, and response header fields, along with the payload of messages (metadata and body content) and mechanisms for content negotiation.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="7231"/>
          <seriesInfo name="DOI" value="10.17487/RFC7231"/>
        </reference>
        <reference anchor="RFC3986">
          <front>
            <title>Uniform Resource Identifier (URI): Generic Syntax</title>
            <author fullname="T. Berners-Lee" initials="T." surname="Berners-Lee"/>
            <author fullname="R. Fielding" initials="R." surname="Fielding"/>
            <author fullname="L. Masinter" initials="L." surname="Masinter"/>
            <date month="January" year="2005"/>
            <abstract>
              <t>A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource. This specification defines the generic URI syntax and a process for resolving URI references that might be in relative form, along with guidelines and security considerations for the use of URIs on the Internet. The URI syntax defines a grammar that is a superset of all valid URIs, allowing an implementation to parse the common components of a URI reference without knowing the scheme-specific requirements of every possible identifier. This specification does not define a generative grammar for URIs; that task is performed by the individual specifications of each URI scheme. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="66"/>
          <seriesInfo name="RFC" value="3986"/>
          <seriesInfo name="DOI" value="10.17487/RFC3986"/>
        </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="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="I-D.ietf-mls-extensions">
          <front>
            <title>The Messaging Layer Security (MLS) Extensions</title>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="23" month="October" year="2023"/>
            <abstract>
              <t>   This document describes extensions to the Messaging Layer Security
   (MLS) protocol.

Discussion Venues

   This note is to be removed before publishing as an RFC.

   Source for this draft and an issue tracker can be found at
   https://github.com/mlswg/mls-extensions.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mls-extensions-03"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="RFC8555">
          <front>
            <title>Automatic Certificate Management Environment (ACME)</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="J. Hoffman-Andrews" initials="J." surname="Hoffman-Andrews"/>
            <author fullname="D. McCarney" initials="D." surname="McCarney"/>
            <author fullname="J. Kasten" initials="J." surname="Kasten"/>
            <date month="March" year="2019"/>
            <abstract>
              <t>Public Key Infrastructure using X.509 (PKIX) certificates are used for a number of purposes, the most significant of which is the authentication of domain names. Thus, certification authorities (CAs) in the Web PKI are trusted to verify that an applicant for a certificate legitimately represents the domain name(s) in the certificate. As of this writing, this verification is done through a collection of ad hoc mechanisms. This document describes a protocol that a CA and an applicant can use to automate the process of verification and certificate issuance. The protocol also provides facilities for other certificate management functions, such as certificate revocation.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8555"/>
          <seriesInfo name="DOI" value="10.17487/RFC8555"/>
        </reference>
      </references>
    </references>
    <?line 1505?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>:</t>
        </li>
      </ul>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+19a3fbRpbg9/oVWOWcjeSQdOwk3TN2xmlZljva2LHXkic7
p09OCJKghDEJcABQMttx/5b9LfvL9j6rbgGgRMnumdmzow+2RAL1uHXrvh/D
4dA1ebPIHiV7L8sqS06KukmLJnmZ1XV6nhfn8EmTVeUqq9JJvsibTbL/8uTl
yUGyrvHbH8/OXp8maTFLXr443XPpZFJllzgYPPMVfJS8rsqmnJaLPTdNm+y8
rDaPkrqZOTcrp0W6hIlnVTpvhnnWzIfLfJkPV/LG8OuvXb2eLPO6zsui2azg
2ZPjs+dJ8kWSLuoSZsmLWbbK4J+i2Rske9ksb8oqTxf4x8nhU/ivrOC3N2fP
91yxXk6y6pGbwTIeuWlZ1FlRr+tHSVOtMwdr/salVZbCqIer1SKH1cKsNW3t
TZYuhmf5MttzV2X17rwq16vdAbbn3mUbeG/2yCXDBLeI/+fhqUWWLPVt/Gp6
kTb4f51N15X97jIr1rD2JLn1CpKE4bf3C6wfH/kzjoCfL9N8AZ/jsv6EZzAq
q3P8PK2mF/D5RdOs6kf37+Nj+FF+mY30sfv4wf1JVV7V2X0c4D6+eJ43F+sJ
vDrJ5+uKwXi/e7r46AKOom7MLOaVEY8zysuel+8zzlSABk1ZxN+NLpoljO7S
dXNRVghzmClJ5uvFgvHtTQ4ArmbJi1HyNK2KrKbvYT9pkf+V5n6UHOX1tKTP
MwZQtZj8KV9djur33QFfpk1zkV0lP5az87oseoY7u8jwqSp/j3BLnpfrYkZf
JUejk9HRyM605NH+tPTPd2f8qSyqdAb/XQD03/VM+PqizIr8ffLmvz+zY7+j
90bv+L0/wRrS+qLKi2w0y3oAVV6kBaz7YtMzw9sinc8Bu+AIZxGg8CVCkT+d
4yejabnsDn1WpZd5nbzhA/xEiDU0WHUtxN6kq4s0W8CegAg0u0OMNlLxyxW9
SxtyRVnBdHAbHjmXF3Pz13A4TNJJDYuaNs6dXcA2gdStl0CjknqVTfN5ntVJ
g/u7FcF1MGJRr8qqSRTVB8nVBSAzUMMF3EGgyFlVJ+U8meXzeVbhhJ524DuX
+QwfaEoXiE+TASViekJ0p072q7Jc1gcD+Hy6WM/w3aYEWgR0EGlhlU0z2KiM
nNUDV8NtyhJ8K1mVQDg3A3ownc2SVVo1+TRfwQZxXhlgWcL70VfzCl6meUcO
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
q0ofYlwE4CjRzl+yxZQ9E2zIRY8acJO6NZaPflqRWR3OlS/5cOjXCM/IEgfR
epvSxUjr3JPk3r2fX50dP7p3j504WRK5TYibkuuEXI4hFIK5kHpyKL5kit/C
iPBhU5HQJKpFxKZ/ET8tHAZdWrLMo5TBzohCmDUcKPBvJFdPkjpfomUBHaTW
JOFpLf/o7pPo76f+b9GB7jmyOcRy8E1/7/zOKaJ08tPrerd3vv9b9PPVnd95
k/3bGuGFM++2n6/iYZ78ntyHq/RSb9JOMGiZXJ7cCm4Pv/46efXTjfMQLL9v
WXT63mnDZQcY3B4PnGLR8Ing16ME5Gs5dnNPf/3V46c+ekiPVuakhPDiw/KI
Gfb1q9Oz+Ex+Cr/LeTv/9D/Dx/ONldLQiCriKDNHJo5mkeHtl2n1DlbWrCuU
QHFpKYWe4fczWqaSReDi+prZl5xltECKW9OH4Zk3gVoy+av5opyX5PlQ+SdA
QuFHYMMnAUzWkpdOhu9WQ4lIYq2Pd/4cP2oxlsDjxFhCNr7/OGLC/F/MMXe8
sLvMQz+HUwzWgJOES45OZUCUa95pX6TPcsmFuw2SMzQP9b7TvuTt/e4A67u8
03PJXUC911W2QmnHyGsqkO1/BQh1MEBh6t6Wy66n7HdP6Rwnxbz8YZC8SRFN
GwTID4YEtO4yz0WzsNxF8aas2ksQoX/Rq1G1lybYbmB0zZ9eo36IUX76zFba
w6jSr4hxuPGHsLNoNx8DaXkDkvs5WrdFRdGFIXmKhFUSZP34gcjoVSOA9k/X
JQwYahXRhMMe1SbIqN6CKt+ihM6ZN0glUEHCV0k9YnNupCBtVy+uMMIlmQDi
cMIVRwRNsmmKIAx0muNcJCJeDSfWIoKCE2oW8TJIP6+zLJLbpmQHYjM6yrck
nKL9FFUzlLTqZD9QRuEKrH4wVgGoJLSZNEUy+WAoGwZbwxOohtplBpmflKC6
HCQFxrsJlUeMrdQgDPinlNR6snA4DjdUw5HSXxI9Oa6vDOHOvGG5kgJuPhfU
l+m3IOUacRi5GkVMkXexukqrmapRipb+4aMeWfNpzB4CO+hnF0f+b3796E7s
okOe7jrGLWXT9t93kVV3GuOWsmv7751k2U+XbT+rrPspsu/fQxa+zV52HsMp
1itjObpJVn76IBarr5WVrfx5C1n50Kzm7iI2ruTzCtjeSCYvHf29xWu/thtH
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
ocTWq7popmEF1rNncj/5nnVRox00fWMTDjK0BacuswmyLLltKW5cwhZepmon
wdFKQGKrLVmmJD15xNHQkXaC91YsbZZxAKRGyasiI98SOkHe4a3SJ1NnnktS
X0lDuC4VqYWxVX3FWg6+UgILHt4ejY053N5FucIaIBS5yyipRi71xrhDvkw9
VnZ1s1qvIB8vg4VNQqaGhU8abjsZhJ4JhMdA5asMQ6LSqkp90VpZAZW8bSQ0
mYPDW2tDVXPcsRaMubNSXbYzWRwjqOCnSbQMyIhvwRnUDPZiEy6QWCZ9YQEi
Zpysz1FTGDLlS0t5mfTATIMnrd1NQrnlskBCVBDcxtEKNdIWXU6L7JLJBBd6
wLI27KwV54ykEO1muG9lHfgMirbo+Hl0TGGXjWXM22KKegXQw1uLoIPArVsp
ZHEom6En2qEmvFn2+JxGyfU/faLvMsi9VoDSEa9ATP2NU5o6kpTYzqzAcgvj
WBBGIrQSIUSLHyEjOvJ+OyVAiP9tLx+iIVXVKQJa+CI9LhAGzFH2DL5FANCL
jokhcTIrOQI0lJUumqSpoiEsSDqYZ8juEnT/dLV+8uSkri0C6Zd4/9DWxh54
rdhBaUkeeyNygFzERdI+Ck2q1wG0YvlJSaSRDXA4joJx2fsVk2eTQxGCd6RR
ViuVIuRSouU9cNsfQT67VB+U8f3apyzzXnHhP8kcI8gSQfRz73P+Jnm7ktla
2nEdBLTnHMkc9u2TC8spCD7wMJ61w8Bn6s8MdOEiP7/QOuJc1AUznSkWrAbp
LK3yEk/cN9Qlvb/KpKiP+nNOf3z19sUzu9yWCyx2lQw4VTLbSAyKdDP28p3k
VUQuI3ZDZxgAtMJzziuuXUHlSNg9e+gfFjBznA0XAeOV+dIvOfqVJMDc95lK
k2UK0MRYFMLOCciVl3po7Iml18qJxqtoHEpLE6Vog+gih4D6oiRVeGRr6fmg
+xCh3lFf61YMBKeIez1h/+HXD+KRKAre8SAS/IEJGGjPDAhPiEfxQmmuSSvB
fMuOTvVXIRZS6zAxkiw9czbCoiQS+zgkLS2ntpTOMqXuHszOWIQR/1WUVzJI
1MErTrPzdT4j9uaFd9HmtbqHzMWV2BxFkARF5A2OP6QoaC4SmIqy5psWW4rm
L5iuxsl9HwtrDnnM3qOAKlAWhZMEokXiQABU8ICznGCNJYSRGhxl5vNgaTRb
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

-->

</rfc>
