<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY RFC2119 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml">
  <!ENTITY RFC8174 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml">
  <!ENTITY RFC8439 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8439.xml">
  <!ENTITY RFC5869 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5869.xml">
  <!ENTITY RFC7748 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7748.xml">
  <!ENTITY RFC8610 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8610.xml">
  <!ENTITY RFC8949 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8949.xml">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="exp"
     docName="draft-myclerk-protocol-00"
     ipr="trust200902"
     obsoletes=""
     updates=""
     submissionType="independent"
     xml:lang="en"
     version="3">

  <front>
    <title abbrev="MyClerk Protocol">The MyClerk Protocol: Tiered Security Communication for Distributed Family Systems</title>

    <seriesInfo name="Internet-Draft" value="draft-myclerk-protocol-00"/>

    <author fullname="Michael J. Arcan" initials="M.J." surname="Arcan">
      <organization>Arcan Consulting</organization>
      <address>
        <email>rfc@arcan-consulting.de</email>
        <uri>https://myclerk.eu</uri>
      </address>
    </author>

    <date year="2025" month="December"/>

    <area>Applications</area>
    <workgroup>Independent Submission</workgroup>

    <keyword>protocol</keyword>
    <keyword>family</keyword>
    <keyword>distributed</keyword>
    <keyword>encryption</keyword>
    <keyword>smart home</keyword>

    <abstract>
      <t>
        This document specifies the MyClerk Protocol, a tiered-security
        communication protocol designed for distributed family orchestration
        systems. The protocol provides six security tiers ranging from 1-byte
        minimal overhead for tunneled messages to 144-byte full security for
        critical operations. It supports multiple transport mechanisms including
        NATS, Matrix, WebSocket, and direct TCP, while maintaining end-to-end
        encryption using ChaCha20-Poly1305 and X25519 key exchange.
      </t>
      <t>
        The protocol is transport-agnostic, federation-capable, and optimized
        for environments ranging from resource-constrained IoT devices to
        full-featured desktop clients.
      </t>
    </abstract>

  </front>

  <middle>

    <!-- ============================================================ -->
    <section anchor="introduction">
      <name>Introduction</name>

      <t>
        Modern families operate across multiple locations and devices: a primary
        home with network-attached storage, a vacation house with a mini-PC,
        grandparents with a Raspberry Pi, and mobile devices requiring access
        while traveling. The MyClerk Protocol addresses the communication
        requirements of such distributed family systems.
      </t>

      <t>
        Traditional protocols impose significant overhead that becomes
        problematic for constrained channels. The MyClerk Protocol introduces
        tiered security levels, allowing applications to select appropriate
        overhead based on the security requirements of each operation.
      </t>

      <section anchor="requirements-language">
        <name>Requirements Language</name>
        <t>
          The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
          "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
          "OPTIONAL" 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>
      </section>

      <section anchor="terminology">
        <name>Terminology</name>

        <dl>
          <dt>Node</dt>
          <dd>A device participating in a MyClerk deployment, such as a server,
              desktop client, mobile device, or IoT device.</dd>

          <dt>Core Node</dt>
          <dd>A node classified as stable and reliable, expected to maintain
              high availability (>95% uptime over 30 days).</dd>

          <dt>Bonus Node</dt>
          <dd>A node with variable availability, used opportunistically for
              additional redundancy.</dd>

          <dt>Family</dt>
          <dd>A group of users and nodes sharing a common trust domain and
              cryptographic key hierarchy.</dd>

          <dt>Federation</dt>
          <dd>The interconnection of multiple families for resource sharing
              or communication.</dd>

          <dt>Tier</dt>
          <dd>A security level (0-5) determining the header structure and
              cryptographic protections applied to a message.</dd>

          <dt>Session</dt>
          <dd>A stateful connection between two endpoints with established
              cryptographic keys.</dd>
        </dl>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="protocol-overview">
      <name>Protocol Overview</name>

      <t>
        The MyClerk Protocol is a binary protocol using MessagePack
        <xref target="RFC8949"/> for payload encoding. It defines six security
        tiers with increasing header sizes and cryptographic protections.
      </t>

      <section anchor="design-goals">
        <name>Design Goals</name>

        <ol>
          <li><strong>Tiered Security:</strong> 1-144 bytes overhead depending
              on security requirements.</li>
          <li><strong>Transport Agnostic:</strong> Operates over NATS, Matrix,
              WebSocket, TCP, or other transports.</li>
          <li><strong>Federation Ready:</strong> Supports multi-server,
              multi-family deployments.</li>
          <li><strong>Future Proof:</strong> Extensible operations and feature
              negotiation.</li>
        </ol>
      </section>

      <section anchor="security-tiers-overview">
        <name>Security Tiers Overview</name>

        <table anchor="tier-overview-table">
          <name>Security Tier Summary</name>
          <thead>
            <tr>
              <th>Tier</th>
              <th>Header Size</th>
              <th>Encryption</th>
              <th>Authentication</th>
              <th>Use Case</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>0</td><td>1 byte</td><td>None (tunneled)</td><td>None</td><td>Inside secure session</td></tr>
            <tr><td>1</td><td>4 bytes</td><td>None</td><td>None</td><td>Fire-and-forget commands</td></tr>
            <tr><td>2</td><td>6 bytes</td><td>Optional</td><td>CRC-16</td><td>Home automation</td></tr>
            <tr><td>3</td><td>12 bytes</td><td>ChaCha20-Poly1305</td><td>HMAC-32</td><td>Conversational</td></tr>
            <tr><td>4</td><td>42 bytes</td><td>ChaCha20-Poly1305</td><td>HMAC-64</td><td>Key exchange</td></tr>
            <tr><td>5</td><td>58+ bytes</td><td>ChaCha20-Poly1305</td><td>HMAC-256 + Poly1305</td><td>Maximum security</td></tr>
          </tbody>
        </table>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="message-format">
      <name>Message Format</name>

      <t>
        All messages consist of a header, optional payload, and optional trailer.
        The header format varies by security tier.
      </t>

      <section anchor="common-header">
        <name>Common Header Fields</name>

        <t>
          The first byte (Flags) is present in all tiers and has the following
          structure:
        </t>

        <artwork><![CDATA[
 0
 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|V V|T T T|C|F|E|
+-+-+-+-+-+-+-+-+

V: Protocol Version (2 bits) - Currently 0
T: Security Tier (3 bits) - Values 0-5
C: Compressed (1 bit) - Payload is compressed
F: Fragmented (1 bit) - Message is fragmented
E: Encrypted (1 bit) - Payload is encrypted
]]></artwork>
      </section>

      <section anchor="tier0-header">
        <name>Tier 0 Header (1 byte)</name>

        <t>
          Tier 0 is used for messages tunneled inside an already-secure session.
          It provides minimal overhead.
        </t>

        <artwork><![CDATA[
 0
 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|0 0|0 0 0|C|F|E|
+-+-+-+-+-+-+-+-+
]]></artwork>

        <t>
          Tier 0 messages MUST only be sent within an established Tier 3+
          session. Implementations receiving a Tier 0 message outside of a
          secure session MUST discard it.
        </t>
      </section>

      <section anchor="tier1-header">
        <name>Tier 1 Header (4 bytes)</name>

        <artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V V|0 0 1|C|F|E|        Operation Code         |   Sequence    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>

        <dl>
          <dt>Operation Code (16 bits)</dt>
          <dd>Identifies the operation. See <xref target="operations"/>.</dd>

          <dt>Sequence (8 bits)</dt>
          <dd>Message sequence number, wrapping at 255.</dd>
        </dl>
      </section>

      <section anchor="tier2-header">
        <name>Tier 2 Header (6 bytes)</name>

        <artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V V|0 1 0|C|F|E|        Operation Code         |   Sequence    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Session ID           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>

        <dl>
          <dt>Session ID (16 bits)</dt>
          <dd>Identifies the session context for this message.</dd>
        </dl>

        <t>
          Tier 2 messages SHOULD include a CRC-16 trailer for error detection.
        </t>
      </section>

      <section anchor="tier3-header">
        <name>Tier 3 Header (12 bytes)</name>

        <artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V V|0 1 1|C|F|E|        Operation Code         |   Sequence    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Session ID           |           Timestamp           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Timestamp (cont.)        |             Nonce             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>

        <dl>
          <dt>Timestamp (32 bits)</dt>
          <dd>Unix timestamp in seconds. Used for replay protection.</dd>

          <dt>Nonce (16 bits)</dt>
          <dd>Random nonce component. Combined with timestamp and counter
              to form the full 96-bit nonce for ChaCha20-Poly1305.</dd>
        </dl>

        <t>
          Tier 3 messages with the E flag set MUST be encrypted using
          ChaCha20-Poly1305 as specified in <xref target="RFC8439"/>.
        </t>
      </section>

      <section anchor="tier4-header">
        <name>Tier 4 Header (42 bytes)</name>

        <artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V V|1 0 0|C|F|E|        Operation Code         |   Sequence    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Session ID           |           Timestamp           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Timestamp (cont.)        |             Nonce             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Key ID                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                    ECDH Public Key (X25519)                   |
|                         (32 bytes)                            |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>

        <dl>
          <dt>Key ID (32 bits)</dt>
          <dd>Identifier for the key being used or negotiated.</dd>

          <dt>ECDH Public Key (256 bits)</dt>
          <dd>X25519 public key as specified in <xref target="RFC7748"/>.</dd>
        </dl>
      </section>

      <section anchor="tier5-header">
        <name>Tier 5 Header (58 bytes)</name>

        <t>
          Tier 5 extends Tier 4 with a full Poly1305 authentication tag in
          the header:
        </t>

        <artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    [Tier 4 Header - 42 bytes]                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                   Poly1305 Tag (16 bytes)                     |
|                                                               |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>

        <t>
          Tier 5 messages MUST include a full HMAC-SHA256 (32 bytes) in the
          trailer, providing dual authentication: Poly1305 for AEAD integrity
          and HMAC-SHA256 for post-quantum resistance.
        </t>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="nonce-construction">
      <name>Nonce Construction</name>

      <t>
        ChaCha20-Poly1305 requires a 96-bit (12-byte) nonce that MUST NOT be
        reused with the same key. The MyClerk Protocol constructs nonces as
        follows:
      </t>

      <artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Timestamp (32 bits)                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       Random (32 bits)                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Counter (32 bits)                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>

      <dl>
        <dt>Timestamp (32 bits)</dt>
        <dd>Unix epoch seconds. Provides cross-session replay protection.</dd>

        <dt>Random (32 bits)</dt>
        <dd>Cryptographically random value generated per session using a
            CSPRNG. Provides 2^32 possible values per second.</dd>

        <dt>Counter (32 bits)</dt>
        <dd>Per-message counter starting at 0, incremented for each message.
            Allows 2^32 messages per session.</dd>
      </dl>

      <t>
        All fields are encoded in big-endian byte order.
      </t>

      <t>
        This construction provides a collision probability of less than 2^-80
        per year at 1 million operations per second, assuming proper CSPRNG
        implementation.
      </t>
    </section>

    <!-- ============================================================ -->
    <section anchor="key-derivation">
      <name>Key Derivation</name>

      <t>
        Session keys are derived using HKDF as specified in
        <xref target="RFC5869"/> with SHA-256 as the hash function.
      </t>

      <section anchor="ecdh-key-exchange">
        <name>ECDH Key Exchange</name>

        <t>For Tier 4+ sessions:</t>

        <artwork><![CDATA[
shared_secret = X25519(local_private_key, remote_public_key)

session_key = HKDF-SHA256(
    IKM  = shared_secret,
    salt = nonce_initiator || nonce_responder,
    info = "myclerk-session-v0",
    L    = 32
)
]]></artwork>
      </section>

      <section anchor="key-rotation">
        <name>Key Rotation</name>

        <t>
          Keys MUST be rotated after any of the following conditions:
        </t>

        <ul>
          <li>2^32 messages sent (nonce exhaustion)</li>
          <li>24 hours elapsed (time-based)</li>
          <li>Explicit KEY_ROTATE operation received</li>
        </ul>

        <t>Rotated keys are derived as:</t>

        <artwork><![CDATA[
new_key = HKDF-SHA256(
    IKM  = current_key,
    salt = "rotate",
    info = rotation_counter (4 bytes, big-endian),
    L    = 32
)
]]></artwork>
      </section>
    </section>

    <!-- ============================================================ -->
    <section anchor="operations">
      <name>Protocol Operations</name>

      <t>
        Operations are identified by a 16-bit operation code. The operation
        space is divided into ranges:
      </t>

      <table anchor="opcode-ranges">
        <name>Operation Code Ranges</name>
        <thead>
          <tr>
            <th>Range</th>
            <th>Category</th>
          </tr>
        </thead>
        <tbody>
          <tr><td>0x0000-0x00FF</td><td>Core Operations (Session, Key Management)</td></tr>
          <tr><td>0x0100-0x01FF</td><td>Standard Operations (Device, Identity, Messaging)</td></tr>
          <tr><td>0x0200-0x02FF</td><td>Resource Sharing</td></tr>
          <tr><td>0x0300-0x03FF</td><td>Federation</td></tr>
          <tr><td>0x0400-0x04FF</td><td>Billing and Economics</td></tr>
          <tr><td>0x0500-0x05FF</td><td>Virtual File System (VFS)</td></tr>
          <tr><td>0xF000-0xFFFE</td><td>Vendor Extensions</td></tr>
          <tr><td>0xFFFF</td><td>Reserved</td></tr>
        </tbody>
      </table>

      <section anchor="core-operations">
        <name>Core Operations (0x0000-0x00FF)</name>

        <section anchor="session-management">
          <name>Session Management (0x0000-0x000F)</name>

          <table>
            <name>Session Management Operations</name>
            <thead>
              <tr><th>Code</th><th>Name</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>0x0000</td><td>NOP</td><td>No operation</td></tr>
              <tr><td>0x0001</td><td>KEEPALIVE</td><td>Session keepalive</td></tr>
              <tr><td>0x0002</td><td>KEEPALIVE_ACK</td><td>Keepalive acknowledgment</td></tr>
              <tr><td>0x0003</td><td>SESSION_INIT</td><td>Initialize session</td></tr>
              <tr><td>0x0004</td><td>SESSION_ACK</td><td>Session acknowledgment</td></tr>
              <tr><td>0x0005</td><td>SESSION_CLOSE</td><td>Close session</td></tr>
              <tr><td>0x0006</td><td>SESSION_CLOSE_ACK</td><td>Close acknowledgment</td></tr>
              <tr><td>0x0007</td><td>SESSION_RESUME</td><td>Resume session with ticket</td></tr>
              <tr><td>0x0008</td><td>SESSION_RESUMED</td><td>Session resumed</td></tr>
            </tbody>
          </table>
        </section>

        <section anchor="key-management">
          <name>Key Management (0x0010-0x001F)</name>

          <table>
            <name>Key Management Operations</name>
            <thead>
              <tr><th>Code</th><th>Name</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>0x0010</td><td>KEY_EXCHANGE_INIT</td><td>Initiate key exchange</td></tr>
              <tr><td>0x0011</td><td>KEY_EXCHANGE_RESPONSE</td><td>Key exchange response</td></tr>
              <tr><td>0x0012</td><td>KEY_EXCHANGE_COMPLETE</td><td>Key exchange complete</td></tr>
              <tr><td>0x0016</td><td>SESSION_ROTATE</td><td>Rotate session key</td></tr>
              <tr><td>0x0017</td><td>SESSION_REVOKE</td><td>Revoke session key</td></tr>
            </tbody>
          </table>
        </section>

      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="payload-formats">
      <name>Payload Formats</name>

      <t>
        Payloads are encoded using MessagePack (a subset of CBOR). This section
        defines payload structures using CDDL <xref target="RFC8610"/>.
      </t>

      <section anchor="session-init-payload">
        <name>SESSION_INIT Payload</name>

        <sourcecode type="cddl"><![CDATA[
session-init = {
    nonce: bstr .size 8,
    timestamp: uint,
    ? capabilities: [* capability],
    ? device-id: bstr .size 16,
}

capability = &(
    compression-lz4: 0,
    compression-zstd: 1,
    encryption-chacha20: 2,
    encryption-aes256gcm: 3,
    fragmentation: 4,
    streaming: 5,
    federation: 6,
    vfs: 8,
)
]]></sourcecode>
      </section>

      <section anchor="session-ack-payload">
        <name>SESSION_ACK Payload</name>

        <sourcecode type="cddl"><![CDATA[
session-ack = {
    session-id: uint .size 2,
    nonce: bstr .size 8,
    selected-tier: uint .le 5,
    ? selected-capabilities: [* capability],
}
]]></sourcecode>
      </section>

      <section anchor="session-resume-payload">
        <name>SESSION_RESUME Payload</name>

        <sourcecode type="cddl"><![CDATA[
session-resume = {
    old-session-id: uint .size 2,
    ticket: bstr .size 64,
}

; Ticket structure (encrypted with server key, AES-256-GCM):
; - session-key: 32 bytes
; - device-id: 16 bytes
; - issued-at: 4 bytes (Unix timestamp)
; - expires-at: 4 bytes (Unix timestamp)
; - ticket-nonce: 8 bytes
]]></sourcecode>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="tier-compatibility">
      <name>Tier Compatibility</name>

      <t>
        When endpoints support different maximum tiers, they MUST negotiate
        to the highest common tier. The server MUST respond with the minimum
        of its supported tier and the client's requested tier.
      </t>

      <t>
        Servers MAY enforce minimum tier requirements for specific operations.
        If a client requests an operation at an insufficient tier, the server
        MUST respond with error code 0x12 (FORBIDDEN) and include the required
        tier in the error payload.
      </t>

      <section anchor="minimum-tier-requirements">
        <name>Minimum Tier Requirements</name>

        <t>
          The following operations have minimum tier requirements:
        </t>

        <table>
          <name>Minimum Tier Requirements</name>
          <thead>
            <tr><th>Operation Category</th><th>Minimum Tier</th></tr>
          </thead>
          <tbody>
            <tr><td>Lock/Unlock (physical access)</td><td>3</td></tr>
            <tr><td>Key Exchange</td><td>4</td></tr>
            <tr><td>Federation Operations</td><td>4</td></tr>
            <tr><td>Emergency Operations</td><td>3</td></tr>
          </tbody>
        </table>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="error-handling">
      <name>Error Handling</name>

      <t>
        Error codes are 8-bit values organized into ranges:
      </t>

      <table anchor="error-codes">
        <name>Error Codes</name>
        <thead>
          <tr><th>Range</th><th>Category</th></tr>
        </thead>
        <tbody>
          <tr><td>0x00-0x0F</td><td>Success</td></tr>
          <tr><td>0x10-0x1F</td><td>Client Errors</td></tr>
          <tr><td>0x20-0x2F</td><td>Server Errors</td></tr>
          <tr><td>0x30-0x3F</td><td>Federation Errors</td></tr>
          <tr><td>0xF0-0xFF</td><td>Reserved</td></tr>
        </tbody>
      </table>

      <section anchor="specific-error-codes">
        <name>Specific Error Codes</name>

        <dl>
          <dt>0x00 OK</dt>
          <dd>Operation completed successfully.</dd>

          <dt>0x10 BAD_REQUEST</dt>
          <dd>Malformed message or invalid parameters.</dd>

          <dt>0x11 UNAUTHORIZED</dt>
          <dd>Authentication required or failed.</dd>

          <dt>0x12 FORBIDDEN</dt>
          <dd>Insufficient permissions or tier.</dd>

          <dt>0x13 NOT_FOUND</dt>
          <dd>Requested resource does not exist.</dd>

          <dt>0x17 INVALID_SESSION</dt>
          <dd>Session expired or invalid.</dd>

          <dt>0x20 INTERNAL_ERROR</dt>
          <dd>Server encountered an unexpected error.</dd>

          <dt>0x21 SERVICE_UNAVAILABLE</dt>
          <dd>Service temporarily unavailable.</dd>

          <dt>0x22 TIMEOUT</dt>
          <dd>Operation timed out.</dd>
        </dl>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="security-considerations">
      <name>Security Considerations</name>

      <section anchor="nonce-reuse">
        <name>Nonce Reuse</name>
        <t>
          Reusing a nonce with the same key in ChaCha20-Poly1305 completely
          compromises the confidentiality and authenticity of all messages
          encrypted with that key-nonce pair. Implementations MUST ensure
          nonces are never reused by:
        </t>
        <ul>
          <li>Using cryptographically random values for the Random field</li>
          <li>Maintaining a monotonic counter per session</li>
          <li>Rotating keys before counter exhaustion</li>
        </ul>
      </section>

      <section anchor="replay-protection">
        <name>Replay Protection</name>
        <t>
          Tier 3+ messages include timestamps for replay protection.
          Implementations SHOULD reject messages with timestamps more than
          5 minutes in the past or future. Session resumption tickets include
          a nonce that MUST be tracked to prevent replay attacks.
        </t>
      </section>

      <section anchor="tier-downgrade">
        <name>Tier Downgrade Attacks</name>
        <t>
          An attacker might attempt to force communication at a lower tier.
          Servers MUST enforce minimum tier requirements for sensitive
          operations. Clients SHOULD warn users when connecting at a lower
          tier than expected.
        </t>
      </section>

      <section anchor="key-compromise">
        <name>Key Compromise</name>
        <t>
          If a session key is compromised, an attacker can decrypt all messages
          in that session. The 24-hour automatic key rotation limits the window
          of exposure. For forward secrecy, implementations SHOULD use ephemeral
          ECDH keys for each session.
        </t>
      </section>

      <section anchor="post-quantum">
        <name>Post-Quantum Considerations</name>
        <t>
          The X25519 key exchange is not quantum-resistant. Tier 5 includes
          an additional HMAC-SHA256 trailer that provides some protection
          against future quantum attacks on Poly1305. Implementations concerned
          about long-term confidentiality SHOULD use Tier 5 for sensitive data.
        </t>
      </section>

    </section>

    <!-- ============================================================ -->
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>

      <t>
        This document has no IANA actions.
      </t>

      <t>
        If this protocol were to be standardized, IANA would be requested to
        create a registry for MyClerk Protocol operation codes with the ranges
        defined in <xref target="operations"/>.
      </t>
    </section>

  </middle>

  <back>

    <references>
      <name>References</name>

      <references>
        <name>Normative References</name>
        &RFC2119;
        &RFC8174;
        &RFC8439;
        &RFC5869;
        &RFC7748;
        &RFC8610;
        &RFC8949;
      </references>


    </references>

    <section anchor="acknowledgements" numbered="false">
      <name>Acknowledgements</name>
      <t>
        This specification is part of the MyClerk project, a privacy-first
        family orchestration platform currently in development. For more
        information, visit https://myclerk.eu.
      </t>
    </section>

  </back>

</rfc>
