<?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.23 (Ruby 3.4.1) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-mimi-protocol-03" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.27.0 -->
  <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-03"/>
    <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>Rohan Mahy Consulting Services</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="2025" month="March" day="03"/>
    <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 105?>

<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 117?>

<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. Concrete authorization policies
are defined in <xref target="I-D.ietf-mimi-room-policy"/>.</t>
          </dd>
          <dt>Knock and invite flows:</dt>
          <dd>
            <t>This document describes how user can be added, or how authorized users can
add themselves to a group based on the policy of the room. It does not include
flows where a user can "knock" to ask to enter a room, nor does it
include "invitations", where a user offers information to another user about
how to be added to a room.</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>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 <em>roles</em>
and their permissions (defined in <xref target="I-D.ietf-mimi-room-policy"/> and
<em>preauthorization</em> policy).</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 (defined in <xref target="participant-list"/>).</t>
            </li>
            <li>
              <t>Room metadata, such as the room name, description, and image (defined in
<xref target="room-metadata"/>).</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 as a list of adds, removes, and
role changes, as described in <xref target="participant-list"/>.</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", role: 4 (admin)],
     ["mimi://e.example/u/eric", role: 3 (moderator)],
Remove: ["mimi://b.example/u/bob"],
SetRole: [["mimi://c.example/u/cathy", role: 1 (banned)]]
]]></artwork>
          </figure>
          <t>To put these changes into effect, a client or server encodes them in an
AppDataUpdate <xref target="I-D.ietf-mls-extensions"/> 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 (a user URI in the participant list of 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 struct {
            uint8[32] serverFrank;
            uint8[32] franking_integrity_check;
          };
        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 generating an application message with the MIMI content format
<xref target="I-D.ietf-mimi-content"/>, the sender generates a per-message cryptographically
random 256-bit salt. (An example mechanism to safely generate the salt is
discussed in Section 8.2 of <xref target="I-D.ietf-mimi-content"/>.)</t>
            <t>Next the sender attaches to the message any 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 room URI and
the sender's user 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 /
{
  / RoomURI        / 1: "mimi://hub.example/r/Rl33FWLCYWOwxHrYnpWDQg",
  / SenderUserURI  / 2: "mimi://b.example/u/alice"
}
]]></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>salt</tt> in the MIMI content format:</t>
            <artwork><![CDATA[
franking_tag = HMAC_SHA256( salt, 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 provider integrity over the message metadata the Hub uses
(serverURI, roomURI) and adds (acceptedTimestamp, serverFrank) while franking.
It derives the <tt>franking_integrity_secret</tt>, using the label
"franking_integrity", 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="400" width="480" viewBox="0 0 480 400" 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,352" fill="none" stroke="black"/>
                    <path d="M 360,176 L 360,288" fill="none" stroke="black"/>
                    <path d="M 56,144 L 224,144" fill="none" stroke="black"/>
                    <polygon class="arrowhead" points="368,288 356,282.4 356,293.6" fill="black" transform="rotate(90,360,288)"/>
                    <polygon class="arrowhead" points="232,144 220,138.4 220,149.6" fill="black" transform="rotate(0,224,144)"/>
                    <polygon class="arrowhead" points="64,352 52,346.4 52,357.6" fill="black" transform="rotate(90,56,352)"/>
                    <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="312" y="164">=</text>
                      <text x="396" y="164">ap_exporter_secret</text>
                      <text x="64" y="228">DeriveSecret(.,</text>
                      <text x="160" y="228">"init")</text>
                      <text x="200" y="308">DeriveSecret(.,</text>
                      <text x="352" y="308">"franking_integrity")</text>
                      <text x="216" y="324">=</text>
                      <text x="328" y="324">franking_integrity_secret</text>
                      <text x="64" y="372">init_secret_[n]</text>
                    </g>
                  </svg>
                </artwork>
                <artwork type="ascii-art"><![CDATA[
         ...
          |
          |
          V
    ap_epoch_secret
          |
          |
          +--------------------> DeriveSecret(., "ap_exporter")
          |                               = ap_exporter_secret
          |                                     |
          |                                     |
          V                                     |
    DeriveSecret(., "init")                     |
          |                                     |
          |                                     |
          |                                     |
          |                                     V
          |          DeriveSecret(., "franking_integrity")
          |                   = franking_integrity_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_integrity_check = HMAC_SHA256(franking_integrity_secret,
  serverFrank || 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 <tt>franking_integrity_check</tt> is used by receivers to verify that the
values added by the Hub (the <tt>serverFrank</tt>, and <tt>acceptedTimestamp</tt>) were not
modified by a follower provider, and that the <tt>senderURI</tt> and <tt>roomURI</tt> match
those provided by the sending client.
The specific construction used is discussed in the Security Considerations
in <xref target="franking"/>.</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_integrity_check</tt>. Note that the <tt>senderURI</tt> is encrypted 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_integrity_check</tt>). If those fields are available, the client derives the
<tt>franking_integrity_secret</tt> from the <tt>ap_exporter_secret</tt> in the Associated
Party Key Schedule <xref target="I-D.kohbrok-mls-associated-parties"/>.</t>
            <t>Next it verifies the integrity of the <tt>serverFrank</tt>, <tt>acceptedTimestamp</tt>,
<tt>senderURI</tt>, and <tt>roomURI</tt> by calculating its own <tt>franking_integrity_check</tt>
from these values with the <tt>franking_integrity_secret</tt> and comparing it to the
provided <tt>franking_integrity_check</tt>.</t>
            <t>Finally it verifies the construction of the <tt>franking_tag</tt> from the content
of the message (including the embedded <tt>salt</tt>),
that the sender's identity in its credential in its MLS LeafNode matches
the sender's user identity asserted in the FrankingAssertion map inside the MIMI
Content, and that the RoomURI inside the MIMI Content matches the room ID in
the received message.</t>
            <t>The receiver needs to store the frank and context 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 MIMI
use case involves traffic which can transit multiple federated providers,
any of which may be compromised or malicious. The MIMI franking scheme
described here differs in the following ways.</t>
            <t>The sender
includes its <tt>franking_tag</tt> as Additional Authenticated Data (AAD) inside the end-to-end encrypted message. This insures that the <tt>franking_tag</tt> is not tampered with by the sender's provider.
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".</t>
            <t>In MLS, the Hub cannot view the sender identity in an application message,
so the sender sends its identity to the Hub. The hub never sends the
identity of the sender to receivers, since this would be observed by
follower providers. However, the receiver needs to verify that the sender
identity provided by the sender's provider to the Hub matches the identity
the receiver sees after it decrypts the message. Using a key shared between
members and the Hub (the <tt>franking_integrity_secret</tt>) the Hub sends an HMAC
of its context (sender identity, room id, and timestamp) and the serverFrank
with this key. The second change provides two functions. Itallows receivers to
validate the sender URI in the hub's context, without revealing the sender URI
to follower providers. It also prevents a follower provider from "mauling" the
serverFrank, or breaking the context comparison (by modifying the
<tt>acceptedTimestamp</tt>). Each receiver uses this to verify that the timestamp and
franking parameters added by the Hub were not modified.</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] serverFrank;
  uint8[32] franking_integrity_check;
} 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;
        case proposal:
           /* a list of additional proposals, each represented */
           /* as either PublicMessage or SemiPrivateMessage    */
           MLSMessage moreProposals<V>;
        case commit:
           struct {};
      };
  };
} 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 was obviously deleted.</t>
        <t>The <tt>moreProposals</tt> list in a <tt>FanoutMessage</tt> <bcp14>MUST</bcp14> be the same as the
corresponding <tt>moreProposals</tt> list in the <tt>HandshakeBundle</tt> of an
<tt>UpdateRequest</tt>.</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(requestingSignatureKey,          */
      /*    "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;
  opaque room_id<V>;
  GroupInfoCode status;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      ExternalSender hub_sender;
      HPKECiphertext encrypted_groupinfo_and_tree;
  };
} GroupInfoResponseTBS;

struct {
  Protocol version;
  opaque room_id<V>;
  GroupInfoCode status;
  select (status) {
    case success:
      select (protocol) {
        case mls10:
          CipherSuite cipher_suite;
          ExternalSender hub_sender;
          HPKECiphertext encrypted_groupinfo_and_tree;
          /* SignWithLabel(hub_sender, "GroupInfoResponseTBS", */
          /*                GroupInfoResponseTBS) */
          opaque signature<V>;
      };
  default: struct{};
  };
} 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 below. Each request can contain multiple
query elements, which all have to match for the request to match (AND
semantics). For example matching both the OpenID Connect (OIDC) <xref target="OidcCore"/>
          <tt>given_name</tt> and <tt>family_name</tt>, or matching the OIDC <tt>given_name</tt> and the
organization (from the vCard <xref target="RFC6350"/> ORG property).</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;
  select(type) {
    case oidcStdClaim:
      opaque claimName<V>;
    case vcardField:
      opaque propertyName<V>;
  };
  opaque searchValue<V>;  /* a UTF8 string */
} QueryElement;

struct {
  QueryElement query_elements<V>;
} IdentifierRequest;
]]></sourcecode>
        <t>The semantics of the <tt>SearchIdentifierType</tt> values are as follows. <tt>handle</tt>
means that the entire handle URI matches exactly (for example: <tt>im:alice.smith@a.example</tt>). <tt>nick</tt> means that the nickname or handle
user part matches exactly (for example: <tt>alice.smith</tt>). The same account or
human user may have multiple values which all match the <tt>nick</tt> field. <tt>email</tt>
means the <tt>addr-spec</tt> production from <xref target="RFC5322"/> matches the query string
exactly, for example (<tt>asmith@a.example</tt>). <tt>phone</tt> means the international
format of a telephone number with the "+" prefix matches exactly (for example:
<tt>+12125551212</tt>).</t>
        <t><tt>partialName</tt> means that the query string matches a case-insensitive substring
of any field which contains the name of a (usually human) user. For example,
<tt>mat</tt> would match first (given) or middle names Matt, Matthew, Mathias, or
Mathieu and last (family) names of Mather and Matali. <tt>wholeProfile</tt> means that
the query string matches a substring of any searchable field in
a user's profile.</t>
        <t><tt>oidcStdClaim</tt> means that the query string exactly matches the specified
UserInfo Standard Claim (defined in Section 5.1 of <xref target="OidcCore"/>).
<tt>vcardField</tt> means that the query string exactly matches the specified vCard
property listed in the vCard Properties IANA registry.</t>
        <t>As noted above, searches only return results for a user when the fields searched
are searchable according the user's and provider's search policies.</t>
        <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="minimal-metadata-rooms">
      <name>Minimal metadata rooms</name>
      <t>The room state is visible to the hub and with it the room's participant list,
giving the hub access to a significant amount of user metadata.</t>
      <t>To limit the amount of metadata the hub has access to, rooms can be created as
<em>minimal metadata rooms</em> (MMR). In an MMR the participant list and the
credentials in the room's underlying MLS group consist only of pseudonyms. The
real identifiers are stored alongside the pseudonyms encrypted under a key known
only to room participants, but not the hub.</t>
      <t>MMRs requires some additional key management, which leads to restrictions in how
the MMR can be joined and which users each participant can add to the room.</t>
      <section anchor="credential-encryption">
        <name>Credential encryption</name>
        <t>Identifiers of participants and their clients occur in two locations in a room's
state: the participant list and the credentials of the room's underlying MLS
group. In an MMR, the real identifiers of clients and users are replaced by
pseudonyms in the shape of random UUIDs qualified with the domain of the user's
provider.</t>
        <t>In MMRs, all leaves of the underlying group <bcp14>MUST</bcp14> contain PseudonymousCredentials.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  IdentifierUri client_pseudonym;
  IdentifierUri user_pseudonym;
  opaque signature_public_key;
  opaque identity_link_ciphertext<V>;
} PseudonymousCredential
]]></sourcecode>
        <ul spacing="normal">
          <li>
            <t><tt>user_pseudonym</tt>: The pseudonym of the client's user in this group</t>
          </li>
          <li>
            <t><tt>client_pseudonym</tt>: The pseudonym of the client identified by this credential</t>
          </li>
          <li>
            <t><tt>signature_public_key</tt>: The signature public key used to authenticate MLS
messages</t>
          </li>
          <li>
            <t><tt>identity_link_ciphertext</tt>: A ciphertext containing a credential with the
clients real identifier</t>
          </li>
        </ul>
        <t>In any given room, the <tt>user_pseudonym</tt> of a client <bcp14>MUST</bcp14> be the same across all
clients of a user and it <bcp14>MUST</bcp14> be the same as the user's entry in the participant
list.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  IdentifierUri client_pseudonym;
  IdentifierUri user_pseudonym;
  opaque signature_public_key;
} PseudonymousCredentialTBS

struct {
  /* SignWithLabel(., "PseudonymousCredentialTBS",
    PseudonymousCredentialTBS) */
  opaque pseudonymous_credential_signature<V>;
  Credential client_credential;
} IdentityLinkTBE
]]></sourcecode>
        <t>The <tt>identity_link_ciphertext</tt> is created by encrypting the IdentityLinkTBE.
The IdentityLinkTBE contains the client's real credential, and a signature over the
PseudonymousCredentialTBS signed with the client credential's <tt>signature_public_key</tt>.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Specify a key management scheme that ideally
- is efficient
- allows the basic MIMI flows
- ensures that all participants can learn the identities of all other
  participants at all times
- provides FS and PCS w.r.t. metadata hiding</t>
            <t>There are several options that represent different trade-offs, but are not yet
fully specified. They will be added at a later date.</t>
          </li>
        </ul>
      </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. Application state
that is stored in the MLS GroupContext is stored as application components
in the <tt>app_data_dictionary</tt> extension, as described in <xref section="4.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>.</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 anchor="participant-list">
        <name>Participant List</name>
        <t>The participant list is a list of "users" in a room. Within a room, each user
is assigned exactly one <em>role</em> (expressed with a <tt>role_index</tt> and described
in <xref target="I-D.ietf-mimi-room-policy"/> at any given time (specifically within any MLS
epoch). In a room that has multiple MLS clients per "user", the identifier for
each user in <tt>participants.user</tt> is the same across all that user's clients in
the room. Note that each user has a single role at any point in time, and
therefore all clients of the same user also have the same role.</t>
        <t>The participant list may include inactive participants, which currently do not
have any clients in the corresponding MLS group, for example if their clients
do not have available KeyPackages or if all of their clients are temporarily
"kicked" out of the group. The participant list can also contain participants
that are explicitly banned, by assigning them a suitable role which does not
have any capabilities.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  opaque user<V>;
  uint32 role_index;
} UserRolePair;

struct {
  UserRolePair participants<V>;
} ParticipantListData;
]]></sourcecode>
        <t>ParticipantListData is the format of the <tt>data</tt> field inside the ComponentData
struct for the Participant list Metadata component in the <tt>app_data_dictionary</tt>
GroupContext extension.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint32 user_index;
  uint32 role_index;
} UserindexRolePair;

struct {
  UserindexRolePair changedRoleParticipants<V>
  uint32 removedIndices<V>;
  UserRolePair addedParticipants<V>;
} ParticipantListUpdate;
]]></sourcecode>
        <t>ParticipantListUpdate is the contents of an AppDataUpdate Proposal with the
component ID for the participant list. The index of the <tt>participants</tt> vector
in the current <tt>ParticipantListData</tt> struct is referenced as the <tt>user_index</tt>
when making changes. First the <tt>changedRoleParticipants</tt> list contains
<tt>UserindexRolePair</tt>s with the index of a user who changed roles and their new
role. Next is the <tt>removedIndices</tt> list which has a list of users to remove
completely from the participant list. Finally there is a list of
<tt>addedParticipants</tt> (which contains a user and role) that is appended to the
end of the <tt>ParticipantListData</tt>.</t>
        <t>Each of these actions (modifying a user's role, removing a user, and adding a
user) is authorized separately according to the rules specified in
<xref target="I-D.ietf-mimi-room-policy"/>. If all the changes are authorized, the
<tt>ParticipantListData</tt> is modified accordingly.</t>
        <t>A single commit is not valid if it contain any combination of Participant list
updates that operate on (add, remove, or change the role of) the same user in
the participant list more than once.</t>
      </section>
      <section anchor="room-metadata">
        <name>Room Metadata</name>
        <t>The Room Metadata component contains data about a room which might be displayed
as human-readable information for the room, such as the name of the room and a
URL pointing to its room image/avatar.</t>
        <t>It can contain a list of <tt>room_descriptions</tt>, each of which can have a specific
<tt>language_tag</tt> and <tt>media_type</tt> along with the <tt>description_content</tt>. An empty
<tt>media_type</tt> implies <tt>text/plain;charset=utf-8</tt>.</t>
        <t>RoomMetaData is the format of the <tt>data</tt> field inside the ComponentData struct
for the Room Metadata component in the <tt>app_data_dictionary</tt> GroupContext
extension.</t>
        <sourcecode type="tls-presentation"><![CDATA[
/* a valid URI (ex: MIMI URI) */
struct {
  opaque uri<V>;
} Uri;

/* a sequence of valid UTF8 without nulls */
struct {
  opaque string<V>;
} UTF8String;

struct {
  /* an empty media_type is equivalent to text/plain;charset=utf-8 */
  opaque media_type<V>;
  opaque language_tag<V>;
  opaque description_content<V>;
} RichDescription;

struct {
  Uri room_uri;
  UTF8String room_name;
  RichDescription room_descriptions<V>;
  /* an https URI resolving to an avatar image */
  Uri room_avatar;
  UTF8String room_subject;
  UTF8String room_mood;
} RoomMetaData;

RoomMetaData RoomMetaUpdate;
]]></sourcecode>
        <t>RoomMetaUpdate (which has the same format as RoomMetaData) is the format of the
<tt>update</tt> field inside the AppDataUpdate struct in an AppDataUpdate Proposal for
the Room Metadata component.
If the contents of the <tt>update</tt> field are valid and if the proposer is
authorized to generate such an update, the value of the <tt>update</tt> field
completely replaces the value of the <tt>data</tt> field.</t>
        <t>Only a single Room metadata update is valid per 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>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Add MIMI threat model, and great expand this section.</t>
        </li>
      </ul>
      <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>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Present the franking mechanism to CFRG for review.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Add registration of MIMI content format extension, and a SafeAAD
component.</t>
        </li>
      </ul>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="OidcCore" target="https://openid.net/specs/openid-connect-core-1_0.html">
          <front>
            <title>OpenID Connect Core 1.0 incorporating errata set 2</title>
            <author initials="N." surname="Sakimura" fullname="Nat Sakimura">
              <organization/>
            </author>
            <author initials="J." surname="Bradley" fullname="John Bradley">
              <organization/>
            </author>
            <author initials="M. B." surname="Jones" fullname="Michael B. Jones">
              <organization/>
            </author>
            <author initials="B. de" surname="Medeiros" fullname="Breno de Medeiros">
              <organization/>
            </author>
            <author initials="C." surname="Mortimore" fullname="Chuck Mortimore">
              <organization/>
            </author>
            <date year="2023" month="December" day="15"/>
          </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" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9420.xml">
          <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" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
          <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" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
          <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>A Safe Application Interface to Messaging Layer Security</title>
            <author fullname="Joël" initials="" surname="Joël">
              <organization>Amazon</organization>
            </author>
            <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>
            <author fullname="Marta Mularczyk" initials="M." surname="Mularczyk">
              <organization>Amazon</organization>
            </author>
            <date day="12" month="December" year="2024"/>
            <abstract>
              <t>   The Messaging Layer Security protocol enables a group of participants
   to negotiate a common cryptographic state.  While the primary
   function of MLS is to establish shared secret state for the group, an
   MLS group also captures authentication information for group
   participants and information on which the group has confirmed
   agreement.  This document defines an interface interface by which
   multiple uncoordinated application functions may safely reuse the
   cryptographic state of an MLS group for application purposes.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-barnes-mls-appsync-01"/>
        </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-mimi-room-policy">
          <front>
            <title>Room Policy for the More Instant Messaging Interoperability (MIMI) Protocol</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="2" month="March" year="2025"/>
            <abstract>
              <t>   This document describes a set of concrete room policies for the More
   Instant Messaging Interoperability (MIMI) Working Group.  It
   describes several independent properties and policy attributes which
   can be combined to model a wide range of chat and multimedia
   conference types.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-room-policy-01"/>
        </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="19" month="February" year="2025"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol is an asynchronous group
   authenticated key exchange protocol.  MLS provides a number of
   capabilities to applications, as well as several extension points
   internal to the protocol.  This document provides a consolidated
   application API, guidance for how the protocol's extension points
   should be used, and a few concrete examples of both core protocol
   extensions and uses of the application API.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mls-extensions-06"/>
        </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>
        <reference anchor="I-D.ietf-mimi-content">
          <front>
            <title>More Instant Messaging Interoperability (MIMI) message content</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="20" month="December" year="2024"/>
            <abstract>
              <t>   This document describes content semantics common in Instant Messaging
   (IM) systems and describes a profile suitable for instant messaging
   interoperability of messages end-to-end encrypted inside the MLS
   (Message Layer Security) Protocol.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-content-05"/>
        </reference>
        <reference anchor="I-D.kohbrok-mls-associated-parties">
          <front>
            <title>MLS Associated parties</title>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="21" month="October" year="2024"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol allows a group of clients
   to exchange symmetric keys, agree on group state and send application
   messages.

   The main purpose of an MLS group is thus to facilitate agreement on
   group state and key material between the members of the group.  In
   some cases, however, it is useful to share agreement on the (public)
   group state, as well as key material with another party that is not a
   full member of the group.

   This document describes a safe extension to do just that.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-kohbrok-mls-associated-parties-00"/>
        </reference>
        <reference anchor="RFC6350" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6350.xml">
          <front>
            <title>vCard Format Specification</title>
            <author fullname="S. Perreault" initials="S." surname="Perreault"/>
            <date month="August" year="2011"/>
            <abstract>
              <t>This document defines the vCard data format for representing and exchanging a variety of information about individuals and other entities (e.g., formatted and structured name and delivery addresses, email address, multiple telephone numbers, photograph, logo, audio clips, etc.). This document obsoletes RFCs 2425, 2426, and 4770, and updates RFC 2739. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6350"/>
          <seriesInfo name="DOI" value="10.17487/RFC6350"/>
        </reference>
        <reference anchor="RFC5322">
          <front>
            <title>Internet Message Format</title>
            <author fullname="P. Resnick" initials="P." role="editor" surname="Resnick"/>
            <date month="October" year="2008"/>
            <abstract>
              <t>This document specifies the Internet Message Format (IMF), a syntax for text messages that are sent between computer users, within the framework of "electronic mail" messages. This specification is a revision of Request For Comments (RFC) 2822, which itself superseded Request For Comments (RFC) 822, "Standard for the Format of ARPA Internet Text Messages", updating it to reflect current practice and incorporating incremental changes that were specified in other RFCs. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="5322"/>
          <seriesInfo name="DOI" value="10.17487/RFC5322"/>
        </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 2197?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to Paul Grubs, Jon Millican, and Julia Len for their reviews of the
franking mechanism and suggested changes.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+2963bbRpYw+r+eAqNe64RySMqyk3Ta6U5alu1Y03bskeTO
5OuVZYIkJGJEAhwAtKxxu5/lPMt5srOvVbsAUBfHPfOdi38kIokqVO3ate+X
0WjkmrxZZo+SnZdllSVHRd2kRZO8zOo6Pc+Lc/imyapynVXpNF/mzVUyeHn0
8mg32dT46/PT09cnSVrMk5cvTnZcOp1W2TucDJ75Er5KXldlU87K5Y6bpU12
XlZXj5K6mTs3L2dFuoIXz6v0rBnlWXM2WuWrfLSWEaP7D129ma7yus7Lorla
w7NHT0+fJcnvknRZl/CWvJhn6wz+UzQ7w2Qnm+dNWeXpEj8cHTyG/5UV/HV8
+mzHFZvVNKseuTks45GblUWdFfWmfpQ01SZzsOaHLq2yFGY9WK+XOawW3lrT
1o6zdDk6zVfZjrssq4vzqtysbw+wHXeRXcG4+SOXjBLcIv4/D08ts2Slo/Gn
2SJt8P91NttU9rd3WbGBtSfJnVeQJAy/nZ9h/fjIjzgDfr9K8yV8j8v6M57B
uKzO8fu0mi3g+0XTrOtHe3v4GH6Vv8vG+tgefrE3rcrLOtvDCfZw4HneLDZT
GDrNzzYVg3Gve7r46BKOom7MW8yQMc8zzsuewXuMMxWgQVMW8W/jRbOC2V26
aRZlhTCHNyXJ2Wa5ZHw7zgHA1Tx5MU4ep1WR1fQ77Cct8v+idz9KDvN6VtL3
GQOoWk7/nK/fjev33Qlfpk2zyC6T5+X8vC6LnulOFxk+VeXvEW7Js3JTzOmn
5HB8ND4c2zeteLY/r/zz3Tf+pSyqdA7/WwD0L3pe+HpRZkX+Pjn+P57YuS9o
3PiCx/0Z1pDWiyovsvE86wFUuUgLWPfiqucN4cfkEO7JZtkgWp1k1bt8JiBV
0OGThDR/PsdvxrNy1X3ZaZW+y+vkmI/0N8Kwocmqa2F4nK4XabaEjQBZaG4P
Q9pIxYMrGksbckVZwevgfjyip1/l89khXE/+hP+atDrPANsV2eGCFvl8XGTN
Xr3OZrV8MQLSVGSzBv5fZaP9t/cJocMsQq1fwcNHTxD2+HCCr0r2x/eBrsC4
dVmldB5ZBX+kQEma5MGOn4NIYPLg/oOHo/0Ho/2v/Q/+zoR/o4TB9VPaJCfp
Rb7aVGnf7/9aLorkMWDXMrvq+/0l3joA9+MxPKqXrvXM4yorymQO55zNs7wq
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
QhrM5vycWy2oH9L93xptFumNaAEA

-->

</rfc>
