<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.4.1) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-mimi-protocol-04" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.29.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-04"/>
    <author fullname="Richard L. Barnes">
      <organization>Cisco</organization>
      <address>
        <email>rlb@ipv.sx</email>
      </address>
    </author>
    <author fullname="Matthew Hodgson">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>matthew@matrix.org</email>
      </address>
    </author>
    <author fullname="Konrad Kohbrok">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>konrad.kohbrok@datashrine.de</email>
      </address>
    </author>
    <author fullname="Rohan Mahy">
      <organization>Rohan Mahy Consulting Services</organization>
      <address>
        <email>rohan.ietf@gmail.com</email>
      </address>
    </author>
    <author fullname="Travis Ralston">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>travisr@matrix.org</email>
      </address>
    </author>
    <author fullname="Raphael Robert">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>ietf@raphaelrobert.com</email>
      </address>
    </author>
    <date year="2025" month="July" day="07"/>
    <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[32] server_frank;
  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[32] franking_tag
} 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 scheme in the cipher suite of the MLS group.</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. The 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>
            <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>
            <artwork><![CDATA[
context = sender_uri || room_uri || accepted_timestamp
server_frank = HMAC_SHA256(hub_key, franking_tag || context )
franking_integrity_signature =
  Signature.Sign(franking_private_key, server_frank || context)
]]></artwork>
            <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 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, 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> and the
<tt>franking_integrity_signature</tt>). If those fields are available, 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>signed_content</tt> and verifying
the <tt>franking_integrity_signature</tt> as described below.</t>
            <artwork><![CDATA[
signed_content = server_frank ||
                  sender_uri || room_uri || accepted_timestamp
Signature.Verify(franking_signature_key, signed_content,
                           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_integrity_signature</tt>,
and <tt>context</tt> fields with the decoded message, so they can be used later.</t>
          </section>
          <section anchor="comparison-with-the-facebook-franking-scheme">
            <name>Comparison with the Facebook franking scheme</name>
            <t>Unlike in the Facebook franking scheme <xref target="SecretConversations"/>, the MIMI
use case involves traffic which can transit multiple federated providers,
any of which may be compromised or malicious. The MIMI franking scheme
described here differs in the following ways.</t>
            <t>Firstly, the sender includes its <tt>franking_tag</tt> application component as
Additional Authenticated Data (AAD) inside the end-to-end encrypted message.
This insures that the <tt>franking_tag</tt> is not tampered with by the sender's
provider. According to <xref target="Grubbs2017"/>,
"... [Facebook's] franking scheme does not bind [the franking tag] to [the
ciphertext] by including [the franking tag] in the associated data during
encryption".</t>
            <t>In MLS, the Hub cannot view the sender identity in an application message,
so the sender sends its identity to the Hub. The hub never sends the
identity of the sender to receivers, since this would be observed by
follower providers. However, the receiver needs to verify that the sender
identity provided by the sender's provider to the Hub matches the identity
the receiver sees after it decrypts the message. Using the
<tt>franking_integrity_signature</tt> generated by the Hub, receivers can verify the
message context (sender identity, room id, and timestamp) and the server_frank
with the <tt>franking_signature_key</tt> in the <tt>franking_agent</tt> component in the
GroupContext.
This second change provides two functions. It allows receivers to
validate the <tt>sender_uri</tt> in the hub's context, without revealing the sender URI
to follower providers. It also prevents a follower provider from modifying the
server_frank, or any elements of the context (ex: modifying the
<tt>accepted_timestamp</tt>) without detection. A valid signature ensures
that follower providers did not tamper with the context or the server_frank.</t>
          </section>
        </section>
      </section>
      <section anchor="fanout-messages-and-room-events">
        <name>Fanout Messages and Room Events</name>
        <t>If the hub provider accepts an application or handshake message (proposal or
commit) message, it forwards that message to all other providers with active
participants in the room and all local clients which are active members.
This is described as fanning the message out. One can think of fanning a
message out as presenting an ordered list of MLS-protected events to the next
"hop" toward the receiving client.</t>
        <t>An MLS Welcome message is sent to the providers and local users associated with
the <tt>KeyPackageRef</tt> values in the <tt>secrets</tt> array of the Welcome. In the case
of a Welcome message, a <tt>RatchetTreeOption</tt>
(see Section 3 of <xref target="I-D.mahy-mls-ratchet-tree-options"/>) is also included
in the FanoutMessage.</t>
        <t>The hub provider also fans out any messages which originate from itself (ex: MLS
External Proposals).</t>
        <ul empty="true">
          <li>
            <t>An external commit will invalidate certain pending proposals. For example, if
the hub generates Remove proposals to remove a lost client or a deleted user,
an external commit can invalidate pending Remove proposals. The hub would then
be expected to regenerate any relevant, comparable proposals in the new epoch.
To prevent a race condition where a member commit arrives before the
regenerated proposals arrive, the hub can staple regenerated proposals to an
external commit during the fanout process.</t>
          </li>
        </ul>
        <t>The hub can include multiple concatenated <tt>FanoutMessage</tt> objects relevant to
the same room. This endpoint uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /notify/{roomId}
]]></artwork>
        <sourcecode type="tls"><![CDATA[
struct {
  /* the hub acceptance time (in milliseconds from the UNIX epoch) */
  uint64 timestamp;
  select (protocol) {
    case mls10:
      /* A PrivateMessage containing an application message, */
      /* a SemiPrivateMessage or PublicMessage containing a  */
      /* proposal or commit, or a Welcome message.           */
      MLSMessage message;
      select (message.wire_format) {
        case application:
           optional Frank frank;
        case welcome:
           RatchetTreeOption ratchetTreeOption;
        case proposal:
           /* a list of additional proposals, each represented */
           /* as either PublicMessage or SemiPrivateMessage    */
           MLSMessage moreProposals<V>;
        case commit:
           /* If this was an external commit, and any pending      */
           /* proposals were invalidated, staple the new epoch's   */
           /* replacement proposals (from the hub) to the commit   */
           /* commit */
           MLSMessage externalProposals<V>;
      };
  };
} FanoutMessage;
]]></sourcecode>
        <ul empty="true">
          <li>
            <t><strong>NOTE:</strong> Correctly fanning out Welcome messages relies on the hub and target
providers storing the <tt>KeyPackageRef</tt> of claimed KeyPackages.</t>
          </li>
        </ul>
        <t>A client which receives a <tt>success</tt> to either an <tt>UpdateRoomResponse</tt> or a
<tt>SubmitMessageResponse</tt> can view this as a commitment from the hub provider that
the message will eventually be distributed to the group. The hub is not
expected to forward the client's own message to the client or its provider.
However, the client and its provider need to be prepared to receive the
client's (effectively duplicate) message. This situation can occur during
failover in high availability recovery scenarios.</t>
        <t>Clients that are being removed <bcp14>SHOULD</bcp14> receive the corresponding
Commit message, so they can recognize that they have been removed and clean up
their internal state. A removed client might not receive a commit if it was
removed as a malicious or abusive client, or if it was obviously deleted.</t>
        <t>The <tt>moreProposals</tt> list in a <tt>FanoutMessage</tt> <bcp14>MUST</bcp14> be the same as the
corresponding <tt>moreProposals</tt> list in the <tt>HandshakeBundle</tt> of an
<tt>UpdateRequest</tt>.</t>
        <t>The response to a FanoutMessage contains no body. The HTTP response code
indicates if the messages in the request were accepted (201 response code), or
if there was an error. The hub need not wait for a response before sending the
next fanout message.</t>
        <t>If the hub server does not contain an HTTP 201 response code, then it <bcp14>SHOULD</bcp14>
retry the request, respecting any guidance provided by the server in HTTP header
fields such as Retry-After.  If a follower server receives a duplicate request
to the <tt>/notify</tt> endpoint, in the sense of a request from the same hub server
with the same request body as a previous <tt>/notify</tt> request, then the follower
server <bcp14>MUST</bcp14> return a 201 Accepted response.  In such cases, the follower server
<bcp14>SHOULD</bcp14> process only the first request; subsequent duplicate requests <bcp14>SHOULD</bcp14> be
ignored (despite the success response).</t>
        <ul empty="true">
          <li>
            <t><strong>NOTE:</strong> These deduplication provisions require follower servers to track
which request bodies they have received from which hub servers.  Since the
matching here is byte-exact, it can be done by keeping a rolling list of
hashes of recent messages.</t>
            <t>This byte-exact replay criterion might not be the right deduplication
strategy.  There might be situations where it is valid for the same hub server
to send the same payload multiple times, e.g., due to accidental collisions.</t>
            <t>If this is a concern, then an explicit transaction ID could be introduced.
The follower server would still have to keep a list of recently seen
transaction IDs, but deduplication could be done irrespective of the content
of request bodies.</t>
          </li>
        </ul>
      </section>
      <section anchor="claim-group-key-information">
        <name>Claim group key information</name>
        <t>When a client joins an MLS group without an existing member adding the
client to the MLS group, that is called an external join. This is useful
a) when a new client of an existing user needs to join the groups of all the
user's rooms. It can also be used b) when a client did not have key packages
available but their user is already in the participation list for the
corresponding room, c) when joining an open room, or d) when joining using
an external authentication joining code. In MIMI, external joins are
accomplished by fetching the MLS GroupInfo for a room's MLS group, and then
sending an external commit incorporating the GroupInfo.</t>
        <t>The GroupInfoRequest uses the HTTP POST method.</t>
        <artwork><![CDATA[
POST /groupInfo/{roomId}
]]></artwork>
        <t>The request provides an MLS credential proving the requesting client's real or
pseudonymous identity. This user identity is used by the hub to correlate this
request with the subsequent external commit. The credential may constitute
sufficient permission to authorize providing the GroupInfo and later joining
the group. Alternatively, the request can include an optional opaque joining
code, which the requester could use to prove permission to fetch the GroupInfo,
even if it is not yet a participant.</t>
        <t>The request also
provides a signature public key
corresponding to the requester's credential. It also specifies a CipherSuite
which merely needs to be one ciphersuite in common with the hub. It is
needed only to specify the algorithms used to sign the
GroupInfoRequest and GroupInfoResponse.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  Protocol protocol;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      SignaturePublicKey requestingSignatureKey;
      Credential requestingCredential;
      HPKEPublicKey groupInfoPublicKey;
      optional opaque joiningCode<V>;
  };
} GroupInfoRequestTBS;

struct {
  Protocol protocol;
  select (protocol) {
    case mls10:
      CipherSuite cipher_suite;
      SignaturePublicKey requestingSignatureKey;
      Credential requestingCredential;
      HPKEPublicKey groupInfoPublicKey;
      opaque joiningCode<V>;
      /* SignWithLabel(requestingSignatureKey,          */
      /*    "GroupInfoRequestTBS", GroupInfoRequestTBS) */
      opaque signature<V>;
  };
} GroupInfoRequest;
]]></sourcecode>
        <t>If successful, the response body contains the GroupInfo and a way
to get the ratchet_tree, both encrypted with the <tt>groupInfoPublcKey</tt>
passed in the request.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  success(1),
  notAuthorized(2),
  noSuchRoom(3),
  (255)
} GroupInfoCode;

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

GroupInfoRatchetTreeTBE group_info_ratchet_tree_tbe;

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

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

struct {
  Protocol version;
  opaque room_id<V>;
  GroupInfoCode status;
  select (status) {
    case success:
      select (protocol) {
        case mls10:
          CipherSuite cipher_suite;
          ExternalSender hub_sender;
          HPKECiphertext encrypted_groupinfo_and_tree;
          /* SignWithLabel(hub_sender.signature_key,        */
          /*  "GroupInfoResponseTBS", GroupInfoResponseTBS) */
          opaque signature<V>;
      };
  default: struct{};
  };
} GroupInfoResponse;
]]></sourcecode>
        <t>The semantics of the <tt>GroupInfoCode</tt> are as follows:</t>
        <ul spacing="normal">
          <li>
            <t><tt>success</tt> indicates that GroupInfo and ratchet tree was provided as
requested.</t>
          </li>
          <li>
            <t><tt>notAuthorized</tt> indicates that the requester was not authorized to access
the GroupInfo.</t>
          </li>
          <li>
            <t><tt>noSuchRoom</tt> indicates that the requested room does not exist. If the hub
does not want to reveal if a room ID does not exist it can use
<tt>notAuthorized</tt> instead.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Consider adding additional failure codes/semantics for joining
codes (ex: code expired, already used, invalid)</t>
          </li>
        </ul>
        <t><strong>ISSUE</strong>: What security properties are needed to protect a
GroupInfo object in the MIMI context are still under discussion. It is
possible that the requester only needs to prove possession of their private
key. The GroupInfo in another context might be sufficiently sensitive that
it should be encrypted from the end client to the hub provider (unreadable
by the local provider).</t>
      </section>
      <section anchor="convey-explicit-consent">
        <name>Convey explicit consent</name>
        <t>As discussed in <xref target="consent"/>, there are many ways that a provider could
implicitly determine consent. This section describes a mechanism by which providers can explicitly request consent from a user of another provider,
cancel such a request, convey that consent was granted, or convey that
consent was revoked or preemptively denied.</t>
        <t>Since they are not necessarily in the context of a room, consent requests
are sent directly from the provider of the user requesting consent, to the
provider of the target user. (There is no concept of a hub outside of the
context of a room.)</t>
        <artwork><![CDATA[
POST /requestConsent/{targetDomain}
POST /updateConsent/{requesterDomain}
]]></artwork>
        <t>A <tt>requestConsent</tt> request is used by one provider to request explicit
consent from a target user at another provider to fetch the target's
KeyPackages (which is a prerequisite for adding the target to a group); or
to cancel that request.
The request body is a <tt>ConsentEntry</tt>, with a <tt>consentOperation</tt> of <tt>request</tt>
or <tt>cancel</tt> respectively. It includes the URI of requesting user in the
<tt>requesterUri</tt> and the target user URI in the <tt>targetUri</tt>. If consent is only
requested for a single room, the requester includes the <tt>roomId</tt>. The
combination of the <tt>requesterUri</tt>, <tt>targetUri</tt>, and optional <tt>roomId</tt>
represents the <tt>ConsentScope</tt>. A <tt>cancel</tt> <bcp14>MUST</bcp14> use the same <tt>ConsentScope</tt>
as a previous <tt>request</tt>.</t>
        <t>For a <tt>requestContent</tt>, the <tt>targetUri</tt> needs to be in one of the domains of
the receiving provider, and the <tt>requesterUri</tt> needs to be in one of the
domains of the sending provider.</t>
        <t>The response to a <tt>requestConsent</tt> request is usually a 201 Accepted
(indicating the <tt>requestConsent</tt> was received), optionally a 404 Not Found
(indicating the <tt>targetUri</tt> is unknown), or a 500-class response. The
201 response code merely indicates that the request was received. A provider
that does not wish to reveal if a user is not found can respond with a 201
Accepted. Likewise in response to a <tt>cancel</tt> which has no <tt>request</tt> matching the
<tt>ConsentScope</tt>, a 201 Accepted is sent and no further action is taken.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  cancel(0),
  request(1),
  grant(2),
  revoke(3),
  (255)
} ConsentOperation;

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

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

struct {
  SearchIdentifierType searchType;
  select(type) {
    case oidcStdClaim:
      opaque claimName<V>;
    case vcardField:
      opaque propertyName<V>;
  };
  opaque searchValue<V>;  /* a UTF8 string */
} QueryElement;

struct {
  QueryElement query_elements<V>;
} IdentifierRequest;
]]></sourcecode>
        <t>The semantics of the <tt>SearchIdentifierType</tt> values are as follows. <tt>handle</tt>
means that the entire handle URI matches exactly (for example: <tt>im:alice.smith@a.example</tt>). <tt>nick</tt> means that the nickname or handle
user part matches exactly (for example: <tt>alice.smith</tt>). The same account or
human user may have multiple values which all match the <tt>nick</tt> field. <tt>email</tt>
means the <tt>addr-spec</tt> production from <xref target="RFC5322"/> matches the query string
exactly, for example (<tt>asmith@a.example</tt>). <tt>phone</tt> means the international
format of a telephone number with the "+" prefix matches exactly (for example:
<tt>+12125551212</tt>).</t>
        <t><tt>partialName</tt> means that the query string matches a case-insensitive substring
of any field which contains the name of a (usually human) user. For example,
<tt>mat</tt> would match first (given) or middle names Matt, Matthew, Mathias, or
Mathieu and last (family) names of Mather and Matali. <tt>wholeProfile</tt> means that
the query string matches a substring of any searchable field in
a user's profile.</t>
        <t><tt>oidcStdClaim</tt> means that the query string exactly matches the specified
UserInfo Standard Claim (defined in Section 5.1 of <xref target="OidcCore"/>).
<tt>vcardField</tt> means that the query string exactly matches the specified vCard
property listed in the vCard Properties IANA registry.</t>
        <t>As noted above, searches only return results for a user when the fields searched
are searchable according the user's and provider's search policies.</t>
        <t>The response body is described as an <tt>IdentifierResponse</tt>. It can contain
multiple matches depending on the type of query and the policy of the target
provider.</t>
        <t>The response contains a code indicating the status of the query. <tt>success</tt>
means that at least one result matched the query. <tt>notFound</tt> means that
while the request was acceptable, no results matched the query.
<tt>ambiguous</tt> means that a field (ex: handle) or combination of fields
(ex: first and last name) need to match exactly for the provider to return
any responses. <tt>forbidden</tt> means that use of this endpoint is not allowed
by the provider or that an unspecified field or combination of fields is
not allowed in an identifier query. <tt>unsupportedField</tt> means that the
provider does not support queries on one of the fields queried.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  success(0),
  notFound(1),
  ambiguous(2),
  forbidden(3),
  unsupportedField(4),
  (255)
} IdentifierQueryCode;

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

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

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

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

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

struct {
  IdentifierUri reportingUser;
  IdentifierUri allegedAbuserUri;
  AbuseType reasonCode;
  opaque note<V>;
  AbusiveMessage messages<V>;
} AbuseReport;
]]></sourcecode>
        <t>There is no response body. The response code only indicates if the abuse report was accepted, not if any specific automated or human action was taken.</t>
        <t>To validate an allegedly AbusiveMessage, the hub finds the salt, sender URI, and
room URI inside the <tt>message_content</tt> and the <tt>accepted_timestamp</tt> to
recalculate the <tt>franking_tag</tt> and <tt>context</tt>. Then the hub selects its relevant
<tt>hub_key</tt> to regenerate the <tt>server_frank</tt>. Finally the hub verifies its <tt>franking_integrity_signature</tt>.</t>
      </section>
      <section anchor="download-files">
        <name>Download Files</name>
        <t>IM systems make extensive use of inline images, videos, and sounds, and often
include attached files, all of which will be referred to as "assets" in this
section. Assets are stored (encrypted) on various external servers, and
typically uploaded and fetched using HTTP <xref target="RFC9110"/> protected with TLS
<xref target="RFC8446"/>.</t>
        <ul empty="true">
          <li>
            <t>In a MIMI content <xref target="I-D.ietf-mimi-content"/> message, the download URI is an
<tt>https</tt> URL conveyed in the <tt>uri</tt> field in an <tt>ExternalPart</tt> in a MIMI
content message.</t>
          </li>
        </ul>
        <t>Broadly, two approaches are possibly for storage of assets in federated IM
systems. In the vast majority of deployed systems, the assets are uploaded to
the local provider of the uploader. With the other approach, the assets are
uploaded to the equivalent of the Hub system. MIMI is capable of asset
downloads for both of these approaches.</t>
        <t>The client consults the intersection of the room policy and its local policy to
determine if and how to upload assets, where to upload them, and with which
credentials. The details of the upload process are out of scope of this
document.</t>
        <t>The MIMI room policy <xref target="I-D.ietf-mimi-room-policy"/> in the group's GroupContext
includes an <tt>asset_policy</tt> component that specifies which domain name to use
for asset download for each potential asset provider. This prevents the
download proxy from using a host part associated with the same domain that is
not used for the storage of MIMI assets.</t>
        <t>For downloads, the clients can use any of three methods to download assets. The
hub is not involved in the first and is required to implement support for the
other two methods.</t>
        <section anchor="direct-download">
          <name>Direct download</name>
          <t>Without any additional MIMI protocol mechanism, MIMI clients can download assets
directly from the asset provider. Unfortunately this usually reveals sensitive
private information about the client. In this case, the asset provider learns
the IP address of the client, and timing information about when assets are downloaded, which is strongly linked with online presence. The asset provider
can correlate other clients downloading the same assets and infer which clients
are in which rooms. For this reason, direct client downloads of assets,
especially from an asset provider which is not the download client's provider,
are <bcp14>NOT RECOMMENDED</bcp14>.</t>
        </section>
        <section anchor="download-using-a-hub-proxy">
          <name>Download using a hub proxy</name>
          <t>The hub offers the <tt>proxyDownload</tt> endpoint to proxy asset requests from
downloading providers to known asset providers. This allows clients to hide
their IP addresses from the asset provider (and the hub), although the hub and
the downloading provider are still privy to the request.</t>
          <t>The <tt>proxyDownload</tt> endpoint includes the target asset URL, but does not include
the specific room or requester. When the provider hosting the asset has several
rooms hosted by the hub, the provider also does not directly learn with which
room to associate a specific asset.</t>
          <t>As with other MIMI protocol endpoints, the actual endpoint URL is discovered
using the MIMI protocol directory <xref target="directory"/>.</t>
          <artwork><![CDATA[
GET /proxyDownload/{downloadUrl}
]]></artwork>
          <t>The downloading provider sends the request to the hub. The hub <bcp14>MUST</bcp14> verify that
the host part of the <tt>downloadUrl</tt> is associated with the asset server domain
for one of its peer providers. This prevents the hub from becoming an open
proxy.</t>
          <t>The overall flow is as shown below.</t>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="568" viewBox="0 0 568 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,320" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,320" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,320" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,320" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,320" fill="none" stroke="black"/>
                <path d="M 416,80 Q 418,76.8 420,80 Q 422,83.2 424,80 Q 426,76.8 428,80 Q 430,83.2 432,80 Q 434,76.8 436,80 Q 438,83.2 440,80 Q 442,76.8 444,80 Q 446,83.2 448,80 Q 450,76.8 452,80 Q 454,83.2 456,80 Q 458,76.8 460,80 Q 462,83.2 464,80 Q 466,76.8 468,80 Q 470,83.2 472,80 Q 474,76.8 476,80 Q 478,83.2 480,80 Q 482,76.8 484,80 Q 486,83.2 488,80 Q 490,76.8 492,80 Q 494,83.2 496,80 Q 498,76.8 500,80 Q 502,83.2 504,80 Q 506,76.8 508,80 Q 510,83.2 512,80 Q 514,76.8 516,80 Q 518,83.2 520,80 Q 522,76.8 524,80 Q 526,83.2 528,80 Q 530,76.8 532,80 Q 534,83.2 536,80 " fill="none" stroke="black"/>
                <path d="M 408,96 Q 410,92.8 412,96 Q 414,99.2 416,96 Q 418,92.8 420,96 Q 422,99.2 424,96 Q 426,92.8 428,96 Q 430,99.2 432,96 Q 434,92.8 436,96 Q 438,99.2 440,96 Q 442,92.8 444,96 Q 446,99.2 448,96 Q 450,92.8 452,96 Q 454,99.2 456,96 Q 458,92.8 460,96 Q 462,99.2 464,96 Q 466,92.8 468,96 Q 470,99.2 472,96 Q 474,92.8 476,96 Q 478,99.2 480,96 Q 482,92.8 484,96 Q 486,99.2 488,96 Q 490,92.8 492,96 Q 494,99.2 496,96 Q 498,92.8 500,96 Q 502,99.2 504,96 Q 506,92.8 508,96 Q 510,99.2 512,96 Q 514,92.8 516,96 Q 518,99.2 520,96 Q 522,92.8 524,96 Q 526,99.2 528,96 " fill="none" stroke="black"/>
                <path d="M 416,144 Q 418,140.8 420,144 Q 422,147.2 424,144 Q 426,140.8 428,144 Q 430,147.2 432,144 Q 434,140.8 436,144 Q 438,147.2 440,144 Q 442,140.8 444,144 Q 446,147.2 448,144 Q 450,140.8 452,144 Q 454,147.2 456,144 Q 458,140.8 460,144 Q 462,147.2 464,144 Q 466,140.8 468,144 Q 470,147.2 472,144 Q 474,140.8 476,144 Q 478,147.2 480,144 Q 482,140.8 484,144 Q 486,147.2 488,144 Q 490,140.8 492,144 Q 494,147.2 496,144 Q 498,140.8 500,144 Q 502,147.2 504,144 Q 506,140.8 508,144 Q 510,147.2 512,144 Q 514,140.8 516,144 Q 518,147.2 520,144 Q 522,140.8 524,144 Q 526,147.2 528,144 Q 530,140.8 532,144 Q 534,147.2 536,144 " fill="none" stroke="black"/>
                <path d="M 288,160 L 408,160" fill="none" stroke="black"/>
                <path d="M 160,176 L 400,176" fill="none" stroke="black"/>
                <path d="M 32,192 Q 34,188.8 36,192 Q 38,195.2 40,192 Q 42,188.8 44,192 Q 46,195.2 48,192 Q 50,188.8 52,192 Q 54,195.2 56,192 Q 58,188.8 60,192 Q 62,195.2 64,192 Q 66,188.8 68,192 Q 70,195.2 72,192 Q 74,188.8 76,192 Q 78,195.2 80,192 Q 82,188.8 84,192 Q 86,195.2 88,192 Q 90,188.8 92,192 Q 94,195.2 96,192 Q 98,188.8 100,192 Q 102,195.2 104,192 Q 106,188.8 108,192 Q 110,195.2 112,192 Q 114,188.8 116,192 Q 118,195.2 120,192 Q 122,188.8 124,192 Q 126,195.2 128,192 Q 130,188.8 132,192 Q 134,195.2 136,192 Q 138,188.8 140,192 Q 142,195.2 144,192 Q 146,188.8 148,192 Q 150,195.2 152,192 " fill="none" stroke="black"/>
                <path d="M 408,192 Q 410,188.8 412,192 Q 414,195.2 416,192 Q 418,188.8 420,192 Q 422,195.2 424,192 Q 426,188.8 428,192 Q 430,195.2 432,192 Q 434,188.8 436,192 Q 438,195.2 440,192 Q 442,188.8 444,192 Q 446,195.2 448,192 Q 450,188.8 452,192 Q 454,195.2 456,192 Q 458,188.8 460,192 Q 462,195.2 464,192 Q 466,188.8 468,192 Q 470,195.2 472,192 Q 474,188.8 476,192 Q 478,195.2 480,192 Q 482,188.8 484,192 Q 486,195.2 488,192 Q 490,188.8 492,192 Q 494,195.2 496,192 Q 498,188.8 500,192 Q 502,195.2 504,192 Q 506,188.8 508,192 Q 510,195.2 512,192 Q 514,188.8 516,192 Q 518,195.2 520,192 Q 522,188.8 524,192 Q 526,195.2 528,192 " fill="none" stroke="black"/>
                <path d="M 24,240 Q 26,236.8 28,240 Q 30,243.2 32,240 Q 34,236.8 36,240 Q 38,243.2 40,240 Q 42,236.8 44,240 Q 46,243.2 48,240 Q 50,236.8 52,240 Q 54,243.2 56,240 Q 58,236.8 60,240 Q 62,243.2 64,240 Q 66,236.8 68,240 Q 70,243.2 72,240 Q 74,236.8 76,240 Q 78,243.2 80,240 Q 82,236.8 84,240 Q 86,243.2 88,240 Q 90,236.8 92,240 Q 94,243.2 96,240 Q 98,236.8 100,240 Q 102,243.2 104,240 Q 106,236.8 108,240 Q 110,243.2 112,240 Q 114,236.8 116,240 Q 118,243.2 120,240 Q 122,236.8 124,240 Q 126,243.2 128,240 Q 130,236.8 132,240 Q 134,243.2 136,240 Q 138,236.8 140,240 Q 142,243.2 144,240 " fill="none" stroke="black"/>
                <path d="M 152,256 L 272,256" fill="none" stroke="black"/>
                <path d="M 280,272 L 400,272" fill="none" stroke="black"/>
                <path d="M 288,288 L 408,288" fill="none" stroke="black"/>
                <path d="M 160,304 L 280,304" fill="none" stroke="black"/>
                <path d="M 32,320 Q 34,316.8 36,320 Q 38,323.2 40,320 Q 42,316.8 44,320 Q 46,323.2 48,320 Q 50,316.8 52,320 Q 54,323.2 56,320 Q 58,316.8 60,320 Q 62,323.2 64,320 Q 66,316.8 68,320 Q 70,323.2 72,320 Q 74,316.8 76,320 Q 78,323.2 80,320 Q 82,316.8 84,320 Q 86,323.2 88,320 Q 90,316.8 92,320 Q 94,323.2 96,320 Q 98,316.8 100,320 Q 102,323.2 104,320 Q 106,316.8 108,320 Q 110,323.2 112,320 Q 114,316.8 116,320 Q 118,323.2 120,320 Q 122,316.8 124,320 Q 126,323.2 128,320 Q 130,316.8 132,320 Q 134,323.2 136,320 Q 138,316.8 140,320 Q 142,323.2 144,320 Q 146,316.8 148,320 Q 150,323.2 152,320 " fill="none" stroke="black"/>
                <polygon class="arrowhead" points="536,192 524,186.4 524,197.6" fill="black" transform="rotate(0,528,192)"/>
                <polygon class="arrowhead" points="536,96 524,90.4 524,101.6" fill="black" transform="rotate(0,528,96)"/>
                <polygon class="arrowhead" points="424,144 412,138.4 412,149.6" fill="black" transform="rotate(180,416,144)"/>
                <polygon class="arrowhead" points="424,80 412,74.4 412,85.6" fill="black" transform="rotate(180,416,80)"/>
                <polygon class="arrowhead" points="408,272 396,266.4 396,277.6" fill="black" transform="rotate(0,400,272)"/>
                <polygon class="arrowhead" points="408,176 396,170.4 396,181.6" fill="black" transform="rotate(0,400,176)"/>
                <polygon class="arrowhead" points="296,288 284,282.4 284,293.6" fill="black" transform="rotate(180,288,288)"/>
                <polygon class="arrowhead" points="296,160 284,154.4 284,165.6" fill="black" transform="rotate(180,288,160)"/>
                <polygon class="arrowhead" points="280,256 268,250.4 268,261.6" fill="black" transform="rotate(0,272,256)"/>
                <polygon class="arrowhead" points="168,304 156,298.4 156,309.6" fill="black" transform="rotate(180,160,304)"/>
                <polygon class="arrowhead" points="168,176 156,170.4 156,181.6" fill="black" transform="rotate(180,160,176)"/>
                <polygon class="arrowhead" points="152,240 140,234.4 140,245.6" fill="black" transform="rotate(0,144,240)"/>
                <polygon class="arrowhead" points="40,320 28,314.4 28,325.6" fill="black" transform="rotate(180,32,320)"/>
                <polygon class="arrowhead" points="40,192 28,186.4 28,197.6" fill="black" transform="rotate(180,32,192)"/>
                <g class="text">
                  <text x="36" y="36">ClientB1</text>
                  <text x="152" y="36">ServerB</text>
                  <text x="276" y="36">HubA</text>
                  <text x="400" y="36">ServerC</text>
                  <text x="532" y="36">ClientC1</text>
                  <text x="452" y="68">Upload</text>
                  <text x="504" y="68">asset</text>
                  <text x="436" y="116">send</text>
                  <text x="488" y="116">message</text>
                  <text x="428" y="132">w/</text>
                  <text x="464" y="132">asset</text>
                  <text x="508" y="132">link</text>
                  <text x="364" y="148">submit</text>
                  <text x="228" y="164">fanout</text>
                  <text x="56" y="212">fetch</text>
                  <text x="104" y="212">asset</text>
                  <text x="48" y="228">via</text>
                  <text x="72" y="228">B</text>
                  <text x="96" y="228">and</text>
                  <text x="128" y="228">hub</text>
                  <text x="216" y="244">proxyDownload</text>
                  <text x="304" y="260">GET</text>
                  <text x="344" y="260">asset</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientB1       ServerB          HubA          ServerC         ClientC1
  |               |               |               |               |
  |               |               |               |  Upload asset |
  |               |               |               |<~~~~~~~~~~~~~~+
  |               |               |               +~~~~~~~~~~~~~~>|
  |               |               |               | send message  |
  |               |               |               | w/ asset link |
  |               |               |       submit  |<~~~~~~~~~~~~~~+
  |               |      fanout   |<--------------+               |
  |               |<--------------+-------------->|               |
  |<~~~~~~~~~~~~~~+               |               +~~~~~~~~~~~~~~>|
  | fetch asset   |               |               |               |
  | via B and hub |               |               |               |
  +~~~~~~~~~~~~~~>| proxyDownload |               |               |
  |               +-------------->| GET asset     |               |
  |               |               +-------------->|               |
  |               |               |<--------------+               |
  |               |<--------------+               |               |
  |<~~~~~~~~~~~~~~+               |               |               |
]]></artwork>
          </artset>
          <t>If the request succeeds, the response body contains the contents of the
downloaded URL. The hub can reject <tt>proxyDownload</tt> requests by replying with
standard HTTP error codes.</t>
          <t>In terms of the privacy of this mechanism, the hub only sees that a specific
provider requested an (opaque to the hub) URL from another provider. It does not
know the room or the specific client.
The asset provider sees requests for an (encrypted) asset coming from the hub
provider. When caching is employed, the asset provider will only see periodic
requests.
The receiver's provider will see one request to the hub, among presumably many
requests. It has no information about the sender, URL, or room associated with
that request, however it can collect the domains of specific asset providers,
and it can use timing analysis to correlate incoming messages (which are
associated with a room) and outgoing <tt>proxyDownload</tt> requests.</t>
          <t>Both the downloading provider and the hub can cache requests. This would tend to
hide from the asset provider the number of downloading participants in a
specific room, and make it more difficult for the hub to correlate a URL with a
specific room based on the number of participants.</t>
          <t>The proxy download method improves the privacy of the clients with respect to
the asset provider, and to some extent with the hub, but it still allows the
downloading provider to correlate URLs with downloading users and infer which
URLs are sent in which rooms.</t>
          <t>The hub is <bcp14>REQUIRED</bcp14> to implement this mechanism.</t>
        </section>
        <section anchor="download-using-oblivious-http">
          <name>Download using Oblivious HTTP</name>
          <t>Oblivious HTTP (OHTTP) <xref target="RFC9458"/> is a mechanism for the encapsulation of HTTP
requests that provides a variety of desirable privacy properties. It provides
the best privacy of the download mechanisms described here, but requires the
client to implement an additional protocol.</t>
          <t>Using OHTTP for asset download privacy works as follows. The clients sends an
OHTTP request to the downloading provider's OHTTP Relay which forwards the
request to the hub's OHTTP Gateway. The hub then sends a GET request for the
asset to the asset provider (the Target)</t>
          <t>The hub <bcp14>MUST</bcp14> only accept OHTTP requests to Targets which are configured as asset
storage locations for one of its peer providers.</t>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="336" width="568" viewBox="0 0 568 336" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 24,48 L 24,320" fill="none" stroke="black"/>
                <path d="M 152,48 L 152,320" fill="none" stroke="black"/>
                <path d="M 280,48 L 280,320" fill="none" stroke="black"/>
                <path d="M 408,48 L 408,320" fill="none" stroke="black"/>
                <path d="M 536,48 L 536,320" fill="none" stroke="black"/>
                <path d="M 416,80 Q 418,76.8 420,80 Q 422,83.2 424,80 Q 426,76.8 428,80 Q 430,83.2 432,80 Q 434,76.8 436,80 Q 438,83.2 440,80 Q 442,76.8 444,80 Q 446,83.2 448,80 Q 450,76.8 452,80 Q 454,83.2 456,80 Q 458,76.8 460,80 Q 462,83.2 464,80 Q 466,76.8 468,80 Q 470,83.2 472,80 Q 474,76.8 476,80 Q 478,83.2 480,80 Q 482,76.8 484,80 Q 486,83.2 488,80 Q 490,76.8 492,80 Q 494,83.2 496,80 Q 498,76.8 500,80 Q 502,83.2 504,80 Q 506,76.8 508,80 Q 510,83.2 512,80 Q 514,76.8 516,80 Q 518,83.2 520,80 Q 522,76.8 524,80 Q 526,83.2 528,80 Q 530,76.8 532,80 Q 534,83.2 536,80 " fill="none" stroke="black"/>
                <path d="M 408,96 Q 410,92.8 412,96 Q 414,99.2 416,96 Q 418,92.8 420,96 Q 422,99.2 424,96 Q 426,92.8 428,96 Q 430,99.2 432,96 Q 434,92.8 436,96 Q 438,99.2 440,96 Q 442,92.8 444,96 Q 446,99.2 448,96 Q 450,92.8 452,96 Q 454,99.2 456,96 Q 458,92.8 460,96 Q 462,99.2 464,96 Q 466,92.8 468,96 Q 470,99.2 472,96 Q 474,92.8 476,96 Q 478,99.2 480,96 Q 482,92.8 484,96 Q 486,99.2 488,96 Q 490,92.8 492,96 Q 494,99.2 496,96 Q 498,92.8 500,96 Q 502,99.2 504,96 Q 506,92.8 508,96 Q 510,99.2 512,96 Q 514,92.8 516,96 Q 518,99.2 520,96 Q 522,92.8 524,96 Q 526,99.2 528,96 " fill="none" stroke="black"/>
                <path d="M 416,144 Q 418,140.8 420,144 Q 422,147.2 424,144 Q 426,140.8 428,144 Q 430,147.2 432,144 Q 434,140.8 436,144 Q 438,147.2 440,144 Q 442,140.8 444,144 Q 446,147.2 448,144 Q 450,140.8 452,144 Q 454,147.2 456,144 Q 458,140.8 460,144 Q 462,147.2 464,144 Q 466,140.8 468,144 Q 470,147.2 472,144 Q 474,140.8 476,144 Q 478,147.2 480,144 Q 482,140.8 484,144 Q 486,147.2 488,144 Q 490,140.8 492,144 Q 494,147.2 496,144 Q 498,140.8 500,144 Q 502,147.2 504,144 Q 506,140.8 508,144 Q 510,147.2 512,144 Q 514,140.8 516,144 Q 518,147.2 520,144 Q 522,140.8 524,144 Q 526,147.2 528,144 Q 530,140.8 532,144 Q 534,147.2 536,144 " fill="none" stroke="black"/>
                <path d="M 288,160 L 408,160" fill="none" stroke="black"/>
                <path d="M 160,176 L 400,176" fill="none" stroke="black"/>
                <path d="M 32,192 Q 34,188.8 36,192 Q 38,195.2 40,192 Q 42,188.8 44,192 Q 46,195.2 48,192 Q 50,188.8 52,192 Q 54,195.2 56,192 Q 58,188.8 60,192 Q 62,195.2 64,192 Q 66,188.8 68,192 Q 70,195.2 72,192 Q 74,188.8 76,192 Q 78,195.2 80,192 Q 82,188.8 84,192 Q 86,195.2 88,192 Q 90,188.8 92,192 Q 94,195.2 96,192 Q 98,188.8 100,192 Q 102,195.2 104,192 Q 106,188.8 108,192 Q 110,195.2 112,192 Q 114,188.8 116,192 Q 118,195.2 120,192 Q 122,188.8 124,192 Q 126,195.2 128,192 Q 130,188.8 132,192 Q 134,195.2 136,192 Q 138,188.8 140,192 Q 142,195.2 144,192 Q 146,188.8 148,192 Q 150,195.2 152,192 " fill="none" stroke="black"/>
                <path d="M 408,192 Q 410,188.8 412,192 Q 414,195.2 416,192 Q 418,188.8 420,192 Q 422,195.2 424,192 Q 426,188.8 428,192 Q 430,195.2 432,192 Q 434,188.8 436,192 Q 438,195.2 440,192 Q 442,188.8 444,192 Q 446,195.2 448,192 Q 450,188.8 452,192 Q 454,195.2 456,192 Q 458,188.8 460,192 Q 462,195.2 464,192 Q 466,188.8 468,192 Q 470,195.2 472,192 Q 474,188.8 476,192 Q 478,195.2 480,192 Q 482,188.8 484,192 Q 486,195.2 488,192 Q 490,188.8 492,192 Q 494,195.2 496,192 Q 498,188.8 500,192 Q 502,195.2 504,192 Q 506,188.8 508,192 Q 510,195.2 512,192 Q 514,188.8 516,192 Q 518,195.2 520,192 Q 522,188.8 524,192 Q 526,195.2 528,192 " fill="none" stroke="black"/>
                <path d="M 24,238 L 144,238" fill="none" stroke="black"/>
                <path d="M 24,242 L 144,242" fill="none" stroke="black"/>
                <path d="M 280,272 L 400,272" fill="none" stroke="black"/>
                <path d="M 288,288 L 400,288" fill="none" stroke="black"/>
                <path d="M 32,318 L 144,318" fill="none" stroke="black"/>
                <path d="M 32,322 L 144,322" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="536,192 524,186.4 524,197.6" fill="black" transform="rotate(0,528,192)"/>
                <polygon class="arrowhead" points="536,96 524,90.4 524,101.6" fill="black" transform="rotate(0,528,96)"/>
                <polygon class="arrowhead" points="424,144 412,138.4 412,149.6" fill="black" transform="rotate(180,416,144)"/>
                <polygon class="arrowhead" points="424,80 412,74.4 412,85.6" fill="black" transform="rotate(180,416,80)"/>
                <polygon class="arrowhead" points="408,272 396,266.4 396,277.6" fill="black" transform="rotate(0,400,272)"/>
                <polygon class="arrowhead" points="408,176 396,170.4 396,181.6" fill="black" transform="rotate(0,400,176)"/>
                <polygon class="arrowhead" points="296,288 284,282.4 284,293.6" fill="black" transform="rotate(180,288,288)"/>
                <polygon class="arrowhead" points="296,160 284,154.4 284,165.6" fill="black" transform="rotate(180,288,160)"/>
                <polygon class="arrowhead" points="168,176 156,170.4 156,181.6" fill="black" transform="rotate(180,160,176)"/>
                <polygon class="arrowhead" points="152,240 140,234.4 140,245.6" fill="black" transform="rotate(0,144,240)"/>
                <polygon class="arrowhead" points="40,320 28,314.4 28,325.6" fill="black" transform="rotate(180,32,320)"/>
                <polygon class="arrowhead" points="40,192 28,186.4 28,197.6" fill="black" transform="rotate(180,32,192)"/>
                <g class="text">
                  <text x="36" y="36">ClientB1</text>
                  <text x="152" y="36">ServerB</text>
                  <text x="276" y="36">HubA</text>
                  <text x="400" y="36">ServerC</text>
                  <text x="532" y="36">ClientC1</text>
                  <text x="452" y="68">Upload</text>
                  <text x="504" y="68">asset</text>
                  <text x="436" y="116">send</text>
                  <text x="488" y="116">message</text>
                  <text x="428" y="132">w/</text>
                  <text x="464" y="132">asset</text>
                  <text x="508" y="132">link</text>
                  <text x="364" y="148">submit</text>
                  <text x="228" y="164">fanout</text>
                  <text x="56" y="212">fetch</text>
                  <text x="104" y="212">asset</text>
                  <text x="56" y="228">OHTTP</text>
                  <text x="112" y="228">wrapped</text>
                  <text x="184" y="244">OHTTP</text>
                  <text x="216" y="260">::::::::::::::&gt;</text>
                  <text x="304" y="260">GET</text>
                  <text x="344" y="260">asset</text>
                  <text x="216" y="308">&lt;::::::::::::::</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
ClientB1       ServerB          HubA          ServerC         ClientC1
  |               |               |               |               |
  |               |               |               |  Upload asset |
  |               |               |               |<~~~~~~~~~~~~~~+
  |               |               |               +~~~~~~~~~~~~~~>|
  |               |               |               | send message  |
  |               |               |               | w/ asset link |
  |               |               |       submit  |<~~~~~~~~~~~~~~+
  |               |      fanout   |<--------------+               |
  |               |<--------------+-------------->|               |
  |<~~~~~~~~~~~~~~+               |               +~~~~~~~~~~~~~~>|
  | fetch asset   |               |               |               |
  | OHTTP wrapped |               |               |               |
  +==============>| OHTTP         |               |               |
  |               +::::::::::::::>| GET asset     |               |
  |               |               +-------------->|               |
  |               |               |<--------------|               |
  |               |<::::::::::::::+               |               |
  |<==============|               |               |               |
]]></artwork>
          </artset>
          <t>For the hub, an OHTTP Gateway is <bcp14>REQUIRED</bcp14> to implement. The hub <bcp14>SHOULD</bcp14> provide
the OHTTP Gateway capability for its peer providers.</t>
          <t>Other providers <bcp14>SHOULD</bcp14> implement the OHTTP Relay capability and <bcp14>SHOULD</bcp14> enable
the relay to access</t>
          <t>The main benefit of this mechanism is that the downloading provider does not
learn the domains of every asset provider.</t>
        </section>
      </section>
    </section>
    <section anchor="minimal-metadata-rooms">
      <name>Minimal metadata rooms</name>
      <t>The room state is visible to the hub and with it the room's participant list,
giving the hub access to a significant amount of user metadata.</t>
      <t>To limit the amount of metadata the hub has access to, rooms can be created as
<em>minimal metadata rooms</em> (MMR). In an MMR the participant list and the
credentials in the room's underlying MLS group consist only of pseudonyms. The
real identifiers are stored alongside the pseudonyms encrypted under a key known
only to room participants, but not the hub.</t>
      <t>MMRs requires some additional key management, which leads to restrictions in how
the MMR can be joined and which users each participant can add to the room.</t>
      <section anchor="credential-encryption">
        <name>Credential encryption</name>
        <t>Identifiers of participants and their clients occur in two locations in a room's
state: the participant list and the credentials of the room's underlying MLS
group. In an MMR, the real identifiers of clients and users are replaced by
pseudonyms in the shape of random UUIDs qualified with the domain of the user's
provider.</t>
        <t>In MMRs, all leaves of the underlying group <bcp14>MUST</bcp14> contain PseudonymousCredentials.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  IdentifierUri client_pseudonym;
  IdentifierUri user_pseudonym;
  opaque signature_public_key;
  opaque identity_link_ciphertext<V>;
} PseudonymousCredential
]]></sourcecode>
        <ul spacing="normal">
          <li>
            <t><tt>user_pseudonym</tt>: The pseudonym of the client's user in this group</t>
          </li>
          <li>
            <t><tt>client_pseudonym</tt>: The pseudonym of the client identified by this credential</t>
          </li>
          <li>
            <t><tt>signature_public_key</tt>: The signature public key used to authenticate MLS
messages</t>
          </li>
          <li>
            <t><tt>identity_link_ciphertext</tt>: A ciphertext containing a credential with the
clients real identifier</t>
          </li>
        </ul>
        <t>In any given room, the <tt>user_pseudonym</tt> of a client <bcp14>MUST</bcp14> be the same across all
clients of a user and it <bcp14>MUST</bcp14> be the same as the user's entry in the participant
list.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  IdentifierUri client_pseudonym;
  IdentifierUri user_pseudonym;
  opaque signature_public_key;
} PseudonymousCredentialTBS

struct {
  /* SignWithLabel(., "PseudonymousCredentialTBS",
    PseudonymousCredentialTBS) */
  opaque pseudonymous_credential_signature<V>;
  Credential client_credential;
} IdentityLinkTBE
]]></sourcecode>
        <t>The <tt>identity_link_ciphertext</tt> is created by encrypting the IdentityLinkTBE.
The IdentityLinkTBE contains the client's real credential, and a signature over the
PseudonymousCredentialTBS signed with the client credential's <tt>signature_public_key</tt>.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Specify a key management scheme that ideally
- is efficient
- allows the basic MIMI flows
- ensures that all participants can learn the identities of all other
  participants at all times
- provides FS and PCS w.r.t. metadata hiding</t>
            <t>There are several options that represent different trade-offs, but are not yet
fully specified. They will be added at a later date.</t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="relation-between-mimi-state-and-cryptographic-state">
      <name>Relation between MIMI state and cryptographic state</name>
      <section anchor="room-state">
        <name>Room state</name>
        <t>The state of a room consists of its room ID, its base policy, its
participant list (including the role and participation state of each
participant), and the associated end-to-end protocol state (its MLS group
state) that anchors the room state cryptographically.</t>
        <t>While all parties involved in a room agree on the room's state during a
specific epoch, the Hub is the arbiter that decides if a state change is valid,
consistent with the room's then-current policy. All state-changing events are
sent to the Hub and checked for their validity and policy conformance, before
they are forwarded to any follower servers or local clients.</t>
        <t>As soon as the Hub accepts an event that changes the room state, its effect is
applied to the room state and future events are validated in the context of that
new state.</t>
        <t>The room state is thus changed based on events, even if the MLS proposal
implementing the event was not yet committed by a client. Note that this only
applies to events changing the room state.</t>
      </section>
      <section anchor="cryptographic-room-representation">
        <name>Cryptographic room representation</name>
        <t>Each room is represented cryptographically by an MLS group. The Hub that
manages the room also manages the list of group members, i.e. the
list of clients belonging to users currently in the room. Application state
that is stored in the MLS GroupContext is stored as application components
in the <tt>app_data_dictionary</tt> extension, as described in <xref section="4.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>.</t>
      </section>
      <section anchor="proposal-commit-paradigm">
        <name>Proposal-commit paradigm</name>
        <t>The MLS protocol follows a proposal-commit paradigm. Any
party involved in a room (follower server, Hub or clients) can send proposals
(e.g. to add/remove/update clients of a user or to re-initialize the group with
different parameters). However, only clients can send commits, which contain all
valid previously sent proposals and apply them to the MLS group state.</t>
        <t>The MIMI usage of MLS ensures that the Hub, all follower servers and the clients
of all active participants agree on the group state, which includes the client
list and the key material used for message encryption (although the latter is
only available to clients). Since the group state also includes a copy of the
room state at the time of the most recent commit, it is also covered by the
agreement.</t>
      </section>
      <section anchor="authenticating-proposals">
        <name>Authenticating proposals</name>
        <t>MLS requires that MLS proposals from the Hub and
from follower servers (external senders in MLS terminology) be authenticated
using key material contained in the <tt>external_senders</tt> extension of the MLS
group. Each MLS group associated with a MIMI room <bcp14>MUST</bcp14> therefore contain an
<tt>external_senders</tt> extension. That extension <bcp14>MUST</bcp14> contain at least the
Certificate of the Hub.</t>
        <t>When a user from a follower server becomes a participant in the room, the
Certificate of the follower server <bcp14>MAY</bcp14> be added to the extension. When the last
participant belonging to a follower server leaves the room, the certificate of
that user <bcp14>MUST</bcp14> be removed from the list. Changes to the <tt>external_senders</tt>
extension only take effect when the MLS proposal containing the event is
committed by a MIMI commit.</t>
      </section>
      <section anchor="participant-list">
        <name>Participant List</name>
        <t>The participant list is a list of "users" in a room. Within a room, each user
is assigned exactly one <em>role</em> (expressed with a <tt>role_index</tt> and described
in <xref target="I-D.ietf-mimi-room-policy"/> at any given time (specifically within any MLS
epoch). In a room that has multiple MLS clients per "user", the identifier for
each user in <tt>participants.user</tt> is the same across all that user's clients in
the room. Note that each user has a single role at any point in time, and
therefore all clients of the same user also have the same role.</t>
        <t>The participant list may include inactive participants, which currently do not
have any clients in the corresponding MLS group, for example if their clients
do not have available KeyPackages or if all of their clients are temporarily
"kicked" out of the group. The participant list can also contain participants
that are explicitly banned, by assigning them a suitable role which does not
have any capabilities.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  opaque user<V>;
  uint32 role_index;
} UserRolePair;

struct {
  UserRolePair participants<V>;
} ParticipantListData;

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

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

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

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

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

RoomMetaData room_metadata;

RoomMetaData RoomMetaUpdate;
]]></sourcecode>
        <t>RoomMetaUpdate (which has the same format as RoomMetaData) is the format of the
<tt>update</tt> field inside the AppDataUpdate struct in an AppDataUpdate Proposal for
the Room Metadata component.
If the contents of the <tt>update</tt> field are valid and if the proposer is
authorized to generate such an update, the value of the <tt>update</tt> field
completely replaces the value of the <tt>data</tt> field.</t>
        <t>Only a single Room metadata update is valid per commit.</t>
      </section>
    </section>
    <section anchor="consent">
      <name>Consent</name>
      <t>Most instant messaging systems have some notion of how a user consents to be
added to a room, and how they manipulate this consent.</t>
      <t>In the connection-oriented model, once two users are connected, either user
can add the other to any number of rooms. In other systems (often with many
large and/or public rooms), a user needs to consent individually to be added
to a room.</t>
      <t>The MIMI consent mechanism supports both models and allows them to coexist.
It allows a user to request consent, grant consent, revoke consent, and
cancel a request for consent. Each of these consent operations can indicate
a specific room, or indicate any room.</t>
      <t>A connection grant or revoke does not need to specify a room if a connection
request did, or vice versa. A connection grant or revoke does not even need
to follow a connection request.</t>
      <t>For example, Alice could ask for consent to add Bob to a specific room. Bob
could send a connection grant for Alice to add him to any room, or a
connection revoke preventing Alice from adding him to any room. Similarly,
Alice might have sent a connection request to add Bob for any room (as a
connection request), which Bob ignored or did not see. Later, Bob wants to
join a specific room administered by Alice. Bob sends a connection grant for
the specific room for Alice and sends a Knock request to Alice asking to be
added. Finally, Cathy could send a connection grant for Bob (even if Bob did
not initiate a connection request to Cathy), and Alice could recognize Cathy
on the system and send a connection revoke for her preemptively.</t>
      <ul empty="true">
        <li>
          <t><strong>NOTE</strong>: Many providers use additional factors to apply default consent
within their service such as a user belonging to a specific workgroup or
employer, participating in a related room (ex: WhatsApp "communities"), or
presence of a user in the other user's contact list. MIMI does not need to
provide a way to replicate or describe these supplemental mechanisms,
since they are strongly linked to specific provider policies.</t>
        </li>
      </ul>
      <t>Consent requests have sensitive privacy implications. The sender of a
consent request should receive an acknowledgement that the request was
received by the provider of the target user. For privacy reasons, the
requestor should not know if the target user received or viewed the request.
The original requestor will obviously find out if the target grants consent,
but a consent revocation/rejection is typically not communicated to the
revoked/rejected user (again for privacy reasons).</t>
      <t>Consent operations are only sent directly between the acting provider
(sending the request, grant, revoke, or cancel) and the target provider (the
object of the consent). In other words, the two providers must have a direct
peering relationship.</t>
      <t>In our example, Alice requests consent from Bob for any room. Later, Bob
sends a grants consent to Alice to add him to any room. At the same time as
sending the consent request, Alice grants consent to Bob to add her to any
room.</t>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Add MIMI threat model, and great expand this section.</t>
        </li>
      </ul>
      <t>The MIMI protocol incorporates several layers of security.</t>
      <t>Individual protocol actions are protected against network attackers with
mutually-authenticated TLS, where the TLS certificates authenticate the
identities that the protocol actors assert at the application layer.</t>
      <t>Messages and room state changes are protected end-to-end using MLS.  The
protection is "end-to-end" in the sense that messages sent within the group are
confidentiality-protected against all servers involved in the delivery of those
messages, and in the sense that the authenticity of room state changes is
verified by the end clients involved in the room.  The usage of MLS ensures that
the servers facilitating the exchange cannot read messages in the room or
falsify room state changes, even though they can read the room state change
messages.</t>
      <t>Each room has an authorization policy that dictates which protocol actors can
perform which actions in the room.  This policy is enforced by the hub server
for the room.  The actors for whom the policy is being evaluated authenticate
their identities to the hub server using the MLS PublicMessage signed object
format, together with the identity credentials presented in MLS.  This design
means that the hub is trusted to correctly enforce the room's policy, but this
cost is offset by the simplicity of not having multiple policy enforcement points.</t>
      <section anchor="franking">
        <name>Franking</name>
        <t>TBD.</t>
      </section>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document registers the following four MLS application components per
<xref section="7.6" sectionFormat="of" target="I-D.ietf-mls-extensions"/>.</t>
      <section anchor="iana-frank-aad">
        <name>frank_aad app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD1</t>
          </li>
          <li>
            <t>Name: frank_aad</t>
          </li>
          <li>
            <t>Where: AD</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
      <section anchor="iana-franking-sig-key">
        <name>franking_signature_key app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD2</t>
          </li>
          <li>
            <t>Name: franking_signature_key</t>
          </li>
          <li>
            <t>Where: GC</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
      <section anchor="participantlist-app-component">
        <name>participant_list app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD3</t>
          </li>
          <li>
            <t>Name: participant_list</t>
          </li>
          <li>
            <t>Where: GC</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
      <section anchor="roommetadata-app-component">
        <name>room_metadata app component</name>
        <ul spacing="normal">
          <li>
            <t>Value: TBD4</t>
          </li>
          <li>
            <t>Name: room_metadata</t>
          </li>
          <li>
            <t>Where: GC</t>
          </li>
          <li>
            <t>Recommended: Y</t>
          </li>
          <li>
            <t>Reference: RFCXXXX</t>
          </li>
        </ul>
      </section>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="OidcCore" target="https://openid.net/specs/openid-connect-core-1_0.html">
          <front>
            <title>OpenID Connect Core 1.0 incorporating errata set 2</title>
            <author initials="N." surname="Sakimura" fullname="Nat Sakimura">
              <organization/>
            </author>
            <author initials="J." surname="Bradley" fullname="John Bradley">
              <organization/>
            </author>
            <author initials="M. B." surname="Jones" fullname="Michael B. Jones">
              <organization/>
            </author>
            <author initials="B. de" surname="Medeiros" fullname="Breno de Medeiros">
              <organization/>
            </author>
            <author initials="C." surname="Mortimore" fullname="Chuck Mortimore">
              <organization/>
            </author>
            <date year="2023" month="December" day="15"/>
          </front>
        </reference>
        <reference anchor="I-D.barnes-mimi-arch">
          <front>
            <title>An Architecture for More Instant Messaging Interoperability (MIMI)</title>
            <author fullname="Richard Barnes" initials="R." surname="Barnes">
              <organization>Cisco</organization>
            </author>
            <date day="4" month="March" year="2024"/>
            <abstract>
              <t>   The More Instant Messaging Interoperability (MIMI) working group is
   defining a suite of protocols that allow messaging providers to
   interoperate with one another.  This document lays out an overall
   architecture enumerating the MIMI protocols and how they work
   together to enable an overall messaging experience.

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

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-barnes-mls-appsync-01"/>
        </reference>
        <reference anchor="RFC3986">
          <front>
            <title>Uniform Resource Identifier (URI): Generic Syntax</title>
            <author fullname="T. Berners-Lee" initials="T." surname="Berners-Lee"/>
            <author fullname="R. Fielding" initials="R." surname="Fielding"/>
            <author fullname="L. Masinter" initials="L." surname="Masinter"/>
            <date month="January" year="2005"/>
            <abstract>
              <t>A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource. This specification defines the generic URI syntax and a process for resolving URI references that might be in relative form, along with guidelines and security considerations for the use of URIs on the Internet. The URI syntax defines a grammar that is a superset of all valid URIs, allowing an implementation to parse the common components of a URI reference without knowing the scheme-specific requirements of every possible identifier. This specification does not define a generative grammar for URIs; that task is performed by the individual specifications of each URI scheme. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="66"/>
          <seriesInfo name="RFC" value="3986"/>
          <seriesInfo name="DOI" value="10.17487/RFC3986"/>
        </reference>
        <reference anchor="RFC9110">
          <front>
            <title>HTTP Semantics</title>
            <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
            <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
            <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
            <date month="June" year="2022"/>
            <abstract>
              <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document describes the overall architecture of HTTP, establishes common terminology, and defines aspects of the protocol that are shared by all versions. In this definition are core protocol elements, extensibility mechanisms, and the "http" and "https" Uniform Resource Identifier (URI) schemes.</t>
              <t>This document updates RFC 3864 and obsoletes RFCs 2818, 7231, 7232, 7233, 7235, 7538, 7615, 7694, and portions of 7230.</t>
            </abstract>
          </front>
          <seriesInfo name="STD" value="97"/>
          <seriesInfo name="RFC" value="9110"/>
          <seriesInfo name="DOI" value="10.17487/RFC9110"/>
        </reference>
        <reference anchor="RFC6125">
          <front>
            <title>Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)</title>
            <author fullname="P. Saint-Andre" initials="P." surname="Saint-Andre"/>
            <author fullname="J. Hodges" initials="J." surname="Hodges"/>
            <date month="March" year="2011"/>
            <abstract>
              <t>Many application technologies enable secure communication between two entities by means of Internet Public Key Infrastructure Using X.509 (PKIX) certificates in the context of Transport Layer Security (TLS). This document specifies procedures for representing and verifying the identity of application services in such interactions. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6125"/>
          <seriesInfo name="DOI" value="10.17487/RFC6125"/>
        </reference>
        <reference anchor="I-D.ietf-mimi-room-policy">
          <front>
            <title>Room Policy for the More Instant Messaging Interoperability (MIMI) Protocol</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="2" month="March" year="2025"/>
            <abstract>
              <t>   This document describes a set of concrete room policies for the More
   Instant Messaging Interoperability (MIMI) Working Group.  It
   describes several independent properties and policy attributes which
   can be combined to model a wide range of chat and multimedia
   conference types.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-room-policy-01"/>
        </reference>
        <reference anchor="I-D.ietf-mls-extensions">
          <front>
            <title>The Messaging Layer Security (MLS) Extensions</title>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="3" month="July" year="2025"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol is an asynchronous group
   authenticated key exchange protocol.  MLS provides a number of
   capabilities to applications, as well as several extension points
   internal to the protocol.  This document provides a consolidated
   application API, guidance for how the protocol's extension points
   should be used, and a few concrete examples of both core protocol
   extensions and uses of the application API.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mls-extensions-07"/>
        </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="22" month="April" year="2025"/>
            <abstract>
              <t>   The Messaging Layer Security (MLS) protocol needs to share its
   ratchet_tree object to welcome new clients into a group and in
   external joins.  While the protocol only defines a mechanism for
   sharing the entire tree, most implementations use various
   optimizations to avoid sending this structure repeatedly in large
   groups.  This document describes a way to convey these improvements
   in a standardized way and to convey the parts of a GroupInfo object
   that are not visible to an intermediary server.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mls-ratchet-tree-options-02"/>
        </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="21" month="April" year="2025"/>
            <abstract>
              <t>   This document defines a SemiPrivateMessage for the Messaging Layer
   Security (MLS) protocol.  It allows members to share otherwise
   private commits and proposals with a designated list of external
   receivers rather than send these handshakes in a PublicMessage.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mls-semiprivatemessage-05"/>
        </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="28" month="February" year="2025"/>
            <abstract>
              <t>   This document describes content semantics common in Instant Messaging
   (IM) systems and describes a profile suitable for instant messaging
   interoperability of messages end-to-end encrypted inside the MLS
   (Message Layer Security) Protocol.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-mimi-content-06"/>
        </reference>
        <reference anchor="RFC6350" xml:base="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6350.xml">
          <front>
            <title>vCard Format Specification</title>
            <author fullname="S. Perreault" initials="S." surname="Perreault"/>
            <date month="August" year="2011"/>
            <abstract>
              <t>This document defines the vCard data format for representing and exchanging a variety of information about individuals and other entities (e.g., formatted and structured name and delivery addresses, email address, multiple telephone numbers, photograph, logo, audio clips, etc.). This document obsoletes RFCs 2425, 2426, and 4770, and updates RFC 2739. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="6350"/>
          <seriesInfo name="DOI" value="10.17487/RFC6350"/>
        </reference>
        <reference anchor="RFC5322">
          <front>
            <title>Internet Message Format</title>
            <author fullname="P. Resnick" initials="P." role="editor" surname="Resnick"/>
            <date month="October" year="2008"/>
            <abstract>
              <t>This document specifies the Internet Message Format (IMF), a syntax for text messages that are sent between computer users, within the framework of "electronic mail" messages. This specification is a revision of Request For Comments (RFC) 2822, which itself superseded Request For Comments (RFC) 822, "Standard for the Format of ARPA Internet Text Messages", updating it to reflect current practice and incorporating incremental changes that were specified in other RFCs. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="5322"/>
          <seriesInfo name="DOI" value="10.17487/RFC5322"/>
        </reference>
        <reference anchor="RFC9458">
          <front>
            <title>Oblivious HTTP</title>
            <author fullname="M. Thomson" initials="M." surname="Thomson"/>
            <author fullname="C. A. Wood" initials="C. A." surname="Wood"/>
            <date month="January" year="2024"/>
            <abstract>
              <t>This document describes Oblivious HTTP, a protocol for forwarding encrypted HTTP messages. Oblivious HTTP allows a client to make multiple requests to an origin server without that server being able to link those requests to the client or to identify the requests as having come from the same client, while placing only limited trust in the nodes used to forward the messages.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9458"/>
          <seriesInfo name="DOI" value="10.17487/RFC9458"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="SecretConversations" target="https://about.fb.com/wp-content/uploads/2016/07/messenger-secret-conversations-technical-whitepaper.pdf">
          <front>
            <title>Messenger Secret Conversations: Technical Whitepaper, Version 2.0</title>
            <author>
              <organization>Facebook</organization>
            </author>
            <date year="2017" month="May" day="18"/>
          </front>
        </reference>
        <reference anchor="Grubbs2017" target="https://eprint.iacr.org/2017/664.pdf">
          <front>
            <title>Message Franking via Committing Authenticated Encryption</title>
            <author initials="P." surname="Grubbs" fullname="Paul Grubbs">
              <organization>Cornell Tech</organization>
            </author>
            <author initials="J." surname="Lu" fullname="Jiahui Lu">
              <organization>Shanghai Jiao Tong University</organization>
            </author>
            <author initials="T." surname="Ristenpart" fullname="Thomas Ristenpart">
              <organization>Cornell Tech</organization>
            </author>
            <date year="2017"/>
          </front>
        </reference>
        <reference anchor="InvisibleSalamanders" target="https://link.springer.com/content/pdf/10.1007/978-3-319-96884-1_6.pdf">
          <front>
            <title>Fast Message Franking: From Invisible Salamanders to Encryptment</title>
            <author initials="Y." surname="Dodis" fullname="Yevgeniy Dodis">
              <organization>New York University</organization>
            </author>
            <author initials="P." surname="Grubbs" fullname="Paul Grubbs">
              <organization>Cornell Tech</organization>
            </author>
            <author initials="T." surname="Ristenpart" fullname="Thomas Ristenpart">
              <organization>Cornell Tech</organization>
            </author>
            <author initials="J." surname="Woodage" fullname="Joanne Woodage">
              <organization>Royal Holloway, University of London</organization>
            </author>
            <date year="2018"/>
          </front>
        </reference>
        <reference anchor="RFC8555">
          <front>
            <title>Automatic Certificate Management Environment (ACME)</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="J. Hoffman-Andrews" initials="J." surname="Hoffman-Andrews"/>
            <author fullname="D. McCarney" initials="D." surname="McCarney"/>
            <author fullname="J. Kasten" initials="J." surname="Kasten"/>
            <date month="March" year="2019"/>
            <abstract>
              <t>Public Key Infrastructure using X.509 (PKIX) certificates are used for a number of purposes, the most significant of which is the authentication of domain names. Thus, certification authorities (CAs) in the Web PKI are trusted to verify that an applicant for a certificate legitimately represents the domain name(s) in the certificate. As of this writing, this verification is done through a collection of ad hoc mechanisms. This document describes a protocol that a CA and an applicant can use to automate the process of verification and certificate issuance. The protocol also provides facilities for other certificate management functions, such as certificate revocation.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8555"/>
          <seriesInfo name="DOI" value="10.17487/RFC8555"/>
        </reference>
        <reference anchor="I-D.mahy-mimi-identity">
          <front>
            <title>More Instant Messaging Interoperability (MIMI) Identity Concepts</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Rohan Mahy Consulting Services</organization>
            </author>
            <date day="3" month="March" year="2025"/>
            <abstract>
              <t>   This document explores the problem space in instant messaging (IM)
   identity interoperability when using end-to-end encryption, for
   example with the MLS (Message Layer Security) Protocol.  It also
   describes naming schemes for different types of IM identifiers.

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

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thanks to Paul Grubs, Jon Millican, and Julia Len for their reviews of the
franking mechanism and suggested changes. Thanks to Felix Linker for his
preliminary <eref target="https://github.com/felixlinker/mimi-franking-tamarin/">formal methods
analysis</eref> of MIMI
franking.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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
aYl2cVe9uSk4oopbCtrrtuYQ/aBQYbnHFVcKlRSXgXdJurY0xJGz3GkL9nde
UjLOjpuApjoNTu2X34Psz/tEY1QYzkKU9F2hArOlQ/1ipzKBX4WUneiVrc5J
JumA0+RwKWQzxqrppbQQzGcYLqLmjk55yJSuEcMlni+ZpqYbdViSXYYIfKyR
ecWQTRJovcD6JnWXJgRTSqtFsOsCRNT2kvPgyBreRDUMWcvB6iakRYk6Zwlg
dF7R7mHvsgb7rDRZilVvR896R3NL+Q5KLJz22+f//O747fNnsQknJoX9avHr
6TLnFEJyYbv4czJ4jf/bV7P4N99+T23to/ImvnNxMUvXNfWyZaMnzejJGd1V
U6oSLfaZmovrXNv98KGF2jlEKXQYndaUK55Gp2swQZZl47TQWsqHJrYuKWHv
a88EmKE5ImpWQpoZwI779hE4kh5Lo67nsqw+1FFM7qlBPtbB0sK9lqL1Ed3s
wx6gufzs2wzLVjMGmFZomesSXz/mz4Bxl+k2MOIGeYMsgkQlX1pdrHy8K5mq
bXTA705J498P2EcKI3EQdpYl0daIavIYG7NhMhvSWmzuahddShYxM8DdyuJ/
K3X2838rdfTvv5W6q+ET74Wv6mWVrtfZDRSwnjm+/kP074nOebt1tPb7OPr3
f6xSd6M5fh9v5mZKXQzU258LKXUvggCGEk3MEnYKDYFXhLYVF2Kdbk1BXlPu
xnOm/YTaJPp1pCb5NhZWRskiBmcmRXFIns8KqgLH6ig+FgoWEiMij9s0K7Kz
vOkqgZz0mza7RWqvurFxuKUxZNRoqOV0wliK5FVe5CusWJ41KXVjJtlMorJR
oqWeP9QNIpcKfSGi0Ltr88Zri6hiBWmXguiH7jz3Fdy13V7N3QYp9RHlZ3wY
NK4N+7k5TUbWxGE0y3wlrwmP+VXrzAsJ26HZuWFwrbF3syojhSat3ftV77bf
J4NXr97uk+8M69C/estyeGs/PhnO+KdtW9avaq5zyKaA0KYB/etUTwFlDdQK
tGC9uDupkL0NNTXBIukSlFEf8BNGmqqEXFsxpY4I5LxxWpucfd1GB2FRUr1T
aD53DnZbB+mSNAcjR+KkoP8CS1yRX5AlIUC2ucQlYrgjtz2mdlflJeE6glDA
jxmYErXCg1llYOe2gfCMBVjv1IG1S5XEUEY7lAN27tgArKVq6UHlwXHIDbrw
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
q/kXjZkBAA==

-->

</rfc>
