<?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.2 (Ruby 3.2.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ralston-mimi-protocol-01" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.18.2 -->
  <front>
    <title abbrev="MIMI+MLS Protocol">More Instant Messaging Interoperability (MIMI) using HTTPS and MLS</title>
    <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-protocol-01"/>
    <author fullname="Travis Ralston">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>travisr@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="Raphael Robert">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>ietf@raphaelrobert.com</email>
      </address>
    </author>
    <author fullname="Matthew Hodgson">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>matthew@matrix.org</email>
      </address>
    </author>
    <date year="2023" month="November" day="06"/>
    <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 54?>

<t>This document specifies the More Instant Messaging Interoperability (MIMI)
protocol, which allows users of different messaging providers to share
membership in rooms and send messages to one-another.</t>
      <t>More specifically, the MIMI protocol defines message formats and conventions
that allows the servers of different providers to interoperate, leaving the
provider-internal client-server communication up to the provider.</t>
      <t>To ensure that communications between users are confidential and authentic, the
MIMI protocol relies on MLS (<xref target="RFC9420"/>, through the MIMI DS protocol
<xref target="I-D.robert-mimi-delivery-service"/>) to protect messages end-to-end.</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-ralston-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 68?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>Providers of secure messaging services typically allow their users to only
communicate with other users of the same provider. This can be limiting for
users, who frequently have to run clients of multiple messaging applications in
parallel, each for a different secure messaging provider.</t>
      <t>The More Instant Messaging Interoperability (MIMI) protocol specified in this
document allows interoperability on the provider level based on rooms. Each MIMI
protocol room is hosted at a single provider, but allows users from different
providers to become participants in the room.</t>
      <t>Users and providers can use events to interact with the provider hosting the
room and with one-another, for example, to add or remove users from the room.</t>
      <t>Each user can have clients in the room, who can then communicate with
one-another, where messages are end-to-end encrypted using the Messaging Layer
Security (MLS) protocol (<xref target="RFC9420"/>).</t>
      <t>An MLS group (through the MIMI DS protocol
<xref target="I-D.robert-mimi-delivery-service"/>) forms the cryptographic core of each room
and ensures that clients in the room agree on room state and group state such as
user and client level membership.</t>
    </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"/>.</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>
      <ul empty="true">
        <li>
          <t><strong>ISSUE</strong>: Come to consensus on a specific binary encoding for the MIMI
transport protocol.</t>
        </li>
      </ul>
      <ul empty="true">
        <li>
          <t><strong>ISSUE</strong>: Come to consensus on a specific set of MIMI transport protocol
semantics.</t>
        </li>
      </ul>
    </section>
    <section anchor="example-protocol-flow">
      <name>Example protocol flow</name>
      <t>This section shows how three users (Alice, Bob and Cathy) from different
providers can use the protocol specified in this document to join the same room
and send messages to one-another. (Not all of these steps are part of the MIMI
transport protocol):</t>
      <ul spacing="normal">
        <li>
          <t>Alice get the internal identifier for Bob</t>
        </li>
        <li>
          <t>Alice gains consent to talk to Bob</t>
        </li>
        <li>
          <t>Alice fetches initial keying material for Bob's clients</t>
        </li>
        <li>
          <t>(Alice create a room) †</t>
        </li>
        <li>
          <t>Alice adds Bob to a room</t>
        </li>
        <li>
          <t>Alice sends a message to the room</t>
        </li>
        <li>
          <t>Bob sends a message to the room</t>
        </li>
        <li>
          <t>The hub/owning provider fans out the message</t>
        </li>
        <li>
          <t>Bob adds a new client</t>
        </li>
        <li>
          <t>Alice repeats the first three steps for Cathy</t>
        </li>
        <li>
          <t>Alice adds Cathy to the room</t>
        </li>
        <li>
          <t>Alice removes Bob from the room</t>
        </li>
      </ul>
      <t>Throughout this section, we will detail the individual operations through
Alice's lens. All actions by Alice are taken through Alice's client and her
server's proprietary API. While some parts of the individual messages originate
from Alice's clients, the MIMI protocol is only concerned with the communication
between Alice's, Bob's and Cathy's servers. So whenever users are referenced
throughout this section, it is implied that they are communicating with their
respective servers, which then communicate with one-another.</t>
      <t>† as mentioned in the text, creating a room is a local provider
action, which is out of scope of MIMI.</t>
      <section anchor="get-internal-identifier-for-bob">
        <name>Get internal identifier for Bob</name>
        <t>This is an example/placeholder for a possibly more sophisticated discovery
mechanism. It is not intended to be directly implemented.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Replace with or reference a discovery mechanism with WG consensus</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Details will follow once the WG has concensus on identifiers, their
mapping and their retrieval/discovery. 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>
        <t>Alice obtains Bob's internal identifier.</t>
        <t>Alice fetches the internal identifier for some field of Bob's, in
this example his handle.</t>
        <artwork><![CDATA[
GET /identifierDiscovery/{domain}
]]></artwork>
        <t>The request body is described as:</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  handle(1),
  nick(2),
  email(3),
  phone(4),
  partialName(5),
  wholeProfile(6),
  oidcStdClaim(7),
  vcardField(8),
  (255)
} IdentifierType;

struct {
  IdentifierType type;
  string searchValue;
  select(type) {
     case oidcStdClaim:
       string claimName;
    case vcardField:
       string fieldName;
  };
} IdentifierRequest;

]]></sourcecode>
        <t>The response body is described as:</t>
        <sourcecode type="tls"><![CDATA[
enum {
  success(0),
  notFound(1),
  ambiguous(2),
  forbidden(3),
  unsupportedField(4),
  (255)
} IdentifierDiscoveryCode;

struct {
  IdentifierDiscoverCode responseCode;
  IdentifierUri uri;
} IdentifierResponse;
]]></sourcecode>
        <ul empty="true">
          <li>
            <t><strong>ISSUE</strong>: In the course of discovering Bob, Alice might or might not
obtain a list of Bob's clients.</t>
          </li>
        </ul>
      </section>
      <section anchor="fetch-initial-key-material-for-bob">
        <name>Fetch initial key material for Bob</name>
        <t>The action attempts to claim initial keying material for all the clients
of a list of users at a single provider. The keying material may not be
reused unless identified as "last resort" keying material.</t>
        <t>Alice sends an Event (framed in a MIMIMessage) of type <tt>ds.fetch_key_packages</tt>
to Bob's server, requesting key material for each of Bob's clients.</t>
        <t>See <xref target="event-schema"/> for the definition of Events in general and
<xref target="ev-fetchkeypackage"/> for the <tt>ds.fetch_key_packages</tt> event.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: For now, the event fetches key packages based on client identifiers,
not user identifiers. This is because KeyPackage fetching is part of MIMI DS,
which doesn't know what a user is. We could, however, send multiple MIMI DS
requests in a single MIMI protocol request.</t>
          </li>
        </ul>
        <t>If the request was successful, the response contains a list of KeyPackages, one
for each client.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: For now, responses are simple, we can improve granularity when we
start optimizing.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Once we have framing for MIMIResponses, add a reference here.</t>
          </li>
        </ul>
      </section>
      <section anchor="create-a-room">
        <name>Create a room</name>
        <t>Creating a room is done between a client and its local provider and is out of
scope of MIMI. Since Alice creates the room on the server of her local provider,
it becomes the Hub for the room. However, the room policy format is in scope for MIMI.
We assume that this room is a members-only room, and that only users who have
the admin or owner role can add and remove users.</t>
        <t>We also assume that Alice has both the <tt>owner</tt> and <tt>admin</tt> roles within the room.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Add information on room policy here once we have consensus on what
that looks like.</t>
          </li>
        </ul>
      </section>
      <section anchor="alice-adds-bob">
        <name>Alice adds Bob</name>
        <t>Management of the participants list (i.e. the list of users in the room) is done
through <tt>m.room.user</tt> events. To add Bob to the room, Alice creates an
<tt>m.room.user</tt> event. See <xref target="ev-mroomuser"/> for more information on user state
changes.</t>
        <t>Room state is anchored in the room's underlying MLS group through a GroupContext
Extension, which mirrors all of the room's state variables.</t>
        <t><tt>m.room.user</tt> events are MLS proposals, which change the room state outside of
the MLS group immediately upon reception and align the mirror of the room state
in the extension (which is part of the group state) upon the next <tt>ds.commit</tt>
event. This reflects the MLS proposal-commit paradigm that allows members and
external parties to propose changes, but only members to commit them. See
<xref target="anchoring"/> for more information on how the room state is cryptographically
anchored.</t>
        <t>Alice does not only want to add Bob as a participant, but also Bob's client. To
do that, she sends a <tt>ds.commit</tt> event (<xref target="ev-commitupdate"/>) to the group. As
<tt>ds.commit</tt> events can contain an arbitrary number of proposals, Alice includes
the <tt>m.room.user</tt> proposal, as well as a proposal to add Bob's client. She
creates the latter by using the key material she previously fetched from Bob's
server.</t>
        <t>She then sends the resulting <tt>ds.commit</tt> to the Hub. Upon reception, the Hub
processes the commit and the proposals therein by updating the participant list
to include Bob and the underlying MLS group state to add Bob's client.</t>
        <t>Finally, the Hub fans out the commit event to Bob.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Especially when adding new clients, we will want to forward a
<tt>ds.commit</tt> event selectively, as existing group members will only be
interested in the actual commit, whereas new group members only need the
Welcome.</t>
          </li>
        </ul>
      </section>
      <section anchor="alice-sends-a-message-to-the-room">
        <name>Alice sends a message to the room</name>
        <t>After Bob has joined the room, Alice creates a message using the MIMI content
format <xref target="I-D.ietf-mimi-content"/>, and sends a <tt>ds.send_message</tt>
(<xref target="ev-sendmessage"/>) event to the Hub.</t>
      </section>
      <section anchor="the-hubowning-provider-fans-out-the-message">
        <name>The hub/owning provider fans out the message</name>
        <t>If the Hub accepts the message it fans the message out to all guest servers,
which in this case is Bob's server.</t>
        <t>Generally, the Hub also fans out any messages which originate from itself (ex:
removing clients of deleted users).</t>
      </section>
      <section anchor="bob-sends-a-message-to-the-room">
        <name>Bob sends a message to the room</name>
        <t>This is no different from Alice sending a message, which is fanned out in
exactly the same way.</t>
      </section>
      <section anchor="bob-adds-a-new-client">
        <name>Bob adds a new client</name>
        <t>For Bob's new client to join the MLS group and therefore fully participate in
the room with Alice, Bob needs to fetch the current group and room information
through a <tt>ds.fetch_group_info</tt> event (<xref target="ev-fetchgroupinfo"/>), which he sends to
the Hub.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: in the MLS case, 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>
          </li>
        </ul>
        <t>The new client can use the information to add itself to the group via a
<tt>ds.commit</tt> that contains an MLS ExternalInit proposal.</t>
      </section>
      <section anchor="alice-adds-cathy">
        <name>Alice adds Cathy</name>
        <t>Alice gets the identifier for Cathy and waits for her to join the room in
exactly the same way as in previous steps.</t>
      </section>
      <section anchor="alice-removes-bob-from-the-room">
        <name>Alice removes Bob from the room</name>
        <t>Alice removes Bob by sending an <tt>ds.commit</tt> event. The <tt>ds.commit</tt> event
contains an <tt>m.room.user</tt> event which removes Bob from the participant list, as
well as proposals to remove Bob's clients.</t>
      </section>
    </section>
    <section anchor="framing">
      <name>Framing</name>
      <t>MIMI protocol messages are sent described using the TLS presentation language
format (<xref section="3" sectionFormat="of" target="RFC8446"/>).</t>
      <t>All MIMI protocol messages are framed by a MIMIMessage.</t>
      <sourcecode type="tls"><![CDATA[
enum {
   reserved(0),
   mimi10(1), // MIMI 1.0
   (65535)
} ProtocolVersion;

enum {
   reserverd(0),
   event(1),
   event_response(2),
} MIMIMessageType;

struct {
   // The protocol version this event is created for.
   ProtocolVersion version;

   // The room ID where the event is sent in context of.
   opaque roomId;

   // Who or what sent this event. For example, a user ID.
   opaque sender;

   MIMIMessageType message_type;
   select (MIMIMessage.message_type) {
      case event:
        Event event;
      case event_response:
        EventResponse response;
   }
} MIMIMessage
]]></sourcecode>
    </section>
    <section anchor="rooms-and-events">
      <name>Rooms and Events</name>
      <t>Rooms, described by <xref target="I-D.barnes-mimi-arch"/>, consist of a user participation
list, a cryptographic representation of the room as defined by
<xref target="I-D.robert-mimi-delivery-service"/>, policy, and other metadata as needed.</t>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Consider renaming "event" to something else.</t>
        </li>
      </ul>
      <t>A room's state is modified, used, and retrieved through <em>events</em>. Some events
are fanned out to other participating servers while other events are operations
performed exclusively with the hub server for a room.</t>
      <t>Events that change the state of the room are implemented through MLS proposals
as defined in <xref target="RFC9420"/>, thus allowing the underlying MIMI DS protocol to
anchor the current room state cryptographically. MLS proposals are signed,
allowing every recipient in their path to verify their authenticity.</t>
      <t>This document defines additional events to encapsulate MIMI DS protocol
messages, for example, to add clients to a room's underlying MLS group or to
request single-use key material for another user's clients.</t>
      <t>Events carry information, and are not required to be persisted. The current
participation and policy state is confirmed by the cryptographic security layer
rather than being confirmed in events specifically.</t>
      <section anchor="event-schema">
        <name>Event Schema</name>
        <t>Events are validated against their TLS presentation language format
(<xref section="3" sectionFormat="of" target="RFC8446"/>):</t>
        <artwork><![CDATA[
// See the "MIMI Event Types" IANA registry for values.
// Example: "m.room.info"
opaque EventType;

struct {
   // The event type.
   EventType type;

   // Additional fields may be present as dependent on event type.
   select (Event.type) {
      case "m.room.user":
         // MLSMessage containing a UserEvent proposal
         MLSMessage user_event_proposal;
      case "ds.proposal":
         DSRequest ds_proposal;
      case "ds.commit":
         DSRequest ds_commit;
      case "ds.fetch_key_packages":
         DSRequest fetch_key_packages;
      case "ds.fetch_group_info":
         DSRequest fetch_group_info;
      case "ds.send_message":
         DSRequest send_message;
      // more cases as required by registry
   }
} Event;
]]></artwork>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Consider splitting <tt>sender</tt> into an object of <tt>{type, identifier}</tt>.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: The <tt>sender</tt> field might be a bit redundant now that signaling is
largely handled through MLS proposals.</t>
          </li>
        </ul>
        <t>Note an "event ID" is not specified on the struct. Events are sent ephemerally
and confirmed by the underlying cryptographic group state rather than referenced
by a consistent identifier.</t>
        <t>The "origin server" of an event is the server implied by the <tt>sender</tt> field.</t>
        <t>Recipients of an event respond with a MIMIMessage of type event_response.</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  ok(1),
  key_package(2),
  group_info(3),
  error(4),
} EventResponseType

enum {
  // TODO
} EventErrorType

struct {
  EventErrorType type;

   select (EventResponse.type) {
      // TODO
   }
} EventError

struct {
   EventResponseType type;

   // Additional fields may be present as dependent on event type.
   select (EventResponse.type) {
      case ok:
         struct {};
      case key_package:
         DSResponse key_package;
      case group_info:
         DSResponse group_info;
      case error:
         EventError error;
   }
} EventResponse
]]></sourcecode>
      </section>
      <section anchor="room-state">
        <name>Room state</name>
        <t>The state of a room consists of the room's RoomID, its policy, and the
participant list (including the role and participation state of each
participant). Also associated with the room is the MLS group managed by the MIMI
DS protocol, which anchors the room state cryptographically as part of the group
state.</t>
        <t>While (through the MIMI DS protocol) all parties involved in a room agree on the
room's state, the Hub is the arbiter that decides if a state change is valid.
All state-changing events are sent to the Hub, checked for their validity and
policy conformance before they are forwarded to any follower servers.</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, but not for MIMI DS specific events
that change the group state. For more information on the proposal-commit
paradigm and the role of the MIMI DS protocol see <xref target="mimi-ds"/>.</t>
      </section>
      <section anchor="mimi-ds">
        <name>Cryptographic room representation</name>
        <t>Each room is represented cryptographically by an MLS group and the Hub that
manages the room uses the MIMI DS protocol specified in
<xref target="I-D.robert-mimi-delivery-service"/> to manage that group.</t>
        <t>In particular, the MIMI DS protocol manages the list of group members, i.e. the
list of clients belonging to users currently in the room.</t>
        <section anchor="proposal-commit-paradigm">
          <name>Proposal-commit paradigm</name>
          <t>The MIMI DS protocol uses MLS, which 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 DS protocol ensures that the Hub, all follower servers and the clients
of all participants (or at least those in the <tt>join</tt> state) 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="anchoring">
          <name>Cryptographically anchoring room state</name>
          <t>To allow all parties involved to agree on the state of the room in addition to
the state of the associated group, the room state is anchored in the MLS group
via a GroupContext extension.</t>
          <sourcecode type="tls"><![CDATA[
struct {
   opaque user_id;
   opaque role;
   ParticipationState state;
} ParticipantData

struct {
  opaque room_id;
  ParticipantData participants<V>;
  // TODO: Add any remaining room data
} RoomState;
]]></sourcecode>
          <t>As part of the MIMI DS protocol, clients create commits to update the group
state, which are then included in MIMI DS specific events. The time between two
commits denotes an epoch.</t>
          <t>Whenever a client creates a commit, it <bcp14>MUST</bcp14> include all valid proposals accepted
by the Hub during the current epoch. This includes both proposals that carry
room-state changes, as well as proposals sent as part of MIMI DS events.</t>
          <t>Note that the validity of a proposal depend on the current room state, which may
change during an epoch based on room-state changing events. The changes of these
events are applied to the room state even if the commits that carry the event
information have not yet been committed.</t>
        </section>
        <section anchor="authenticating-proposals">
          <name>Authenticating proposals</name>
          <t>The MLS specification <xref target="RFC9420"/> 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 DS commit. See <xref target="ev-mroomuser"/> for more information.</t>
        </section>
        <section anchor="mimi-ds-events">
          <name>MIMI DS events</name>
          <t>The MIMI DS protocol operations are encapsulated in DSRequest structs and
contain a <tt>request_type</tt> field that details the operation in question. To
disambiguate MIMI DS operations on the event-level, each operation is assigned
its own distinct event type.</t>
          <t>The MIMI DS protocol deals with authentication of each request and upon
successful processing returns a DSResponse to be sent to the sender of the
event, optionally an MLSMessage for full fan-out and optionally one or more
Welcome messages for fan-out to individual follower servers.</t>
          <t>Depending on the event, a DSResponse either indicates successful processing, the
requested data (e.g. group information required for joins), or an error message.</t>
          <t>Messages meant for fan-out are DSFanoutRequests, which contain an MLS message,
as well as information to which clients messages should be fanned out to.</t>
          <ul empty="true">
            <li>
              <t><strong>TODO</strong>: Update the MIMI DS doc to allow for messages to contain more than one
proposal and a generic "commit" action.</t>
            </li>
          </ul>
          <section anchor="ev-proposeupdate">
            <name>Propose group update</name>
            <t><strong>Event type</strong>: <tt>ds.proposal</tt></t>
            <t>Group members, the Hub, and follower servers can use this event to propose
updates to the group. Each such event contains one or more proposals that can be
committed to update the state of the MLS group associated with the room. In
particular, this event can be used to add, remove or update clients in the
group.</t>
            <sourcecode type="tls"><![CDATA[
struct {
  DSRequest proposal;
} DSProposal
]]></sourcecode>
            <t><strong>Additional validation rules</strong>:</t>
            <ul spacing="normal">
              <li>
                <t>Clients can only be added to the group if the associated user is on the
participant list and in the <tt>join</tt> state.</t>
              </li>
            </ul>
          </section>
          <section anchor="ev-commitupdate">
            <name>Commit group update</name>
            <t><strong>Event type</strong>: <tt>ds.commit</tt></t>
            <t>Group members can use this event to commit any pending proposals (including both
group updates and room updates). The sender of this event can include additional
group updates without proposing them separately through the <tt>ds.proposal</tt>
event.</t>
            <t>Note that this event can also be used by a client to add itself to the group. To
do that, the sender requires the current group information (see
<xref target="ev-fetchgroupinfo"/>).</t>
            <sourcecode type="tls"><![CDATA[
struct {
  DSRequest commitBundle;
} DSCommit
]]></sourcecode>
            <t><strong>Additional validation rules</strong>:</t>
            <ul spacing="normal">
              <li>
                <t>Clients can only be added to the group if the associated user is on the
participant list and in the <tt>join</tt> state.</t>
              </li>
            </ul>
          </section>
          <section anchor="ev-fetchkeypackage">
            <name>Fetch KeyPackage</name>
            <t><strong>Event type</strong>: <tt>ds.fetch_key_packages</tt></t>
            <ul empty="true">
              <li>
                <t><strong>TODO</strong>: For now, we assume that KeyPackages are fetched directly, i.e. not in the
context of a room and via a Hub. This might change in the future. If it does
change, this event needs an additional authentication mechanism.</t>
              </li>
            </ul>
            <t>Group members can use this event to request a
KeyPackage from the Hub or another follower server.</t>
            <sourcecode type="tls"><![CDATA[
struct {
  DSRequest fetch_key_packages;
} DSFetchKeyPackages
]]></sourcecode>
            <t><strong>Additional validation rules</strong>:</t>
            <t>None</t>
          </section>
          <section anchor="ev-fetchgroupinfo">
            <name>Fetch group information</name>
            <t><strong>Event type</strong>: <tt>ds.fetch_group_info</tt></t>
            <t>Group members or follower servers can use this event to request group
information from the Hub. Up-to-date group information is required for clients
to be able to add themselves to a group via the <tt>ds.commit</tt> event. The
group info returned to the sender includes any pending proposals.</t>
            <sourcecode type="tls"><![CDATA[
struct {
  DSRequest fetch_group_info;
} DSFetchGroupInfo
]]></sourcecode>
            <t><strong>Additional validation rules</strong>:</t>
            <t>None</t>
          </section>
          <section anchor="ev-sendmessage">
            <name>Send Message</name>
            <t><strong>Event type</strong>: <tt>ds.send_message</tt></t>
            <ul empty="true">
              <li>
                <t><strong>TODO</strong>: This is not a proposal and there is no way for the Hub or follower servers
to authenticate this event at the moment. We might want to a way to do that
later.</t>
              </li>
            </ul>
            <t>Group members can use this event to request to send an encrypted (application)
message to the other group members.</t>
            <sourcecode type="tls"><![CDATA[
struct {
  DSRequest send_message;
} DSSendMessage
]]></sourcecode>
            <t><strong>Additional validation rules</strong>:</t>
            <t>None</t>
          </section>
        </section>
      </section>
      <section anchor="room-creation">
        <name>Creation</name>
        <t>Rooms (and the underlying MLS groups) are first created within the provider, out
of scope from MIMI. When the room is exposed to another server over the MIMI
protocol, such as with an explicit invite to another user, the creating server
<bcp14>MUST</bcp14> produce the following details:</t>
        <ul spacing="normal">
          <li>
            <t>An <tt>m.room.info</tt> (<xref target="ev-mroomcreate"/>) event describing the encryption
and policy details for the room.</t>
          </li>
          <li>
            <t>A universally unique room ID (represented by the room info event).</t>
          </li>
          <li>
            <t>An <tt>m.room.user</tt> (<xref target="ev-mroomuser"/>) event which invites the desired user.</t>
          </li>
          <li>
            <t>Any relevant cryptographic state needed to verify the invite is legitimate.
For example, the ciphersuite used by the cryptographic security layer.</t>
          </li>
        </ul>
        <t>This is the minimum state required by a MIMI room. Room creators <bcp14>MAY</bcp14> wish to
include additional details in the initial state, such as configuration of the
room's policy, adding the creator's other clients to the MLS group state, etc.</t>
        <section anchor="ev-mroomcreate">
          <name><tt>m.room.info</tt></name>
          <t>The <tt>m.room.info</tt> event contains the current room state, thus allowing servers
to bootstrap the room. Note that this event does not contain any of the
cryptographic state of the underlying MIMI DS group. Clients that want to join a
room need to use a <tt>ds.fetch_group_info</tt> event to obtain the information
required to join the room.</t>
          <t><strong>Event type</strong>: <tt>m.room.info</tt></t>
          <t><strong>Additional event fields</strong>:</t>
          <artwork><![CDATA[
struct {
  RoomState room_state;
} InfoEvent;
]]></artwork>
          <ul empty="true">
            <li>
              <t><strong>TODO</strong>: Include fields for policy information (previously called a "policy
ID" in ralston-mimi-signaling).</t>
            </li>
          </ul>
          <t><strong>Fanout considerations</strong>:</t>
          <t><tt>InfoEvent</tt> is <em>unsigned</em> in all cases it is used, but authenticated implicitly
through the transport layer (<xref target="transport"/>). The room info event is used during
invites to ensure the server is capable of participating in the room and is not
fanned out more generally. See <xref target="op-check"/> for usage.</t>
        </section>
      </section>
    </section>
    <section anchor="membership">
      <name>User Participation and Client Membership</name>
      <t>In a MIMI room, users are <em>participants</em> with an associated
<em>participation state</em> whereas clients of those users are <em>members</em> of the
cryptographic state. The user's participation state is updated concurrent to or
before changes are made to the cryptographic state.</t>
      <t>Users will always exist in one of the following participation states:</t>
      <artwork><![CDATA[
enum {
   invite,  // "Invited" state.
   join,    // "Joined" state.
   ban,     // "Banned" state.
   knock,   // "Knocking" state.
} ParticipationState;
]]></artwork>
      <t>These states allow a user to remain logically "joined" to the conversation when
they have zero encryption-capable clients available. The user will not be able to see
messages sent while they had no clients, but can add their clients to the
cryptographic state at any time. A user with zero clients in the cryptographic
state is considered to be an <em>inactive participant</em>. Users with one or more clients
in the cryptographic state are <em>active participants</em>.</t>
      <t>All servers with at least one user of theirs in the "joined" participation state
are considered to be "in" or "participating" in the room. Events which require
full fanout (<xref target="fanout"/>) are sent to all participating servers by default. Some
events <bcp14>MAY</bcp14> be sent to additional servers as needed by their fanout considerations.</t>
      <t>The participant list is anchored in the cryptographic state of the room as
described in <xref target="anchoring"/>.</t>
      <section anchor="adds">
        <name>Adds</name>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: We will probably want some kind of mechanism here that allows the
adder to signal that they are authorized (by the added user) to add the added
user to the room.</t>
          </li>
        </ul>
        <t>An <em>add</em> is when a user adds another user to the list of participants in the
<em>join</em> state. The <tt>m.room.user</tt> event that effects this change is typically sent
as part of a commit that also adds the user's clients to the room's MLS group.</t>
        <ol spacing="normal" type="1"><li>
            <t>The adder generates an <tt>m.room.user</tt> (<xref target="ev-mroomuser"/>) event to add the
target user.</t>
          </li>
          <li>
            <t>The adder sends (<xref target="op-send"/>) the <tt>m.room.user</tt> event to the hub server. If
the adder is a client, the event is likely sent as part of a <tt>ds.commit</tt>
event.</t>
          </li>
          <li>
            <t>The hub server validates the event to ensure the following:  </t>
            <ul spacing="normal">
              <li>
                <t>The target user of the add <bcp14>MUST NOT</bcp14> already be in the banned or joined
states.</t>
              </li>
              <li>
                <t>The sender of the invite <bcp14>MUST</bcp14> already be in the joined state.</t>
              </li>
            </ul>
          </li>
          <li>
            <t>If the event is invalid, it is rejected. Otherwise, it is forwarded by the
hub to the servers of all participants in the joined state. This includes the
server of the user added by the event.</t>
          </li>
          <li>
            <t>The target user (or its server) can reject the addition by sending an
<tt>m.room.user</tt> event that proposes the removal of the user and its clients
(<xref target="leaves"/>).</t>
          </li>
        </ol>
      </section>
      <section anchor="invites">
        <name>Invites</name>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: For now, the invite flow implies that the user has to explicitly
accept by adding one or more clients via external commit as part of the "Join"
flow. In the future, we can either make the "Invite" flow more versatile and
allow for Welcome based invitations, or create an additional "Add" flow, that
allows participants to add other users (and their clients) directly via
Welcome.</t>
          </li>
        </ul>
        <t>An <em>invite</em> is when a user (or more specifically, a user's client) adds another
user to the list of participants in the <tt>invite</tt> state.</t>
        <t>Once the user is on the participant list (and has been notified of this fact by
the Hub), one of the user's clients can add itself, as well as any other clients
to the room's underlying group.</t>
        <t>Updating the target user's participation state is done using the following
steps, and is visualized in <xref target="fig-invites"/>.</t>
        <ol spacing="normal" type="1"><li>
            <t>The inviter's server generates an <tt>m.room.user</tt> (<xref target="ev-mroomuser"/>)
event to invite the target user. Typically this begins with a
client-initiated request to the server using the provider-specific API.</t>
          </li>
          <li>
            <t>The inviter's server sends (<xref target="op-send"/>) the <tt>m.room.user</tt> event to the hub
server.</t>
          </li>
          <li>
            <t>The hub server validates the event to ensure the following:  </t>
            <ul spacing="normal">
              <li>
                <t>The target user of the invite <bcp14>MUST NOT</bcp14> already be in the banned or joined
states.</t>
              </li>
              <li>
                <t>The sender of the invite <bcp14>MUST</bcp14> already be in the joined state.</t>
              </li>
            </ul>
          </li>
          <li>
            <t>If the event is invalid, it is rejected. Otherwise, it is forwarded by the
hub to the target user's server to give it the opportunity to reject the
invite early in the process. This is described by <xref target="op-check"/>.</t>
          </li>
          <li>
            <t>If the target server rejected the event, the event is rejected by the hub as
well. Otherwise, the event is fanned out (<xref target="fanout"/>) to all participating
servers, plus the target server if not already participating.</t>
          </li>
        </ol>
        <t>At this stage, the <em>user</em> is now invited but their clients are not members of
the cryptographic state. The invite is delivered to the target's clients through
relevant provider-specific API where the user can then accept or decline the invite.</t>
        <t>If the user declines the invite, they are removed from the participant list.
Accepting is done by joining (<xref target="joins"/>) the room.</t>
        <figure anchor="fig-invites">
          <name>Invite happy path</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="496" width="568" viewBox="0 0 568 496" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 8,32 L 8,64" fill="none" stroke="black"/>
                <path d="M 24,72 L 24,480" fill="none" stroke="black"/>
                <path d="M 40,32 L 40,64" fill="none" stroke="black"/>
                <path d="M 232,112 L 232,144" fill="none" stroke="black"/>
                <path d="M 272,32 L 272,64" fill="none" stroke="black"/>
                <path d="M 296,72 L 296,480" fill="none" stroke="black"/>
                <path d="M 320,32 L 320,64" fill="none" stroke="black"/>
                <path d="M 512,240 L 512,272" fill="none" stroke="black"/>
                <path d="M 528,32 L 528,64" fill="none" stroke="black"/>
                <path d="M 544,72 L 544,480" fill="none" stroke="black"/>
                <path d="M 560,32 L 560,64" fill="none" stroke="black"/>
                <path d="M 8,32 L 40,32" fill="none" stroke="black"/>
                <path d="M 272,32 L 320,32" fill="none" stroke="black"/>
                <path d="M 528,32 L 560,32" fill="none" stroke="black"/>
                <path d="M 8,64 L 40,64" fill="none" stroke="black"/>
                <path d="M 272,64 L 320,64" fill="none" stroke="black"/>
                <path d="M 528,64 L 560,64" fill="none" stroke="black"/>
                <path d="M 32,112 L 232,112" fill="none" stroke="black"/>
                <path d="M 32,144 L 232,144" fill="none" stroke="black"/>
                <path d="M 32,192 L 288,192" fill="none" stroke="black"/>
                <path d="M 304,240 L 512,240" fill="none" stroke="black"/>
                <path d="M 304,272 L 512,272" fill="none" stroke="black"/>
                <path d="M 32,320 L 288,320" fill="none" stroke="black"/>
                <path d="M 304,368 L 536,368" fill="none" stroke="black"/>
                <path d="M 304,416 L 536,416" fill="none" stroke="black"/>
                <path d="M 32,464 L 288,464" fill="none" stroke="black"/>
                <path d="M 304,464 L 536,464" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="544,464 532,458.4 532,469.6" fill="black" transform="rotate(0,536,464)"/>
                <polygon class="arrowhead" points="544,368 532,362.4 532,373.6" fill="black" transform="rotate(0,536,368)"/>
                <polygon class="arrowhead" points="312,416 300,410.4 300,421.6" fill="black" transform="rotate(180,304,416)"/>
                <polygon class="arrowhead" points="312,272 300,266.4 300,277.6" fill="black" transform="rotate(180,304,272)"/>
                <polygon class="arrowhead" points="296,192 284,186.4 284,197.6" fill="black" transform="rotate(0,288,192)"/>
                <polygon class="arrowhead" points="40,464 28,458.4 28,469.6" fill="black" transform="rotate(180,32,464)"/>
                <polygon class="arrowhead" points="40,320 28,314.4 28,325.6" fill="black" transform="rotate(180,32,320)"/>
                <polygon class="arrowhead" points="40,144 28,138.4 28,149.6" fill="black" transform="rotate(180,32,144)"/>
                <g class="text">
                  <text x="24" y="52">A</text>
                  <text x="296" y="52">Hub</text>
                  <text x="544" y="52">B</text>
                  <text x="60" y="100">Create</text>
                  <text x="136" y="100">m.room.user</text>
                  <text x="212" y="100">invite</text>
                  <text x="52" y="180">Send</text>
                  <text x="96" y="180">event</text>
                  <text x="152" y="180">request</text>
                  <text x="224" y="180">initiated</text>
                  <text x="340" y="228">Validate</text>
                  <text x="424" y="228">m.room.user</text>
                  <text x="496" y="228">event</text>
                  <text x="72" y="308">200</text>
                  <text x="100" y="308">OK</text>
                  <text x="124" y="308">to</text>
                  <text x="156" y="308">send</text>
                  <text x="200" y="308">event</text>
                  <text x="256" y="308">request</text>
                  <text x="328" y="356">Check</text>
                  <text x="376" y="356">event</text>
                  <text x="432" y="356">request</text>
                  <text x="496" y="404">200</text>
                  <text x="524" y="404">OK</text>
                  <text x="136" y="452">Async</text>
                  <text x="188" y="452">fanout</text>
                  <text x="228" y="452">of</text>
                  <text x="264" y="452">event</text>
                  <text x="328" y="452">Async</text>
                  <text x="380" y="452">fanout</text>
                  <text x="420" y="452">of</text>
                  <text x="456" y="452">event</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
+---+                            +-----+                         +---+
| A |                            | Hub |                         | B |
+---+                            +-----+                         +---+
  |                                 |                              |
  | Create m.room.user invite       |                              |
  |-------------------------+       |                              |
  |                         |       |                              |
  |<------------------------+       |                              |
  |                                 |                              |
  | Send event request initiated    |                              |
  |-------------------------------->|                              |
  |                                 |                              |
  |                                 | Validate m.room.user event   |
  |                                 |--------------------------+   |
  |                                 |                          |   |
  |                                 |<-------------------------+   |
  |                                 |                              |
  |    200 OK to send event request |                              |
  |<--------------------------------|                              |
  |                                 |                              |
  |                                 | Check event request          |
  |                                 |----------------------------->|
  |                                 |                              |
  |                                 |                       200 OK |
  |                                 |<-----------------------------|
  |                                 |                              |
  |           Async fanout of event | Async fanout of event        |
  |<--------------------------------|----------------------------->|
  |                                 |                              |
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="joins">
        <name>Joins</name>
        <t>Users join a room either in response to an invite (therefore accepting it) or
after discovering it as a public room. In both cases, the user first updates
their participation state before the cryptographic security layer is engaged to
add their clients. Note that both of these actions can be performed either
sequentially, or through a single <tt>ds.commit</tt> event.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Describe policy considerations for what makes a room "public".</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Move the following paragraph to the MIMI DS subsection describing
<tt>ds.commit</tt>.</t>
          </li>
        </ul>
        <t>A user already in the join participation state <bcp14>MAY</bcp14> add and remove their own
clients from the cryptographic state at will. Clients are unable to remove
themselves via <tt>ds.commit</tt>, however they are able to propose that they be
removed in the next commit via <tt>ds.proposal</tt>.</t>
        <t>The joining user can follow one of two flows. Either it first updates the
participation state and then adds their clients, or it perfoms both actions in
the same event.</t>
        <t>The two-step flow looks as follows:</t>
        <ol spacing="normal" type="1"><li>
            <t>Option a: The joiner's server generates an <tt>m.room.user</tt> (<xref target="ev-mroomuser"/>)
event to add the user.  </t>
            <t>
Option b: The joiner's client generates a commit that contains an
<tt>m.room.user</tt> event, as well as an Add proposal for itself (this requires
that the client has previously obtained a the room's group info through a
<tt>ds.fetch_group_info</tt> event (<xref target="ev-fetchgroupinfo"/>)). The joiner's server
generates a <tt>ds.commit</tt> event from the commit.</t>
          </li>
          <li>
            <t>The joiners's server sends (<xref target="op-send"/>) the generated event to the hub
server.</t>
          </li>
          <li>
            <t>The hub server validates the event to ensure the following:  </t>
            <ul spacing="normal">
              <li>
                <t>The joining user <bcp14>MUST NOT</bcp14> already be in the banned from the room.</t>
              </li>
              <li>
                <t>The sender and joining user <bcp14>MUST</bcp14> be the same.</t>
              </li>
            </ul>
          </li>
          <li>
            <t>If the event is invalid, it is rejected. Otherwise, the event is fanned out
(<xref target="fanout"/>) to all participating servers, plus the joiner's server as they
are now participating in the room too.</t>
          </li>
        </ol>
        <t>If the user was added to the room via a standalone <tt>m.room.user</tt> event, the
user's clients are able to add themselves to the cryptographic group state via
one or more <tt>ds.commit</tt> events after fetching the room's current information via
a <tt>ds.fetch_group_info</tt> event.</t>
      </section>
      <section anchor="leaves">
        <name>Leaves/Kicks</name>
        <t>Leaving a room can signal a user declining an invite, voluntarily leaving the
room, or being kicked (removed) from the room. When the sender and target of
an <tt>m.room.user</tt> (<xref target="ev-mroomuser"/>) leave event are different, the target user
is being kicked. Otherwise the event represents a voluntary leave or declined
invite (if the previous participation state was "invited").</t>
        <t>Like with other participation/membership operations, a user's leave is initiated
by updating their participation state first. This is done by sending
(<xref target="op-send"/>) the relevant <tt>m.room.user</tt> (<xref target="ev-mroomuser"/>) state event to the
hub, which validates it as follows:</t>
        <ul spacing="normal">
          <li>
            <t>If the target and sender are the same, the user <bcp14>MUST</bcp14> be in the invited,
joined, or knocking participation state.</t>
          </li>
          <li>
            <t>Otherwise:  </t>
            <ul spacing="normal">
              <li>
                <t>The target user of the kick <bcp14>MUST</bcp14> be in the joined participation state.</t>
              </li>
              <li>
                <t>The sender for a kick <bcp14>MUST</bcp14> be in the joined participation state.</t>
              </li>
            </ul>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Include special case permissions constraints.</t>
          </li>
        </ul>
        <t>If the event is valid, it is fanned out (<xref target="fanout"/>) to all particpating
servers, plus the target user's server.</t>
        <t>The next <tt>ds.commit</tt> event <bcp14>MUST</bcp14> remove <em>all</em> of the target user's clients. If
multiple users leave the room, all of their clients <bcp14>MUST</bcp14> be removed in the same
operation. Other cryptographically-relevant changes <bcp14>MAY</bcp14> be committed alongside
the removals, however the operation <bcp14>MUST</bcp14> at a minimum remove the affected
clients.</t>
        <t>The hub server <bcp14>MAY</bcp14> be permitted to generate the needed changes to remove the
affected clients, requiring that those changes be confirmed/accepted by a client
remaining in the group promptly.</t>
        <t>As mentioned in <xref target="joins"/>, a user already in the join participation state <bcp14>MAY</bcp14>
add and remove their own clients from the cryptographic state at will.</t>
      </section>
      <section anchor="bans">
        <name>Bans</name>
        <t>Bans imply kick, and are operated the same way as <xref target="leaves"/>, though with the
<tt>m.room.user</tt> (<xref target="ev-mroomuser"/>) state event using a <tt>ban</tt> participation state.</t>
        <t>In contrast to leaving users, banned users remain on the participant list in the
<tt>ban</tt> state.</t>
        <t>An added exception on the validation is also applied to permit preemptive bans:
the target user is not required to be in the joined state to allow the
participation state change.</t>
        <t>Unbans can be performed by removing a user in the banned participation
state from the participant list <xref target="leaves"/>.</t>
      </section>
      <section anchor="knocks">
        <name>Knocks</name>
        <t>In this state, the sender of a knock is requesting an invite (<xref target="invites"/>) to
the room. They do not have access to the cryptographic state.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Discuss if this participation state is desirable, and figure out
details for how it works. It'd likely just be an <tt>m.room.user</tt> state event
with no MLS interaction, like invites are.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: If we have an Add event as discussed in a TODO in the "Invites"
section, an "Add" would probably be the response to a knock.</t>
          </li>
        </ul>
      </section>
      <section anchor="ev-mroomuser">
        <name><tt>m.room.user</tt></name>
        <t><strong>Event type</strong>: <tt>m.room.user</tt></t>
        <t>An <tt>m.room.user</tt> event can be used to change the participation state of a user.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Do we also want this to be able to change a participant's role?</t>
          </li>
        </ul>
        <t>It is transported via an MLS proposal of type UserEvent. If the event adds a
user to the room and it is the first user in the room that belongs to the
sending follower server, the UserEvent <bcp14>MAY</bcp14> contain the Certificate that can be
used to validate external proposals from that follower server. If it does, the
commit that contains the proposal adds the Certificate to <tt>external_senders</tt>
extension of the underlying MLS group.</t>
        <t>If the event removes the last user of a follower server from a room, the commit
that contains the MLS proposal that carries the event removes the Certificate of
that follower server from the extension.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: This proposal needs to be added to the IANA proposal list, or
specified as an extension proposal as specified in the MLS extensions
document. We might want to have one MIMIProposal type that in turn can
encapsulate more than just this event.</t>
          </li>
        </ul>
        <sourcecode type="tls"><![CDATA[
enum {
   invite,
   join,
   leave,
   ban,
   knock,
} ParticipationStateChange;

struct {
   // The user ID being affected by this participation state change.
   opaque targetUserId;

   // The new participation state for the target user. "Leave" removes
   // the user from the list.
   ParticipationStateChange state;

   // Optional human-readable reason for the change. Typically most
   // useful on bans and knocks.
   opaque [[reason]];
   optional<Certificate> follower_server_certificate;
} UserEvent;
]]></sourcecode>
        <t><strong>Additional validation rules</strong>:</t>
        <ul spacing="normal">
          <li>
            <t>Rules described by <xref target="invites"/>, <xref target="joins"/>, <xref target="leaves"/>, <xref target="bans"/>, <xref target="knocks"/>.</t>
          </li>
          <li>
            <t>The proposal <bcp14>MUST</bcp14> be authenticated as an MLS message based on the room's
underlying MLS group.</t>
          </li>
        </ul>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Include validation rules for permissions.</t>
          </li>
        </ul>
        <t><strong>Fanout considerations</strong>:</t>
        <t>Each <tt>m.room.user</tt> event is fanned out as normal (<xref target="fanout"/>). The event <bcp14>MAY</bcp14> be
sent to additional servers, as required by <xref target="invites"/>, <xref target="joins"/>, <xref target="leaves"/>,
<xref target="bans"/>, <xref target="knocks"/>.</t>
        <t><strong>Additional validation rules</strong>:</t>
        <t>None.</t>
        <t><strong>Fanout considerations</strong>:</t>
        <t>This event is not fanned out.</t>
      </section>
    </section>
    <section anchor="transport">
      <name>Transport</name>
      <t>Servers communicate with each other over HTTP <xref target="RFC9110"/> by "sending" events
(<xref target="event-schema"/>) to each other. Responses are also events for ease of handling.</t>
      <section anchor="authentication">
        <name>Authentication</name>
        <t>All endpoints, with the exception of <tt>.well-known</tt> endpoints, use the mutually
authenticated mode of TLS <xref target="RFC5246"/>. This provides guarantees that each
server is speaking to an expected party.</t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: More information specific to how TLS should be used, i.e. mandate
best practices that make sense in a mutually authenticated scenario that
involves two WebPKI based certificates.</t>
          </li>
        </ul>
        <t>Individual events <bcp14>MAY</bcp14> transit between multiple servers. TLS provides
point-to-point security properties while an event's <tt>signature</tt> provides
authenticity over multiple hops.</t>
      </section>
      <section anchor="endpoint-discovery">
        <name>Endpoint Discovery</name>
        <t>A messaging provider that wants to query the endpoint of another messaging
provider first has to discover the fully qualified domain name it can use to
communicate with that provider. It does so by performing a GET request to
<tt>https://example.org/.well-known/mimi/domain</tt>. example.org could, for example,
answer by providing the domain <tt>mimi.example.org</tt> (assuming that this is where
it responds to the REST endpoints defined in <xref target="rest-api"/>).</t>
        <t>The expected response format is simply a <tt>text/plain</tt> body containing the fully
qualified domain name.</t>
        <artwork><![CDATA[
GET https://example.org/.well-known/mimi/domain

Response
mimi.example.org
]]></artwork>
      </section>
      <section anchor="rest-api">
        <name>REST Endpoints</name>
        <t>The following REST endpoints can be used to communicate with a MIMI server.</t>
        <t>All operations rely on TLS-encoded structs and therefore requests and responses
<bcp14>SHOULD</bcp14> use a <tt>Content-Type</tt> of <tt>application/octet-stream</tt>.</t>
        <section anchor="op-send">
          <name>Send Event</name>
          <t>Asks the server to send an event (<xref target="event-schema"/>). Each event is subject to
additional validation and handling within this endpoint, such as ensuring the
room's policy is not violated.</t>
          <t>Follower servers in a room <bcp14>MUST</bcp14> only send to the hub server. The hub server is
responsible for further fanout (<xref target="fanout"/>) if required by the event, after the
send request has been completed.</t>
          <t>Follower servers receiving an event from another
follower server <bcp14>MUST</bcp14> reject the request with a <tt>400</tt> HTTP status code. The hub
server <bcp14>MUST</bcp14> validate the event according to the event's rules, then perform any
additional actions on the event as required by the event. For example, the hub
server may check that an invite is legal under the room's policy, then ensure
the target server accepts the event with <xref target="op-check"/>, then finally continue
processing.</t>
          <t>Rejected send requests <bcp14>MUST</bcp14> return a <tt>400</tt> HTTP status code. Accepted send
requests <bcp14>MUST</bcp14> return a <tt>200</tt> HTTP status code, and an event in the response body
if one is applicable.</t>
          <t>If the event requires fanout (<xref target="fanout"/>), the event is then fanned out
<xref target="fanout"/> to relevant servers in the room.</t>
          <t>Follower servers <bcp14>SHOULD</bcp14> apply the same validation as hub servers upon receiving
a send request to identify potentially malicious hub servers.</t>
          <artwork><![CDATA[
POST /send
Content-Type: application/octet-stream

Body
TLS-serialized Event

Response
TLS-serialized Event, or empty if no useful event.
]]></artwork>
          <t>Servers <bcp14>SHOULD</bcp14> retry this request with exponential backoff (to a limit) if they
receive timeout/network errors.</t>
          <section anchor="fanout">
            <name>Fanout</name>
            <t>A hub server fans an event out by using the send endpoint described above on all
participating servers in the room. A server is considered "participating" if it
has at least one user in the joined participation state, described by
<xref target="membership"/>.</t>
            <t>Additional servers <bcp14>MAY</bcp14> have the event sent to them if required by the steps
leading up to fanout.</t>
          </section>
        </section>
        <section anchor="op-check">
          <name>Check Invite Event</name>
          <ul empty="true">
            <li>
              <t><strong>TODO</strong>: Consider reducing this down to <tt>m.room.check_invite</tt> or something,
to reuse <tt>/send</tt>.</t>
            </li>
          </ul>
          <t>Used by the hub server to ensure a follower server can (and is willing to)
process an incoming invite. The called server <bcp14>MAY</bcp14> use this opportunity to ensure
the inviting user has general consent to invite the target user. For example,
ensuring the invite does not appear spammy in nature and if the inviter already
has a connection with the invitee.</t>
          <t>If the server does not recognize the event format of the <tt>InfoEvent</tt>
(<xref target="ev-mroomcreate"/>) event, or does not understand the policy/encryption
configuration contained within, it <bcp14>MUST</bcp14> reject the request.</t>
          <t>The request <bcp14>MAY</bcp14> be rejected with a <tt>400</tt> HTTP status code. If everything looks
OK to the server, it responds with a <tt>200</tt> HTTP status code.</t>
          <artwork><![CDATA[
struct {
   // The `m.room.user` invite event.
   Event invite;

   // The room creation information.
   InfoEvent roomInfo;
} CheckInviteRequest;
]]></artwork>
          <ul empty="true">
            <li>
              <t><strong>TODO</strong>: If we plan to keep this as an independent request, it will need a
protocol version field.</t>
            </li>
          </ul>
          <artwork><![CDATA[
POST /check-invite
Content-Type: application/octet-stream

Body
TLS-serialized CheckInviteRequest

Response
Any meaningful information. The pass/fail is identified by the HTTP response
status code, not the response body.
]]></artwork>
          <t>The hub server <bcp14>SHOULD</bcp14> consider a network error as a rejection. It is expected
that the original sender will attempt to re-send the invite once the server is
reachable again.</t>
        </section>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>Overall, the user participation state leads any possible MLS group state to
ensure malicious clients are not able to easily get access to messages.</t>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Other security guarantees? Consensus may be required here.</t>
        </li>
      </ul>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>IANA has created the following registries:</t>
      <ul spacing="normal">
        <li>
          <t>MIMI Event Types</t>
        </li>
      </ul>
      <section anchor="mimi-event-types">
        <name>MIMI Event Types</name>
        <t>An event type denotes the nature of a payload contained in an event, in the
context of the MIMI protocol. The event type is a string composed of substrings
separated by dots.</t>
        <t>The first substring is "m", followed by the logical container being affected
(typically just "room"), then a number of descriptor strings.</t>
        <t>Example: <tt>m.room.info</tt></t>
        <ul empty="true">
          <li>
            <t><strong>TODO</strong>: Does IANA need any other information for legal event types?</t>
          </li>
        </ul>
      </section>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC9420">
          <front>
            <title>The Messaging Layer Security (MLS) Protocol</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="B. Beurdouche" initials="B." surname="Beurdouche"/>
            <author fullname="R. Robert" initials="R." surname="Robert"/>
            <author fullname="J. Millican" initials="J." surname="Millican"/>
            <author fullname="E. Omara" initials="E." surname="Omara"/>
            <author fullname="K. Cohn-Gordon" initials="K." surname="Cohn-Gordon"/>
            <date month="July" year="2023"/>
            <abstract>
              <t>Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that messages are only accessible to the communicating endpoints, and not to any servers involved in delivering messages. Establishing keys to provide such protections is challenging for group chat settings, in which more than two clients need to agree on a key but may not be online at the same time. In this document, we specify a key establishment protocol that provides efficient asynchronous group key establishment with forward secrecy (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9420"/>
          <seriesInfo name="DOI" value="10.17487/RFC9420"/>
        </reference>
        <reference anchor="I-D.robert-mimi-delivery-service">
          <front>
            <title>MIMI Delivery Service</title>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="23" month="October" year="2023"/>
            <abstract>
              <t>   This document describes the MIMI Delivery Service.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-robert-mimi-delivery-service-05"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="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="23" month="October" year="2023"/>
            <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-02"/>
        </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="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="RFC5246">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.2</title>
            <author fullname="T. Dierks" initials="T." surname="Dierks"/>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2008"/>
            <abstract>
              <t>This document specifies Version 1.2 of the Transport Layer Security (TLS) protocol. The TLS protocol provides communications security over the Internet. The protocol allows client/server applications to communicate in a way that is designed to prevent eavesdropping, tampering, or message forgery. [STANDARDS-TRACK]</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="5246"/>
          <seriesInfo name="DOI" value="10.17487/RFC5246"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="I-D.mahy-mimi-identity">
          <front>
            <title>More Instant Messaging Interoperability (MIMI) Identity Concepts</title>
            <author fullname="Rohan Mahy" initials="R." surname="Mahy">
              <organization>Wire</organization>
            </author>
            <date day="10" month="July" year="2023"/>
            <abstract>
              <t>   This document discusses concepts in instant messaging identity
   interoperability when using end-to-end encryption, for example with
   the MLS (Message Layer Security) Protocol.  The goal is to explore
   the problem space in preparation for framework and requirements
   documents.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-mahy-mimi-identity-02"/>
        </reference>
        <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>Wire</organization>
            </author>
            <date day="23" month="October" year="2023"/>
            <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-01"/>
        </reference>
        <reference anchor="I-D.kohbrok-mimi-transport">
          <front>
            <title>MIMI Transport</title>
            <author fullname="Konrad Kohbrok" initials="K." surname="Kohbrok">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <author fullname="Raphael Robert" initials="R." surname="Robert">
              <organization>Phoenix R&amp;D</organization>
            </author>
            <date day="21" month="September" year="2023"/>
            <abstract>
              <t>   This document defines an HTTPS based transport layer for use with the
   MIMI Protocol.

Discussion Venues

   This note is to be removed before publishing as an RFC.

   Discussion of this document takes place on the More Instant Messaging
   Interoperability Working Group mailing list (mimi@ietf.org), which is
   archived at https://mailarchive.ietf.org/arch/browse/mimi/.

   Source for this draft and an issue tracker can be found at
   https://github.com/kkohbrok/mimi-transport.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-kohbrok-mimi-transport-01"/>
        </reference>
        <reference anchor="I-D.ralston-mimi-signaling">
          <front>
            <title>MIMI Signaling Protocol</title>
            <author fullname="Travis Ralston" initials="T." surname="Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <author fullname="Matthew Hodgson" initials="M." surname="Hodgson">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date day="22" month="September" year="2023"/>
            <abstract>
              <t>   The MIMI signaling protocol describes a framework for user-level
   interactions in the overall MIMI protocol stack.  The event structure
   can be used by control protocols described by [I-D.barnes-mimi-arch].

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-signaling-00"/>
        </reference>
        <reference anchor="I-D.ralston-mimi-policy">
          <front>
            <title>MIMI Policy Envelope</title>
            <author fullname="Travis Ralston" initials="T." surname="Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <author fullname="Matthew Hodgson" initials="M." surname="Hodgson">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date day="22" month="September" year="2023"/>
            <abstract>
              <t>   The MIMI Policy Envelope describes a _policy control protocol_ and
   _participation control protocol_ for use in a room, applied at the
   user participation level, as described by [I-D.barnes-mimi-arch].

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-policy-00"/>
        </reference>
      </references>
    </references>
    <?line 1275?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <ul empty="true">
        <li>
          <t><strong>TODO</strong>: Refactor acknowledgements to match sections of interest.</t>
        </li>
      </ul>
      <t>This document is the consolidation of the following documents:</t>
      <ul spacing="normal">
        <li>
          <t><xref target="I-D.kohbrok-mimi-transport"/> forms the majority of <xref target="transport"/>.</t>
        </li>
        <li>
          <t><xref target="I-D.robert-mimi-delivery-service"/> describes details for <xref target="membership"/>,
subsections of <xref target="rest-api"/> (per transport draft).</t>
        </li>
        <li>
          <t><xref target="I-D.ralston-mimi-signaling"/> describes <xref target="event-schema"/>,
<xref target="room-creation"/>, details of <xref target="membership"/>, and subsections of <xref target="rest-api"/>.</t>
        </li>
      </ul>
      <t>Aspects of <xref target="I-D.ralston-mimi-policy"/> are additionally taken into
consideration in this document through subsections of <xref target="membership"/>, but is
largely unincorporated and may require updates to match this document's
specifics.</t>
      <t><xref target="I-D.barnes-mimi-arch"/> was additionally used throughout the writing
of this document.</t>
    </section>
    <section anchor="contributors" numbered="false" toc="include" removeInRFC="false">
      <name>Contributors</name>
      <contact initials="R." surname="Mahy" fullname="Rohan Mahy">
        <organization>Wire</organization>
        <address>
          <email>rohan.mahy@wire.com</email>
        </address>
      </contact>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA91963Lb2Jng//MUWLpqW1JIqt2XJGNn3FH70q1pu+211OlK
paYskABFRCTAAUDJjFqpfZR5ln2UfZL9rud8BwBle3Kp3c2PtAwC5/Kd7347
k8nEtUW7yh8lo1dVnSenZdOmZZu8ypsmvSzKS3jS5nW1yet0VqyKdpccvDp9
dXqYbBv89fvz8zdnSVpmyauXZyOXzmZ1fo2DwTu/gkfJm7pqq3m1Grl52uaX
Vb17lDRt5lxWzct0DRNndbpoJ3W6atqqnKyLdTHZyEeTzx+6ZjtbF01TVGW7
28Drp8/PXyTJgwTer2CioszyTQ7/V7ajcTLKs6Kt6iJd4T9OT76F/1Q1/PX2
/MXIldv1LK8fuQxW8sjNq7LJy2bbPEraeps7WPaXLq3zFEY92WxWBSwYZm1o
d2/zdDU5L9b5yN1U9dVlXW03Hw+zkbvKd/Bd9sglkwS3iP8twlurPFnr1/jT
fJm2+N8mn29r+9t1Xm5h7UnyyStIEobf6GdYP77yHY6Az9dpsYLnuKzfF3m7
mFb1JT5P6/kSni/bdtM8Oj7G1/BRcZ1P9bVjfHA8q6ubJj/GAY7xw8uiXW5n
8OmsWGxrBuMxfhKfLr66gqNoWjOL+WTK40yLauDj43vQZrps1zC6S7ftsqoR
5jBTkiy2qxWj3HmdXhdN8pY/ph9hM2lZ/IUmhheWefIqbeviPe4yeVFty4x+
Sp5OT6dPp/RJzoBrabD692v/fn/CH6qyTjP4zxJgdTUw4ZtllZfF++Ttf39m
x76i76ZX/N3vYQ1ps6yLMp9meX+Wt+lmmear5G0FaN5+/CwI3d/X/HFN307n
1bo/PkCkXeY3yfdVdtn8zXBb82gWbkiT8I/ZtsVjmySyrWqZljDscudovkfJ
z0UN29eBavx9uobff38DP9DaXVnVMDDg6iPninJh/jWZTJJ01sCxzVvnzpeA
CMCLtmvgIEmzyefFosibpMWdfBJHdIp+4+RmWcyXwKFWQBfAKPO6SapFkhWL
RV7jNJ6eE/jmusjwhbZKmiWwH7fOkUs1y2IDHAI2V62ZBQGzyuTLnF6vynyS
lhWstJ46R4uV9c9h6t2Y9wBLS3RlSZYvAHkaHSZhuPD4AHvgLsTyXAv8R9eP
o8AWrnu7iNYemFmbj5NVDjQB24Nvnb42oVfKdJXMVwV8P+FBYd71elsKt022
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
JjXXaRMUH/t2/weRsGe1mrkAAA==

-->

</rfc>
