<?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.7 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ralston-mimi-protocol-02" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.20.0 -->
  <front>
    <title abbrev="MIMI+MLS Protocol">More Instant Messaging Interoperability (MIMI) using HTTPS and MLS</title>
    <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-protocol-02"/>
    <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="March" day="04"/>
    <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-ralston-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="23" month="October" year="2023"/>
            <abstract>
              <t>   The More Instant Messaging Interoperability (MIMI) working group is
   defining a suite of protocols that allow messaging providers to
   interoperate with one another.  This document lays out an overall
   architecture enumerating the MIMI protocols and how they work
   together to enable an overall messaging experience.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-barnes-mimi-arch-02"/>
        </reference>
        <reference anchor="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:
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
Kq5qhGSk2zQb1G5wK1zohr/AGWd2NqeLoZDBkCrWAz4T7KVhVIrBmHlZYu2Z
2sHAlGv8N/A4wetHDz8ji2N2+dof0qeO1SPye1vm7dcV/9xVzP+cov3nFAt3
E+FjGf7asW4ttt9ijzf+3Y9Dn1Ps/5yi3d3GYtPPPm61Pvi0sbac1W3G0pv1
SXvcEXd3W5dcphvWvZPo/zfFVX/dPnmsu+BqUEt3U8+jscT62Dm3DryC7b4z
1i29yVvUsDupWv82d7vH3s9y1L2BN/YPMdhri5G//fCdbfntgfrt+fxUHabr
te0/ZtHl85r4A9lWleiB14nYNRzounfrt1XgiCzeyjXSVYyvA+c238jRRTZ9
h0mrJNgL4vvihv+6ztZW4HtMse2rvviBfkDewadwy0PY4o940OuPCErrwxu+
b72f7HO9VY1BO4gdGENWV4wHo6Wqxl4JilrjgleseTj3EnP6ODCMS39hTgam
tGrkVjlvMlDF1gWVXANhOeTXivbi9k1VOSzFdlEWlDFH+bONaC+k3q0b2MKI
w+i0tJTPfIRliYF+kJiqflTwp9a6U5hEKaW4SKWKdDlbPND5JDgq9ICqnFbW
ykLZPasfUY401wIsuMpnVAMJpyRlVFLHcBz9rL3S86xhxUVKNPpbRUVDxxVf
rF8buFljrfBHKays5x2/l0K8ggdWDcMlnrw8GThVobhuKFWIMnpoXEfUzz/g
ZEJWNAHEpFerW4Tq+1ByNQD6EsuYC7ThHVAdrY5GwJXdS+aluoEQu+SpfUHq
rw/8mUXnpTuvsjkaADB6chNOpMmc8evwlOI903EDxENZTO+Rk/0KcN15VnAV
5x4Aq2tThsXSat3deBV52/l0Sj6GpDM4dy/7xUmrbW0TNsU//884oii86G8w
rj/EzztuV9s9txN9LkP+b3fUfK+Dw5f22092cDU+YoY+a0mndx63Jal+Pny4
6zg3jetv82ce95bpJTuO+7msNTfB9z8dtNusO/1a2o3j3nAv/mM5znZ5746O
6tZzN1u8tsH70+jD/z+O6l3x9Xbj/ts5qu+yXi9MxVqvBrN35PLr1FsvHhhN
sB371rIOeFGOCuxGJUmsIEwutm0qbXJ1v2edVKWe1Qdi4B0F8mvaqBGAic0H
O8DXwb7SFmNNCGUbcMrLPot54DZxk2oZqJPLdJFzYxUP3Sj6/ybbQBtE7d1T
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

-->

</rfc>
