<?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.6.27 (Ruby 2.7.0) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ralston-mimi-linearized-matrix-00" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.17.0 -->
  <front>
    <title abbrev="Linearized Matrix API">Linearized Matrix API</title>
    <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-linearized-matrix-00"/>
    <author fullname="Travis Ralston">
      <organization>The Matrix.org Foundation C.I.C.</organization>
      <address>
        <email>travisr@matrix.org</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="March" day="24"/>
    <area>Applications and Real-Time</area>
    <workgroup>More Instant Messaging Interoperability</workgroup>
    <keyword>matrix</keyword>
    <keyword>linearized</keyword>
    <keyword>interoperability</keyword>
    <keyword>messaging</keyword>
    <keyword>mimi</keyword>
    <abstract>
      <t>Matrix is an existing openly specified decentralized secure communications protocol
able to provide a framework for instant messaging interoperability. Matrix rooms
(aka conversations) currently use a Directed Acyclic Graph (DAG) for persisting
events/messages. Servers broadcast their changes to the DAG to every other server in
order to create new events.</t>
      <t>This model provides excellent decentralization characteristics and conversation history
replication, but proves complex when aiming to use Matrix strictly for interoperability
between today's existing messaging service providers, which often do not persist
chat history serverside, and do not seek to replicate it between servers.</t>
      <t>This document explores an API surface for Matrix which optimizes for ease of
interoperability at the expense of decentralized conversation history at a per-room level.
We call this API surface "Linearized Matrix".</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://turt2live.github.io/ietf-mimi-linearized-matrix/draft-ralston-mimi-linearized-matrix.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ralston-mimi-linearized-matrix/"/>.
      </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/turt2live/ietf-mimi-linearized-matrix"/>.</t>
    </note>
  </front>
  <middle>
    <section anchor="introduction">
      <name>Introduction</name>
      <t>At a high level, rooms using Linearized Matrix have a single server which owns that room.
The owner can change, but will typically be the server which created the room. All other
servers are known as participating servers and call the owner server to send events. The
owner server is then responsible for informing all the other servers of any changes/messages
in the room.</t>
      <t>Many aspects for how Matrix works as an interoperable messaging framework is described by
<xref target="I-D.ralston-mimi-matrix-framework"/>. This document replaces the eventual consistency model,
federation API, and DAG-related features of the framework document by presenting rooms as a
single, flat, array of events, without being incompatible with those same replaced components.</t>
      <t>This document does not currently define a transport layer for the Linearized Matrix API, instead
focusing its efforts on the operational aspects of a room.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>This document additionally uses the following definitions:</t>
      <ul spacing="normal">
        <li>Owner Server: The server responsible for holding the room history, accepting new events, etc.</li>
        <li>Participant Server: Every other server. Note that a server may inherit this role even if not
(currently) participating in the room.</li>
      </ul>
      <t><strong>TODO</strong>: Merge/add definitions from framework to here, such as "homeserver", "user", etc.</t>
    </section>
    <section anchor="identifiers">
      <name>Identifiers</name>
      <t><strong>TODO</strong>: Expand upon this section.</t>
      <t>A room ID has the format <tt>!localpart:domain</tt>, where the localpart is an opaque string and the domain
provides global uniqueness. The domain does not indicate that the room exists on that server, just
that it was originally created there.</t>
      <t>A user ID has the format <tt>@localpart:domain</tt>, where the localpart is again an opaque string and
the domain is where the user was created (the server owns the user account).</t>
    </section>
    <section anchor="room-architecture">
      <name>Room Architecture</name>
      <t>As mentioned, rooms over Linearized Matrix have a concept of an "owning server". Typically the
room owner will be the server which created the room, however ownership can shift as needed. The
room owner is responsible for applying the room version semantics/access controls and distributing
the changes to other applicable servers (called participant servers).</t>
      <t>At an implementation level, it should be possible for an owning server to use a DAG if it so
wishes, however for the protocol considerations a room has a single flat array to store state
changes and room events.</t>
      <t>Room state is the same as non-Linearized Matrix: represented by an event type and state key tuple
which maps to a state event. "Current state" is simply the most recent instance of each event type
and state key pair in the array.</t>
      <t>To send an event into the room, each "participant server" (non-owner) asks the owner to send it
to the room. The owner applies access controls to the event, following Matrix's existing access
controls (power levels, bans, server_acls etc.) and then adds the event to the room's array, and sends it
out to all participating servers (including the original sender, for simplicity of implementation).
If the owner would like to send an event, it simply adds the event to the array (assuming such an
action is valid) and broadcasts it. The owner server MUST follow the access control semantics defined
by the room's current state - it MUST NOT make up its own rules. For instance, the owning server
must only let Alice invite Bob to a room if Alice has permission to invite, and if Alice's server
sent the invite event.</t>
      <t>Each room additionally records which Matrix room version it is using for access control behaviours,
such as Authorization Rules <xref target="MxV10AuthRules"/>. This is required for when rooms gain a DAG-compatible
server in them. Note that this document introduces new semantics requiring a new room version.</t>
    </section>
    <section anchor="event-signing">
      <name>Event Signing</name>
      <t>Events are signed by the participant/original server to ensure the owning server is not spoofing
events on behalf of another server. The exact details for how a server's signing keys are shared
to other servers is left as a transport consideration, however signing keys are currently expected
to be Ed25519 keys.</t>
      <t>In the existing Matrix Federation APIs, a PDU <xref target="MxV10PDUFormat"/> contains an event and has several
DAG-specific fields to it. When using the Linearized Matrix API, we introduce a concept of a <em>Linear
PDU</em> which looks similar to a regular room event, but has all non-essential fields removed.</t>
      <sourcecode type="jsonc"><![CDATA[
{
  // the room ID the event is sent within
  "room_id": "!room:example.org",
  // the implied (or explicit) event type
  "type": "org.example.event_type",
  // for state events, even if an empty string
  "state_key": "",
  // the user ID of the sender
  "sender": "@user:example.org",
  // milliseconds since epoch
  "origin_server_ts": 123456789,
  // the domain of the room owner
  "authorized_sending_server": "owner.example.org",
  "content": {
    // the normal event content
  },
  "hashes": {
    "sha256": "<content hash, just like in Matrix today>"
  }
}
]]></sourcecode>
      <t><xref target="MxContentHashCalculation"/></t>
      <t>The Linear PDU is then redacted <xref target="MxRedaction"/>, canonicalized <xref target="MxCanonicalJSON"/>, and signed
<xref target="MxSigning"/>. The signature is supplied to the owner server alongside the event itself for sending
to the room.</t>
    </section>
    <section anchor="membership">
      <name>Membership</name>
      <t>After a room is created (by an imagined <tt>/createRoom</tt> API, for example), it will exist on a single
server: the owner's. This is not particularly helpful if the goal is to talk to other people, so a
way to involve others in the conversation is needed.</t>
      <t>Matrix currently has membership states for join, leave, invite, kick, ban, and knock (request invite).
These states have their own set of rules governed by the room version to prevent cases of, for example,
ban evasion.</t>
      <t><strong>TODO</strong>: Describe those membership transitions. Currently specified in the Client-Server API
https://spec.matrix.org/v1.6/client-server-api/#room-membership (we should move that).</t>
      <t>The owner server broadcasts successful membership changes as <tt>m.room.member</tt> events to all participant
servers in the room, including the sending server.</t>
      <t>A server is considered to be "in the room" if it has at least one user with <tt>join</tt> membership state.</t>
    </section>
    <section anchor="state-events-api">
      <name>State Events API</name>
      <t>Matrix, and therefore Linearized Matrix, tracks changes to the room as <em>state events</em>. State events
have both an event type and state key to differentiate them from room (or non-state) events. While history
for state changes is stored in the room, only the most recent change for an event type and state key
pair is considered "current state". For example, the current room name is the most recent <tt>m.room.name</tt>
state event.</t>
      <t>As mentioned above, a transport layer would be responsible for the request/response
structure for this API, however a need would be present to send (arbitrary) state events, read those
state events back, and read the whole of current state (including membership).</t>
    </section>
    <section anchor="room-events-api">
      <name>Room Events API</name>
      <t>Room events include messages and redactions, as well as messaging features like reactions, edits, etc.
These may be encrypted in supported rooms (ones which specify an encryption algorithm in their room state),
and in their unencrypted form will use the Matrix concept of Extensible Events.</t>
      <t><strong>TODO</strong>: Update the message format I-D for MSC1767 extensible events and link it here.
https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/1767-extensible-events.md</t>
      <t>A transport layer would specify request/response structures for sending, receiving, reading, and
discovering nearby events (for scrollback purposes).</t>
    </section>
    <section anchor="room-transfers">
      <name>Room Transfers</name>
      <t>The current room owner would be stored as a state event within the room, defaulting to the room creator.
To transfer ownership, the current owner chooses a participant server and requests that it accept the
ownership role. If the participant server agrees to take ownership, it would create and sign a new room
ownership state event. The current owner then signs the ownership state event itself and sends it to all
participating servers (including the new owner), just as it would for any other event. All requests from
that point forward now go to the new owner, and the old owner becomes a regular participating server.</t>
      <t><strong>TODO</strong>: What do you do if the owner server dies or partitions before transferring to a successor?</t>
    </section>
    <section anchor="other-apis">
      <name>Other APIs</name>
      <t><strong>TODO</strong>: Expand upon this section.</t>
      <t>A transport layer would specify request/response structures for:</t>
      <ul spacing="normal">
        <li>Media/attachment distribution</li>
        <li>APIs to support end-to-end encryption</li>
        <li>Ephemeral data such as receipts, typing notifications, and presence</li>
        <li>Resolving an identifer to a room ID</li>
        <li>User profiles (display names and avatars)</li>
        <li>Other APIs as required to support interoperable messaging</li>
      </ul>
    </section>
    <section anchor="matrix-room-version">
      <name>Matrix Room Version</name>
      <t>The first room version which supports Linearized Matrix will base its requirements on Matrix's existing
Room Version 10 definition <xref target="MxRoomVersion10"/>. Changes will be made to support the following features:</t>
      <ul spacing="normal">
        <li>A description of the authorization rules when not using a DAG.</li>
        <li>The DAG-compatible signing structure for events.</li>
        <li>The use of Matrix's Extensible Events content format.</li>
      </ul>
      <t><strong>TODO</strong>: Expand upon this section with formal details of what the above looks like for a room version.</t>
    </section>
    <section anchor="anti-abuse-and-anti-spam">
      <name>Anti-Abuse and Anti-Spam</name>
      <t><strong>TODO</strong>: Expand upon this section.</t>
      <t>In a Matrix room, state events get appended to the DAG/array to show intent. If a server wishes to decline
the request, such as in the case where the recipient server believes an invite is spammy, it can do so
by sending another event to the room. For example, an antispam system might issue redactions for messages
which look spammy on behalf of a room admin.</t>
    </section>
    <section anchor="dag-compatible-event-structure">
      <name>DAG-Compatible Event Structure</name>
      <t>Linearized Matrix is essentially an alternative API for accessing normal Matrix rooms over federation,
which means servers which support a full-blown DAG can still join and participate in the room.
This is critical in order to avoid breaking compatibility with today's fully-decentralized Matrix, and
provides a way to decentralize ownership of rooms even if large messaging providers are themselves
not able to implement full decentralization yet. <xref target="I-D.nottingham-avoiding-internet-centralization"/></t>
      <t>With DAG-compatible servers in the room, the DAG-compatible servers talk to each other directly as they
do with the current Matrix APIs.  Any DAG-compatible server which can also speak Linearized Matrix
can connect to the owner server - effectively trunking Linearized Matrix into normal Matrix and tracking
its events into the DAG.  As long as servers speaking Linearized Matrix uphold the room's access controls,
then they appear as a single logical DAG-compatible server to normal Matrix, and will maintain consistency
with the rest of normal Matrix.</t>
      <t>Normally, events are checked for signatures from the "origin" server implied by the <tt>sender</tt> on an event.
Events sent with the Linearized Matrix API are already signed by the participant server to ensure the owner
server isn't spoofing them, however an owner server might not always be DAG-compatible itself. To remedy this,
owner servers can delegate their DAG involvement to a DAG-compatible server in the room.</t>
      <t>Delegating to a DAG-compatible server means creating a <em>Delegated Linear PDU</em> from a <em>Linear PDU</em>. The owner
moves the <tt>authorized_sending_server</tt> value (which should be itself) to <tt>original_authorized_sending_server</tt>
then populates <tt>authorized_sending_server</tt> with the domain name for the DAG-compatible server it is using.
The owner server then signs the Delegated Linear PDU and sends it to the DAG-compatible server, which then
appends all the DAG-specific fields and signs the resulting PDU itself before sending it to all the other
DAG-compatible servers in the room.</t>
      <t>Note that while a Delegated Linear PDU modifies the structure that was signed as a Linear PDU, it is easily
possible to reconstruct a Linear PDU from a Delegated Linear PDU. Similarly, a DAG-ready PDU can be redacted
down to a Delegated Linear PDU with ease.</t>
      <t>A complete DAG-ready PDU would look like:</t>
      <sourcecode type="jsonc"><![CDATA[
{
  // the room ID the event is sent within
  "room_id": "!room:example.org",
  // the implied (or explicit) event type
  "type": "org.example.event_type",
  // for state events, even if an empty string
  "state_key": "",
  // the user ID of the sender
  "sender": "@user:example.org",
  // milliseconds since epoch
  "origin_server_ts": 123456789,
  // the domain of the room owner
  "original_authorized_sending_server": "owner.example.org",
  // DAG-capable server
  "authorized_sending_server": "dag.example.org",
  "content": {
    // the normal event content
  },
  "hashes": {
    "sha256": "<content hash, just like in Matrix today>"
  },
  // other event format stuff:
  "auth_events": ["$event1", "$event2", "$etc"],
  "depth": 42,
  "prev_events": ["$event3", "$event4", "$etc2"],
  "signatures": {
    "dag.example.org": {
      "ed25519:abc": "<signature for PDU>"
    },
    "owner.example.org": {
      "ed25519:def": "<signature for Delegated Linear PDU>"
    },
    "example.org": {
      "ed25519:ghi": "<signature for non-delegated Linear PDU>"
    }
  }
}
]]></sourcecode>
      <t>When validating the signatures <xref target="MxSignatureValidation"/> on this PDU, DAG-capable servers would apply the
following algorithm. If at any point the check fails, the algorithm bails.</t>
      <ol spacing="normal" type="1"><li>If an <tt>original_authorized_sending_server</tt> is present, construct the implied Linear PDU from the PDU and
validate the signature for the server implied by the <tt>sender</tt>. Additionally, redact the PDU down to a
Delegated Linear PDU and validate the signature for the <tt>authorized_sending_server</tt> value.</li>
        <li>If an <tt>original_authorized_sending_server</tt> is NOT present, redact the PDU down to a Linear PDU and validate
the signature for the <tt>authorized_sending_server</tt> value.</li>
        <li>Without considering the signatures from the domains in previous steps, verify the signatures per normal.
Note that the step where the signature for the "origin server" (defined as the one implied by the PDU's
<tt>sender</tt>) is implicitly checked as part of step 1 and 2, and not actually possible to verify in the
traditional sense. That particular step in event validation is therefore skipped when step 1 or 2 is
performed.</li>
      </ol>
      <t><strong>TODO</strong>: How does an owner server pick a DAG server to communicate with, and how does the owner receive events
from the DAG to send to participant servers? One option might be to have DAG-capable servers identify themselves
during joins with the owner server, then the current owner can transfer ownership to the DAG-capable server.
The DAG-capable owner would simply shuffle events around internally to feed both API surfaces, though this means
all DAG-capable servers need to implement both API surfaces.</t>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t><strong>TODO</strong>: Expand upon this section.</t>
      <t>As discussed in the Event Signing section, we ensure servers are not able to spoof events.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="I-D.ralston-mimi-matrix-framework">
          <front>
            <title>Matrix as a Messaging Framework</title>
            <author fullname="Travis Ralston" initials="T." surname="Ralston">
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date day="13" month="March" year="2023"/>
            <abstract>
              <t>   This document describes how Matrix, an existing openly specified
   decentralized protocol for secure interoperable communications, works
   to create a framework for messaging.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ralston-mimi-matrix-framework-01"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="MxV10AuthRules" target="https://spec.matrix.org/v1.6/rooms/v10/#authorization-rules">
          <front>
            <title>Matrix Specification | v1.6 | Room Version 10 | Authorization Rules</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxV10PDUFormat" target="https://spec.matrix.org/v1.6/rooms/v10/#event-format-1">
          <front>
            <title>Matrix Specification | v1.6 | Room Version 10 | Event Format</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxContentHashCalculation" target="https://spec.matrix.org/v1.6/server-server-api/#calculating-the-content-hash-for-an-event">
          <front>
            <title>Matrix Specification | v1.6 | Federation API | Calculating the Content Hash</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxRedaction" target="https://spec.matrix.org/v1.6/client-server-api/#redactions">
          <front>
            <title>Matrix Specification | v1.6 | Client-Server API | Redaction Algorithm</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxCanonicalJSON" target="https://spec.matrix.org/v1.6/appendices/#canonical-json">
          <front>
            <title>Matrix Specification | v1.6 | Appendices | Canonical JSON</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxSigning" target="https://spec.matrix.org/v1.6/appendices/#signing-details">
          <front>
            <title>Matrix Specification | v1.6 | Appendices | Signing</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxRoomVersion10" target="https://spec.matrix.org/v1.6/rooms/v10">
          <front>
            <title>Matrix Specification | v1.6 | Room Version 10</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="MxSignatureValidation" target="https://spec.matrix.org/v1.6/server-server-api/#validating-hashes-and-signatures-on-received-events">
          <front>
            <title>Matrix Specification | v1.6 | Federation API | Validating Hashes and Signatures</title>
            <author>
              <organization>The Matrix.org Foundation C.I.C.</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        <reference anchor="I-D.nottingham-avoiding-internet-centralization">
          <front>
            <title>Internet Centralization: What Can Standards Do?</title>
            <author fullname="Mark Nottingham" initials="M." surname="Nottingham">
         </author>
            <date day="17" month="February" year="2023"/>
            <abstract>
              <t>   Despite the Internet being designed and operated as a decentralized
   network-of-networks, forces often (and increasingly) encourage
   consolidation of power over its functions into few hands.

   This document discusses centralization in Internet protocols and
   relates it to consolidation of power, explains why both are
   undesirable, identifies forces that contribute to them, catalogues
   limitations of common approaches to decentralization, and explores
   what Internet standards efforts can do.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-nottingham-avoiding-internet-centralization-09"/>
        </reference>
      </references>
    </references>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>Thank you to the Matrix Spec Core Team (SCT), and in particular Richard van der Hoff, for
exploring how Matrix rooms could be represented as a linear structure, leading to this document.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+1cbZPbNpL+zl+BVa4qMy692M7b7dTdbmbHzsZX5zhlT+IP
V1ceiIQkZiiCS5AzVnyT335PdwMEKGkSO/FV7YfLh4wkAg10o/vpN9Cz2Szr
yq4yZ2ryn2VtdFv+bAr1XHdt+Vadf/9skunlsjU39z/PdWfWtt2dKdcVWVbY
vNZb0Ctavepmra5cZ+vZttyWs2qgMNsyhdnDh5nrl9vSudLW3a7BvGdPL79R
6hOFiRarlnVhGoP/1d1kqibPzv+GP7bFp5eX30yyut8uTXuWFdjFWZbb2pna
9e5MdW1vMmz7s0y3RoPQedNUJTaLhZzSdaFeGl3NLsutmWS3tr1et7ZvMO65
bY16VrtO1516bpzT67Je45fOtLYxrV6WVdntJtm12WFecZapmRJ26FPkkb6V
e7N4bKDJXyCX7MbUPXav1AfvQSkR2uQ1OKAhfycK9PtWlxV+J/pfl6ZbzW27
pt91m2/w+6brGne2WNAw+qm8MfMwbEE/LJatvXVmQQQWNHFddpt+iald33aP
K0xY0IR7TpZmVDgT1yWLDTPnQmxe2l+jsXgfFZpvum01yTLddxvb0mFgZaVW
fVWJHl62+qZ06qVQ4YfgUdflz6wLGLAxXqGJefWN7euCH6mL+bP5xZynGJFn
x8Tar7fD+MMFQavbmFv1rS3W7g+vuBVq6YpZbVt8hRzPsqysV/GbUs/f/vjo
4Tlk8bKvjDtjSp1u1wbnEI7BNSafR3qLm0fzLxettVuHjw8Xn4go/W5nLRES
Oh4ovPW/Aply5U1K/Y8iMvjzEoTUj6Yli1aPHuKX85Se4o1NmCAbrXr88PFn
/HU4Qv5vRkJ7L1kxz98/+eEbFsTv49nABruZiHL26A+x+5RIKdnMR+bzAiAJ
4t9qt7nQVd5XolDvz7Ez7Y1pZ/6PbsrFJ3kgVK9n0LRZLmvMNliEBDLT9Yyl
8wFC+cYUACn+DT4CP1zERRQWUZ4RRZx8ZBm9NIXOP1AseVUSy6lY2kDmQ3T/
Qui8Yjqe9WE/6ryCnwTwbT+2Vuja1thL9R+vXnz3AVzrhhxrmRtHWuBpzH4K
mPV+LJ8PRPiYPRVFW/nIbL4q1zX053cy6GT2rDAdcPVDDnXEod/Ex9ZZgIjH
kEcPfw+A/X7A+j84JA0/b37UVVl8BHi68XRwdIRIxgGPipkLy7gZuSiTG/i/
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
g05y9sENbLAyS1Y+uTUhRyQo5xDkdJ4lVWev4kmYigiJoidSjoTSkM05dbWd
s47L0yuPswcBPKBkcOWx/kTHmoby3nhCDEHlkRiBBF8vdgnRThJKE5/Isgvr
SGnYIEKhg2qdV6RPVwe6xtb5in2Ej5tI1l5PpyGPac2KktkDlzyl88zhYPe6
UxK4OvUg9T4P5n4h36VkvVzCcH49ibWqKFcr07I/5tDRbKUux6uQlySPzTNO
h+r8602JjDz0pqIjDBslnKMEvRgfCMf6+6mvzAnVhPt2mkneOzqpySgnmUjC
EaxHkMIPYF7o/lQoA6QbCFpGz6+yNIEf15+UXlpCi8Ny9G2ojewXeJh1gY+F
fwb47Nqey1t+iDSNYoCpGdAiUV+RGPLHE90uS2yh3Z3uxR8A9EJAIWXDAdEI
17g8IiMM4jcq6wKpxnldkv5GXU6qc6kWv4ylFm9qoSMSajHDJZcpqeutqajU
nnZNQnOCfTr2FkYbJGWhmi1oS2VpyMLUebtrOlEscqU4BFP4DOkEpxSSN4E8
qeDIHMJcHe7IeL0sfZwq6j3lUsvwpK/jalQ4FXdI1a1uaL6nEfLTt4g45Oyf
hgJUBO0fmsLbVxBSqMY+mz2RJuari0dfffkVNHig46VL26rK+ppBiGu7Aa79
TUckhAvfVCLQ9h9JBrOmtY11unKLZWWXdCOzXsTfaMFZXNBfcZhvC4LH42oe
JLuv12rQa5cGK1Ml9yf8Ry2/Ufm4KF1ODlJ6GFDqXeD3hOfnyKgrUl3V9C32
a1yiiJe0txWX/i/3DT2tvCxNQCKpJUaz8LlDAk+FWem+6nwLfUBajpMsPMal
FZGs0trvGGh8g3VjabvUKj6ouXnLYNn5/ixOVbo5XJOOVWXqvMyVLycdo7Ru
jfcKVIBJtkSxG7PvryiE+DTJ8ZN1RjXLywNuODym2Ul1cH9eiFLTYpv309l7
FdpoW1KH9GG+dpEL8Q2heeU3Sg3oQY7ksaQt0sARdzTjVrcFfNctorBwnMMi
g+tVFuSFzSXyqC0fWkhhj218ZNOvacHCqp3t6U+ZFv78GRVUILWelhS3l+Lu
gyq1Xt90iIds+1dS8xfMLJUE3ru79YcMlhuTz4G8eqG7Tucb6coOrQZb4zlt
hx2RQC+wtZh1dsad+wFmMe5pgziCShJ0mUkPDT2Ggoagna4bkN3bbrg35eRU
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

-->

</rfc>
