<?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.19 (Ruby 3.3.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-mimi-protocol-02" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.23.2 -->
  <front>
    <title abbrev="MIMI+MLS Protocol">More Instant Messaging Interoperability (MIMI) using HTTPS and MLS</title>
    <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-protocol-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="October" day="21"/>
    <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 103?>

<t>This document specifies the More Instant Messaging Interoperability (MIMI)
transport protocol, which allows users of different messaging providers to
interoperate in group chats (rooms), including to send and receive messages,
share room policy, and add participants to and remove participants from rooms.
MIMI describes messages between providers, leaving most aspects of the
provider-internal client-server communication up to the provider.  MIMI
integrates the Messaging Layer Security (MLS) protocol to provide end-to-end security
assurances, including authentication of protocol participants, confidentiality
of messages exchanged within a room, and agreement on the state of the room.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://bifurcation.github.io/ietf-mimi-protocol/draft-ralston-mimi-protocol.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ietf-mimi-protocol/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        More Instant Messaging Interoperability Working Group mailing list (<eref target="mailto:mimi@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/mimi/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/mimi/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/bifurcation/ietf-mimi-protocol"/>.</t>
    </note>
  </front>
  <middle>
    <?line 115?>

<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>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 for end-to-end security, using the MLS AppSync proposal type to
efficiently synchronize room state across the clients involved in a room
<xref target="RFC9420"/> <xref target="I-D.barnes-mls-appsync"/>. 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 protocol, it is necessary to have consent (see <xref target="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="I-D.barnes-mls-appsync"/>) 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}",
  "requestConsent":
     "https://mimi.example.com/v1/requestConsent/{targetUser}",
  "updateConsent":
     "https://mimi.example.com/v1/updateConsent/{requesterUser}",
  "identifierQuery":
     "https://mimi.example.com/v1/identifierQuery/{domain}",
  "reportAbuse":
     "https://mimi.example.com/v1/reportAbuse/{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, using the
<tt>RatchetTreeOption</tt> and <tt>PartialGroupInfo</tt> structs defined in
<xref target="I-D.mahy-mls-ratchet-tree-options"/>:</t>
        <sourcecode type="tls"><![CDATA[
struct {
  /* A Proposal or Commit which is either a PublicMessage; */
  /* or a SemiPrivateMessage                               */
  MLSMessage proposalOrCommit;
  select (proposalOrCommit.content.content_type) {
    case commit:
      /* Both the Welcome and GroupInfo omit the ratchet_tree */
      optional<Welcome> welcome;
      GroupInfoOption groupInfoOption;
      RatchetTreeOption ratchetTreeOption;
    case proposal:
      /* a list of additional proposals, each represented */
      /* as either PublicMessage or SemiPrivateMessage    */
      MLSMessage moreProposals<V>;
} HandshakeBundle;

enum {
  reserved(0),
  full(1),
  partial(2),
  (255)
} GroupInfoRepresentation;

struct {
   GroupInfoRepresentation representation;
   select (representation) {
     case full:
       GroupInfo groupInfo;
     case partial:
       PartialGroupInfo partialGroupInfo;
   }
} GroupInfoOption;

struct {
  select (room.protocol) {
    case mls10:
      HandshakeBundle bundle;
  };
} UpdateRequest;
]]></sourcecode>
        <t>The semantics of <tt>GroupInfoRepresentation</tt> are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>full</tt> means that the entire GroupInfo will be included.</t>
          </li>
          <li>
            <t><tt>partial</tt> means that a <tt>PartialGroupInfo </tt> struct will be shared and
 that the Distribution Service is expected to reconstruct the GroupInfo
 as described in <xref target="I-D.mahy-mls-ratchet-tree-options"/>.</t>
          </li>
        </ul>
        <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>A handshake message could be sent by the client as an MLS
<tt>PublicMessage</tt> (which is visible to all providers), or as an MLS
<tt>SemiPrivateMessage</tt> <xref target="I-D.mahy-mls-semiprivatemessage"/> encrypted
for the members and the hub provider as the sole <tt>external_receiver</tt>.
(The contents and sender of a <tt>SemiPrivateMessage</tt> would not be visible to
other providers). The use of <tt>SemiPrivateMessage</tt> allows the Hub to
accomplish its policy enforcement responsibilities without the other
providers being aware of the membership of non-local users.</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;
      IdentifierURI sendingUri;
  };
} SubmitMessageRequest;
]]></sourcecode>
        <t>If the protocol is MLS 1.0, the request body (<tt>appMessage</tt>) is an MLSMessage
with a WireFormat of PrivateMessage, and a <tt>content_type</tt> of <tt>application</tt>.
The <tt>sendingUri</tt> is a valid URI of the sender and is an active participant
in the room.</t>
        <t>The response indicates if the message was accepted by the hub provider. If a
<tt>frankingTag</tt> was included in the <tt>FrankAAD</tt> extension in the PrivateMessage
Additional Authenticated Data (AAD) in the request, the server attempts to
frank the message and includes the <tt>serverFrank</tt> in a successful response
(see the next subsection).</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;
          optional uint8[32] serverFrank;
        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 anchor="message-franking">
          <name>Message Franking</name>
          <t>Franking is the placing of a cryptographic "stamp" on a message. In the
MIMI context, the Hub is able to mark that it received a message without
learning the message content. A receiver that decrypts the message can use
a valid frank to prove it was received by the Hub and that the content was
sent by a specific sender. Outsiders (including follower providers) never
learn the content of the message, nor the sender.</t>
          <t>Franking was popularized by Facebook and described in their whitepaper
<xref target="SecretConversations"/> about their end-to-end encryption system. This
franking mechanism is largely motivated by that solution with two
significant changes as discussed in the final paragraph of this section.</t>
          <section anchor="client-creation-and-sending">
            <name>Client creation and sending</name>
            <t>When ready to send an application message with the MIMI content format,
the sender generates a new cryptographically random 256-bit <tt>franking_key</tt>.
An example mechanism to generate the <tt>franking_key</tt> safely is discussed in
<xref target="example-franking-alg"/>.</t>
            <t>Next the sender attaches to the message the <tt>franking_key</tt> and any other
fields the sender wishes to commit that are not otherwise represented in the
content. For a MIMI content object, the sender creates a CBOR "FrankingAssertion" map containing the <tt>franking_key</tt>, sender URI, and room
URI. It adds this FrankingAssertion to the extensions map at the top level
of the MIMI content using the integer key TBD1.</t>
            <sourcecode type="cbor-diag"><![CDATA[
/ FrankingAssertion map /
{
  / FrankingKey    / 1: h'9c8af7674941aa95f8df37bd36ea89f2
                          a3ab433aa5baa8e5e465f08a7e8e3b57',
  / SenderURI      / 2: "mimi://b.example/u/alice",
  / RoomURI        / 3: "mimi://hub.example/r/Rl33FWLCYWOwxHrYnpWDQg",
}
]]></sourcecode>
            <t>Note that this assertion does not vouch for the validity of these values,
it just means that the sender is claiming it sent the values in the content,
and cannot later deny to a receiver that it sent them.</t>
            <t>Then the client calculates the <tt>franking_tag</tt>, as the HMAC SHA256 of the
<tt>application_data</tt> (which includes the FrankingAssertion extension), using the <tt>franking_key</tt>:</t>
            <artwork><![CDATA[
franking_tag = HMAC_SHA256( franking_key, application_data)
]]></artwork>
            <t>The client includes the <tt>franking_tag</tt> in the Additional Authenticated Data
of the MLS PrivateMessage using the Safe Extension <tt>FrankAAD</tt>. The client
uses the MIMI submitMessage to send its message, and also asserts a sender
identity to the Hub, which could be a valid pseudonym, and needs to match
the sender URI value embedded in the message. If the message is accepted,
the response includes the accepted timestamp and the serverFrank (generated
by the server).</t>
          </section>
          <section anchor="hub-processing">
            <name>Hub processing</name>
            <t>The Hub relies on a per-epoch secret shared among the members of the group
and itself to obfuscate the message metadata (the <tt>context</tt>) the Hub uses
while franking. It derives the <tt>franking_context_secret</tt> (with the label
"franking_context") from the <tt>ap_exporter_secret</tt> in the Associated Party
Key Schedule <xref target="I-D.kohbrok-mls-associated-parties"/>.</t>
            <figure anchor="extended-ap-key-schedule">
              <name>The Extended Associated Party Key Schedule</name>
              <artset>
                <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="520" viewBox="0 0 520 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                    <path d="M 56,32 L 56,80" fill="none" stroke="black"/>
                    <path d="M 56,112 L 56,208" fill="none" stroke="black"/>
                    <path d="M 56,240 L 56,288" fill="none" stroke="black"/>
                    <path d="M 312,176 L 312,208" fill="none" stroke="black"/>
                    <path d="M 56,144 L 224,144" fill="none" stroke="black"/>
                    <polygon class="arrowhead" points="320,208 308,202.4 308,213.6" fill="black" transform="rotate(90,312,208)"/>
                    <polygon class="arrowhead" points="232,144 220,138.4 220,149.6" fill="black" transform="rotate(0,224,144)"/>
                    <polygon class="arrowhead" points="64,288 52,282.4 52,293.6" fill="black" transform="rotate(90,56,288)"/>
                    <polygon class="arrowhead" points="64,208 52,202.4 52,213.6" fill="black" transform="rotate(90,56,208)"/>
                    <polygon class="arrowhead" points="64,80 52,74.4 52,85.6" fill="black" transform="rotate(90,56,80)"/>
                    <g class="text">
                      <text x="48" y="36">.</text>
                      <text x="64" y="36">.</text>
                      <text x="64" y="100">ap_epoch_secret</text>
                      <text x="296" y="148">DeriveSecret(.,</text>
                      <text x="420" y="148">"ap_exporter")</text>
                      <text x="240" y="164">=</text>
                      <text x="324" y="164">ap_exporter_secret</text>
                      <text x="64" y="228">DeriveSecret(.,</text>
                      <text x="160" y="228">"init")</text>
                      <text x="296" y="228">DeriveSecret(.,</text>
                      <text x="440" y="228">"franking_context")</text>
                      <text x="240" y="244">=</text>
                      <text x="344" y="244">franking_context_secret</text>
                      <text x="64" y="308">init_secret_[n]</text>
                    </g>
                  </svg>
                </artwork>
                <artwork type="ascii-art"><![CDATA[
         ...
          |
          |
          V
    ap_epoch_secret
          |
          |
          +--------------------> DeriveSecret(., "ap_exporter")
          |                      = ap_exporter_secret
          |                               |
          |                               |
          V                               V
    DeriveSecret(., "init")      DeriveSecret(., "franking_context")
          |                      = franking_context_secret
          |
          |
          V
    init_secret_[n]
]]></artwork>
              </artset>
            </figure>
            <t>When the Hub receives an acceptable application message with the <tt>FrankAAD</tt>
AAD extension and a valid sender identity, it calculates a server frank for
the message as follows:</t>
            <artwork><![CDATA[
context = senderURI || roomURI || acceptedTimestamp
serverFrank = HMAC_SHA256(HUBkey, franking_tag || context )
franking_context_hash = SHA256(franking_context_secret || context)
]]></artwork>
            <t><tt>HUBkey</tt> is a secret symmetric key used on the Hub which the Hub can use to verify its own tags.</t>
            <t>The Hub fans out the encrypted message (which includes the <tt>franking_tag</tt>),
the <tt>serverFrank</tt>, the <tt>acceptedTimestamp</tt>, the room URI, and the
<tt>franking_context_hash</tt>. Note that the <tt>senderURI</tt> is not included in the
application message, so the sender can remain anonymous with respect to
follower providers.</t>
          </section>
          <section anchor="receiver-verification-of-frank">
            <name>Receiver verification of frank</name>
            <t>When a client receives and decrypts an otherwise valid application message
from a hub provider, the client looks for the existence of a frank
(consisting of the <tt>franking_tag</tt> in the AAD, the <tt>serverFrank</tt> and the
<tt>franking_context_hash</tt>. If so, it derives the <tt>franking_context_secret</tt>
from the <tt>ap_exporter_secret</tt> in the Associated Party Key Schedule
<xref target="I-D.kohbrok-mls-associated-parties"/>; then it verifies the construction of
the <tt>franking_tag</tt> from the content of the message, and the construction of
the <tt>franking_context_hash</tt> from the sender URI, room ID,
<tt>acceptedTimestamp</tt>, and <tt>franking_context_secret</tt>.</t>
            <t>The receiving client receives a sender identifier in three different locations. The receiver verifies that they are all the same:</t>
            <ul spacing="normal">
              <li>
                <t>the sender's identity in its credential in its MLS LeafNode</t>
              </li>
              <li>
                <t>the sender's identity asserted in the FrankingAssertion map inside the MIMI Content</t>
              </li>
              <li>
                <t>the (hidden) sender's identity in the context used to create the <tt>serverFrank</tt>. The client hashes the concatenation of the sender's identity, the room ID, and the acceptedTimestamp. If this hash matches the context_validation hash, then the identity used by the server was correct.</t>
              </li>
            </ul>
            <t>The receiver needs to store the frank with the decoded message so it can be
used later.</t>
          </section>
          <section anchor="comparison-with-the-facebook-franking-scheme">
            <name>Comparison with the Facebook franking scheme</name>
            <t>Unlike in the Facebook franking scheme <xref target="SecretConversations"/>, the sender
"commits to" its <tt>franking_tag</tt> as Additional Authenticated Data (AAD) inside the end-to-end encrypted message, and the hub only sends a hash of
its context. This first change insures that the client cannot come up with
another <tt>franking_key</tt> and message that has the same <tt>franking_tag</tt>
              <xref target="Grubbs2017"/><xref target="InvisibleSalamanders"/>. According to <xref target="Grubbs2017"/>,
"... [Facebook's] franking scheme does not bind [the franking tag] to [the
ciphertext] by including [the franking tag] in the associated data during
encryption".
The second change allows receivers to validate the sender URI in the hub's
context, without revealing the sender URI to follower providers.</t>
          </section>
        </section>
      </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>
(see Section 3 of <xref target="I-D.mahy-mls-ratchet-tree-options"/>) 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 {
  uint8[32] franking_tag;
  uint8[32] serverFrank;
  uint8[32] franking_context_hash;
} Frank;

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 application:
           optional Frank frank;
        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 as 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;
      HPKEPublicKey groupInfoPublicKey;
      optional opaque joiningCode<V>;
  };
} GroupInfoRequestTBS;

struct {
  Protocol protocol;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      SignaturePublicKey requestingSignatureKey;
      Credential requestingCredential;
      HPKEPublicKey groupInfoPublicKey;
      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, both encrypted with the <tt>groupInfoPublcKey</tt>
passed in the request.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  success(1),
  notAuthorized(2),
  noSuchRoom(3),
  (255)
} GroupInfoCode;

struct {
  GroupInfo groupInfo;   /* without embedded ratchet_tree */
  RatchetTreeOption ratchetTreeOption;
} GroupInfoRatchetTreeTBE;

GroupInfoRatchetTreeTBE group_info_ratchet_tree_tbe;

encrypted_groupinfo_and_tree = EncryptWithLabel(
  groupInfoPublicKey,
  "GroupInfo and ratchet_tree encryption",
  room_id,                         /* context */
  group_info_ratchet_tree_tbe)

struct {
  Protocol version;
  GroupInfoCode status;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      opaque room_id<V>;
      ExternalSender hub_sender;
      opaque encrypted_groupinfo_and_tree<V>;
  };
} GroupInfoResponseTBS;

struct {
  Protocol version;
  GroupInfoCode status;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      opaque room_id<V>;
      ExternalSender hub_sender;
      opaque encrypted_groupinfo_and_tree<V>;
      /* 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 anchor="convey-explicit-consent">
        <name>Convey explicit consent</name>
        <t>As discussed in <xref target="consent"/>, there are many ways that a provider could
implicitly determine consent. This section describes a mechanism by which providers can explicitly request consent from a user of another provider,
cancel such a request, convey that consent was granted, or convey that
consent was revoked or preemptively denied.</t>
        <t>Since they are not necessarily in the context of a room, consent requests
are sent directly from the provider of the user requesting consent, to the
provider of the target user. (There is no concept of a hub outside of the
context of a room.)</t>
        <artwork><![CDATA[
POST /requestConsent/{targetDomain}
POST /updateConsent/{requesterDomain}
]]></artwork>
        <t>A <tt>requestConsent</tt> request is used by one provider to request explicit
consent from a target user at another provider to fetch the target's
KeyPackages (which is a prerequisite for adding the target to a group); or
to cancel that request.
The request body is a <tt>ConsentEntry</tt>, with a <tt>consentOperation</tt> of <tt>request</tt>
or <tt>cancel</tt> respectively. It includes the URI of requesting user in the
<tt>requesterUri</tt> and the target user URI in the <tt>targetUri</tt>. If consent is only
requested for a single room, the requester includes the <tt>roomId</tt>. The
combination of the <tt>requesterUri</tt>, <tt>targetUri</tt>, and optional <tt>roomId</tt>
represents the <tt>ConsentScope</tt>. A <tt>cancel</tt> <bcp14>MUST</bcp14> use the same <tt>ConsentScope</tt>
as a previous <tt>request</tt>.</t>
        <t>For a <tt>requestContent</tt>, the <tt>targetUri</tt> needs to be in one of the domains of
the receiving provider, and the <tt>requesterUri</tt> needs to be in one of the
domains of the sending provider.</t>
        <t>The response to a <tt>requestConsent</tt> request is usually a 201 Accepted
(indicating the <tt>requestConsent</tt> was received), optionally a 404 Not Found
(indicating the <tt>targetUri</tt> is unknown), or a 500-class response. The
201 response code merely indicates that the request was received. A provider
that does not wish to reveal if a user is not found can respond with a 201
Accepted. Likewise in response to a <tt>cancel</tt> which has no <tt>request</tt> matching the
<tt>ConsentScope</tt>, a 201 Accepted is sent and no further action is taken.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  cancel(0),
  request(1),
  grant(2),
  revoke(3),
  (255)
} ConsentOperation;

struct {
  ConsentOperation consentOperation;
  IdentifierUri requesterUri;
  IdentifierUri targetUri;
  optional<RoomId> roomId;
  select (consentOperation) {
      case grant:
          KeyPackage clientKeyPackages<V>;
  };
} ConsentEntry;

struct {
  IdentifierUri requesterUri;
  IdentifierUri targetUri;
  optional<RoomId> roomId;
} ConsentScope;
]]></sourcecode>
        <t>An <tt>updateConsent</tt> request is used by one provider to provide explicit
notice from a target user at one provider that consent for a specific
"requester" was granted, revoked, or preemptively denied. In this context,
the requester is the party that will later request KeyPackages for the target. The request body is
a <tt>ConsentEntry</tt>, with a <tt>consentOperation</tt> of <tt>grant</tt> (for a grant), or
<tt>revoke</tt> for revocation or denial. Like a request, it includes the URI of the
"requesting user" in the <tt>requesterUri</tt> and the target user URI in the
<tt>targetUri</tt>. If consent is only granted or denied for a single room, the request includes the optional <tt>roomId</tt>.</t>
        <t>A <tt>grant</tt> or <tt>revoke</tt> does not need to be in response to an explicit request, nor does the <tt>ConsentScope</tt> need to match a previous <tt>request</tt> for the same <tt>targetUri</tt> and <tt>requesterUri</tt> pair.</t>
        <t>For example, in some systems there is a notion of a bilateral connection
request. The party that initiates the connection request (for example Alice)
would send a <tt>requestConsent</tt> for the target (ex: Bob), and send an
unsolicited <tt>updateConsent</tt> with Bob as the "requestor" and itself (Alice)
as the target.</t>
        <t>In a <tt>grant</tt>, the sender includes a list of <tt>clientKeyPackages</tt> for the
target user, which can be empty. For the case of a bilateral connection,
a grant of consent with a matching <tt>ConsentScope</tt> often results in an
immediate Add to a group. If the list is non-empty this reduces the
number of messages which need to be sent.</t>
        <t>For <tt>updateConsent</tt> the <tt>requesterUri</tt> needs to be in one of the domains of
the receiving provider, and the <tt>targetUri</tt> needs to be in one of the
domains of the sending provider.</t>
        <t>The response to an <tt>updateConsent</tt> is usually a 201 Accepted (indicating
the <tt>updateConsent</tt> was received), optionally a 404 Not Found (indicating the
<tt>requesterUri</tt> is unknown), or a 500-class response. The response code
merely indicates that the request was received. A provider that does not
wish to reveal if a user is not found can respond with a 201 Accepted.</t>
        <ul empty="true">
          <li>
            <t><strong>NOTE</strong>: Revoking consent for a user might be privacy sensitive. If this
is the case the target provider does not need to send a <tt>revoke</tt> to inform
the requester provider.</t>
          </li>
        </ul>
      </section>
      <section anchor="find-internal-address">
        <name>Find internal address</name>
        <t>The identifier query is to find the internal URI for a specific user on a
specific provider. It is only sent from the local provider to the target
provider (it does not transit a hub).</t>
        <t>Note that this POST request is
idempotent and safe in the sense defined by <xref section="9.2.2" sectionFormat="of" target="RFC9110"/>.</t>
        <artwork><![CDATA[
POST /identifierQuery/{domain}
]]></artwork>
        <t>Consider three users Xavier, Yolanda, and Zach all with accounts on provider
XYZ. Xavier is a sales person and wants to be contactable easily by
potential clients on the XYZ provider. He configures his profile on XYZ so
that searching for his first or last name or handle will find his profile
and allow Alice to send him a consent request (it is out of scope how
Alice verifies she has found the intended Xavier and not a different
Xavier or an impostor).
Yolanda has her XYZ handle on her business cards and the email signature
she uses with clients. She configures her profile so that a query for her
exact handle will find her profile and allow Alice to send her a consent
request. Zach does not wish to be queryable at all. He has configured his
account so even an exact handle search returns no results. He could still
send a join link out-of-band to Alice for her to join a room of Zach's
choosing.</t>
        <t>The request body is described as:</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  handle(1),
  nick(2),
  email(3),
  phone(4),
  partialName(5),
  wholeProfile(6),
  oidcStdClaim(7),
  vcardField(8),
  (255)
} SearchIdentifierType;

struct {
  SearchIdentifierType searchType;
  opaque searchValue<V>;  /* a UTF8 string */
  select(type) {
    case oidcStdClaim:
      opaque claimName<V>;
    case vcardField:
      opaque fieldName<V>;
  };
} IdentifierRequest;
]]></sourcecode>
        <t>The response body is described as an <tt>IdentifierResponse</tt>. It can contain
multiple matches depending on the type of query and the policy of the target
provider.</t>
        <t>The response contains a code indicating the status of the query. <tt>success</tt>
means that at least one result matched the query. <tt>notFound</tt> means that
while the request was acceptable, no results matched the query.
<tt>ambiguous</tt> means that a field (ex: handle) or combination of fields
(ex: first and last name) need to match exactly for the provider to return
any responses. <tt>forbidden</tt> means that use of this endpoint is not allowed
by the provider or that an unspecified field or combination of fields is
not allowed in an identifier query. <tt>unsupportedField</tt> means that the
provider does not support queries on one of the fields queried.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  success(0),
  notFound(1),
  ambiguous(2),
  forbidden(3),
  unsupportedField(4),
  (255)
} IdentifierQueryCode;

enum {
  reserved(0),
  oidcStdClaim(7),
  vcardField(8),
  (255)
} FieldSource;

struct {
  FieldSource fieldSource;
  string fieldName;
  opaque fieldValue<V>;
} ProfileField;

struct {
  IdentifierUri stableUri;
  ProfileField fields<V>;
} UserProfile;

struct {
  IdentifierQueryCode responseCode;
  IdentifierUri uri<V>;
  UserProfile foundProfiles<V>;
} IdentifierResponse;
]]></sourcecode>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: The format of specific identifiers is discussed in
<xref target="I-D.mahy-mimi-identity"/>. Any specific conventions which are needed
should be merged into this document.</t>
          </li>
        </ul>
      </section>
      <section anchor="report-abuse">
        <name>Report abuse</name>
        <t>Abuse reports are only sent to the hub provider. They are sent as an HTTP
POST request.</t>
        <artwork><![CDATA[
POST /reportAbuse/{roomId}
]]></artwork>
        <t>The <tt>reportingUser</tt> optionally contains the identity of the user sending the
<tt>abuseReport</tt>, while the <tt>allegedAbuserUri</tt> contains the URI of the alleged
sender of abusive messages. The <tt>reasonCode</tt> is reserved to identify the type of
abuse, and the <tt>note</tt> is a UTF8 human-readable string, which can be empty.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Find a standard taxonomy of reason codes to reference for
the <tt>AbuseType</tt>. The IANA Messaging Abuse Report Format parameters are
insufficient.</t>
          </li>
        </ul>
        <t>Finally, abuse reports can optionally contain a handful of allegedly
<tt>AbusiveMessage</tt>s, each of which contains an allegedly abusive message, its franks, and its timestamp.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  /* the MIMI Content message containing */
  /* alleged abusive content */
  opaque mimi_content<V>;
  Frank frank;
  uint64 acceptedTimestamp;
} AbusiveMessage;

enum {
  reserved(0),
  (255)
} AbuseType;

struct {
  IdentifierUri reportingUser;
  IdentifierUri allegedAbuserUri;
  AbuseType reasonCode;
  opaque note<V>;
  AbusiveMessage messages<V>;
} AbuseReport;
]]></sourcecode>
        <t>There is no response body. The response code only indicates if the abuse report was accepted, not if any specific automated or human action was taken.</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="consent">
      <name>Consent</name>
      <t>Most instant messaging systems have some notion of how a user consents to be
added to a room, and how they manipulate this consent.</t>
      <t>In the connection-oriented model, once two users are connected, either user
can add the other to any number of rooms. In other systems (often with many
large and/or public rooms), a user needs to consent individually to be added
to a room.</t>
      <t>The MIMI consent mechanism supports both models and allows them to coexist.
It allows a user to request consent, grant consent, revoke consent, and
cancel a request for consent. Each of these consent operations can indicate
a specific room, or indicate any room.</t>
      <t>A connection grant or revoke does not need to specify a room if a connection
request did, or vice versa. A connection grant or revoke does not even need
to follow a connection request.</t>
      <t>For example, Alice could ask for consent to add Bob to a specific room. Bob
could send a connection grant for Alice to add him to any room, or a
connection revoke preventing Alice from adding him to any room. Similarly,
Alice might have sent a connection request to add Bob for any room (as a
connection request), which Bob ignored or did not see. Later, Bob wants to
join a specific room administered by Alice. Bob sends a connection grant for
the specific room for Alice and sends a Knock request to Alice asking to be
added. Finally, Cathy could send a connection grant for Bob (even if Bob did
not initiate a connection request to Cathy), and Alice could recognize Cathy
on the system and send a connection revoke for her preemptively.</t>
      <ul empty="true">
        <li>
          <t><strong>NOTE</strong>: Many providers use additional factors to apply default consent
within their service such as a user belonging to a specific workgroup or
employer, participating in a related room (ex: WhatsApp "communities"), or
presence of a user in the other user's contact list. MIMI does not need to
provide a way to replicate or describe these supplemental mechanisms,
since they are strongly linked to specific provider policies.</t>
        </li>
      </ul>
      <t>Consent requests have sensitive privacy implications. The sender of a
consent request should receive an acknowledgement that the request was
received by the provider of the target user. For privacy reasons, the
requestor should not know if the target user received or viewed the request.
The original requestor will obviously find out if the target grants consent,
but a consent revocation/rejection is typically not communicated to the
revoked/rejected user (again for privacy reasons).</t>
      <t>Consent operations are only sent directly between the acting provider
(sending the request, grant, revoke, or cancel) and the target provider (the
object of the consent). In other words, the two providers must have a direct
peering relationship.</t>
      <t>In our example, Alice requests consent from Bob for any room. Later, Bob
sends a grants consent to Alice to add him to any room. At the same time as
sending the consent request, Alice grants consent to Bob to add her to any
room.</t>
    </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 anchor="franking">
        <name>Franking</name>
        <t>TBD.</t>
        <section anchor="example-franking-alg">
          <name>Example algorithm for generating franking keys</name>
          <t>To ensure a strong source of entropy for the <tt>franking_key</tt> included in each
message, the client can export a secret from the MLS key schedule, for
example with the label <tt>franking_base_secret</tt> and calculate the
<tt>franking_key</tt> as the HMAC of a locally generated nonce and the
<tt>franking_base_secret</tt>.</t>
          <artwork><![CDATA[
franking_key = HMAC_SHA256( franking_base_secret, nonce )
]]></artwork>
        </section>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="I-D.kohbrok-mls-associated-parties">
          <front>
            <title>MLS Associated parties</title>
            <author initials="K." surname="Kohbrok" fullname="Konrad Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date year="2024"/>
          </front>
        </reference>
        <reference anchor="I-D.barnes-mimi-arch">
          <front>
            <title>An Architecture for More Instant Messaging Interoperability (MIMI)</title>
            <author fullname="Richard Barnes" initials="R." surname="Barnes">
              <organization>Cisco</organization>
            </author>
            <date day="4" month="March" year="2024"/>
            <abstract>
              <t>   The More Instant Messaging Interoperability (MIMI) working group is
   defining a suite of protocols that allow messaging providers to
   interoperate with one another.  This document lays out an overall
   architecture enumerating the MIMI protocols and how they work
   together to enable an overall messaging experience.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-barnes-mimi-arch-03"/>
        </reference>
        <reference anchor="RFC9420">
          <front>
            <title>The Messaging Layer Security (MLS) Protocol</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="B. Beurdouche" initials="B." surname="Beurdouche"/>
            <author fullname="R. Robert" initials="R." surname="Robert"/>
            <author fullname="J. Millican" initials="J." surname="Millican"/>
            <author fullname="E. Omara" initials="E." surname="Omara"/>
            <author fullname="K. Cohn-Gordon" initials="K." surname="Cohn-Gordon"/>
            <date month="July" year="2023"/>
            <abstract>
              <t>Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that messages are only accessible to the communicating endpoints, and not to any servers involved in delivering messages. Establishing keys to provide such protections is challenging for group chat settings, in which more than two clients need to agree on a key but may not be online at the same time. In this document, we specify a key establishment protocol that provides efficient asynchronous group key establishment with forward secrecy (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9420"/>
          <seriesInfo name="DOI" value="10.17487/RFC9420"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="RFC7231">
          <front>
            <title>Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2014"/>
            <abstract>
              <t>The Hypertext Transfer Protocol (HTTP) is a stateless \%application- level protocol for distributed, collaborative, hypertext information systems. This document defines the semantics of HTTP/1.1 messages, as expressed by request methods, request header fields, response status codes, and response header fields, along with the payload of messages (metadata and body content) and mechanisms for content negotiation.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="7231"/>
          <seriesInfo name="DOI" value="10.17487/RFC7231"/>
        </reference>
        <reference anchor="I-D.barnes-mls-appsync">
          <front>
            <title>Using Messaging Layer Security to Synchronize Application State</title>
            <author fullname="Richard Barnes" initials="R." surname="Barnes">
              <organization>Cisco</organization>
            </author>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="7" month="July" year="2024"/>
            <abstract>
              <t>   One feature that the Messaging Layer Security (MLS) protocol provides
   is that it allows the members of a group to confirm that they agree
   on certain data.  In this document, we define a mechanism for
   applications using MLS to exploit this feature of MLS to ensure that
   the group members are in agreement on the state of the application in
   addition to MLS-related state.  We define a GroupContext extension
   that captures the state of the application and an AppSync proposal
   that can be used to update the application state.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-barnes-mls-appsync-00"/>
        </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="21" month="October" year="2024"/>
            <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-05"/>
        </reference>
        <reference anchor="I-D.mahy-mls-ratchet-tree-options">
          <front>
            <title>Ways to convey the Ratchet Tree in Messaging Layer Security</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="20" month="October" year="2024"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol needs to share its
   ratchet_tree object to welcome new clients into a group and in
   external joins.  While the protocol only defines a mechanism for
   sharing the entire tree, most implementations use various
   optimizations to avoid sending this structure repeatedly in large
   groups.  This document describes a way to convey these improvements
   in a standardized way and to convey the parts of a GroupInfo object
   that are not visible to an intermediary server.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mls-ratchet-tree-options-01"/>
        </reference>
        <reference anchor="I-D.mahy-mls-semiprivatemessage">
          <front>
            <title>Semi-Private Messages in the Messaging Layer Security (MLS) Protocol</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="20" month="October" year="2024"/>
            <abstract>
              <t>   This document defines a SemiPrivateMessage for the Messaging Layer
   Security (MLS) protocol.  It allows members to share otherwise
   private commits and proposals with a designated list of external
   receivers rather than send these handshakes in a PublicMessage.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mls-semiprivatemessage-04"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="SecretConversations" target="https://about.fb.com/wp-content/uploads/2016/07/messenger-secret-conversations-technical-whitepaper.pdf">
          <front>
            <title>Messenger Secret Conversations: Technical Whitepaper, Version 2.0</title>
            <author>
              <organization>Facebook</organization>
            </author>
            <date year="2017" month="May" day="18"/>
          </front>
        </reference>
        <reference anchor="Grubbs2017" target="https://eprint.iacr.org/2017/664.pdf">
          <front>
            <title>Message Franking via Committing Authenticated Encryption</title>
            <author initials="P." surname="Grubbs" fullname="Paul Grubbs">
              <organization>Cornell Tech</organization>
            </author>
            <author initials="J." surname="Lu" fullname="Jiahui Lu">
              <organization>Shanghai Jiao Tong University</organization>
            </author>
            <author initials="T." surname="Ristenpart" fullname="Thomas Ristenpart">
              <organization>Cornell Tech</organization>
            </author>
            <date year="2017"/>
          </front>
        </reference>
        <reference anchor="InvisibleSalamanders" target="https://link.springer.com/content/pdf/10.1007/978-3-319-96884-1_6.pdf">
          <front>
            <title>Fast Message Franking: From Invisible Salamanders to Encryptment</title>
            <author initials="Y." surname="Dodis" fullname="Yevgeniy Dodis">
              <organization>New York University</organization>
            </author>
            <author initials="P." surname="Grubbs" fullname="Paul Grubbs">
              <organization>Cornell Tech</organization>
            </author>
            <author initials="T." surname="Ristenpart" fullname="Thomas Ristenpart">
              <organization>Cornell Tech</organization>
            </author>
            <author initials="J." surname="Woodage" fullname="Joanne Woodage">
              <organization>Royal Holloway, University of London</organization>
            </author>
            <date year="2018"/>
          </front>
        </reference>
        <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>
        <reference anchor="I-D.mahy-mimi-identity">
          <front>
            <title>More Instant Messaging Interoperability (MIMI) Identity Concepts</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Wire</organization>
            </author>
            <date day="10" month="July" year="2023"/>
            <abstract>
              <t>   This document discusses concepts in instant messaging identity
   interoperability when using end-to-end encryption, for example with
   the MLS (Message Layer Security) Protocol.  The goal is to explore
   the problem space in preparation for framework and requirements
   documents.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mimi-identity-02"/>
        </reference>
      </references>
    </references>
    <?line 1935?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>:</t>
        </li>
      </ul>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+2963rbRrYo+L+eAkf5vonkkJQvudrdTsuy3faJHXtbSmfn
5MtngiQoYpsEeABQMnfifpZ5lnmyWdeqVQCoi+PeZ+bM6IctkahC1apV634Z
DoeuyZtldj/Ze1lWWfK8qJu0aJKXWV2nZ3lxBp80WVWusyqd5Mu82Sb7L5+/
fH6QbGr89tnp6euTJC1mycsXJ3sunUyq7Bwng2e+gI+S11XZlNNyueemaZOd
ldX2flI3M+dm5bRIV/DiWZXOm2GeNfPhKl/lw7WMGN6+6+rNZJXXdV4WzXYN
zz5/cvo0ST5L0mVdwlvyYpatM/inaPYGyV42y5uyytMl/vH86BH8V1bw25vT
p3uu2KwmWXXfzWAZ9920LOqsqDf1/aSpNpmDNd9zaZWlMOvRer3MYbXw1pq2
9iZLl8PTfJXtuYuyendWlZv19QG2595lWxg3u++SYYJbxP/z8NQyS1Y6Gr+a
LtIG/6+z6aay351nxQbWniQ3XkGSMPz2fob14yN/xxnw81WaL+FzXNbf8AxG
ZXWGn6fVdAGfL5pmXd8/PMTH8KP8PBvpY4f4weGkKi/q7BAnOMSBZ3mz2Exg
6CSfbyoG42H3dPHRJRxF3Zi3mCEjnmeUlz2DDxlnKkCDpizi70aLZgWzu3TT
LMoKYQ5vSpL5ZrlkfHuTA4CrWfJilDxKqyKr6XvYT1rk/0nvvp8c5/W0pM8z
BlC1nPwtX5+P6vfdCV+mTbPILpJn5eysLoue6U4XGT5V5e8RbsnTclPM6Kvk
ePR8dDyyb1rxbH9b+ee7b/yhLKp0Bv8tAPrvel74elFmRf4+efN/PLZzv6Nx
o3c87m+whrReVHmRjWZZD6DKRVrAuhfbnjf8VKTzOWAXHOEsAhQOIhT52xl+
MpqWq+7Up1V6ntfJGz7APwmxhiarLoXYm3S9SLMl7AmIQHN9iNFGKh5c0Vja
kCvKCl4HtwGv4/PhY4XpcLWsh2ldl1OCzHCdVk2e1fdpTqG0SBaP/COJPEJP
eKSln52HTYvvrvma5ww/RASTu7fvfumcy4u53c1JNq2y5rgszrOqZiooy0+r
swyuq97WdFJumtF8ghA5vFgPgaY2QIkPN+tlmc7qw7u373x9ePubQyRgWXGW
VcOapsYHw9zDJpsuCqC3y+HFIm+ydQqEa7SezS3I9l7qHLK8JF5fcqqTJD/7
SQbJP+AJxJm7o9t70b7vfDO8/dXwzrc9QBfYPk2n2aQkeP+92kwmNQ7qh0O2
BtA2ozydVkQW8cnDr7/+sr0JJtBZ8rRKCyLC53kK+1it8qbBP49gHQA/ZD2A
Fk+KabVd4/ZaK+9Z89CvnVHmdbpZyrLjXR2XQPCWSwLXjrH/PU8Xmzx5sYlH
nsC1PlukOX5fJqclrPenIscjAAazY6rTRblK4ZbnNeAFovmli3lewC3OgRue
pMt0BXwX5u4H+DIv3o1qhDogBGGfoh5A/PDO7dGd24B2333z7fDe8N6d74bf
ff3tt18O77z9uoNWT9O66ZwLHH5VrsJ6ErOgpCn1ZFYodcRn04dPbaD8kp2f
wa3dJo/LWd46nh+Bi/wCHPpq0P6ZE77ZsfTiSJkWRZb8XJYzAFw8/E25hVv4
rFwuy4t0OzBbScp58qIsZoDRzg2HwySd1EC7p41zpwvgBiARbhCoSb3Opvkc
aGLSIBu4kVzqYMaiXpdVk6hEMEiAsEwXIDTCkmoQXPEcYS2zfD7PKnyhF7Fw
zHkuB+2CjNZkILCx2EXiWZ3sV2W5qg8G8Pl0uZnhWEANoFEzEhmrbJrBvmXm
rB64GoSOLMFRyboE+RJAgw+mM+EA03wNGyQE4wlWJYyPvpojWtJ7Rw43m8yy
elrlEwCUvieZZM1FlhVhI4NkmQF/hPWtSkD2FIHb0P4BuE4fG9JeCzi56TIH
kACpruDYErhcq00h0nACu4fl4aHouFGS4EoIVGcIJzkzD9AX6ZaJ9qbiQ3px
cuBPBmeTmRKA3LAphwjAWp52wEg3cJxTgJ+BcxroJC4KduLns+AawOKLeY7K
AagEOB086eGUvZ8iRQNCewGCJhxuSpCVQzmrsoxQEebH/QDyAQowzOi5EWPw
Kp/NlplznyE6VuVsMyWC7U5vjLdJF28BJKgc1AYpy7kzcMqYEMEecnlNQGSA
rEXfEUgcHl3weT4mPDoS64EJN6hs/P779yjNTEgwZsEav//wYRBhPwJplgOS
NwGigN4ufkNWrQjR9ghn9wBXnqRwDwl1/SbpRsDtXwB2wrgUUDRB1XIZkDPZ
x8XugTqw52GxB1dvsmniS00XJFzr6DJPMsDl1oUSMNCBksgJr/CjcFFVBkdS
MBcAIQkoHHyBqhgDAMhXDougy6UXHU4FnpwSMbH3nJhC/p/22VHyvCFVFjTE
bA0QBIxdby2aMeIpAeMrIFfMUBJ6gdmYW8LK/KAmmaaeHiBeFMBl/qMEabCC
FdCJ+C3TYkAkh33D23K8OAlor7RoWAjq1gSHHCnIRSFg379YlPD9FogPLH4O
7Dk7GLWJeqBVuPqYrqQrlCf6Dq4AOgrAqrZ4hPVmTRckYHkaVHUQ9gu6fXTX
B7TM7H26WgOjd+4WCjB4chZu8OnRjEmKUlw6thaKMGWAh58wzcBnIt0chHf3
vEh0eXx+deZXBEghNJNRHqGcLFK82HDBUO4msj/PGjpkArtrgx2XyE8Q/DYV
QSoiTBsUUZY0rEslkC75FSBwDCl7qXe4xjmBmBBBRswgaCHj6iU7bAOKCL67
nOD//vt/e/P0+Lsv795GkoJ7Cq8BbAmaE5FleMChtkSkZ0SKE8EOLTcVYRKQ
C2ZY5qSYfCvpbt0T50+XrAwJTZrXiWdgSLrgMIhI5XioKDkkIMrA4vCU+N38
6tTxy3ECulEzYt/0zs/rxC8d1rLcJjmfEg/5nGkWbdoZjLM0iQHEb1ou7Ubx
CZ452ithg7P0Y9+zzehGDPwTsA77dqQceHc/+yz5ocAb/vd0zdjd4G0+F4VK
XqGXG2gN0M4U5BUgiAyEabomhpIV5eZsgawY1bbMRbeU4UkWsEla59PL7jNQ
M3hsls3hghCC47y41zRg17wC8RRNdMz+ZqRKAWe5oGMBSauEVVeGqETvAGQA
HuDmJLriO/z9pRuwzN9lS1oykLkiy2aw0clWqRkAtcmMyEm8CThiUQKGgiRX
wdPwbqRFR8IKeJuMmvfd/USBHEE1F7kig33CXLRWgma2JkpTlSghwNG6WPYh
lgAMmK2n9AQ/C5IAsHqYJFDRegusF1g1neAKiL/jDb2nWS5AGRiqSB4YmVk9
SupkDBCWo4gKfMc16btM5W8Bpr+ogGdHs3OU72Z0fQ5RUgWyiRy9HyB4DeAc
6+RQBGT8DYfi/zSaz4qJKF5mFAmciHj+1pBdGM4uNbwwQSaWLqssnW2ZOHvo
4ZnjQwOHJABXBPhyBu9E0DChgquOtKSPMdWeb6XJOfCgjDUhRkXa6yCpUTSB
DxlQ9AqP1Bc5vATxzbBAgNxzEmzhSCqC1XFWNSnsET9Ec5IV8eSAdRLE31xH
e1nQ209RE3ddRKSbF2FhvS2a9D3LA2ExgvqKR3ztgUABdVqUm+UM385zzfD8
J0AF4SxxU6h6OzL94QkC7wehIkOOm9crXqWVJwihdRygH/AiwJ1JBkicI3eD
w3RdvS4CHIp35XJDBkBGNzqHaVpnwrLDvpBaz5isMGrFIkwt/IqIulvlZ4uG
NupFGhJNW1MSZQ9QoTeoHrZEcvQUrrWn2Dz3UI0SAJcZeg7oVeZkV4B6yodm
G3Yv6KQuvJyInYWnQKgFdoQyscAAqhFTsKCBAeh+JuKM/M5PwwRdBKSWzjYQ
wVH2Tjwdlo5rdbDwfZIvyjO0u6JNb7kF9SjPDPjsFeKpWC/N6UxRwwVk8PoD
0Lynm4oebumOzN1hNAlNSrf8XCLesrDk8C9gl/xWefaA5F7dAOw7J4gjB2UT
ZRHcSI+JdzFJIA0RRLwEHUN1svfyp5NT9Frh/8mPr+j3N0/+7afnb548xt9P
nh29eOF/cfLEybNXP714HH4LI49fvXz55MfHPBg+TaKP3N7Lo1/2mEnsvXp9
+vzVj0cv9rp3DEmp0AvEoDVeZTiuOtbzHh2//r/+zztfimx3986d7z58kD++
vfPNl/DHBcCc30aCEP8JYAQNH5A1rYgloISTrvMGgDnAMwHkAPkDiQFA89av
CJnf7id/mUzXd758KB/ghqMPFWbRhwSz7iedwQzEno96XuOhGX3egnS83qNf
or8V7ubDv3yPulMyvPPt9w8d4Agp0KRqBtQR/gZwyZW/IbD7tXa45T9nrNWt
kBEjsUXZjSb2JEnubVdCJyWuQkELmXuLJ+BIIU4ky9IHp+TyzVCP4Bv2AhSm
DRoJBSG+/PJrQAiWa4ElZKsUbyOZCdCXLK//5u69O/BYuMtLFL/deplOs0W5
JFUVBpMENMkLFOVAKylnrF0r8aK3eLOKf9eIb5/f8RI1FhwpUi2xzB5zDOkn
CYuHwHPdHRClikhkpZmYrKvtJrCgSNZ0d2GwN3TZgZ6A9hjEEgAlrKvJ1KN0
C4mMtXERwfZaKT9y1LGXgSRWAmEDlCCyR4YwIntkqNFh1ggWjBEwuCrr2qgy
KGucl8tzpgaiLd/D/QUg9m1QdOhZtkQL8TYy5JWT/yAzpZgzcUlskcTT++c/
/5mkaX1+5r4Y7vj5wv0hRmnjzecP/vBfdUaHUfD/k7tPghoLo/TpS0ahX1M2
rO+6ZIWwDff7/eSzeX42JPjU7Jf4615sIVP83Es+OLb7wm1j7ZJUui6eDKxm
jt7G9fpkW0xxynVZg+iG0QAoTmbzOYrvRQP3C8S5KVz2Iv/P7ObHbalGmxyh
R3S9xumRIJ12b1hO0kKG3IEDShwqTMlqg3rKcjtMI8cYkBhir0+Y9hjtD+6l
WJ3qjK4aqO3Ld7h2omGwVhZK6incziovGR9BvN6gHwJt16gqihEB1cjaWSna
SMi4CT+LgINhFLRHvmRsewLUzaeZsWuN05HQzvEgGU/MH0i0xlP/Acq4TE9J
3XT+HiTjE/rlCCfgXx/pcP7zeBwRUFjHTyTPHC1xLfvjFP8fHwySR+UE/pyU
k/EBjT9Om8UWPpni//CZ0MX6T+0iLGQEKzkWVBrzL0d3cAL5/W74/RF+njXT
ERCCZVmoZZvNaySdoQ2PD2w8XW4mwKhqeJ0Yk0HFiyy6Zr0ohFTMswA9MpmN
5Rw4OdQT2AxmdaMBW6tiC7E9HpS5yxXqYegoE9XKjXE5YxwmDgKF6FiU6WY7
JrLMePbTm+fCBu999+3XeGdOWPueOpyoRuVVkYB8SvESzAJEGUMbBHyhkwMJ
faJ8O3KDIVWgj4w6F81O992vEc0bLKTJLWnYkgMndQFo/0diNC0iOH/4O4vD
gQ4DLUVq/FrhCU+MUXrB4IJwUvYHH0csVirdefxwc8h47R9nTNr1+OzQYyA/
/gZxaefs1aHBMnw82Pj6Hj+LH0dqT9IZUOmhl50s0UfA6Bd7QO6PUB8T0O+U
8gZdGsWCNuvZAatJ9VAPYec6f+5ZbMJeKjXY6Ail/ymxGnrUee9ZezrFQ8TQ
IMoTx1JzGSyNMdTVm6rCEB/G4PGvv8LoDSETLOJdBu/87bcxmyWZeh1XGRHs
lM6LBbp5XtVoEc/WipDLfJ41OZtWBHHV0owejClOQteRH0dawfsaMRth5xk+
AX8sSwwvEf9ne7dM8WYl6c8o/TVpjjZ7vnXB8O5nRCA/Ky+ycxybN8DsYO1Z
jVcor9nGrw6YjvNx4MS1QyyH146cja18Pe+CS7wk3imrF+Pb07Jqm/M2FQgI
SDeCnGGtiJ5N4wxDMeOIXZGmM9YKgjSbJ8iwmNJzRJdA60xnq7zYUycV2tuA
3RRHsxne7vHA4V9vyMTHHwhHSYuTrMFP3pRIGnhtBE7nngF+kakK3cYrMdEz
utBG9KKTeZrwx/N6tN1E3NvhTtVtsCYvKsdxAb8hChFo2/0ryASNAADBc7Tp
5K/Jr2GrgyTaKP1ptvjbGGiAKEtBtGhb7GlZr4399z7eoV2kcaDQ/w1n91Ah
I8ZU71VhKBuBh399/vgqKoc+FvXPYICTjzDg+2OQMpxP26pCRGOVYcAu+bxJ
8wyOIEMHyBiM8otgNlMD8eqZz+mY+VbWdg2wguaiTJZwD5d4JZ8iDSGJSBw0
zhuc6IZO6JXxTepxoYwojK4sZjqVbMxdNondoCio6Kcg4tW/oWaxQep8hvZv
oJsMEnIS4tNoXlL3oUPKEC0FlsjPEwnZrGc+eIOmhukwmIWdo7Q0jlRLUDR3
LXQUtYKvB+jEHX2DpleNxCgXKDG1twYibhuc7KgN70k6u5GQi4gFWq5HGKV8
THFOYlxEjiYKQ5O66ItHdJj0WyKu8R+y7WvgS+QyBWKIRuflHM+J1zTLkDfU
ftyRA4TDGEuGrz0XcemWYVE8mfATVo3lWLJ6s0QgOvt6gJmODAf7CG5TtC1d
f5XxrWIeVm4qWKb6C6NZF9lWLMzonOCrSh9iLAHgKNHOn7MlxVSokRe9UMBN
6tZcPmJoTSZ3OFe+5MOhXyM8I0scROsFFTVGWuceJrdu/fjq9Mn9W7fYQWTF
85yUSRs0wLyHw/2bZL/OMMZF/vzw4QCmo+iMKd00DCOsSHgSFSNi1z+LjxMO
hS4vWe9R2mCHRQFzMduGowVOjvhQ5yu0PqBz0ZotPM3lH4VCEv39yP8tutAt
R3aJWB6+6u9rjzlB1E5+eF1fb8xf/hn9fPHRY95k/3OD0MI3X28/X8TTPPwj
OYQr9VJv1LVg0DLLPLwR3O7evp28+uHK9xAs/9Ky+vSNacPlGjC4OR44xaLh
Q8Gv+wnI2XLs5r7+9pvHT330iB6tzEkJAcaH5REz7etXJ6fxmfwQfpfzdv7p
f8DH862V1tDQKmIpM0kmkmaRYfTLtHoHK2s2FUqiuLSUwrbw+xktU8kjcHMd
ZvYlZxktkGK+9GF45k2gmkwGa74oZyV5R1QOCpBQ+BHY8EkAk7X2pZPhu/VQ
onlY++OdP8WPWgwm8DoxmpAd8H8dMWE5QMwyH3lhr/Me+jmaYqADnCRccnQ8
A6JcMqZ9kT7JJRcuN0hO0UzUO6Z9ydv7vQasP2ZMzyV3AfVeV9kapR4jt6lg
tv8FINTBAIWqWzsuu56y3z1ljD0v5uX3g+RNimjaIEC+NySgdZf5XfQWlr8o
VpNVfAnA8wO9OlV7qYLtB0bn/OE16okYIafP7KQ9jCr9ChmH6v4edhbt5kMg
LW9Agj9Dc7ioKrowJE+R0EoCrZ8/EBm9agTQ/td1CQOGKUU04ahHxQmyqrek
yrcoqXNyH1IJVJRwKKlJbNaNFKXdasZFisaVCSAO53RyNM0km6YIwkCnOYpN
osnVgGItIyg4oYYRL4P0dBTGSJPYLJe6jIGY01HOJSEV7aiooqGkVSf7gTIK
V2A1hLEKQCVhwaQxkukHw8AwUBmeQHXULjPI/qQM1eUgKTBWTKg8YmylhmHA
P6Wk1v2B03GonhqQlP5S2A7HxJUhVJg3LFdSwM3ngnoz/RakXSMWI1ejaCPy
QFYXaTVTdUrR0j983CNrPorZQ2AH/ezi2P/Nw48/il10yNPHznFD2bT998fI
qtea44aya/vva8myf162/aSy7p+Rff8VsvBN9nLtOZxivTKW46tk5Ud3YrH6
UlnZyp83kJWPzGo+XsTGlXxaAdsby2TQ8b9avPZru3L2wIR3yuKTaUcWRxDt
ksSVRF8miyfX/QmP62/8v/PkOibYllhHhPr4lj7+yP92dMvFmP3HjX43v7lI
6P8T83zRpnVsdvyI9difL3bQtpvOQ3/10Lcbz/OXfhp3zXmMymOfD+qPUUl2
zfOXXTQ0hhVpNNff147fv4jO9Hrz6G4Usz5qHgvnf17752F3PWENfwoPr7+G
eIef7J66QOwu1f6IiMX6X5uBfYT+12VrfL13qGH8hkcbNDLv0CCvVBw7vGAn
q7xMI3RJ/8+1FMXj6yiKXvVqa4nHyqCOr9ASP0rTZRDvUEgFM+zcYgpof99i
l0ZDRU551KtbhkCiq3RUUFF59ElW4HlrPr5zP6oydsRuS3jbwAQoCWbEGVP8
1YWmUtfpNlmA3lRStBuGGZZFBtperGlh8Gi6rjdL7wNTlwYGMLD763WVn8PX
WiwA1bWaFgwwCqrXgNJIREPT79qqIVYxkfezt2fkjtBlHTCFUkwY53ET6yx9
F28z0jLldTqp08XLq9m1qhFDLe1V5sNVGyXVrzuvXHC9tOWc41ipDErjdW2Q
Qb3U344+iaLZSxzxLz29TztvjxJHhauaK+e5ar3xz5WK3EfOe6Vy97HzXqXw
3WzeXsGIn77CNrxr3iuUzS68d+HPNeG74+/d9vHrzRuEqeu+97/03My3H3v/
rrgXNxG8dgph11nPddd/s3k/Yv0f5x+41no9cY+NH8ADZff7MSs8CCLEcUcC
ZDq4QzzZPWVLHsxVsvJs2fPHjxL49Bx/v2xXHz5O5rrh1JHIdR0Yt8W4a55L
JGVePuafRtybDlf1mUp7vWKaFfpUnkOx8AVn45qgLHYV+DILaRHy9zSrJvEm
fwzmR0uTCNBU3qCWtEVOxUskqMaHFeHEmBwdh7BNWYylHGx89I0U1rGxRA7F
SA2wpO9niWT7SSyPFPG4TmiT49Am9Avxq9qzhsSrXdFjzr0qKChOSmz4Ej6Y
2rDEkMrllhJsOZRWEiMaLNfXC96BU8cNRcXKZDTzNC0wYFWWGuCQV7r1OE9M
AtSwrk2WzgZ+QoyNWa+zQhKP0bBAHhvOkzo1rxWRG2NwmmqDST44b9+xmOXI
caCmpsvaN5WXOtMf7D4wIiSSPY7zYSRwfCzd87jbuwWW/9lgGRYeBH5JFEHR
f5qSNVEDoejJESZJ4QNF9r5hZ1WqU6dNk63WrMNMRRVXNQJty3mV2Zwc1G5w
K1wghr/AN87s25wuhsIGQypZD/hMwBdpGJOAwZiZWWLNltrBxJSL/C/wN8Hw
47ufkMUxu3ztD+nPztUj8ntb5s3XFf98rJj/KUX7TykWXk+Ej2X4S+e6sdh+
gz1e+Xc/Dn1Ksf9TinYfNxebfvZxq/XBn5trx1ndZC69WX9qj9fE3eutSy7T
Feu+luj/L8VVf93+9Fwfg6tBLb2eeh7NJdbHzrl14BVs9525buhL3qGGfZSq
9V9zt3vs/SxH3Rp4Y/8QQ712GPnbD3+0Lb89Ub89n5+qw+t6bfsPWHT5tCb+
QLZVJbrjdSJ2DQe67p36bRU4Ios3co10FePLwLnLN3K8yKbvMHGVBHtBfF8U
8H9uso0V+B5QVPu6L3qgH5Af4VO44SHs8Efc6fVHBKX17hXft8Yn+1ynVCPQ
DmIHxpDVFePBaKmqsVeCYta4UBRrHs69xLw+DgvjklmYl4FprRq3Vc6bDFSx
TUGlykBYDjm2or24fVONDUuYLcqCsuYoh7YR7YXUu00DWxhxEJ2E23kVF5cl
BvpBYqrhUUGgWmq3UFaulLAilSrS5WzRPecT4agQBKpyWpEqC+XqrH5EedJc
Q6/g6phRjSR8JSmjkj6G8+hn7ZWeZQ0rLlLa0N8qKrY5rvhivW3gZo21Mh6l
sbKe9+S9FLAVPLBqGC7x+cvnA6cqFNfbpApSRg+N62/69w84oZAVTQAx6dXq
FqH6P5RgDYA+xy4JAm0YA6qj1dEIuLJ7yb5UNxBilzy1L0h978CfWXReuvMq
m6MBAGMnt+FEmswZvw6/UrxnOm+AeCgn6T1ysl8BrjvLCq5+3ANgdW3KtLCj
nt14FXnX+XRKJYbEMzh3L/vFiattbRM2xT//r3FEUXjRv2Bef4ifdt6utntm
X/SpDPl/fKTmexkcvrDf/mkHV+MjZuizlnT60fO2JNVPhw8fO89V8/rb/Inn
vWFyyTXn/VTWmqvg+/87aHdZd/q1tCvnveJe/D/LcXadcR/pqG49d7XFaxe8
/xx9+P+Oo/q6+Hqzef/rHNUfs14vTMVar4ayd+Tyy9RbLx4YTbAd+9ayDnhR
DouBxGVJrCBMLrZdKm1ycdizTqruzuoDMfCOAnmPNmoEYGLzwQ5wL9hX2mKs
CaFsA0552ScxD9wkblItA3Vyni5zbkjioRvF/l9lG2iDqL17yhJTqn+NSMJr
Wxw+PobxKnvEjpnbLvL+6MfpvSEoN0N1klm3+FGwE/BEkoCnxd9q9dtRjwuq
I0aF/cjUcBoXSpQyfxqyFyoNZ7btorgXqWymXlIqiirlu6g2ueMqD6zSUR8l
U7/NtwHg0QONCQylPS7SLRX1OKXyXtFwrpo/E+czrytNnmGTmUWW4gNSFPDO
ndtUifT5XMt7mBl0XFEWQ+xhMsNARoTEINQ2IsCgKaQsqBwl6+f4JphM3oWL
OStAI56NZLmy8cuXS52e+pd7SmsdY0e1Sfk+Kt8mYLKDCfDqYR+DblxRzfQx
lfxOC7bowHz0NZXCod5wY90NjsAsTJoH61Ckehb5e1gvRmbCgqn2zpgWt6kH
Mp00v9KZ7KrUeUvj/mar9XH5O1sQj5pR4QS2gp2W/othacpw3LrFzfq0smxr
AfM8W86SUNEbPe9Y05GrylMZde31kDe4AKyeQXXAYEJB8J//roWi0VZDZ6k2
UErzzPGGVJjjSXXd9Ts2jiXxSi602PYkaxoKJ3mdVYt0XVPp74bq5mCh/2QP
dzFEHNtD9rNCuk0o9z370U8ptKQopNCkab3RyJ2MvqdjxercUtPSRTUtZaNT
LDI1p4+w/ruputfIG7EkS73ASr44YTSJPaeey67p1AOk12WlDasY57++c/cr
qfYLkClneRYK8gptqKVHCqdXcVi+1v+SLgh4u+BdsD9sUrQGht3U/hmqX2dq
5XLFU3op0L8nXMP0CZV+kZKrL5gSPsGgbVO7jaQDW53K9AxB06NvfNNTSNf1
FNJV2Is5z7QHwXgbY0tbpQWFO7G5bEglo5wUqVrk1nClzMO3RvLBR1jFiDvK
xtEuI92nrSaswW61Gg9DhxNh4qEoKk7aandFHVEp8dnB0s7zqtnQFZ1k3D/D
R7zPdke5cxnekS07q+ZCu1KOeAoFZHX9UojZ7f/++66CsAftnirNolto1oXC
k90GL93eXLbPlI+FJ+M4Vzp2vcMQqD1Q6cQP+arS2LeR1kZ1QhWAmwmApQM/
RLH4q/AqKrwXiiIXs06d+qjLHLAlbR1GMVJcy7ncNL5cKd+L/Wx0NhpcGveP
wHcgCZ7lBQKjvVW8G0+0rLap2qUFo/NCS4eLay3qy5MGuzc2sCgbX2kg1aA8
PhREWyp0Hk3vJmzglkFKWe0jyDIyzJ4gbnT66vEr5EZHQMCbZsmdTCJHSJ3m
wou4WwlW+5X2P9h7IW64gE0NUlMTdQqiBd8tKboqwtyhejC/JwlHwY3PnJVU
xYCdMCGdI7R04cIRDM0BFx/mmrR5hVXCpPMb1jfksvuZit818s2q/j75URo/
IG33IoMhSlpoHcPYcBdtJ6HU0jN3WcjuiUcbX1WN+oelyRwk3NAZxxQ77+/L
Ba84gvP3cJliD8JkTXdBe8gQp0BkjkqjaccNyjcK/Ric1ikPLdt4cr4OUhkP
64bW/fRhoNQSa33VjtoDBU8EP55xSedBwpdosmUa5X1AegVSH4OZCpF2NrCT
HNqj5Efgd2GdsNV0iheY20r2FFrl3WppOz1DW57Ud2SSStfSooW7Mphtc5Ey
eS16vRhoQcBvyrUjVuZrZseN2kgGCOw8e4/1QWemcVMTtzojhPpMHC3JCTWk
sjxcjor9iG0koBOkQ/48QoWBL90xNinvY78uTF2abupa5QxybA3h0aHOwBJ9
6Xu0Iey8lMKhlbIyKfHn2wuYBHCVmkl5M4VIuDY1IWaqzUun7C/lKn6o/yGL
b43zrvvU389cwmF9kzBgEkztUSbDZmqhluw5N+PCRpf5mlK8NnlDOAtkopCv
opLvEsYcSJmjT9W7PF2mObk5oz0bBREPzvYglFW78Ruhhse62qweR4w9s52W
SGBfoYiFCCSN3maOtrqkq9orhZGQj/Kn50cmptWQAM/Q5Sh3EAFcQpXX1HVI
VMZbpurrrfhplil9gd9Zts6onQnPrvW5k0v6S0blcVlx6fRzpEq6MItc+byy
1XdVsb3Vjk8GphcwSF31NTe0qlotL0tVwgMlJHSWcHcq0WuXHfPWn5mhSnsn
LtzD9GJt65rz3EZi4FZRMJlEMYhk4HWLiO7LXcdjtUHPU+qUg4sP6Pkmm6ON
a5NZW4aWqrBIrDTUtg9qTP9bDv72wQ6onxKTpy6+M22W5Dulc0VoMlAol6Ki
mK5dEjMufmn0ZySSpmJv8gKP71jkU67L1DplKr05UdlnZmqnliargo6e9GDt
VelSe7is7tRZxMFCOx+8jCX17/J0TNp8odrlFMkwKGagQfQMXcIcmfS+uOjr
aY41yhssyHs/+XVPKgfPTEXiGTDOdC+UJB5wMrZ/NjPPAnpMo0dZjTIzT8zT
k3KCz5xkDRZSRqOePjU1T1GPAzNpbO+jMteEwkMROdXmp41Ae4kLmf6A26w3
Ws8kiMxIFedzMlb4e+AL+nMXG6YIq1gBcUrJByT9xbkEdDqxgsGnwvlXMp/U
1x2zcdmwz1D/nDprEKN+4nk+zvO0SpEztNprxKKCx5ggLkSVWH0L2kW7DaQQ
HA2HwtwfkVP4tdznBMmUX3LgnYEhaqHaEG1FxjeWreR4ehuj6tUiLSCmeI8z
bJaEXZlw9AVOb1UKWUZPFz2q+54okwamfNe0KgmfNlNhYnLNbA8i/7jtsWwu
a2jyckpygWm7tJS2SwkTrAQ08BM5tHv4Dt+K6UDCaRpS3zar5He6gFrgZ//2
Ad9IUNrv3N6/I3/t3/3qqwP3AYMmaYUP6NagKvGYiq2V1da5F2hHw9UdHb98
Ejazf0I1eHU534zujO7gkr7HNX311Vewpr6GBmR8SKXrNMzvO1E5SpEpzrOt
Mb399OZFHUgzoc7Ud0hU7NxPsRa4F2gXaQVCSOkzivyDB3JE4d0wPTIAFDul
t2c4C7K1DnXdQz9ozDbPd9hW1f305jljuFrUWCL+7yevfgzt10gywoYdAf+p
jwYAS9fGp+f+/uQ0ORyF+Q93rIGPiSgcnOOeEab3uKFUsrdomnUNRBJnUDo5
Ap52eH7H1ps6/J0NjFio/sMeYsUek5W9+5fPwU/9jmTy+UxGspPmqpHiyomH
MoETmnetTUQjWrN5t+W1ZgpOzngWEWuOucr0taaKh+wE7k2mjEbAClWEN5OG
Pi//tgEN7VrTtsYc/s6GZb91VK+oq+c19+2fD0B0Hzw5eaqFyRJFPGFBrDLH
eXKovlzatlyDX1WzprYg3Gxe1LVI8gklLPGmtifE+5+RIWbmRG/lBjkyIVsq
gc+YCNEqY0PT8yYYU0nDJmclOiDKmVzpToW3CCkYQMYrJyIe9o/BXiV5bTwH
6hwEdWoxiqq8KVIE+pWbruTea0EWaCOWB68C9ayFBQIRdNKSwOQMSkfTUbJP
vj/21SAo6BBA1xp0Z5SxblNoJK2WN+kWnBfpuuXqUHKN2411LAMrpb4MmUk5
28aPKu10+xJPsNwm/4HNG1A7vzO6fRB0CplEpW9Rpi3gscEZWt3dKp1lQZ0t
Gkz8DHVXW0sMvcQjJVx8vLxYb23Czhxz8n5pvLY1NNTer0atNc2LEDkpiB0b
BrkzcorMfL18tqj5C2H6xgAY4lUZYwb6cvFWbr1SyjECdKBk3SB7hZgrnCTq
4hddQ0KOlgQ2oyf70l6avaO1NcmydcPhm2fZPN0sm17LR7CMHAQLrrivzDEq
Jrl9lt5xG7UKifAvbU7RLMKhRdpuA4cCmJGxONZcpKxyncLYZFPlf/nHwwcg
T4WuMj9V+QMXP63ClsfNB/RxNMbsAulE3xOBivSOJxrM39TZksCu7zuQheAP
3l4WCu9H5bOO6WhP8GjNqR+bA6et2iF9Z+5Px37Iwz4goLrVLh8EkuhlKo8p
kjeBitoGjU8zsYxqQEDdoe4XKVJHMSVY3iGEVl1U++N6Q80jxgeSgXHlTNrs
O7LywkSk8KfLkzBffPs49QPW7mTZhF5pvtxUoNY/D6Yf3iDqaTwVzhNPLo3s
+N2OHF8gclZpxDQYiEQoiyCB2mSGNLnFf97SV6H8LFSdcXdTGTvnLt68n1pq
NWfyQlR25GRfwSAqextjfQOY5dhbEseD1pMWn7BZXblmlXO5DXrb/unOIVON
FSjZ0yfdtfLzdLqFE01rtMkdOF3hLQT9Lbu+sDRvsh4oc2Fm9/Lol2Rdrsnh
yLq5oMNY2ghRi65ia1pdJwHCYRpphXzpXA7tZhHYZbw0EcYW7f7m+BknWXiM
7BGyFufxw0ohPSsSpT97vyZi2zn67P19of7Grqc3l4N0XmTp/EcEqyAdHv3R
HCYYc9WEdVrHqUMo+LLbBL7eoeEKwoKCy2QlviCg6fLHgCj+FJUA79+VL/uO
eP+efImH9VNB6tj+l2YAcdb9r9qfwEmjYIsJaPtfmykeZ9gqb7b/jXymqreh
gEjLjwE+wDAu2aARJZ+8X6QbFPu8Qt+5TLDHwa73SaAcvzHmUb1Pyf06Ierb
x3T4e2J5H8t3dIx9lR0XjRfQ3O98K1tQLHznf33QP1EHbP1TKuH5i+VmD2Xb
XQ6nPx8Mw2NoGvBeUzroQRNCq92HQXirR9F5rfIrEVh6Si8bRhy19ybbSM9y
xpwGbDtrDxPPVQ2LVu4asVZDxJBDkaNRraps4rdCP87cYrM3ewE8sMyQ3AC1
dNF7kvZ7+ihH521ZToQdaS+3v5bITPFT1uqk4KP16hqJBoWMMhptz1qMy7Nv
JlpqL6tqL7XvdRT/y2qaw/cAZ43g13bzEQ70iXZjic/Tlgq8PFqcoaOdNbX3
KuolPRxrh97T4zdMVLd3xuDt9P6+qIuYpk66uJObOKA6SmabN6IewZGi1D9Y
CpaTBX9KYYYoaiL3AmBQx3uEuhTxDAIsSXcLvDctCM0dmiUqtmmuxZAr8gLJ
LupnJldRDA7DhK6EtW3tKbXYUq8M0V2RClSswWJXDg9OhhVun1yjIkF5tcs/
d0G9UDG85Z3AC4uU5oXEPOTsFGPpunWqVJ/KI5Bw0cs2ZSwQtdZqCpgACP7O
NgeJQMFkIjvPy029xCbQHHdvWqMk9RamYXsQ6IhugmEeM17UKDnqxREMOio3
FXe67pxy7L4kiCm0MM6DfEqkOWw7gBtdgzoH7v0p6bNxEwG6MBWhM+oTTvoO
C1aCkxZlW5B0Ifm686LEvKirNfShRHsoJvrP5K3uz1K3xFM3d9TANSry1WZF
dhlSsFD1iW03Xntkg1DXTpHsl4ULXSijZ56/DCXR+rDde7N8HC1FYo8jJ/s4
bFDGa50yE5t0yZQO6c1VU1pzK6mkJpiwZfkDPVOc4Rz4DZeO/O+zHSZBDnth
LBD/t66NemLLbHIhkxSVix57Y+6b72BHqkqei41tbgwCwvxtATdnpP2nR4B1
b1OjsaCZCLQWdjeinfsnTkelytkSNHXU9bFLP2J1JttWsFoMm9uMAhLYuoQu
hGLQ9qV29pQj1+pF5L/SjHsMcRUru283LR41p8/o203czMAG76AnMq85Lp9Y
TgiTt8UEr2sNl6wodRSwoHlUKER8tEU7cqJkJqTwC5UDXav9NX1/IAFKmnPD
jaMAQ8biih/HtsVQNWNs4h6fzyi3g7yBJtAD4zzGuCD6As/7Nb10TAo1+kTP
s+VWy32wXZitV17n5zcbDblvz05AoiZ8jrjFzYjIKeG1yCZyLGCSFhlzL7+b
KN7K4Xn5dqhwKm9CoUlyxpxnpopi2nsGk5QLooQR5imHaRfAwTJuRM3VJHvX
Rl3V0Yos14CM6nL0Elis4TCuBRokuS13A6F2OSEpSSOX+9ZHd5bYtlZCLCuH
O1L7iV6GAcMc5QGmkF7gUl5Cj2uuQImmFAwzYshwUA+ri33ZAHXSGw3nb9MD
1/d27srb+/52rgJND0CQ2ZDsRDPCs9F4fEMofpm9R5MvseAxR+dwR/DxSbac
6we///7fMB0gz5o5JQMEq/yHD60KoF5OjdclEoyQodiLU5sICYzMvBgE4ubG
JgHzFWnlY+4s/5q1Qp+rOU60KkzIYHGy8FW62NLCJal0iOmiQ1byYQv3e639
h7dAzNMiU3gbNIVSaavcy1YYz4Pk1iGPJmPwSQbUJM7RuPyHRod6vx68ryp+
P6r5xt4SfTeSzDL9/y1SOzWqkP2Dr5saPWCR1Hka0VNZJwI3ZOKWHPWfJbaa
D68xspPI6IcYMoG/qF3Ez8Rnl5zFf+tjnUPW94VPHoRN6LbNNkI4pbmNHjPF
el5lIUfLbwEH+7NsJYNUO47PDzbnhPGVviSZGFueafYXJ/9ac18rXgcDM8W2
J+YOseepNc8D8k1m44ZaRqUdT4Wdpx6UikPxV94CR4DGVXkDWUAKf4gPzLOy
bP94+37qA3+PBn+wW9ODtlvyy0S9s21f7NoWWxAHJZYBL0Y5ltoiB1TS0azG
O6DYo1cloKAgkMZAjtPC6CNon6tMSSrvYVc/xojGCkyi4WmXtiVK3Pw0sMeK
s8hceOlj7QeSS/NL6fmZvV9zP00KrfL1s2hMKNqFOwuEmMLyr0M8UR6OIqV9
GmxVk5jIpxTNjN978+erc1xpBlSfm5SGWmmS721dC33pXaEH6v64E1Y6wbDS
sTj/MZuvU7BaGtaHIP6amosS7GyAQVu3YD7gD0S874573lgSyr5wVXKtMKOJ
LbjSJmuVTHOey7IQ5DNJdQHe3UXvFqe4qnmac+nGEU0bq08eaw3kVAya9L7l
MtgyxY8ZZugSwXEHOeAG5Wt+RtYHooEEbEq8DS5PMp361VBxxdcYmDzW1Km3
EtNdjUeOfX/M23gOyb4jHbp3nZw/LNE8YceOLV1hzyObFN07UxoK3j/Dmtyl
C/oYiT2irGQYcz7NVhwvT8bC3LsoNVwbZ2G3XDAhc55neoFURgw8JjEMPsFg
CcpEV0tg7DzfIU3d7/GmBVcT8piLqizOnqzL6UJYELrr2EIoXCgvyECm/G3/
XsSblKryOsTNZGh493u/aH440XT5rKrK6nHIT7DCjh0SMYCWcwgYumKWxDMU
04y1eNAjkxVcWFBaAItmplL+Tz8+//ckQxAcBO6+yYvm6y99vYxTmAJU8tXa
iCIBdOb16tVEkkJz+ssfkqDbL5ExNJWZvwV4fYn+jekUrUc0XMPyO+Cdvs/m
Jb4efnpmD2qs2RrXNin6eYTLjuOaI3hplWaG/lVs9w3A7LXxRbTCVKII0eME
bLrJbmwBirUSIq94FC8hVkbB+M6rKfpDw3jljpdVq+CNKFvU1IH7VceJKrx/
H3EcQ0i8T9ExdpZhHVmB+VGgGA0cUR4tp3e1UeLy7aM564TbX5lebk86cfcY
fGEU3IM4yp2jdI1FD4FArToiQFFQF4Jqgx6YtEBiKAdZGFtSsLgGY1J/HLCN
Ioq1yghdexS8XgcsU5uOJ7sracI9bykGsZzSVxigT2+A51RzlC+Nd/fNc1Xb
xcFLt/rEAiKOpgqOGd5aXmtkThz8RzDaH4eXj8mIxhxfcUCiN34GSfYpZyXA
DYg3rXVvx1bjZDuaAcCYY07GYS9jDp9ntwtuU70ukk2PzrR6h90pznaLWGC4
M7kyUBHWLA0SUcneUnJppW48r9LiHSzxND1jwtXOFxk/xSeOjh6PQ2xiEGkt
aNAerJroUVT74XHapMk+zHHQcjBEea0mUtrRsqINsbvRiKdjHkbLG0tcM9Nn
UFCC13Ifq1Xj89TDBK6UpAb1Bt0oxEROMGIBywlEb0/L8tVy1lJXGUV3iwR/
7u51ZxdHq4oTiVFwwzedsJSesJLd0kMcKHJDUeJqcYJ/1KBCD3/76727vyXm
XB/Eyzfgb23hRhLIpVKIBLX00Z1rRI90D+qjBIo+gncDueJ/LXNn5xgraxoE
XpDbu85Rls+L9aYJwQESWM2nRkm7qABxhx+f9fc5hwEYBLiRxISp3f4lXjdj
Qy3pQTeRnij77vnJyU9P7t+6lTwusbABtnNFOaBEyYxENO/L9jUTquxss0wr
yyhdkChQTFgvMoxxjczqdZA6oorse5jeu13D/vYc5R3p8wchFZzUwEIKcACe
SG2N/qgCSflVNv1UGINz+pskFFPEB/kFUAclQak8q9I1vDPZo/u9h+maqa6b
ipsjHlG2nOQUDLxamfv4nGSVVu/4LMlBwpnNYSLVJR2IhZV3K62MMELO0yMd
WvFcs4zWGHfNlQgXpxxZ+A2ngFJ3Wbxsfg3CQHG9rMhrGSApbIYR1GqUsInJ
xNxHySsufVNFLcGYEEQ6OZwVpqnQ/qL5y4i5D+BcKyM9jMwZUUADxdhS+URc
0NN0mk3K8p2UeojNUjk5mJpsna7hzZT0WGWY5YUJoKmYvKQaDT/en5/K0SN8
950KFaHAEqX8IL5RW7iGxAYBKxGlJdvw2LN3UTrMWiKULkwlkzquosFGN7J7
p1VKKMiACvm/jNOfSZAgW9pUKNca7pzxD9/MKAdYq/X3ibPe8RhQmY1gICpy
6X4R57QqvdZbjG4JhXcDhGZASe9+9fVwAtjm5bC377ItSI9Hhb/oAYbUgkDK
3RPhjQYldTpH8OYxmOBMZaahPj5Ml2dkx/yR2roZKbRppAtcGd2WnpdxSoyG
WlPwSG2n0hAlbQ4nOl1FEak8ilyp1kUhoXX+JlNoeQxrti0O7JuM+fTRqzdY
Fo/XeQQAqPD49oCwrNve6Hg7A50MJHMtFlCuOAf2ecMdNgivOpMrqIKHkN6m
JLZcJ1yGzWZN62ZCRAPmPp1lXF3o9NHjOyKbTidlNZzl6Zk77HkzvueQ0mTD
t5iHiBJRcud+svj8u+m36fybr7/58rsv76Tpd1/Nv53N730zmd37Oku//W5+
tzcUmH/Se+nky3v30vSrSZp+m32Vffn1V/Pb36bfZN9m9yZfffP5gN57QmBD
fYYlseTu/aSv1EGK5uU9HoPWGT8CP7gXxmCCf+jL8mZ5797Tn18c//Lzq4v3
z6pfivXPj//tDKYRJfjHUgsI0eGkHjQ+PO+83BhZkGh9qK1RZyKbDRwgKOXO
tbwaghUozmjlmbxh87PMt7H+bjpWTheTrpWY6oB9KouthkZZ1mTmEs2usDZt
oBRT0/E9oGwDyppPk3v28ug4OXl2BKREA4qtKvoWZLM0WMGtBtVFKY/FB8Yl
3borbFtwdjHJX2kVb3kV+4l9fpC0F3MQBGjZaKzXRdtU4F6qW/rb1a0PGHZx
AuSRygOzChv02pEpr+hCBUGqBWXlcM8d0Pa9iswBGA/C2Md1mRBrnK/kIiTi
GVaL0QRB8WSo/LGus82sLLZS8MbHp1FVT8tZ8OIQ2iVoKZ8ZATWIW7ElIA9K
A/MoYzwwYPeKRaNqmvdZGIUs2VcORDUbw7cHymqfsQguFfH4mJ9ReZwlFe1E
yRBEjSHL+zWJG967tyq9VMduEzlYktTpXnFBPRK1J/NN7euK6m5XWZPOyNxA
uCTi5vjAy294wA5OYZl5NCUaD8DNzzsoKOPf8jrxGqkIsEwnQNb32k/uHQTF
GK7hWyxHVgEN8DMoPoeaoOj83GJqUXKCDVE3Syw+gb6md+ViUpXvuBylf56q
8gIoiYP/0/eZ8ZR7NBoZuv7Hjt//Qb/jAvEcZHXXGNcq5C/l/JPHBD0WHvdH
WKwmbH3vwM7Vz27+mnRhdfWo/tXe4Nl/XPEsQ6mzOcwShINOer/sYsR1tr8D
4659krgkGfP218LXCJJiQHgJifQhvWijXmJRby/5LJMHh+maKtTVipVYLdxn
jvOdJm4mdkufQH2p6BzoroN/jE2R7apMDpXvCgWVOHrPDVNfTI1oEhrdI1Nh
yw7uNJH9rzIxEtE//iAZT37t2KicJXoxe3v20yPiaxEHhDn0LQeuc5iLtF7A
LDLBjrM2cwiLHPOrxHastHK7AiJXgXqJ0iLFu5bhSEJ2/TNq6iyJHCUW9MFI
e+RdlHqSnqk/FR+co9ijftrg/lCI9kkPMZ8+YN4SGWUHQgXbsJUvKODVC9wk
t/QCbozlKYOgJ2Z1OsWx5tO0rNauBwUHXH0p6A3cizylnFFkveWG3dWJxLmS
HbqjpCufe6OSHAFW3wX8ivbQrSPnb8osWCQwhcJrQtIJobtwJwGrcSCFkROX
oNyH8nLZeyytUXBSTirL2afC5Bxvr7bKfjnr6PGgx7x+5QlhYdmS7um1GKn7
KCYZUSp3PSb5AGcqcGF8UNqVXIOC+NRcD0T8EndZYVQ+unyuCFBhUqtwSnmM
geu9KxT9uQuQ3iGkAbodhIuJKXrZGLwY1xg8yRhmweVRkzCfx25jY936QH7a
RbrKyJQdtvR5HWoY5gWHFYcyGPIJSuqaNL1zNEvUQcLtV4GlurWX2Y/5tGTW
/UUOQnJx0L84f7rvG1+Li+0J3Ttg1QQMtV4ETEIptPAEoHczhuTBQXvU6Zy3
iO95Ta9g+T+8iE6eCAW/DZ8xbSj81mgvkXxOhkHJRYlwxmbDUDlStqsR3/NM
GyhWOTP8oC41sw3r4ODLSNH15jZMO6ry2lv08PDUCumNgyhXrDLnfiqon4Ee
8o7nkh22SWsLcntsbMLN7BGeta40wOB6TkqPUl1rZwBDOEYkzVieRrpJpnx4
GJiA2M/nJn4RDhPU8uA2gyjS/Ml6QOF3mzVXbdZkxR5DXFRCXgu84NVs7R9I
5t+rzWRS371955sPH4CAFhIhdpIu01WKMES9Avuk2Q4MdtDA7YGGkfyq5/R5
/VvnqLz5ZZLD6n71CEUTpme/4ay/kqmPqq4gdH5DdA3G8Z4xgh+mmQLpeTOq
ee2CKXpvJL45dFMqoCWWTVGesF3uUdYix/oi8jqp6DjwgWzoGoOBWlgzDKM6
UD3SAhUJ47iPl9bbQ5lUT86pzJeGMcTRgUQb6rYxGth8NzTSR8ZjtgZfgoOA
pnmjWWGCaqY8FVLyVmygJLFQIILbVS5YDB/LhAP0fL41CYqcvEWBDKLJj7go
WhSth3K6JNxY8R0gNUpeFeykwVzIdyRWaWqOM88lqW9DIlEo1OEX6ZFEx2Mj
DN9mggNxvHkbIwLc3qJcYwMVKuDV9LBSDEZlF2VPsp1mW+PAAD8EjYlbtDjr
C7C3cw1jW+KY2XuNIdhV6jv+ygrUpUZeca4R11obRuT2ZJJwNERUZ/N6Qc8c
LINmLpW0nafXiNqC2abcdUBjHOX1C/QZeIempDb59g4kHImFh8quYDSu7+jl
o7sOzGsQR2RJpsu1Z8kA8XG0Qi3VhbRgmZ2z29Z5esnZ3pLdKYVcr5f516r9
6OtYtoOwQpyDJc0Pom9aERA9Q6xQiZEK8mwrnUdJyp8IC5U4icbGbuyqftIb
M3Z046ixQTButFKN4qI7huSJk8mMLHuyY0dXWHt6s1ziUDXdus54kVfZW3YA
doJtzNaiois+5IWNC/OeQBdJKoqGXTtlyEawRLgvkSvaGAujF459drLSV7yk
7VxmY7z1KOUbOJmAbpQfvdOgRd+wVgD6UOK65xTprwW7iBoYxSWEx2BJakk+
K3y8iQnypXzV1LXjZvRLJBKYcaFuIt/fhWLWPfJHZAv5ZGRVomAbjeQEgMVx
N8oETEzJgqMbgDA4m5CixSKDuPc5m2RaNSND5W2KtfdRGs9AwjhvWQDEMh4n
uEvQx5r7QmoyDAKXVHn/7n2u9k1pvSBOMdJmB+HWcEXtHPbtS1GX0+mmUtkL
K7yV56xXLvKzhbaZ5xZAmIBDRW/qKVDkKi/x0I9FXPBeYc4F0MTVk2evfnrx
2C63lesb54SqaWcrRp1peVbk/xksRlJAMsqN5Xz7DA1kazznvOJOJ9S8hvPQ
j/zDAmYuKMI94nhlvlFQPpegEedfgGi2QscnFt0gBJ1sahzEs3HKOQ0rJ1qY
QwtutMI8yXcY3eVQObAoKbh1ZFst+uqCoRRfJ0Q0SHMSIksNBbwbaB/E/Xgm
SpNxPIlUucBKk5jBEBCeEI8Ko6S5VucMCRuc0a2JuYiFFJUpYdErL0QYcVjU
V69SaOdBjZ7uLHPgDT6MRVjasIoKaA7UwqfZwWcbUASKqSkkF+vOubyLG/Vp
tIMGsL3B+YdU7o17SKZBEZAJDFHzF0xX4+S+j0WECFXvfWoZhs5lUd0MY0dC
sSUAKqT6szxjw58JI7UKjHmfDca17TVhNlk/5VdLEZuUQO47aYcqjCiUEkyQ
hUlblhYgnFxs7bNFOjM9R1qxLOQBh+nC71gprw2vWqnDBHCbG2om+6BUrHNV
5aSmpK7sYBTzvFPy/MMpb4Lo4dtY+bqe7aWz1oBNm2AyZVUeuGJWFELj48ZM
zw7TXQlAdZKTMAYX4CHbeBAVtQnlZNtkw+x9ioEu3swCNwBUosmWauewAFTB
CnNqB8lZEA/VLAWYIjGUetdH7iF8TYQ8zI7BN0tQLkAdw3oxKIF5Aic9mir6
IIIVzANcDw7kbMutOmDRPA4z85RL1NKJyHb59WVvWij70HvW/bfrdLss01kQ
6UkA1WZXsw2TxOmULF5UawKlWe5Bgzs11ZxTUgeAsAt+I816j7vBoCRTQuT5
4+CW9w3QgBI/NP2owo3mNLu6QaGAzlyrGoXEbD4CMgplCLX4ZbUUnIrQ0C+A
DjuvQsUNX9dMrJsP+Q0WATmx5ZhqjHPEMzqITEeYtlMCmx21WlX67ioF+xE4
iA81eFMCWsvKCeHyo6W8LEbLgIREPDbxDeHwZSJKcJmW+Wbp0gNEk0Kj5Hy1
Ovt6qtnhTZS+yza9kVBdbNHO95ChzmvP+eKQ9qmFvif+dfKqWT4LxdMQWmut
Ox6KNU185KMWcEuXHC2oHTU61WQU0123IdQgmcoicCdqtMBCIvwtDJy1HqAQ
FmdhGfde9A8i9yPTANrBBzHoub5sVFAHaAkViVOJHc8xZPGGVnWSKyxHLCbP
woXyGuFNKgwVsPF1WfnyPmFekWxMxjmj8PWU7G4/g242lG9UKYhtnA/0lazI
FKDykjB2/kUZx0fjIJ9Uo7ogLyOB9yHUka19QXmyLKtKldvc17APtnDD3lqg
EydDWDJWPyf/EhDWJnP1Zj4HXMORoe8W0ULtmC777wCejVIUjib44oy+crSk
ZbASEGdOWQsL4apor1IaXCdj0Su4n0NhOiZq4obm+Op47YSF8WoHDjUtEY/F
x7vNmrhsT6u8OV51F06fmhClVN6Z2/hRabT4Rmp9Kl3r59ZXxaGfSD+02BoF
mYby4Y53uwI+B1TeNt1B6m1KyCOlwPO1/hCMdMQXAH7gSPLiLzkC2RfFQ7v1
GZxqs1iFXjG4LSIunTsUVTJ5E/IVbpYKeB27jq2hzvt8SxtVA8SJgp7NN+i2
DffNfwkf64DjgPHhwfChPvbs9Q9PwpSeGviP9LkdSIr5ODZbuA3B00cn187a
+t8DTDuggz+Ht2h9PwP2vcBYNwpu6oHY3qAPjge2Zg69xV/Hy04gZHWGXD4l
Rzbr32u/XRqXguq5dRQr363kA0IX1v8JrrwQlxSBCaE0dlwAr1sUsZM32Cpu
U/sS3ZpFqNRZ0waL8gQ0JSqlfa+/7E03hbCvHg2fk0ptPiS0W7zoWtZDex7h
29NHT2AhO77htbxFKfOtfevbZsLlfwTQb+k5egwOiRf2V+zdjF8HHIOVdtGV
+vbEhxxt0Pj+8FGUDN7ms8FOOy/mC4rTn2BzyRYO+smBdEd7YE/FZGV+Wioh
90e2ZW6oekY4CB85ylv2R7ZGXnYIOy4j37Xd9PB/OwBch+J5oMQkz398c5p3
jYzSCLw3q3Tbe2USujJR3dvUtFny+aOeYl1RgJqL3TZBAJ2Jao69NlqiP02t
hO/SeTkBJ1j9SBv0oe1w0KYCs6ResmMeRcbU9xuKx6sxBRP/unuUcsxRb0Ws
1sxOTKlzGYJHpK0JV7o+DOeGepPKxA+lDjb5MqnthjSZGHgdEqW6gZa0AGoj
maXUypY7Y083FWoaa2rQqp1CEpEZWaJG73aSBhKtJZiEcdnESy5dQWYLKnWq
uWKYLCfi6LqspWpQ97RJRvWSrgjz8HzGwrzvGSOVkbD+OKs0YW0cb0nOHF1T
MB959YZjaWru8kW+GEyWWah9JDBwbwjNfAFdW5AjFCDeFAhxVOk1c4Fd9LYp
F8UuUaNGbyKSkurOHdXtJt7ylcQg4cVEUxgalEEC8cXNQsVsXLzLVzwxGfu1
c6fMpK6WTvPS1GQBwuJZ7wh+t6mxaS23QXPTHlkcP6rFvhX6PpYUiwtPsb86
GbSDOdj3rEzDXHjdpQcX9/ANzzj7DNzG8h3XIF4DwVmt1b+UFTn5N7wFdOuz
ArUXa77sBOeVeqsHfiVqDnZpJRXBuIkk+jIVJ2wXOPybQGA1f55roI1n289H
lfL3T9VAW5RsU1zLwij8i3N8NQWrs3DswxMMGf3dFB9zo8KolnC3PaI+xbWF
uZ53mMub861tQkroiGez9I8o0rgWqtjS8VRuNsaYWGnnhz+vTXec2lRdI5cD
GdVrZPBkV+p0kyMHFzHngwdogUEjCiMlYZ8Xva2+78veJGPZ+5OiqTCZU7vw
yK5eaVFgrtMi48cOS8DyW8ZJsLRibePnrZw0KdjS6qOnweZjfzRU6EWDAi0Q
TVzZWNqbwaPE0BT0ObtDTMdD6W2X+2aNl7a6H7NFjONUMQZskscxqfEyB3Yh
bNbzWrNO5Xx2rrxC4HwyBV40Rgephx95iLhnhIYeRg+7lvNJD0Ga9aUWjdHA
rckDYY2trsaJafbBDT5rjb0OEVxx3cEuEHbP6cKcPtDPztjrob38KnLYQOw+
c/umU5pdn5/C1iFAD2zoEJYmX97+ElMjkqcl8PLuVAZ2uADuzKBN2766fXs4
XabGT8aI0/Gnqn1rt7QWrRGxwrfJ4AIM7V4ZVlKzTVHmuA1x4ZOJTi8yrMkp
xEbJCy3DnRdt+Cs2isuN+zB4XAueNrq1EX4O2n5NDe6jdEwgd5uK40+YNWMp
jPRdVvQZA3gRYgqQd4spgDinmACYQ7bU/+MWxYrVr/a3SZvAoY7R223RN0zq
7bTIX/naxm/o9j80nRZ976rW+0LME2l1tD0btGT7pWmfJmURViWy9Dve8qff
jX8bHfwDLdGfjCN+ey02alrHMRtFj/o028FF49FWqIqbmLo9v829WN4SoWqw
S6risNDch5xrvq/nF7V3WIlYR0FN7BXQ/VouHncM6utIC+LXDdkv7WbMxWxS
3htHlox5e2N6K/4eAp5xf2iQp4btRkLN+/k0Xu+9FrPe8/z3JtzaXcGt9Wx0
kVdy7Xi9HY5L8XAKIpRPFCaeiJrIrjb9M45tDyGsFENju/zbT7Xink493Dl2
2VuGQklJMSTXaV6NurWRqeIUl4epRU/KuQevCidpMskJB7lpRMHqj2+xRVhn
cJZ7dGpVhDDAgziqk0SFjQ+c+OszLt7XZrKtzlikrz8qJ1JFWUrCuE1RlwRe
jCpuUQvCeSzJLNkXin4lIJ7JW9+X5UQtjjHgCZ3Scu5RdRPTtFjjCsYdUuo3
YFvJ+VoDHD5CHYG5pkojkeO7YT9wcjO5xZOodXytPRNtYVM5byi8rt4sOVMA
IJavVtmMOvZgJeog5HtLDu2J2L82ZJaeYxh8wb3lgK1OWCNrxY2bm1BznD5u
rn0wNxH6biRIXkcy/RgpssuJdkqPiRH5OKmgjZXXFR6TlvDY1mmuLT+2gg8/
XnZMItnR/RnZ0cPLBIKhge0N0lZjBhDSbXrHTUJLOm+N8hl6MJcwVLpMhn7E
Tc8s1Q4EiMl6U0qADsYHRbw6KsuWPM2p/KXGf8xmFZpXCXlMXieMrUglRv08
F0T1o5Crtdqls0kIrqrzH5kCoYHLBdtA1262o4shYJQR/Sn2iertLjYTtLS1
SvfYGrgoVMAMq3XZqACOpa3iYEjteQJSGSUGEgP4bnR3dBfv2punx9/duXNb
S2SIQSVA6t8QUIe/z6wlxdt6OTWWM3f+PT3P8db/Ui5hHSlf//+RSgtEyZOa
Au41FB3vFZ9//+V/jGSwJO+nSwAFSEK1lDq4SCUTaSKxvFMunpClNdq/JlvH
+zcdTTX+HiY3x/SMxs/zM8okXHDpwjnWN4HH8dG6ZD2sztKKKTdiQchFhD+W
WGe5QB4v2WVLiXcnLDJzOsn6Ki+kY4Di9CJfcaSdtc0RDuSc+AOnUiOjSBbl
heOxPre4XnDDMb7EirRUrEJgyFpYY4tfO/mK+jgmOaALclvALTkrmhFVNoSB
7AlTZrGzFIZUYYjolFLilKRjMYBl8Nm4mi2Gkg/neyWcLGKI82UliFMYOll9
+SoSoAEdONyyC1gzdCdgqZ6kWqG9TEQ42NGsucZjteUyHBi9siQEWVDyryyZ
DtQJ2uKSKdSGpEezSsYWCfolPVpYu2CcD390QtMoMm9J2XqbZljOhxOCayn7
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
/d/fRkZUcD0BAA==

-->

</rfc>
