<?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.29 (Ruby 3.4.1) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-mimi-protocol-05" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.31.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-05"/>
    <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="October" day="20"/>
    <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}",
  "proxyDownload"
     "https://mimi.example.com/v1/proxyDownload/{downloadUrl}"
}
]]></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 URI (with any necessary percent-encoding). 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.
Next there is an MLS <tt>RequiredCapabilities</tt> object, which contains (possibly
empty) lists of required credential types, non-default proposal types, and
extensions) required by the requesting provider. Next there is a
SignaturePublicKey and a corresponding Credential for the requester. Finally,
the request includes a signature, using the SignaturePublicKey and covering
KeyMaterialRequestTBS.</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;
            SignaturePublicKey requesterSignatureKey;
            Credential requesterCredential;
            /* SignWithLabel(requesterSignatureKey,              */
            /*   "KeyMaterialRequestTBS", KeyMaterialRequestTBS) */
            opaque key_material_request_signature<V>;
    };
} KeyMaterialRequest;

struct {
    Protocol protocol;
    IdentifierUri requestingUser;
    IdentifierUri targetUser;
    IdentifierUri roomId;
    select (protocol) {
        case mls10:
            CipherSuite acceptableCiphersuites<V>;
            RequiredCapabilities requiredCapabilities;
            SignaturePublicKey requesterSignatureKey;
            Credential requesterCredential;
    };
} KeyMaterialRequestTBS;

key_material_request_signature = SignWithLabel(requesterSignatureKey
                      "KeyMaterialRequestTBS", KeyMaterialRequestTBS)
]]></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 accepted_timestamp;
    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>franking_tag</tt> was included in the <tt>frank_aad</tt> component <xref target="iana-frank-aad"/> in
the PrivateMessage Additional Authenticated Data (AAD) in the request, the
server attempts to frank the message and includes the <tt>server_frank</tt> in a
successful response (see the next subsection).</t>
        <sourcecode type="tls"><![CDATA[
enum {
  accepted(0),
  notAllowed(1),
  epochTooOld(2),
  (255)
} SubmitResponseCode;

struct {
  uint8 server_frank[32];
  CipherSuite franking_signature_ciphersuite;
  opaque franking_integrity_signature<V>;
} Frank;

struct {
  Protocol protocol;
  select(protocol) {
    case mls10:
      SubmitResponseCode statusCode;
      select (statusCode) {
        case success:
          /* the hub acceptance time
             (in milliseconds from the UNIX epoch) */
          uint64 accepted_timestamp;
          optional Frank frank;
        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>
          <t>MIMI franking relies on two new MLS application components. The first is the
<tt>frank_aad</tt> Safe AAD component <xref section="4.9" sectionFormat="of" target="I-D.ietf-mls-extensions"/>. The
second is the <tt>franking_agent</tt> GroupContext component <xref section="4.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>. The structure of <tt>franking_agent</tt> mirrors that of
the <tt>ExternerSender</tt> struct described in <xref section="12.1.8.1" sectionFormat="of" target="RFC9420"/>. It
contains a single signature key.</t>
          <sourcecode type="tls"><![CDATA[
struct {
  uint8 franking_tag[32];
} FrankAAD;

FrankAAD frank_aad;

struct {
  SignaturePublicKey franking_signature_key;
  Credential credential;
} FrankingAgentData;

FrankingAgentData franking_agent;
FrankingAgentData FrankingAgentUpdate;
]]></sourcecode>
          <t>The signature algorithm of the <tt>franking_signature_key</tt> is the same as the
signature algorithm of cipher suite of the MLS group which corresponds to the
room.</t>
          <t>FrankingAgentUpdate is the format of the <tt>update</tt> field inside the AppDataUpdate
struct in an AppDataUpdate Proposal for the <tt>franking_agent</tt> component. The use
of AppDataUpdate on the <tt>franking_agent</tt> is <bcp14>RECOMMENDED</bcp14> only when adding a new
<tt>franking_agent</tt>. To avoid confusion about which signature key to use, when an
MLS client rotates the <tt>franking_agent</tt>, the client <bcp14>SHOULD</bcp14> create a new MLS
group by sending a ReInit proposal.</t>
          <section anchor="client-creation-and-sending">
            <name>Client creation and sending</name>
            <t>The franking mechanism requires any franked message format to contain a random
salt, the sender URI, and the room URI. This section describes the exact way to
extract these fields from the MIMI content format <xref target="I-D.ietf-mimi-content"/>.
Other message formats would need to describe how to locate or derive these
values.</t>
            <t>The MIMI content format includes a per-message, mandatory, cryptographically
random 128-bit salt generated by the sender. (An example mechanism to safely
generate the salt is discussed in Section 8.2 of <xref target="I-D.ietf-mimi-content"/>.)</t>
            <t>The sender of a MIMI content message 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 includes the sender's user URI and room URI in
the MIMI content extensions map (see definitions in <xref section="8.3" sectionFormat="of" target="I-D.ietf-mimi-content"/>).</t>
            <sourcecode type="cbor-diag"><![CDATA[
/ MIMI content extensions map /
{
  / sender_uri / 1: "mimi://b.example/u/alice",
  / room_uri   / 2: "mimi://hub.example/r/Rl33FWLCYWOwxHrYnpWDQg"
}
]]></sourcecode>
            <t>Note that these assertions do 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 values in the extensions map above)
using the <tt>salt</tt> in the MIMI content format:</t>
            <ul empty="true">
              <li>
                <t>Note that when the content advertisement mechanism in {Section 6.2 of
!I-D.ietf-mls-extensions} is used, the <tt>application_data</tt> includes the
<tt>media_type</tt> in the <tt>ApplicationFraming</tt> struct.</t>
              </li>
            </ul>
            <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 <tt>frank_aad</tt> Safe AAD component. 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 server_frank (generated
by the server).</t>
          </section>
          <section anchor="hub-processing">
            <name>Hub processing</name>
            <t>When a valid <tt>franking_agent</tt> application component <xref target="iana-franking-sig-key"/> is
present in the GroupContext, the Hub can frank messages, and sign the frank with
the Hub's <tt>franking_private_key</tt> corresponding to the <tt>franking_signature_key</tt>
in the FrankingAgentData struct.</t>
            <t>When the Hub receives an acceptable application message with the <tt>frank_aad</tt>
Safe AAD component and a valid sender identity, it calculates a server frank for
the message, and a <tt>franking_integrity_signature</tt> as follows:</t>
            <sourcecode type="tls"><![CDATA[
struct {
    IdentifierUri sender_uri;
    IdentifierUri room_uri;
    uint64 accepted_timestamp;
} ServerFrankingContext;

ServerFrankingContext context;

server_frank = HMAC_SHA256(hub_key, (franking_tag || context) )

struct {
    opaque server_frank[32];
    CipherSuite franking_signature_ciphersuite;
    ServerFrankingContext context;
} FrankingIntegrityTBS;

franking_integrity_signature = SignWithLabel(franking_private_key,
    "FrankingIntegrityTBS", FrankingIntegrityTBS)
]]></sourcecode>
            <t><tt>hub_key</tt> is a secret symmetric key used on the Hub which the Hub can use to
verify its own <tt>server_frank</tt>.</t>
            <t>The <tt>franking_integrity_signature</tt> is used by receivers to verify that the
values added by the Hub (the <tt>server_frank</tt>, and <tt>accepted_timestamp</tt>) were not
modified by a follower provider, and that the <tt>sender_uri</tt> and <tt>room_uri</tt> match
those provided by the sending client.
The <tt>franking_signature_ciphersuite</tt> is the MLS cipher suite in use at the time
the message is franked. It is used to insure that a frank contains the
signature algorithm used to generate the <tt>franking_integrity_signature</tt>.
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>server_frank</tt>, the <tt>accepted_timestamp</tt>, the room URI, the
<tt>franking_signature_ciphersuite</tt> and the <tt>franking_integrity_signature</tt>.
Note that the <tt>sender_uri</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>server_frank</tt>, the
<tt>franking_signature_ciphersuite</tt> and the <tt>franking_integrity_signature</tt>). If
those fields are available, and the <tt>franking_signature_ciphersuite</tt> matches the
MLS cipher suite in-use, the client looks for the <tt>franking_agent</tt>
application component in the GroupContext. It verifies the domain name in the
<tt>franking_agent.credential</tt> corresponds to the domain of the Hub, and extracts
the <tt>franking_signature_key</tt>.</t>
            <t>Next it verifies the integrity of the <tt>server_frank</tt>, <tt>accepted_timestamp</tt>,
<tt>sender_uri</tt>, and <tt>room_uri</tt> by calculating the <tt>ServerFrankingContext</tt> and
<tt>FrankingIntegrityTBS</tt>, and verifying the <tt>franking_integrity_signature</tt> as
described below.</t>
            <artwork><![CDATA[
VerifyWithLabel(franking_signature_key, "FrankingIntegrityTBS",
     FrankingIntegrityTBS, franking_integrity_signature)
]]></artwork>
            <t>Finally it verifies the construction of the <tt>franking_tag</tt> from the content
format of the message (including the embedded <tt>salt</tt>),
that the sender's identity in its credential in its MLS LeafNode matches
the <tt>sender_uri</tt> asserted in the extensions map inside the MIMI Content, and
that the <tt>room_uri</tt> asserted in the extensions map inside the MIMI Content
matches the room ID in the received message.</t>
            <t>The receiver needs to store the <tt>server_frank</tt>,
<tt>franking_signature_ciphersuite</tt>, <tt>franking_integrity_signature</tt>, and <tt>context</tt>
fields with the decoded message, so they 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>Firstly, the sender includes its <tt>franking_tag</tt> application component 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 the
<tt>franking_integrity_signature</tt> generated by the Hub, receivers can verify the
message context (sender identity, room id, and timestamp) and the server_frank
with the <tt>franking_signature_key</tt> in the <tt>franking_agent</tt> component in the
GroupContext.
This second change provides two functions. It allows receivers to
validate the <tt>sender_uri</tt> in the hub's context, without revealing the sender URI
to follower providers. It also prevents a follower provider from modifying the
server_frank, or any elements of the context (ex: modifying the
<tt>accepted_timestamp</tt>) without detection. A valid signature ensures
that follower providers did not tamper with the context or the server_frank.</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>
        <ul empty="true">
          <li>
            <t>An external commit will invalidate certain pending proposals. For example, if
the hub generates Remove proposals to remove a lost client or a deleted user,
an external commit can invalidate pending Remove proposals. The hub would then
be expected to regenerate any relevant, comparable proposals in the new epoch.
To prevent a race condition where a member commit arrives before the
regenerated proposals arrive, the hub can staple regenerated proposals to an
external commit during the fanout process.</t>
          </li>
        </ul>
        <t>The hub can include multiple concatenated <tt>FanoutMessage</tt> objects relevant to
the same room. This endpoint uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /notify/{roomId}
]]></artwork>
        <sourcecode type="tls"><![CDATA[
struct {
  /* the hub acceptance time (in milliseconds from the UNIX epoch) */
  uint64 timestamp;
  select (protocol) {
    case mls10:
      /* A PrivateMessage containing an application message, */
      /* a SemiPrivateMessage or 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:
           /* If this was an external commit, and any pending      */
           /* proposals were invalidated, staple the new epoch's   */
           /* replacement proposals (from the hub) to the commit   */
           /* commit */
           MLSMessage externalProposals<V>;
      };
  };
} 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.signature_key,        */
          /*  "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
<tt>message_content</tt>, its <tt>server_frank</tt>, its <tt>franking_signature_ciphersuite</tt>,
its <tt>franking_integrity_signature</tt>, and its <tt>accepted_timestamp</tt>.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  /* the message content (ex: MIMI Content message) containing */
  /* allegedly abusive content                                 */
  opaque message_content<V>;
  Frank frank;
  uint64 accepted_timestamp;
} 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>
        <t>To validate an allegedly AbusiveMessage, the hub finds the salt, sender URI, and
room URI inside the <tt>message_content</tt> and the <tt>accepted_timestamp</tt> to
recalculate the <tt>franking_tag</tt> and <tt>context</tt>. Then the hub selects its relevant
<tt>hub_key</tt> to regenerate the <tt>server_frank</tt>. Finally the hub verifies its
<tt>franking_integrity_signature</tt> using the signature algorithm embedded in the
<tt>franking_signature_ciphersuite</tt>.</t>
      </section>
      <section anchor="download-files">
        <name>Download Files</name>
        <t>IM systems make extensive use of inline images, videos, and sounds, and often
include attached files, all of which will be referred to as "assets" in this
section. Assets are stored (encrypted) on various external servers, and
typically uploaded and fetched using HTTP <xref target="RFC9110"/> protected with TLS
<xref target="RFC8446"/>.</t>
        <ul empty="true">
          <li>
            <t>In a MIMI content <xref target="I-D.ietf-mimi-content"/> message, the download URI is an
<tt>https</tt> URL conveyed in the <tt>uri</tt> field in an <tt>ExternalPart</tt> in a MIMI
content message.</t>
          </li>
        </ul>
        <t>Broadly, two approaches are possibly for storage of assets in federated IM
systems. In the vast majority of deployed systems, the assets are uploaded to
the local provider of the uploader. With the other approach, the assets are
uploaded to the equivalent of the Hub system. MIMI is capable of asset
downloads for both of these approaches.</t>
        <t>The client consults the intersection of the room policy and its local policy to
determine if and how to upload assets, where to upload them, and with which
credentials. The details of the upload process are out of scope of this
document.</t>
        <t>The MIMI room policy <xref target="I-D.ietf-mimi-room-policy"/> in the group's GroupContext
includes an <tt>asset_policy</tt> component that specifies which domain name to use
for asset download for each potential asset provider. This prevents the
download proxy from using a host part associated with the same domain that is
not used for the storage of MIMI assets.</t>
        <t>For downloads, the clients can use any of three methods to download assets. The
hub is not involved in the first and is required to implement support for the
other two methods.</t>
        <section anchor="direct-download">
          <name>Direct download</name>
          <t>Without any additional MIMI protocol mechanism, MIMI clients can download assets
directly from the asset provider. Unfortunately this usually reveals sensitive
private information about the client. In this case, the asset provider learns
the IP address of the client, and timing information about when assets are
downloaded, which is strongly linked with online presence. The asset provider
can correlate other clients downloading the same assets and infer which clients
are in which rooms. For this reason, direct client downloads of assets,
especially from an asset provider which is not the download client's provider,
are <bcp14>NOT RECOMMENDED</bcp14>.</t>
        </section>
        <section anchor="download-using-a-hub-proxy">
          <name>Download using a hub proxy</name>
          <t>The hub offers the <tt>proxyDownload</tt> endpoint to proxy asset requests from
downloading providers to known asset providers. This allows clients to hide
their IP addresses from the asset provider (and the hub), although the hub and
the downloading provider are still privy to the request.</t>
          <t>The <tt>proxyDownload</tt> endpoint includes the target asset URL, but does not include
the specific room or requester. When the provider hosting the asset has several
rooms hosted by the hub, the provider also does not directly learn with which
room to associate a specific asset.</t>
          <t>As with other MIMI protocol endpoints, the actual endpoint URL is discovered
using the MIMI protocol directory <xref target="directory"/>.</t>
          <artwork><![CDATA[
GET /proxyDownload/{downloadUrl}
]]></artwork>
          <t>The downloading provider sends the request to the hub. The hub <bcp14>MUST</bcp14> verify that
the host part of the <tt>downloadUrl</tt> is associated with the asset server domain
for one of its peer providers. This prevents the hub from becoming an open
proxy.</t>
          <t>The overall flow is as shown below.</t>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="568" viewBox="0 0 568 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,320" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,320" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,320" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,320" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,320" 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 408,96 Q 410,92.8 412,96 Q 414,99.2 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 " fill="none" stroke="black"/>
                <path d="M 416,144 Q 418,140.8 420,144 Q 422,147.2 424,144 Q 426,140.8 428,144 Q 430,147.2 432,144 Q 434,140.8 436,144 Q 438,147.2 440,144 Q 442,140.8 444,144 Q 446,147.2 448,144 Q 450,140.8 452,144 Q 454,147.2 456,144 Q 458,140.8 460,144 Q 462,147.2 464,144 Q 466,140.8 468,144 Q 470,147.2 472,144 Q 474,140.8 476,144 Q 478,147.2 480,144 Q 482,140.8 484,144 Q 486,147.2 488,144 Q 490,140.8 492,144 Q 494,147.2 496,144 Q 498,140.8 500,144 Q 502,147.2 504,144 Q 506,140.8 508,144 Q 510,147.2 512,144 Q 514,140.8 516,144 Q 518,147.2 520,144 Q 522,140.8 524,144 Q 526,147.2 528,144 Q 530,140.8 532,144 Q 534,147.2 536,144 " fill="none" stroke="black"/>
                <path d="M 288,160 L 408,160" fill="none" stroke="black"/>
                <path d="M 160,176 L 400,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"/>
                <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 24,240 Q 26,236.8 28,240 Q 30,243.2 32,240 Q 34,236.8 36,240 Q 38,243.2 40,240 Q 42,236.8 44,240 Q 46,243.2 48,240 Q 50,236.8 52,240 Q 54,243.2 56,240 Q 58,236.8 60,240 Q 62,243.2 64,240 Q 66,236.8 68,240 Q 70,243.2 72,240 Q 74,236.8 76,240 Q 78,243.2 80,240 Q 82,236.8 84,240 Q 86,243.2 88,240 Q 90,236.8 92,240 Q 94,243.2 96,240 Q 98,236.8 100,240 Q 102,243.2 104,240 Q 106,236.8 108,240 Q 110,243.2 112,240 Q 114,236.8 116,240 Q 118,243.2 120,240 Q 122,236.8 124,240 Q 126,243.2 128,240 Q 130,236.8 132,240 Q 134,243.2 136,240 Q 138,236.8 140,240 Q 142,243.2 144,240 " fill="none" stroke="black"/>
                <path d="M 152,256 L 272,256" fill="none" stroke="black"/>
                <path d="M 280,272 L 400,272" fill="none" stroke="black"/>
                <path d="M 288,288 L 408,288" fill="none" stroke="black"/>
                <path d="M 160,304 L 280,304" fill="none" stroke="black"/>
                <path d="M 32,320 Q 34,316.8 36,320 Q 38,323.2 40,320 Q 42,316.8 44,320 Q 46,323.2 48,320 Q 50,316.8 52,320 Q 54,323.2 56,320 Q 58,316.8 60,320 Q 62,323.2 64,320 Q 66,316.8 68,320 Q 70,323.2 72,320 Q 74,316.8 76,320 Q 78,323.2 80,320 Q 82,316.8 84,320 Q 86,323.2 88,320 Q 90,316.8 92,320 Q 94,323.2 96,320 Q 98,316.8 100,320 Q 102,323.2 104,320 Q 106,316.8 108,320 Q 110,323.2 112,320 Q 114,316.8 116,320 Q 118,323.2 120,320 Q 122,316.8 124,320 Q 126,323.2 128,320 Q 130,316.8 132,320 Q 134,323.2 136,320 Q 138,316.8 140,320 Q 142,323.2 144,320 Q 146,316.8 148,320 Q 150,323.2 152,320 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="536,192 524,186.4 524,197.6" fill="black" transform="rotate(0,528,192)"/>
                <polygon class="arrowhead" points="536,96 524,90.4 524,101.6" fill="black" transform="rotate(0,528,96)"/>
                <polygon class="arrowhead" points="424,144 412,138.4 412,149.6" fill="black" transform="rotate(180,416,144)"/>
                <polygon class="arrowhead" points="424,80 412,74.4 412,85.6" fill="black" transform="rotate(180,416,80)"/>
                <polygon class="arrowhead" points="408,272 396,266.4 396,277.6" fill="black" transform="rotate(0,400,272)"/>
                <polygon class="arrowhead" points="408,176 396,170.4 396,181.6" fill="black" transform="rotate(0,400,176)"/>
                <polygon class="arrowhead" points="296,288 284,282.4 284,293.6" fill="black" transform="rotate(180,288,288)"/>
                <polygon class="arrowhead" points="296,160 284,154.4 284,165.6" fill="black" transform="rotate(180,288,160)"/>
                <polygon class="arrowhead" points="280,256 268,250.4 268,261.6" fill="black" transform="rotate(0,272,256)"/>
                <polygon class="arrowhead" points="168,304 156,298.4 156,309.6" fill="black" transform="rotate(180,160,304)"/>
                <polygon class="arrowhead" points="168,176 156,170.4 156,181.6" fill="black" transform="rotate(180,160,176)"/>
                <polygon class="arrowhead" points="152,240 140,234.4 140,245.6" fill="black" transform="rotate(0,144,240)"/>
                <polygon class="arrowhead" points="40,320 28,314.4 28,325.6" fill="black" transform="rotate(180,32,320)"/>
                <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="276" y="36">HubA</text>
                  <text x="400" y="36">ServerC</text>
                  <text x="532" y="36">ClientC1</text>
                  <text x="452" y="68">Upload</text>
                  <text x="504" y="68">asset</text>
                  <text x="436" y="116">send</text>
                  <text x="488" y="116">message</text>
                  <text x="428" y="132">w/</text>
                  <text x="464" y="132">asset</text>
                  <text x="508" y="132">link</text>
                  <text x="364" y="148">submit</text>
                  <text x="228" y="164">fanout</text>
                  <text x="56" y="212">fetch</text>
                  <text x="104" y="212">asset</text>
                  <text x="48" y="228">via</text>
                  <text x="72" y="228">B</text>
                  <text x="96" y="228">and</text>
                  <text x="128" y="228">hub</text>
                  <text x="216" y="244">proxyDownload</text>
                  <text x="304" y="260">GET</text>
                  <text x="344" y="260">asset</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientB1       ServerB          HubA          ServerC         ClientC1
  |               |               |               |               |
  |               |               |               |  Upload asset |
  |               |               |               |<~~~~~~~~~~~~~~+
  |               |               |               +~~~~~~~~~~~~~~>|
  |               |               |               | send message  |
  |               |               |               | w/ asset link |
  |               |               |       submit  |<~~~~~~~~~~~~~~+
  |               |      fanout   |<--------------+               |
  |               |<--------------+-------------->|               |
  |<~~~~~~~~~~~~~~+               |               +~~~~~~~~~~~~~~>|
  | fetch asset   |               |               |               |
  | via B and hub |               |               |               |
  +~~~~~~~~~~~~~~>| proxyDownload |               |               |
  |               +-------------->| GET asset     |               |
  |               |               +-------------->|               |
  |               |               |<--------------+               |
  |               |<--------------+               |               |
  |<~~~~~~~~~~~~~~+               |               |               |
]]></artwork>
          </artset>
          <t>If the request succeeds, the response body contains the contents of the
downloaded URL. The hub can reject <tt>proxyDownload</tt> requests by replying with
standard HTTP error codes.</t>
          <t>In terms of the privacy of this mechanism, the hub only sees that a specific
provider requested an (opaque to the hub) URL from another provider. It does not
know the room or the specific client.
The asset provider sees requests for an (encrypted) asset coming from the hub
provider. When caching is employed, the asset provider will only see periodic
requests.
The receiver's provider will see one request to the hub, among presumably many
requests. It has no information about the sender, URL, or room associated with
that request, however it can collect the domains of specific asset providers,
and it can use timing analysis to correlate incoming messages (which are
associated with a room) and outgoing <tt>proxyDownload</tt> requests.</t>
          <t>Both the downloading provider and the hub can cache requests. This would tend to
hide from the asset provider the number of downloading participants in a
specific room, and make it more difficult for the hub to correlate a URL with a
specific room based on the number of participants.</t>
          <t>The proxy download method improves the privacy of the clients with respect to
the asset provider, and to some extent with the hub, but it still allows the
downloading provider to correlate URLs with downloading users and infer which
URLs are sent in which rooms.</t>
          <t>The hub is <bcp14>REQUIRED</bcp14> to implement this mechanism.</t>
        </section>
        <section anchor="download-using-oblivious-http">
          <name>Download using Oblivious HTTP</name>
          <t>Oblivious HTTP (OHTTP) <xref target="RFC9458"/> is a mechanism for the encapsulation of HTTP
requests that provides a variety of desirable privacy properties. It provides
the best privacy of the download mechanisms described here, but requires the
client to implement an additional protocol.</t>
          <t>Using OHTTP for asset download privacy works as follows. The clients sends an
OHTTP request to the downloading provider's OHTTP Relay which forwards the
request to the hub's OHTTP Gateway. The hub then sends a GET request for the
asset to the asset provider (the Target)</t>
          <t>The hub <bcp14>MUST</bcp14> only accept OHTTP requests to Targets which are configured as asset
storage locations for one of its peer providers.</t>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="568" viewBox="0 0 568 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,320" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,320" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,320" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,320" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,320" 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 408,96 Q 410,92.8 412,96 Q 414,99.2 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 " fill="none" stroke="black"/>
                <path d="M 416,144 Q 418,140.8 420,144 Q 422,147.2 424,144 Q 426,140.8 428,144 Q 430,147.2 432,144 Q 434,140.8 436,144 Q 438,147.2 440,144 Q 442,140.8 444,144 Q 446,147.2 448,144 Q 450,140.8 452,144 Q 454,147.2 456,144 Q 458,140.8 460,144 Q 462,147.2 464,144 Q 466,140.8 468,144 Q 470,147.2 472,144 Q 474,140.8 476,144 Q 478,147.2 480,144 Q 482,140.8 484,144 Q 486,147.2 488,144 Q 490,140.8 492,144 Q 494,147.2 496,144 Q 498,140.8 500,144 Q 502,147.2 504,144 Q 506,140.8 508,144 Q 510,147.2 512,144 Q 514,140.8 516,144 Q 518,147.2 520,144 Q 522,140.8 524,144 Q 526,147.2 528,144 Q 530,140.8 532,144 Q 534,147.2 536,144 " fill="none" stroke="black"/>
                <path d="M 288,160 L 408,160" fill="none" stroke="black"/>
                <path d="M 160,176 L 400,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"/>
                <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 24,238 L 144,238" fill="none" stroke="black"/>
                <path d="M 24,242 L 144,242" fill="none" stroke="black"/>
                <path d="M 280,272 L 400,272" fill="none" stroke="black"/>
                <path d="M 288,288 L 400,288" fill="none" stroke="black"/>
                <path d="M 32,318 L 144,318" fill="none" stroke="black"/>
                <path d="M 32,322 L 144,322" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="536,192 524,186.4 524,197.6" fill="black" transform="rotate(0,528,192)"/>
                <polygon class="arrowhead" points="536,96 524,90.4 524,101.6" fill="black" transform="rotate(0,528,96)"/>
                <polygon class="arrowhead" points="424,144 412,138.4 412,149.6" fill="black" transform="rotate(180,416,144)"/>
                <polygon class="arrowhead" points="424,80 412,74.4 412,85.6" fill="black" transform="rotate(180,416,80)"/>
                <polygon class="arrowhead" points="408,272 396,266.4 396,277.6" fill="black" transform="rotate(0,400,272)"/>
                <polygon class="arrowhead" points="408,176 396,170.4 396,181.6" fill="black" transform="rotate(0,400,176)"/>
                <polygon class="arrowhead" points="296,288 284,282.4 284,293.6" fill="black" transform="rotate(180,288,288)"/>
                <polygon class="arrowhead" points="296,160 284,154.4 284,165.6" fill="black" transform="rotate(180,288,160)"/>
                <polygon class="arrowhead" points="168,176 156,170.4 156,181.6" fill="black" transform="rotate(180,160,176)"/>
                <polygon class="arrowhead" points="152,240 140,234.4 140,245.6" fill="black" transform="rotate(0,144,240)"/>
                <polygon class="arrowhead" points="40,320 28,314.4 28,325.6" fill="black" transform="rotate(180,32,320)"/>
                <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="276" y="36">HubA</text>
                  <text x="400" y="36">ServerC</text>
                  <text x="532" y="36">ClientC1</text>
                  <text x="452" y="68">Upload</text>
                  <text x="504" y="68">asset</text>
                  <text x="436" y="116">send</text>
                  <text x="488" y="116">message</text>
                  <text x="428" y="132">w/</text>
                  <text x="464" y="132">asset</text>
                  <text x="508" y="132">link</text>
                  <text x="364" y="148">submit</text>
                  <text x="228" y="164">fanout</text>
                  <text x="56" y="212">fetch</text>
                  <text x="104" y="212">asset</text>
                  <text x="56" y="228">OHTTP</text>
                  <text x="112" y="228">wrapped</text>
                  <text x="184" y="244">OHTTP</text>
                  <text x="216" y="260">::::::::::::::&gt;</text>
                  <text x="304" y="260">GET</text>
                  <text x="344" y="260">asset</text>
                  <text x="216" y="308">&lt;::::::::::::::</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientB1       ServerB          HubA          ServerC         ClientC1
  |               |               |               |               |
  |               |               |               |  Upload asset |
  |               |               |               |<~~~~~~~~~~~~~~+
  |               |               |               +~~~~~~~~~~~~~~>|
  |               |               |               | send message  |
  |               |               |               | w/ asset link |
  |               |               |       submit  |<~~~~~~~~~~~~~~+
  |               |      fanout   |<--------------+               |
  |               |<--------------+-------------->|               |
  |<~~~~~~~~~~~~~~+               |               +~~~~~~~~~~~~~~>|
  | fetch asset   |               |               |               |
  | OHTTP wrapped |               |               |               |
  +==============>| OHTTP         |               |               |
  |               +::::::::::::::>| GET asset     |               |
  |               |               +-------------->|               |
  |               |               |<--------------|               |
  |               |<::::::::::::::+               |               |
  |<==============|               |               |               |
]]></artwork>
          </artset>
          <t>For the hub, an OHTTP Gateway is <bcp14>REQUIRED</bcp14> to implement. The hub <bcp14>SHOULD</bcp14> provide
the OHTTP Gateway capability for its peer providers.</t>
          <t>Other providers <bcp14>SHOULD</bcp14> implement the OHTTP Relay capability and <bcp14>SHOULD</bcp14> enable
the relay to access</t>
          <t>The main benefit of this mechanism is that the downloading provider does not
learn the domains of every asset provider.</t>
        </section>
      </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;

ParticipantListData participant_list;
]]></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 room_metadata;

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>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document registers the following four MLS application components per
<xref section="7.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>.</t>
      <section anchor="iana-frank-aad">
        <name>frank_aad app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD1</t>
          </li>
          <li>
            <t>Name: frank_aad</t>
          </li>
          <li>
            <t>Where: AD</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
      <section anchor="iana-franking-sig-key">
        <name>franking_signature_key app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD2</t>
          </li>
          <li>
            <t>Name: franking_signature_key</t>
          </li>
          <li>
            <t>Where: GC</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
      <section anchor="participantlist-app-component">
        <name>participant_list app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD3</t>
          </li>
          <li>
            <t>Name: participant_list</t>
          </li>
          <li>
            <t>Where: GC</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
      <section anchor="roommetadata-app-component">
        <name>room_metadata app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD4</t>
          </li>
          <li>
            <t>Name: room_metadata</t>
          </li>
          <li>
            <t>Where: GC</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
    </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="21" month="July" 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-08"/>
        </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="16" month="October" year="2025"/>
            <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-03"/>
        </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="16" month="October" year="2025"/>
            <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-06"/>
        </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="7" month="July" year="2025"/>
            <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-07"/>
        </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>
        <reference anchor="RFC9458">
          <front>
            <title>Oblivious HTTP</title>
            <author fullname="M. Thomson" initials="M." surname="Thomson"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="January" year="2024"/>
            <abstract>
              <t>This document describes Oblivious HTTP, a protocol for forwarding encrypted HTTP messages. Oblivious HTTP allows a client to make multiple requests to an origin server without that server being able to link those requests to the client or to identify the requests as having come from the same client, while placing only limited trust in the nodes used to forward the messages.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9458"/>
          <seriesInfo name="DOI" value="10.17487/RFC9458"/>
        </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>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="3" month="March" year="2025"/>
            <abstract>
              <t>   This document explores the problem space in instant messaging (IM)
   identity interoperability when using end-to-end encryption, for
   example with the MLS (Message Layer Security) Protocol.  It also
   describes naming schemes for different types of IM identifiers.

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

<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. Thanks to Felix Linker for his
preliminary <eref target="https://github.com/felixlinker/mimi-franking-tamarin/">formal methods
analysis</eref> of MIMI
franking.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
8Y/Y8s0UzPimjnqLuBCgA8hMm/vA42ztava/+hx4piC2CQm3+XVkisI5wtUi
G2xKhiR1B/MTVoUgB60W86WwExkND32SfAimECAeYqFWsqO3yvD6QC9dmdQi
IfsAhUD6aLBwvQiUfKYSgOMRz1Z/q32HLWk2wE52LlBB0rRfskxGwcihPJ12
OTC92tUak/uKQ6wvoAGY/CVqf9DgKL54SDvkvdzBIXlGeSN+Bc797Gu4bGzK
F+1V8yNDRs5QiKfZaGszrpuZ0j7D9xgF0qyxOOtCgqDUyM0hL3WIQHGSXWUr
00gL6QBxEwyaal+d+KVolKsKTtI7eqtBJb5MjhSAk/LuiDvd13EtmEC7dN8o
gfkEEBBHy+JssSHnsOJayQyZ0wtmEjsUr8+xxVMLgUjKmEBZ3+SFCy4mxyuh
WJlTsueSasNjyIibF1p6iovccDwcoRCKt0NJIvLlbTwV9axk6ChVJKez4Ujf
og1Zv3eKfbGc0ldKCdlXuKyf3pzYZuKKmDrK3102HXzahFK/JXfZIO5KP+mg
UAVNQpU/bWSZvgwYrt5ZSIaUMizGhOFerZ3VQm2kkr6eBjx9Dj9LjcKATFm9
DeOTgQq8GBCEshVeuTNf2UOa0mRJ3/JMEiNeBd81IlhLTq4CRxSCKyFbvDqQ
WaSolNow5VlnvBMziVzwIdPE3VXg9mtEOqvYybNjFEaNdTHTBSkFNT0T1b4Z
xnNQ7RS/Fk9F6OJaPkkLIgFUKLoN8qKXs1OErx5dpJiYKWxUzJlhAdEAMZTl
xNaGdTKzuWk4HE/Eaywr5Kn+bx+H9efnJ8ledCwYhMV/va8WxozVe+y+BYiN
0xDIhQKKlIpkenXQ2QWup65w8162HPVwQz43X0ARuSLxaDFjUznTLO7z0GHG
rCPiLZhmIBGYglWOICHYWhJeLJJTDAHiCrD1OV5A0zwrSdP64kwKkz7dF8sD
t/N6avLp19OD8Il/PvSfefThPqjsf2/ZMG79+W5zvDeS4N3m+P0/on/f3mGO
b+MpntxtLxT7pCanO8Ljck9AQcFTt5mDm0PfCh5SKBTHjKJ/37af75ujPSb+
+KQXP9pru2Zv/efC2aYMprvi6UWeJk9ZI4EbeZc5OmtLIlp2p/vShSESSd3p
3e7cjc7lurV+Dfy47h13wI/uHFrCyPIFch1mqoNcUcxIjAwq9hoJFpleYCoc
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

-->

</rfc>
