<?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.35 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-mimi-protocol-06" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.33.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-06"/>
    <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="2026" month="April" day="25"/>
    <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, a way to get the
<tt>ratchet_tree</tt>, and a list of any pending proposals for the epoch, all
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 {
    MLSMessage proposal;
    uint64 hub_accepted_time;
} PendingProposal;

struct {
  GroupInfo groupInfo;   /* without embedded ratchet_tree */
  RatchetTreeOption ratchetTreeOption;
  /* A list of valid pending proposals accepted by the hub */
  /* during the current epoch                              */
  PendingProposal pending_proposals<V>;
} 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>;
  };
  AppDataDictionary consent_extensions;
} 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>
        <t>The <tt>consent_extensions</tt> field is an AppDataDictionary; it is an extension point that borrows the same syntax as the app_data_dictionary MLS extension in <xref section="4.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>.</t>
      </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>
        <t>The <tt>id_request_extensions</tt> field is an extension point using AppDataDictionary-style components.</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>;
  AppDataDictionary id_request_extensions;
} 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>
        <t>The <tt>id_response_extensions</tt> field is an extension point using AppDataDictionary-style components.</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>;
  AppDataDictionary id_response_extensions;
} 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>;
  AppDataDictionary abuse_extensions;
} 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>
        <t>The <tt>abuse_extensions</tt> field is an extension point using AppDataDictionary-style components.</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: 0x0020</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: 0x0021</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: 0x0022</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: 0x0023</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="18" month="December" 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-03"/>
        </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="2" month="March" year="2026"/>
            <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-09"/>
        </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="2" month="March" year="2026"/>
            <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-04"/>
        </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="19" month="April" year="2026"/>
            <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-07"/>
        </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="2" month="March" year="2026"/>
            <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-08"/>
        </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="20" month="October" 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-04"/>
        </reference>
      </references>
    </references>
    <?line 2519?>

<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:
H4sIAAAAAAAAA+y9a3fbyJUo+r1+BY6y1rXkJinL7u507MSJLNuxJn6NJE9P
TlYvEyQhCWMS4ACgZI7j/JbzW+4vu/tZtQsA9WrPnHPXGX/oFklUoWrXrv1+
DIdD1+TNPHucbL0pqyw5LOomLZrkTVbX6VlenME3TVaVy6xKJ/k8b9bJ9pvD
N4c7yarGX1+dnLw/TtJilrx5fbzl0smkyi5wMnjmO/gqeV+VTTkt51tumjbZ
WVmtHyd1M3NuVk6LdAEvnlXpaTPMs+Z0uMgX+XApI4YPfnT1arLI6zovi2a9
hGcPX5y8TJLfJOm8LuEteTHLlhn8p2i2BslWNsubssrTOX443H8G/ysr+Ovo
5OWWK1aLSVY9djNYxmM3LYs6K+pV/ThpqlXmYM2PXFplKcy6v1zOc1gtvLWm
rR1l6Xx4ki+yLXdZVp/OqnK1vDnAttynbA3jZo9dMkxwi/j/PDw1z5KFjsaf
pudpg/+vs+mqsr9dZMUK1p4kt15BkjD8tn6G9eMjf8YZ8PtFms/he1zWn/AM
RmV1ht+n1fQcvj9vmmX9eHcXH8Ov8otspI/t4he7k6q8rLNdnGAXB57lzflq
AkMn+emqYjDudk8XH53DUdSNeYsZMuJ5RnnZM3iXcaYCNGjKIv5tdN4sYHaX
rprzskKYw5uS5HQ1nzO+HeUA4GqWvB4lz9KqyGr6HfaTFvl/0LsfJwd5PS3p
+4wBVM0nf8qXF6P6c3fCN2nTnGeXyatydlaXRc90J+cZPlXlnxFuyctyVczo
p+RgdDg6GNk3LXi2Py388903/qUsqnQG/zsH6H/qeeH78zIr8s/J0f/z3M79
icaNPvG4P8Ea0vq8yotsNMt6AFWepwWs+3zd84bwY3IA92Q1bxCtjrPqIp8K
SBV0+CQhzZ/O8JvRtFx0X3ZSpRd5nRzxkf5KGDY0WXUlDI/S5XmazWEjQBaa
m8OQNlLx4IrG0oZcUVbwOrgfj+npd/lsegDXkz/hvyatzjLAdkV2uKBFPhsV
WbNbL7NpLV8MgTQV2bSB/1fZcO/jA0LoMItQ63fw8OFzhD0+nOCrkr3RA6Ar
MG5ZVimdR1bBHylQkiZ5uOXnIBKYPHzw8NFw7+Fw7wf/g78z4d8wYXC9TZvk
OP2UL1ZV2vf7P5XnRfIMsGuerft+f4O3DsD9bASP6qVrPfOsyooymcE5Z7Ms
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
lT6zkfYwqvQrZBzg+SXsLNrN10BajkCCP0OTuKgqujAkT5HQSgKtnz8QGb1q
BND+13UJAwVIWJqw36PiBFnV21LlV5TUOaMNqQQqSjiU1CQ27UaK0mY14zJF
48oEEIcTGTmUa5JNUwRhoNMaH0GSuxpQrGUEBSfUMOJlkJ6OwhhpEqv5XJcx
EJM6yrkkpKIdFVU0lLTqZDtQRuEKrIYwVgGoJJiUNEYy/WDwEIa3whOojtpl
BtmflKG6xMCQS0/lEWOrTKPMC09JrQsEp+OQEjUgKf29zGFTHElVhgBT3rBc
SQE3nwvqzfRXkHaNWIxc7RJj+ckLWV2m1UzVKUVL//BBj6z5LGYPgR30s4sD
/5mHH9yJXXTI013nuKVs2v58F1n1RnPcUnZtf76RLPvrZdtvKuv+Gtn3P0MW
vs1ebjyHU6xXxnJwnaz8bC8Wq6+Ula38eQtZed+s5u4iNq7k2wrY3lgmgw7+
s8Vrv7ZrZw9MeKMsPpl2ZHEE0SZJXEn0VbJ4ctN/4XH9i//vPLmOCbYl1hGh
Privjz/zf+3fdzFm//1Wf5u/XCT0/4p5vmvTOjY73mE99t93G2jbbeehTz30
7dbz/L6fxt1wHqPy2OeD+mNUkk3z/H4TDY1hRRrNzfe14e/vojO92Ty6G8Ws
O81j4fyPG/972l1PWMOvwsObryHe4Te7py4Quyu1PyJisf7XZmB30P+6bI2v
9wY1jN/wbIVG5g0a5LWKY4cXbGSVV2mENrfe/ruRonhwE0XRq15tLfFAGdTB
NVrinTRdBvEGhVQww84tpoD27y12aTRU5JT7vbplCCa6TkcFFZVHH2cFnrdm
cTv3VpWxfXZbwtsGJkhJMCPOs+GfLjUBt07XyTnoTSVFvGGoYVlkoO3FmhYG
kKbLejX3PjB1aWAAA7u/3lf5BfysKeaortW0YIBRUL3QoV2qhqa/tVVDLNQh
72dvz8jto8s6YApijuA8bmKZpZ/ibUZaprxOJ3W6eHk1u1Y1Yqilvcp8uGqj
pPp155ULrpe2nHMQK5VBabypDTKol/rX/jdRNHuJI37S0/u28/YocVStqbl2
nuvWG/+7VpG747zXKnd3nfc6he928/YKRvz0NbbhTfNeo2x24b0Jf24I3w2f
N9vHbzZvEKZu+t7/0nMzv971/l1zL24jeG0Uwm6ynpuu/3bz3mH9d/MP3Gi9
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
n3xNsSkoLJ2MjCPZpR2HP4yyBLBToQEA

-->

</rfc>
