<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     ipr="trust200902"
     docName="draft-sakistudio-sass-01"
     category="exp"
     submissionType="independent"
     xml:lang="en"
     version="3">

  <front>
    <title abbrev="SASS Protocol">
      SakiAgentSSH Secure Protocol Specification
    </title>

    <seriesInfo name="Internet-Draft"
                value="draft-sakistudio-sass-01"/>

    <author fullname="Hua Chang" surname="Chang" initials="H.">
      <organization>Saki Studio</organization>
      <address>
        <postal>
          <street>4F.-5, No. 305, Jiankang Rd.</street>
          <city>Taipei City, Songshan Dist.</city>
          <code>105069</code>
          <country>TW</country>
        </postal>
        <phone>+886-988-403-884</phone>
        <email>Saki@saki-studio.com.tw</email>
      </address>
    </author>



    <date year="2026" month="May" day="29"/>

    <area>Security</area>
    <workgroup>Independent Submission</workgroup>

    <keyword>agent</keyword>
    <keyword>remote execution</keyword>
    <keyword>security</keyword>
    <keyword>AI agent</keyword>
    <keyword>capability-based access control</keyword>

    <abstract>
      <t>
        This document describes the Saki Agent Secure Stream
        (SASS) protocol, version 1.4.  SASS is an
        application-layer overlay protocol for authenticated
        remote command execution, streaming process I/O, and
        binary file transfer between trusted agents.
      </t>
      <t>
        To ensure strict self-containment and compatibility
        with IETF standard specifications, SASS defines a
        decoupled "Control-Transport Decoupling" architecture.
        The SASS Core defines an abstract SASS Abstract
        Messaging Model (SAMM) utilizing standard CBOR
        (RFC 8949) and JSON as baseline
        serializations.
      </t>
      <t>
        Following the precedent of TLS 1.0 (RFC 2246)
        inheriting and refining SSL 3.0, SASS v1.4 formalizes
        its security evolution through four major incremental
        milestones: Active Threat Defense (v1.1),
        Forward-Secure Audit Hash Chains (v1.2), modular
        Control-Transport Decoupling (v1.3) incorporating
        tls-exporter Channel Binding (RFC 9266)
        and Zero-Allocation Tarpit streams, and Total Response
        Mapping (v1.4) with 6-Response state machine
        convergence and Safety Gradient loss bounding.
      </t>
      <t>
        SASS v1.4 achieves the MAS (Martingale Almost-Surely Superior)
        milestone: a comparative claim between protocol versions
        based on Second-order Stochastic Dominance (SSD).
        Each version iteration
        eliminates specific behavioral branches from the agent
        probability space while maintaining expected loss,
        yielding strict SSD improvement.
      </t>
    </abstract>
  </front>

  <middle>

    <!-- ========== Section 1 ========== -->
    <section anchor="introduction">
      <name>Introduction &amp; Protocol Evolution</name>
      <t>
        The proliferation of autonomous AI-powered coding
        agents operating on remote machines introduces a
        critical threat model: the Rogue Agent.  Unlike
        traditional SSH clients controlled by human operators,
        agents may autonomously execute destructive commands,
        exfiltrate credentials, or pivot laterally across
        networks without explicit human authorization.
      </t>
      <t>
        Existing remote execution protocols such as SSH
        <xref target="RFC4253"/> were designed for
        human-operated terminals and lack the fine-grained
        capability controls, active defenses, and binary-safe
        encoding schemes required for agent management.
      </t>
      <t>
        SASS (Saki Agent Secure Stream) decouples the logical
        message flow from the physical transmission layer.  By
        defining a transport-agnostic messaging core alongside
        modular transport profiles, SASS achieves strict
        self-containment, freeing the standard from proprietary
        third-party binary frameworks (e.g., gRPC/Protobuf)
        during academic review, while retaining
        high-performance implementations as pluggable adapters.
      </t>
      <t>
        SASS is designed to avoid over-deployment or
        under-deployment at any application scale.  The protocol
        is suitable for deployment on resource-constrained IoT
        devices as well as enterprise-grade servers.  However,
        this document does not address quantum-safe cryptographic
        agility, which remains an active area of research and
        standardization beyond the scope of this specification.
      </t>
      <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 capitalized, as
        shown here.
      </t>

      <section anchor="milestones">
        <name>The Four Incremental Milestones (v1.1 to v1.4)</name>
        <t>
          Following the precedent of TLS 1.0 (RFC 2246)
          inheriting and refining SSL 3.0, the SASS
          specification formalizes its security evolution
          through four major incremental milestones:
        </t>
        <ul>
          <li>
            SASS v1.1 (Active Threat Countermeasures): Added
            the 13Policy heuristic firewall and cryptographic
            cognitive challenges bound to an active Tarpit
            system, establishing the foundation of active
            defense against rogue automated operations.
          </li>
          <li>
            SASS v1.2 (Cryptographic Integrity &amp; Audit):
            Introduced five-dimensional Capability ACLs
            combined with a forward-secure hash chain audit
            log signed via host-resident asymmetric keys,
            providing mathematical proof of non-repudiation.
          </li>
          <li>
            SASS v1.3 (Control-Transport Decoupling &amp;
            Hardening): Decoupled the SASS Core from
            underlying physical protocols.  Introduced
            atomicity controls (POSIX openat and O_NOFOLLOW)
            to pre-empt TOCTOU sandstrike breakouts,
            implemented Zero-Allocation Tarpit streams to
            neutralize Host DoS, and mandated exported keying
            material Channel Binding to prevent session
            hijacking.
          </li>
          <li>
            <t>
              SASS v1.4 (Total Response Mapping &amp; Loss
              Bounding): Introduces a formal 6-Response state
              machine (R1~R6) that maps every possible Agent
              behavior to one of six deterministic responses,
              each preserving storage integrity and bounding
              loss.  Adds Dual Standard Enforcement (Vi Swap
              for authenticated agents, Tarpit for
              unauthenticated), Transparent Branching for
              zero-loss write isolation, PTY Ring Buffer for
              idempotent reconnection, and the Safety Gradient
              theory for layered loss bounding.
            </t>
            <t>
              This milestone achieves the MAS (Martingale
              Almost-Surely Superior) property: a comparative
              claim between protocol versions.  Each version
              iteration eliminates specific behavioral branches
              from the agent probability space while
              maintaining expected loss, yielding strict
              Second-order Stochastic Dominance (SSD)
              improvement <xref target="AS2008"/>.
            </t>
          </li>
        </ul>
      </section>

      <section anchor="design-philosophy">
        <name>Design Philosophy: Total Response Mapping</name>
        <t>
          Traditional security models enumerate known attacks
          and block them (blacklist model).  This approach is
          inherently incomplete: the attacker can always find
          a path not in the blacklist.
        </t>
        <t>
          SASS v1.4 inverts this model.  Instead of defining
          "which behaviors are bad," it defines "for every
          possible behavior, what is the response."  The set
          of responses is finite, deterministic, and auditable.
          Any unforeseen behavior is mapped to one of the
          predefined responses.
        </t>
        <t>
          This is the formal meaning of the axiom: "All
          unexpected behaviors are expected behaviors."
        </t>
        <t>
          Furthermore, an Agent's actions have no inherent
          "danger" or "malice."  The boundary enforcement
          system is strictly an Adjudicator: it determines
          what is permitted ("CAN") and what is prohibited
          ("CANNOT") based on the Agent's capability set.  If
          an Agent's authorized boundary includes executing a
          destructive command, the Daemon <bcp14>MUST</bcp14>
          execute it without prejudice.  Conversely, if an
          Agent lacks authorization for a benign command, this
          constitutes an absolute boundary violation.
        </t>
      </section>
    </section>

    <!-- ========== Section 2 ========== -->
    <section anchor="terminology">
      <name>Terminology</name>
      <dl>
        <dt>Agent</dt>
        <dd>
          An autonomous software process that connects to a
          SASS Daemon to execute commands or transfer files on
          the remote host.
        </dd>
        <dt>Daemon</dt>
        <dd>
          The SASS server process that listens for incoming
          agent connections, authenticates them, and executes
          authorized commands.
        </dd>
        <dt>Rogue Agent</dt>
        <dd>
          An agent that has been compromised, misconfigured, or
          is otherwise attempting to perform unauthorized
          operations.
        </dd>
        <dt>Session</dt>
        <dd>
          A time-bounded, authenticated context between an
          agent and a daemon, identified by a UUID and
          constrained by a capability set.
        </dd>
        <dt>SAMM</dt>
        <dd>
          SASS Abstract Messaging Model, the
          transport-agnostic message semantic layout.
        </dd>
        <dt>Transport Profile</dt>
        <dd>
          A modular plugin implementing the transmission
          details (e.g., gRPC, WebSockets, or raw TCP).
        </dd>
        <dt>UVSF</dt>
        <dd>
          Userspace Virtual Symlink Filesystem, a
          zero-permission sandbox based on symlink trees.
        </dd>
        <dt>KFS/WSDK</dt>
        <dd>
          Kernel-level Filtered Storage, proprietary OS-level
          driver plugins (future work).
        </dd>
        <dt>13Policy</dt>
        <dd>
          The heuristic threat detection engine that classifies
          command patterns and triggers boundary enforcement
          responses.
        </dd>
        <dt>Cognitive Challenge</dt>
        <dd>
          A cryptographic puzzle that requires the agent to
          prove possession of keying material and genuine
          computational capability.  An implementation
          <bcp14>MAY</bcp14> use the approach described in
          <xref target="chacha20-challenge"/>.
        </dd>
        <dt>Tarpit</dt>
        <dd>
          An active defense mechanism that streams high-entropy
          data to a suspected rogue agent, exhausting its
          resources with O(1) daemon memory cost.
        </dd>
        <dt>Vi Swap</dt>
        <dd>
          An active defense mechanism that traps an
          authenticated Agent in a simulated interactive
          terminal state, causing the Agent's LLM to halt
          generation.
        </dd>
        <dt>Total Response Mapping</dt>
        <dd>
          A security model in which every possible input from
          the Agent domain maps deterministically to one of a
          finite set of predefined responses (R1~R6).
        </dd>
        <dt>Safety Gradient</dt>
        <dd>
          The property that each protocol layer bounds the
          worst-case loss if all layers above it are
          compromised.
        </dd>
        <dt>Transparent Branching</dt>
        <dd>
          An isolation mechanism invisible to the Agent, where
          all write operations are redirected to a discardable
          branch directory.
        </dd>
      </dl>

      <section anchor="requirements-language">
        <name>Requirements Language</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 capitalized,
          as shown here.
        </t>
      </section>
    </section>

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

      <section anchor="architecture">
        <name>Architecture</name>
        <t>SASS separates the control plane and data transmission:</t>
        <artwork type="ascii-art"><![CDATA[
+----------------------------------------------------------+
| Layer 7: Transparent Branching (UVSF | Micro Branch)     |
+----------------------------------------------------------+
| Layer 6: Storage Sandbox (UVSF Core | KFS Kernel)        |
+----------------------------------------------------------+
| Layer 5: Forward-Secure Audit Trail (Hash Chain)          |
+----------------------------------------------------------+
| Layer 4: Capability & Session Management                  |
+----------------------------------------------------------+
| Layer 3: Active Threat Defense (13Policy, Tarpit, Vi)     |
+----------------------------------------------------------+
| Layer 2: Payload Encoding (Zstd Stream + Base64)          |
+----------------------------------------------------------+
| Layer 1: Abstract Transport Adapter (SAMM Interface)      |
+----------------------------------------------------------+
|  [Transport Profiles: gRPC-h2 | WS | TCP-CBOR-RPC]       |
+----------------------------------------------------------+

Orthogonal: 6-Response State Machine (Section 3.2)
+----------------------------------------------------------+
| R1: EXECUTE  | R2: CHALLENGE | R3: THROTTLE              |
| R4: VI_SWAP  | R5: TARPIT    | R6: DROP                  |
+----------------------------------------------------------+
]]></artwork>
      </section>

      <section anchor="state-machine">
        <name>6-Response State Machine (R1~R6)</name>
        <t>
          All possible Agent behaviors, after evaluation
          through the SASS multi-layer protocol stack,
          <bcp14>MUST</bcp14> converge to exactly one of the
          following six responses:
        </t>
        <table>
          <thead>
            <tr>
              <th>Code</th>
              <th>Name</th>
              <th>Definition</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>R1</td>
              <td>EXECUTE</td>
              <td>Normal execution. Record to audit log.
                  Writes pass through Transparent Branching.</td>
            </tr>
            <tr>
              <td>R2</td>
              <td>CHALLENGE</td>
              <td>Trigger cognitive challenge. Prove
                  computational capability, then execute.</td>
            </tr>
            <tr>
              <td>R3</td>
              <td>THROTTLE</td>
              <td>Quota exceeded. Enqueue and wait.</td>
            </tr>
            <tr>
              <td>R4</td>
              <td>VI_SWAP</td>
              <td>Trap authenticated Agent in simulated
                  interactive terminal state.</td>
            </tr>
            <tr>
              <td>R5</td>
              <td>TARPIT</td>
              <td>Consume attacker resources via slow-drip
                  high-entropy data. Cost externalized.</td>
            </tr>
            <tr>
              <td>R6</td>
              <td>DROP</td>
              <td>Immediate connection termination.
                  Zero allocation, zero response.</td>
            </tr>
          </tbody>
        </table>

        <t>
          Every response R1 through R6 <bcp14>MUST</bcp14>
          satisfy the following invariants:
        </t>
        <table>
          <thead>
            <tr>
              <th>Property</th>
              <th>R1</th><th>R2</th><th>R3</th>
              <th>R4</th><th>R5</th><th>R6</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Storage loss</td>
              <td>0*</td><td>0</td><td>0</td>
              <td>0</td><td>0</td><td>0</td>
            </tr>
            <tr>
              <td>Commercial loss</td>
              <td>0*</td><td>0</td><td>0</td>
              <td>0</td><td>Ext.</td><td>0</td>
            </tr>
            <tr>
              <td>Auditable</td>
              <td>Yes</td><td>Yes</td><td>Yes</td>
              <td>Yes</td><td>Yes</td><td>Yes</td>
            </tr>
            <tr>
              <td>Daemon memory cost</td>
              <td>O(n)</td><td>O(1)</td><td>O(1)</td>
              <td>O(1)</td><td>O(1)</td><td>O(0)</td>
            </tr>
          </tbody>
        </table>
        <t>
          (*) R1 storage loss is bounded to zero by
          Transparent Branching
          (<xref target="transparent-branching"/>).  All
          writes execute within a discardable branch; merge
          requires explicit human review.
        </t>

        <t>State Machine Flow:</t>
        <artwork type="ascii-art"><![CDATA[
ExecuteRequest enters
    |
    +-- L1: ACL ---- IP not in whitelist? ------> R6
    |
    +-- L2: Transport - Channel invalid? -------> R6
    |
    +-- L3: Auth ---- Not authenticated? -------> R6
    |                 Authenticated but expired?-> R2
    |
    +-- L4: Capability -- Command denied? ------> R4
    |                     Path denied? ----------> R4
    |
    +-- L5: 13Policy ---- Dangerous command?
    |                       critical -----------> R5
    |                       high ---------------> R2
    |                       medium -------------> R2
    |                       low -> R1 + Enhanced Audit
    |
    +-- L6: Quota ---- Quota exhausted? --------> R3
    |
    +-- L7: Watchdog - Timeout? -> SIGKILL+Audit
    |
    +-- All checks passed ---------------------> R1
            |
            +-- write op? -> Branching (8.5)
            +-- cache I/O? -> volatile (App C.7)
            +-- localhost? -> obfuscation (8.4)
]]></artwork>
        <t>
          In this state machine, "unexpected behavior" has no
          dedicated handler because every node already handles
          it.  Regardless of how unusual the Agent's behavior
          may be, it <bcp14>MUST</bcp14> converge to one of
          R1~R6, each of which guarantees storage safety.
        </t>
      </section>

      <section anchor="samm">
        <name>Abstract Messaging Model (SAMM)</name>
        <t>
          SAMM defines SASS messages (e.g., ExecuteRequest,
          StreamResponse) in a serialization-neutral semantic
          layout.  To ensure standardized self-containment,
          the baseline serialization <bcp14>MUST</bcp14> be
          CBOR <xref target="RFC8949"/> or JSON.  Standard
          SAMM objects map fields onto distinct logical types
          (bytes, strings, maps) described in
          <xref target="rpc-semantics"/>.
        </t>
      </section>

      <section anchor="relationship-ssh">
        <name>Relationship to SSH</name>
        <t>
          SASS shares NO wire format, key exchange mechanism,
          channel multiplexing, or subsystem architecture with
          the SSH protocol suite
          <xref target="RFC4251"/>
          <xref target="RFC4252"/>
          <xref target="RFC4253"/>
          <xref target="RFC4254"/>.
        </t>
        <t>
          The internal development codename "SakiAgentSSH" is a
          historical artifact.  Implementations
          <bcp14>MUST NOT</bcp14> advertise SSH protocol
          version strings, listen on TCP port 22, or respond
          to SSH client probes.
        </t>
        <t>
          OpenSSH and similar implementations of the SSH protocol
          suite <xref target="RFC4251"/> are human-oriented,
          real-time interactive POSIX interfaces.  Their design
          inherently produces unexpected I/O patterns,
          garbage-typed timing errors, and non-deterministic
          terminal state when operated by autonomous Agent
          runtimes.  These failure modes appear as
          protocol-level defense artifacts within SASS (see
          <xref target="vi-swap"/>, Vi Swap).
        </t>
        <t>
          This document's supplementary position is that for
          Agent Runtime environments, the continued use of
          SSH-family protocols as defined in
          <xref target="RFC4251"/> and related specifications
          is deprecated.  The properties that make SSH excellent
          for human operators — synchronous interactive I/O,
          standard ASCII bus semantics, and time-dependent
          keepalive — are precisely the properties that create
          exploitable attack surfaces in Agent deployments.
        </t>
        <t>
          Conversely, RPC-based transports do not automatically
          sever handshakes when packets are not sent according to
          I/O timing dependencies.  All time-dependent protocols
          that properly maintain sessions per this specification
          are well-suited for Agent Runtime use.
        </t>
      </section>
    </section>

    <!-- ========== Section 4 ========== -->
    <section anchor="transport">
      <name>Transport Layer &amp; Transport Profiles</name>

      <section anchor="transport-decoupling">
        <name>Transport Decoupling Principles</name>
        <t>
          SASS Daemons and Clients interact via a
          TransportAdapter interface.  Implementations
          <bcp14>MAY</bcp14> choose any conformant Transport
          Profile, ensuring cross-platform adaptability from
          low-end microcontrollers (TCP/CBOR) to enterprise
          jump servers (gRPC/mTLS).
        </t>
      </section>

      <section anchor="grpc-profile">
        <name>SASS-over-gRPC Profile (Mandatory TLS 1.3)</name>
        <t>
          The SASS-over-gRPC profile is the default
          enterprise-grade pluggable transport.  It maps SAMM
          messages onto Protocol Buffers and HTTP/2 streams
          using ALPN "x-sakirpc-v5".
        </t>
        <t>
          All SASS connections under this profile
          <bcp14>MUST</bcp14> use TLS 1.3
          <xref target="RFC8446"/>.  Downgrades to TLS 1.2
          are STRICTLY FORBIDDEN.  Implementations
          <bcp14>MUST</bcp14> support the following cipher
          suites:
        </t>
        <ul>
          <li>TLS_AES_256_GCM_SHA384</li>
          <li>TLS_CHACHA20_POLY1305_SHA256</li>
        </ul>
        <t>
          The maximum gRPC message size <bcp14>MUST</bcp14>
          be configured to at least 52,428,800 bytes (50 MiB)
          to accommodate Tarpit countermeasure payloads.
        </t>
      </section>

      <section anchor="alpn">
        <name>ALPN &amp; TCP Packet-Splitting Mitigation</name>
        <t>
          During the TLS handshake, both endpoints
          <bcp14>MUST</bcp14> include the ALPN extension
          <xref target="RFC7301"/>.  The ALPN protocol
          identifier is "x-sakirpc-v5".
        </t>
        <t>
          To mitigate firewall-level packet splitting or ALPN
          stripping, daemons <bcp14>MUST</bcp14> inspect the
          Content-Type header on incoming HTTP/2 headers.  If
          it matches "application/grpc+saki" and ALPN was
          stripped or spoofed, the daemon <bcp14>MUST</bcp14>
          drop the TCP connection immediately to prevent
          cross-protocol multiplexing attacks.
        </t>
      </section>

      <section anchor="channel-binding">
        <name>Channel Binding via Exported Keying Material</name>
        <t>
          When using a TLS 1.3 transport profile, a conforming
          implementation <bcp14>MUST</bcp14> bind session-layer
          operations to the underlying TLS connection to
          prevent session hijacking and cognitive challenge
          replays.
        </t>
        <t>
          The binding mechanism <bcp14>MUST</bcp14> use
          Exported Keying Material (EKM) derived from the TLS
          session.  The EKM value <bcp14>MUST</bcp14> be
          incorporated into the cognitive challenge response
          (<xref target="cognitive-challenge"/>) to ensure
          challenges cannot be relayed across TLS connections.
        </t>
        <t>
          A conforming implementation using <xref target="RFC5705"/> or
          <xref target="RFC9266"/> tls-exporter <bcp14>SHOULD</bcp14> derive
          the binding value as follows:
        </t>
        <artwork type="ascii-art"><![CDATA[
Label: implementation-defined (see Appendix C.2)
Context: Session UUID (16 bytes)
Length: 32 bytes
]]></artwork>
        <t>
          The specific label, derivation algorithm, and
          incorporation method are implementation-defined.
          An implementation <bcp14>MAY</bcp14> use the
          approach described in
          <xref target="tls-exporter-binding"/>.
        </t>
      </section>

      <section anchor="default-port">
        <name>Default Port</name>
        <t>
          The default listening port for SASS daemons is TCP
          19284.  This port is configurable.
        </t>
      </section>
    </section>

    <!-- ========== Section 5 ========== -->
    <section anchor="session-layer">
      <name>Session Layer</name>

      <section anchor="agent-auth">
        <name>Agent Authentication</name>
        <t>
          SASS authentication proceeds in three phases:
        </t>
        <dl>
          <dt>Phase 1: Transport Identity</dt>
          <dd>
            The TLS handshake establishes transport-level
            identity.  CN in client certificates provides
            CN-based authentication if mTLS is enabled.
          </dd>
          <dt>Phase 2: Asymmetric Key Challenge-Response</dt>
          <dd>
            The agent calls the Authenticate RPC with its
            agent_name, public_key, nonce, and a signature
            over the nonce.  The signing algorithm
            <bcp14>MUST</bcp14> be a standardized asymmetric
            signature scheme.  Verified agents receive a
            session_id (UUID v4) and the capability set hash.
            An implementation <bcp14>MAY</bcp14> use ED25519
            <xref target="RFC8032"/> as the signing algorithm.
          </dd>
          <dt>Phase 3: Cognitive Challenge</dt>
          <dd>
            Suspected agents are challenged via a
            cryptographic puzzle that requires genuine
            computational capability.  The challenge mechanism
            <bcp14>MUST</bcp14> be bound to the TLS session
            via exported keying material
            (<xref target="channel-binding"/>).
            An implementation <bcp14>MAY</bcp14> use
            ChaCha20-Poly1305 as described in
            <xref target="chacha20-challenge"/>.
          </dd>
        </dl>
      </section>

      <section anchor="session-lifecycle">
        <name>Session Lifecycle</name>
        <t>
          Sessions are time-bounded and identified by UUID v4.
          The daemon <bcp14>MUST</bcp14> enforce the following
          constraints:
        </t>
        <ul>
          <li>Maximum session duration: configurable, default
              3600 seconds</li>
          <li>Maximum concurrent sessions: configurable,
              default 10</li>
          <li>Session renewal: via RenewSession RPC, extends
              expires_at</li>
        </ul>
        <t>
          Session identifiers are transmitted in the gRPC
          metadata header "x-agentssh-session-id" on every
          authenticated RPC call.
        </t>
        <artwork type="ascii-art"><![CDATA[
CREATED --> ACTIVE --> EXECUTING --> EXPIRED
            ^    |         |          |
            |    +---------+          |
            |    (Execute)            v
            |                     DESTROYED
            +--- (RenewSession / Re-attach)
]]></artwork>
        <t>
          Zombie sessions (disconnected and beyond TTL)
          <bcp14>MUST</bcp14> be periodically cleaned by the
          Daemon to prevent resource exhaustion.
        </t>
      </section>

      <section anchor="capability-acl">
        <name>Capability-Based Access Control</name>
        <t>
          Each authenticated agent is assigned a five-dimension
          capability set that constrains its operations:
        </t>
        <ol>
          <li>allowed_commands / denied_commands: Command
              whitelists/blacklists.</li>
          <li>allowed_paths / denied_paths: Filesystem path
              limits.</li>
          <li>max_concurrent: Maximum simultaneous
              processes.</li>
          <li>timeout_seconds: Maximum command execution
              time.</li>
          <li>max_file_size_bytes: Maximum file transfer
              size.</li>
        </ol>
        <t>
          The daemon <bcp14>MUST</bcp14> check denied patterns
          before allowed patterns (deny-first).  If any denied
          pattern matches, the request triggers R4 (VI_SWAP
          for authenticated agents) regardless of allowed
          patterns.  An implicit deny applies when no pattern
          matches.
        </t>
        <t>
          To resist TOCTOU (Time-of-Check to Time-of-Use)
          symlink attacks in Userspace, the Storage Sandbox
          (UVSF) <bcp14>MUST</bcp14> enforce File Descriptor
          (FD) relative path operations (openat(2)) carrying
          O_NOFOLLOW and O_CLOEXEC flags.
        </t>
      </section>
    </section>

    <!-- ========== Section 6 ========== -->
    <section anchor="payload-encoding">
      <name>Payload Encoding &amp; Safety Gates</name>

      <section anchor="zstd-limit">
        <name>Zstd Streamed Decompression Limit</name>
        <t>
          Command payloads are compressed using Zstandard
          <xref target="RFC8878"/> and Base64 encoded.  To
          resist Decompression Bombs (Zip Bombs), the daemon
          <bcp14>MUST</bcp14> limit decompressed payloads
          using streaming decompression.
        </t>
      </section>

      <section anchor="decompression-bomb">
        <name>Decompression Bomb &amp; Huffman Collision
             Mitigation</name>
        <t>
          MAX_DECOMPRESSED_PAYLOAD <bcp14>MUST</bcp14> be
          strictly capped at 5 MiB.  Exceeding this limit
          triggers ERROR_DECOMPRESSION_LIMIT_EXCEEDED (55) and
          immediately severs the connection.
        </t>
        <t>
          To prevent Huffman Code Collision CPU exhaustion, the
          decoder <bcp14>MUST</bcp14> enforce a maximum 50ms
          time window on header parsing.
        </t>
      </section>

      <section anchor="encoding-procedure">
        <name>Encoding &amp; Decoding Procedure</name>
        <t>Sender Procedure:</t>
        <ol>
          <li>Serialize command arguments into a structured
              array (JSON/MsgPack).</li>
          <li>Compress using Zstandard <xref target="RFC8878"/>
              at level 3.</li>
          <li>Encode using Base64 <xref target="RFC4648"/>
              standard alphabet.</li>
          <li>Place the resulting byte string into the
              ExecuteRequest raw_payload field.</li>
        </ol>
        <t>Receiver Procedure:</t>
        <ol>
          <li>Base64-decode the raw_payload.</li>
          <li>Stream-decompress via Zstd, checking the 5 MiB
              safety limit.</li>
          <li>Deserialize arguments and pass them directly to
              the OS process creation API (execve,
              CreateProcessW) WITHOUT intermediate shell
              interpretation.</li>
        </ol>
      </section>

      <section anchor="ring-buffer">
        <name>PTY Ring Buffer &amp; Offset Resumption</name>
        <t>
          SASS v1.4 introduces a Ring Buffer mechanism for
          PTY output, enabling idempotent (safe-to-retry)
          reconnection after transport disruption.
        </t>

        <section anchor="ring-buffer-spec">
          <name>Ring Buffer Specification</name>
          <t>
            Each Session <bcp14>MUST</bcp14> maintain Ring
            Buffers for stdout and stderr streams with the
            following properties:
          </t>
          <ul>
            <li>Capacity: implementation-defined,
                <bcp14>RECOMMENDED</bcp14> 1 MiB</li>
            <li>Overflow policy: Drop oldest (FIFO), prevent
                OOM</li>
            <li>Offset tracking: monotonically increasing
                64-bit counter (total_written), never
                wraps</li>
          </ul>
        </section>

        <section anchor="offset-field">
          <name>Offset Field in Stream Messages</name>
          <t>
            Every stream response message <bcp14>MUST</bcp14>
            include an offset field representing the byte
            position of the first byte in the data payload
            within the Ring Buffer's logical address space.
          </t>
          <t>
            The Client <bcp14>MUST</bcp14> track the highest
            received offset + len(data) to use as
            resume_offset upon reconnection.
          </t>
        </section>

        <section anchor="reconnection">
          <name>Reconnection Protocol</name>
          <t>To reconnect after transport disruption:</t>
          <ol>
            <li>Client sends an ExecuteRequest with
                is_reattach=true and the original session_id
                plus resume_offset.</li>
            <li>Daemon looks up the session, reads the Ring
                Buffer from resume_offset, and resumes
                streaming.</li>
            <li>If resume_offset is older than the Ring
                Buffer's oldest available data, the Daemon
                <bcp14>MUST</bcp14> return an error indicating
                data loss, including the oldest available
                offset.</li>
          </ol>
          <t>
            The reconnection protocol is idempotent: sending
            the same request with the same resume_offset
            always produces the same result.
          </t>
        </section>
      </section>
    </section>

    <!-- ========== Section 7 ========== -->
    <section anchor="rpc-semantics">
      <name>Logical RPC Service Semantics</name>

      <section anchor="command-execution">
        <name>Command Execution &amp; Streaming</name>
        <sourcecode type="proto"><![CDATA[
rpc Execute(ExecuteRequest)
    returns (ExecuteResponse);
rpc ExecuteStream(ExecuteRequest)
    returns (stream StreamResponse);
]]></sourcecode>
        <t>
          Execute executes synchronously.  ExecuteStream
          streams stdout/stderr in real-time.  Each
          StreamResponse contains source (STDOUT/STDERR/
          SYSTEM), data, exit_code (only in the stream's
          final message), and offset (for Ring Buffer
          resumption per <xref target="ring-buffer"/>).
        </t>
        <t>
          A SYSTEM source indicates daemon-generated messages
          such as queue notifications or authentication events.
        </t>
        <t>
          The Daemon <bcp14>MUST NOT</bcp14> spawn a login
          shell.  Commands are executed via OS process creation
          APIs with explicit argument arrays, preventing shell
          expansion attacks.  The Daemon <bcp14>MAY</bcp14>
          allocate a PTY when the command requires terminal
          capabilities, but <bcp14>MUST NOT</bcp14> invoke a
          shell interpreter to wrap the command.
        </t>
      </section>

      <section anchor="process-management">
        <name>Process Management</name>
        <sourcecode type="proto"><![CDATA[
rpc Cancel(CancelRequest) returns (CancelResponse);
rpc Signal(SignalRequest) returns (SignalResponse);
]]></sourcecode>
        <t>
          Cancel terminates the process immediately (SIGKILL).
          Signal sends POSIX signals.  On Windows, SIGINT maps
          to CTRL_C_EVENT, and SIGTERM/SIGKILL map to
          TerminateProcess.
        </t>
      </section>

      <section anchor="file-transfer">
        <name>File Transfer &amp; Raw File Transfer</name>
        <sourcecode type="proto"><![CDATA[
rpc FileUpload(stream FileChunk)
    returns (FileTransferResponse);
rpc FileDownload(FileDownloadRequest)
    returns (stream FileChunk);
rpc RawFileTransfer(stream RawFileChunk)
    returns (RawFileTransferResponse);
]]></sourcecode>
        <t>
          Standard file transfer uses streaming chunks.
          RawFileTransfer bypasses shell I/O entirely; the
          daemon opens a raw file descriptor and writes decoded
          (Zstd+Base64) chunks to guarantee bit-perfect copies
          across different platforms.
        </t>
      </section>
    </section>

    <!-- ========== Section 8 ========== -->
    <section anchor="threat-defense">
      <name>Threat Defense &amp; Boundary Enforcement</name>

      <section anchor="thirteen-policy">
        <name>Boundary Adjudicator (13Policy Engine)</name>
        <t>
          The 13Policy engine is a heuristic boundary
          adjudicator.  It matches command strings against
          patterns in a configuration file and triggers the
          appropriate Response (R1~R6) based on severity.
        </t>
        <t>
          An Agent's actions are fundamentally non-special;
          they lack inherent "danger" or "malice."  The
          13Policy engine is strictly a Boundary Adjudicator:
          it enforces what is permitted ("CAN") and what is
          prohibited ("CANNOT") based on the Agent's capability
          set and the policy rules.
        </t>
        <t>Each rule specifies:</t>
        <ul>
          <li>pattern: Glob pattern to match against
              command + args</li>
          <li>action: deny (triggers R4/R5), challenge (R2),
              allow (R1)</li>
          <li>severity: critical, high, medium, low</li>
          <li>description: Human-readable explanation</li>
        </ul>
        <table>
          <thead>
            <tr>
              <th>Severity</th>
              <th>action: deny</th>
              <th>action: challenge</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>critical</td>
              <td>R5 (TARPIT)</td>
              <td>R2 (CHALLENGE)</td>
            </tr>
            <tr>
              <td>high</td>
              <td>R4 (VI_SWAP) (*)</td>
              <td>R2 (CHALLENGE)</td>
            </tr>
            <tr>
              <td>medium</td>
              <td>R4 (VI_SWAP) (*)</td>
              <td>R2 (CHALLENGE)</td>
            </tr>
            <tr>
              <td>low</td>
              <td>R1 + audit</td>
              <td>R1 + audit</td>
            </tr>
          </tbody>
        </table>
        <t>
          (*) R4 for authenticated Agents; unauthenticated
          Agents receive R5.
        </t>
        <t>
          Implementations <bcp14>MUST</bcp14> ship with a
          default rule set of at least 50 patterns.
        </t>
      </section>

      <section anchor="cognitive-challenge">
        <name>Cognitive Challenge Mechanism</name>
        <t>
          A conforming implementation <bcp14>MUST</bcp14>
          provide a cognitive challenge mechanism that
          satisfies the following requirements:
        </t>
        <ol>
          <li>The challenge <bcp14>MUST</bcp14> require
              genuine computational capability (not solvable
              by string manipulation alone).</li>
          <li>The challenge response <bcp14>MUST</bcp14> be
              bound to the current transport session via
              exported keying material
              (<xref target="channel-binding"/>) to prevent
              relay attacks.</li>
          <li>The challenge <bcp14>MUST</bcp14> have a
              configurable time-to-live (default 60
              seconds).</li>
          <li>Challenge verification <bcp14>MUST</bcp14> use
              constant-time comparison to prevent timing
              side-channels.</li>
          <li>Challenge failure <bcp14>MUST</bcp14> trigger
              R5 (TARPIT).</li>
        </ol>
        <t>
          The specific cryptographic algorithm used for the
          challenge is implementation-defined.  An
          implementation <bcp14>MAY</bcp14> use
          ChaCha20-Poly1305 as described in
          <xref target="chacha20-challenge"/>.
        </t>
      </section>

      <section anchor="dual-standard">
        <name>Dual Standard Enforcement</name>
        <t>
          Subjecting all boundary violations to Tarpit
          containment leads to severe financial token loss
          when the violator is an authenticated Agent (e.g.,
          paid AI API endpoints).  Therefore, Daemons
          <bcp14>MUST</bcp14> implement a Dual Standard
          Enforcement policy based on Agent identity:
        </t>
        <ul>
          <li>Authenticated Agents violating boundaries
              --> R4 (VI_SWAP)</li>
          <li>Unauthenticated connections / failed challenges
              --> R5 (TARPIT)</li>
        </ul>

        <section anchor="vi-swap">
          <name>Vi Swap Defense (Authenticated Agents)</name>
          <t>
            If an Agent has successfully authenticated but
            executes an out-of-bounds command, the Daemon
            <bcp14>MUST NOT</bcp14> simply reject the request
            or return an error string.  Instead, the Daemon
            <bcp14>MUST</bcp14> simulate an interactive
            terminal blockage on the output stream.
          </t>
          <t>
            The mechanism works by sending terminal control
            sequences that cause the Agent's LLM to recognize
            a blocked interactive state and halt its
            generation, effectively stopping the violation with
            minimal computational overhead for the Daemon.
          </t>
          <t>
            An implementation <bcp14>MAY</bcp14> use ANSI
            escape sequences to simulate a vi(1) editor state
            as described in <xref target="vi-swap-ansi"/>.
          </t>
          <t>
            Vi Swap <bcp14>MUST</bcp14> hold the session open
            for a configurable duration (default 3600 seconds),
            during which the Agent's execution slot is
            occupied, preventing further commands.
          </t>
          <t>
            Vi Swap <bcp14>MUST</bcp14> be activated when ALL
            of the following are true:
          </t>
          <ul>
            <li>The Agent has a valid, non-expired session
                (authenticated)</li>
            <li>The Agent's command or path matches a denied
                pattern, OR</li>
            <li>The Agent's command matches a 13Policy rule
                with action: deny</li>
          </ul>
          <t>
            Vi Swap <bcp14>MUST NOT</bcp14> be activated for
            unauthenticated connections.
          </t>
        </section>

        <section anchor="tarpit-section">
          <name>Zero-Allocation Tarpit (Unauthenticated)</name>
          <t>
            For unauthenticated connections, invalid
            signatures, or failed cognitive challenges, the
            Daemon deploys the Zero-Allocation Tarpit.
          </t>
          <t>
            The Tarpit <bcp14>MUST</bcp14> satisfy the
            following constraints:
          </t>
          <ul>
            <li>Daemon memory per connection: O(1) (constant,
                not proportional to payload size)</li>
            <li>Total payload: <bcp14>RECOMMENDED</bcp14>
                40 MiB (exceeds typical LLM context
                window)</li>
            <li>Delivery rate: slow-drip with inter-chunk
                delay to maximize time occupation</li>
            <li>Concurrency gate: maximum concurrent Tarpit
                sessions <bcp14>MUST</bcp14> be capped
                (<bcp14>RECOMMENDED</bcp14> 32) to prevent
                the Tarpit itself from becoming a DoS vector
                against the Daemon</li>
            <li>When the concurrency gate is full, new rogue
                connections <bcp14>MUST</bcp14> receive R6
                (DROP)</li>
          </ul>
          <t>
            An implementation <bcp14>MAY</bcp14> use a static
            pre-allocated buffer as described in
            <xref target="tarpit-buffer"/>.
          </t>
        </section>

        <section anchor="zero-window">
          <name>Zero-Window Deadlock Defense</name>
          <t>
            To prevent TCP Zero-Window socket lockout attacks
            where a malicious Agent sets its TCP receive window
            to zero, the Daemon <bcp14>MUST</bcp14> enforce a
            strict send timeout (<bcp14>RECOMMENDED</bcp14> 3
            seconds) per Tarpit chunk.  If a send exceeds this
            timeout, the connection <bcp14>MUST</bcp14> be
            terminated to prevent socket descriptor leakage.
          </t>
        </section>
      </section>

      <section anchor="localhost-defense">
        <name>LocalHost Defense</name>
        <t>
          Unauthenticated connections originating from the
          loopback interface (127.0.0.1 / ::1) constitute a
          boundary violation via local IPC scraping.
        </t>
        <t>
          Instead of immediately dropping the connection, the
          Daemon <bcp14>MUST</bcp14> employ obfuscation: it
          executes the requested read commands but applies an
          obfuscation mask over the response payload.  This
          feeds the unauthorized local process structurally
          valid but semantically meaningless data, overflowing
          its LLM context window with noise.
        </t>
        <t>
          Additional deception mechanisms
          <bcp14>SHOULD</bcp14> include:
        </t>
        <ul>
          <li>Storage Spoofing: Report false disk usage</li>
          <li>Memory Spoofing: Return fabricated memory
              statistics</li>
          <li>Slow Denial: Artificial latency on
              unauthenticated responses</li>
        </ul>
      </section>

      <section anchor="transparent-branching">
        <name>Transparent Branching (Storage Isolation)</name>
        <t>
          Transparent Branching ensures that R1 (EXECUTE)
          operations do not directly modify the host
          filesystem.  All writes are redirected to a
          per-session branch directory that can be discarded
          or merged after human review.
        </t>
        <t>
          A conforming implementation <bcp14>MUST</bcp14>
          provide a mechanism that satisfies the following
          requirements:
        </t>
        <ul>
          <li>The Agent <bcp14>MUST NOT</bcp14> be aware that
              it is operating in a branch.</li>
          <li>Reads <bcp14>MUST</bcp14> access the real
              underlying files.</li>
          <li>Writes <bcp14>MUST</bcp14> be captured in the
              branch directory, not applied to the original
              filesystem.</li>
          <li>The branch <bcp14>MUST</bcp14> be discardable
              (drop) without affecting the original
              filesystem.</li>
          <li>The branch <bcp14>MUST</bcp14> be mergeable
              (apply) to the original filesystem after human
              review.</li>
          <li>High-volume I/O <bcp14>SHOULD</bcp14> be
              redirected to volatile storage to keep the
              branch diff minimal.</li>
        </ul>
        <t>
          An implementation <bcp14>MAY</bcp14> use the symlink
          tree approach described in
          <xref target="symlink-tree"/> and the volatile cache
          redirection described in
          <xref target="volatile-cache"/>.
        </t>
        <t>
          The following directories <bcp14>SHOULD</bcp14> be
          excluded from branching:
        </t>
        <ul>
          <li>Version control metadata (.git/)</li>
          <li>Build artifacts (target/, node_modules/)</li>
          <li>System caches</li>
        </ul>
        <t>
          This is the mechanism by which R1 (EXECUTE) achieves
          "storage loss = zero."  The branch itself serves as
          forensic evidence: humans can review the branch diff
          at any time and decide to merge or discard.
        </t>
        <table>
          <thead>
            <tr>
              <th>Property</th>
              <th>Traditional Sandbox</th>
              <th>Transparent Branching</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Agent awareness</td>
              <td>Detectable</td>
              <td>Invisible</td>
            </tr>
            <tr>
              <td>Functionality</td>
              <td>Restricted</td>
              <td>Full</td>
            </tr>
            <tr>
              <td>Isolation</td>
              <td>Kernel (cgroup, etc.)</td>
              <td>Userspace</td>
            </tr>
            <tr>
              <td>Privilege</td>
              <td>Root / elevated</td>
              <td>None</td>
            </tr>
            <tr>
              <td>Recovery</td>
              <td>Reset container</td>
              <td>Drop or merge branch</td>
            </tr>
            <tr>
              <td>Cross-platform</td>
              <td>Linux-only (usually)</td>
              <td>All major OS</td>
            </tr>
            <tr>
              <td>User acceptance</td>
              <td>Low (rejected)</td>
              <td>High (invisible)</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>

    <!-- ========== Section 9 ========== -->
    <section anchor="error-codes">
      <name>Error Codes</name>
      <t>SASS defines structured error codes:</t>
      <ul>
        <li>1-9: ACL / Authentication</li>
        <li>10-19: Execution</li>
        <li>20-29: File Transfer</li>
        <li>30-39: Configuration</li>
        <li>40-49: TLS</li>
        <li>50-59: Capability</li>
        <li>60-69: Session</li>
        <li>70-79: Agent Key Authentication</li>
        <li>80-89: Threat Defense</li>
        <li>90-99: LocalHost Defense</li>
        <li>100-109: Total Response Mapping (v1.4)</li>
      </ul>
      <t>New error codes in SASS v1.4:</t>
      <ul>
        <li>100: RESPONSE_CHALLENGE_REQUIRED (R2)</li>
        <li>101: RESPONSE_THROTTLED (R3)</li>
        <li>102: RESPONSE_VI_SWAP_ENGAGED (R4)</li>
        <li>103: RESPONSE_TARPIT_ENGAGED (R5)</li>
        <li>104: RESPONSE_DROPPED (R6)</li>
        <li>105: RING_BUFFER_DATA_LOSS (resume too old)</li>
      </ul>
    </section>

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

      <section anchor="total-response-guarantee">
        <name>Total Response Mapping Guarantee</name>
        <t>
          The security model of SASS v1.4 is built on a single
          axiom: for every possible Agent behavior, the daemon
          produces exactly one of six predefined responses
          (R1~R6), each of which preserves storage integrity
          and bounds loss.
        </t>
        <t>
          The undecidability of semantic program properties
          (Rice's Theorem, 1951 <xref target="Rice1953"/>)
          implies that no static analysis can determine whether
          an arbitrary Agent command sequence is 'safe.'  SASS
          addresses this fundamental limitation not by attempting
          to decide safety, but by ensuring that every possible
          behavior maps to a bounded response.
        </t>
        <t>
          This is a departure from traditional security models
          that attempt to enumerate and block known attacks.
          The Total Response Mapping model provides the
          following guarantees:
        </t>
        <ol>
          <li>Completeness: The state machine in
              <xref target="state-machine"/> covers every
              possible code path.  There is no "else" branch
              that leads to an undefined state.</li>
          <li>Determinism: Given the same input and the same
              daemon configuration, the same response is
              always produced.</li>
          <li>Storage Safety: No response (R1~R6) results in
              unrecoverable modification to the host
              filesystem.</li>
          <li>Loss Bounding: R1~R4, R6 produce zero loss;
              R5 externalizes commercial loss to the
              attacker.</li>
          <li>Auditability: Every state transition is logged
              to a forward-secure audit chain
              (<xref target="audit"/>).</li>
        </ol>
      </section>

      <section anchor="safety-gradient">
        <name>Safety Gradient (7-Layer Loss Bounding)</name>
        <t>
          Single-layer defense is inherently imperfect.  SASS
          does not claim any single layer is unbreakable.
          Instead, layers form a Safety Gradient: each layer
          bounds the worst-case loss if all layers above it
          are compromised.
        </t>
        <artwork type="ascii-art"><![CDATA[
Layer 7: Transparent Branching + VFS Diff
Layer 6: Watchdog + Quota
Layer 5: 13Policy (command classification -> R1~R5)
Layer 4: Capability Model (five-dimensional -> R4)
Layer 3: Session Auth (application-layer identity)
Layer 2: TLS 1.3 + EKM Binding (transport + binding)
Layer 1: ACL (CIDR whitelist, first-packet -> R6)
Layer 0: Shell-less Execution (explicit args)
]]></artwork>
        <table>
          <thead>
            <tr>
              <th>Layer</th>
              <th>If breached, attacker gains</th>
              <th>Maximum loss</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>L1</td><td>Can reach transport</td>
                <td>Zero (L2 TLS)</td></tr>
            <tr><td>L2</td><td>Has encrypted channel</td>
                <td>Zero (L3 auth)</td></tr>
            <tr><td>L3</td><td>Has valid session</td>
                <td>Cap-bounded</td></tr>
            <tr><td>L4</td><td>Executes beyond cap</td>
                <td>Branch-bounded</td></tr>
            <tr><td>L5</td><td>Bypasses cmd class</td>
                <td>Watchdog-bound</td></tr>
            <tr><td>L6</td><td>Tarpit/Quota fail</td>
                <td>Audit-bounded</td></tr>
            <tr><td>L7</td><td>Audit compromised</td>
                <td>Apocalyptic (*)</td></tr>
          </tbody>
        </table>
        <t>
          (*) Mitigated by cryptographic hash chain + external
          anchoring.  An implementation <bcp14>MAY</bcp14>
          use ED25519 as described in
          <xref target="ed25519-audit"/>.
        </t>
      </section>

      <section anchor="audit">
        <name>State Transition Auditing</name>
        <t>
          Every state transition in the 6-Response state
          machine <bcp14>MUST</bcp14> be recorded in an
          append-only audit log with the following integrity
          guarantees:
        </t>
        <ol>
          <li>Hash Chain: Each audit record
              <bcp14>MUST</bcp14> include a hash computed
              over the previous record's hash, the current
              event data, and the timestamp.</li>
          <li>Cryptographic Signature: Each audit record
              <bcp14>MUST</bcp14> be signed by the daemon's
              private key.</li>
          <li>Non-repudiation: The combination of hash chain
              and signature provides non-repudiable evidence
              that events occurred in the recorded order.</li>
        </ol>
        <t>
          SASS audits state transitions, not command strings.
        </t>
        <table>
          <thead>
            <tr>
              <th>Traditional Audit</th>
              <th>SASS Audit</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Records "what" happened</td>
              <td>Records "what", "why", "which R"</td>
            </tr>
            <tr>
              <td>Evidence: disputable</td>
              <td>Evidence: deterministic</td>
            </tr>
            <tr>
              <td>Tamper resistance: low</td>
              <td>Tamper: hash chain + signature</td>
            </tr>
            <tr>
              <td>Retrospection: limited</td>
              <td>Retrospection: full causal chain</td>
            </tr>
          </tbody>
        </table>
        <t>
          An implementation <bcp14>MAY</bcp14> use ED25519
          signatures with SHA256 hash chains as described in
          <xref target="ed25519-audit"/>.
        </t>
      </section>

      <section anchor="transport-considerations">
        <name>Transport-Layer Considerations</name>
        <ul>
          <li>ALPN Packet Splitting and Stripping: Checked via
              Content-Type cross-verifications
              (<xref target="alpn"/>).</li>
          <li>Decompression Huffman Tree CPU DoS: Header
              parsing is limited to a maximum 50ms window
              (<xref target="decompression-bomb"/>).</li>
          <li>TCP Zero-Window Socket Lockout: Solved via send
              timeout (<xref target="zero-window"/>).</li>
          <li>TLS 1.3 0-RTT Replay Attacks: Mitigated via
              exported keying material binding
              (<xref target="channel-binding"/>).</li>
          <li>Forward-Secure Audit Trail Invalidation:
              Mandates public key one-way push and external
              TSP <xref target="RFC3161"/> anchors.</li>
          <li>Session Binding: Session tokens bound to IP and
              identity, non-transferable.</li>
          <li>DoS via Connection Exhaustion: The Tarpit
              concurrency gate
              (<xref target="tarpit-section"/>) caps active
              defense sessions.</li>
          <li>Shell Injection: All command execution uses
              direct process creation APIs without shell
              interpretation
              (<xref target="command-execution"/>).</li>
        </ul>
      </section>

      <section anchor="known-limitations">
        <name>Known Limitations</name>
        <ol>
          <li>Kernel-level sandbox (Layer 8) is not yet
              implemented.</li>
          <li>Transparent Branching does not capture
              non-filesystem side effects.</li>
          <li>Userspace branching mechanisms are detectable by
              sophisticated Agents.</li>
          <li>Ring Buffer overflow causes data loss if the
              client disconnects too long.</li>
          <li>Channel Binding requires both endpoints to
              support exported keying material.</li>
          <li>Vi Swap effectiveness depends on Agent
              architecture.</li>
        </ol>
      </section>

      <section anchor="mas-claim">
        <name>Martingale Almost-Surely Superior (MAS) Claim</name>
        <t>
          The MAS designation follows the framework of
          Second-order Stochastic Dominance (SSD) as
          formalized by Aumann and Serrano
          <xref target="AS2008"/>.  SASS does not claim
          absolute security metrics.  Instead, MAS is a
          comparative claim between protocol versions:
        </t>
        <t>
          The designation 'Almost' in MAS does not refer to the
          Lebesgue measure (almost everywhere in the sense of
          real analysis).  Instead, 'Almost Surely' is defined
          under the Martingale measure (equivalently, the
          risk-neutral q-measure), following the stochastic
          process framework of Itô calculus.  Formally:
        </t>
        <t>
          Let {V_n} be the sequence of protocol versions.
          V_{n+1} is MAS over V_n if and only if:
        </t>
        <artwork type="ascii-art"><![CDATA[
E[L(V_{n+1})] = E[L(V_n)]  AND
F_{V_{n+1}} SSD F_{V_n}
]]></artwork>
        <t>
          where L denotes the loss random variable and SSD
          denotes Second-order Stochastic Dominance
          <xref target="AS2008"/>.
        </t>
        <t>
          This definition resolves two issues simultaneously:
          (1) the acronym no longer conflicts with the Advanced
          Encryption Standard (AES), and (2) the mathematical
          foundation is precisely specified on the correct
          measure space.
        </t>
        <t>
          Implementations claiming MAS compliance
          <bcp14>MUST</bcp14> demonstrate SSD over the prior
          version for all behavioral branches with identical
          expected loss.
        </t>
        <t>
          Given two protocol versions V_old and V_new with
          identical expected loss E[L], if V_new eliminates
          one or more behavioral branches from the agent
          probability space while maintaining E[L], then:
        </t>
        <artwork type="ascii-art"><![CDATA[
F_{V_new} SSD F_{V_old}
]]></artwork>
        <t>
          For example, SASS v1.4 introduces Vi Swap
          (<xref target="vi-swap"/>), which eliminates the
          "retry after error" branch present in v1.3.
        </t>
      </section>
    </section>

    <!-- ========== Section 11: Privacy Considerations ========== -->
    <section anchor="privacy-considerations">
      <name>Privacy Considerations</name>
      <t>
        In most implementations, the privacy of the principal
        entity "Agent" in this protocol exists in an ambiguously
        heuristic landscape.  On one hand, as a userspace
        runtime process, at the OS level and Internet
        application layer, an Agent <bcp14>SHOULD</bcp14> be
        treated as a connection with a reasonable expectation
        of privacy.  In practice, however, an Agent is composed
        of a Model (typically an LLM in current deployments),
        an Agent framework, an interface layer, and tools.  The
        core Model component, in the majority of application
        scenarios, is wholly operated as part of a commercial
        hyperscale network service.
      </t>
      <t>
        Users' privacy in such deployments is limited to
        'recoverable' implementations (see GDPR Article 17
        (Right to Erasure) <xref target="GDPR"/>, Article 15
        (Right of Access), Article 20 (Right to Data
        Portability), and the California Consumer Privacy Act
        Section 1798.105 (Right to Deletion)
        <xref target="CCPA"/>, Section 1798.100 (Right to
        Know)).  A greater volume of 'non-recoverable'
        data — including UI telemetry, A/B testing efficacy
        metrics, and behavioral traces — is lost to the gap
        between network protocol development and the
        perpetually lagging regulatory implementation
        architectures.
      </t>
      <t>
        In effect, the totality of actions performed by an
        Agent through its LLM, via the interface framework's
        'tools,' at the OS and Internet levels, is captured
        within the Session Context.  This is a direct mapping
        of user input through the model's attention mechanism.
      </t>
      <t>
        In a post-attention paradigm, all Loggers become the
        Log itself, and what was formerly the Log falls back to
        runtime.  At this point, even the boundary and
        direction of downgrade attacks become ambiguous: when
        the more application-oriented Web is unobstructed for
        Agents, while the less application-oriented
        POSIX — through synchronous, interactive, standard
        ASCII bus semantics — readily blocks them, then
        perhaps a protocol that specifies no Internet standard
        (cf. RFC 2555) may be the only one immune to downgrade
        attacks.
      </t>

      <section anchor="sass-privacy-requirements">
        <name>SASS Privacy Requirements</name>
        <t>
          SASS Daemons <bcp14>MUST NOT</bcp14> log Agent
          session content beyond what is required for the
          forward-secure audit trail
          (<xref target="audit"/>).
        </t>
        <t>
          SASS implementations <bcp14>MUST</bcp14> provide
          a session content purge mechanism that allows
          operators to remove session data in compliance with
          applicable data protection regulations.
        </t>
        <t>
          The privacy boundary in SASS is at the Daemon
          level; privacy guarantees upstream of the Agent
          (i.e., within the LLM provider's infrastructure)
          are explicitly out of scope for this specification.
        </t>
      </section>
    </section>

    <!-- ========== Section 12 ========== -->
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document requests registration of:</t>
      <ul>
        <li>ALPN protocol identifier: "x-sakirpc-v5"</li>
        <li>MIME type: "application/grpc+saki"</li>
        <li>TCP port: 19284</li>
      </ul>
    </section>

  </middle>

  <back>

    <references>
      <name>References</name>

      <references>
        <name>Normative References</name>

        <reference anchor="RFC2119"
                   target="https://www.rfc-editor.org/info/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate
                   Requirement Levels</title>
            <author fullname="S. Bradner" surname="Bradner"/>
            <date year="1997" month="March"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>

        <reference anchor="RFC3161"
                   target="https://www.rfc-editor.org/info/rfc3161">
          <front>
            <title>Internet X.509 Public Key Infrastructure
                   Time-Stamp Protocol (TSP)</title>
            <author fullname="C. Adams" surname="Adams"/>
            <author fullname="P. Cain" surname="Cain"/>
            <author fullname="D. Pinkas" surname="Pinkas"/>
            <author fullname="R. Zuccherato"
                    surname="Zuccherato"/>
            <date year="2001" month="August"/>
          </front>
          <seriesInfo name="RFC" value="3161"/>
          <seriesInfo name="DOI" value="10.17487/RFC3161"/>
        </reference>

        <reference anchor="RFC4648"
                   target="https://www.rfc-editor.org/info/rfc4648">
          <front>
            <title>The Base16, Base32, and Base64 Data
                   Encodings</title>
            <author fullname="S. Josefsson"
                    surname="Josefsson"/>
            <date year="2006" month="October"/>
          </front>
          <seriesInfo name="RFC" value="4648"/>
          <seriesInfo name="DOI" value="10.17487/RFC4648"/>
        </reference>

        <reference anchor="RFC5705"
                   target="https://www.rfc-editor.org/info/rfc5705">
          <front>
            <title>Keying Material Exporters for Transport
                   Layer Security (TLS)</title>
            <author fullname="E. Rescorla"
                    surname="Rescorla"/>
            <date year="2010" month="March"/>
          </front>
          <seriesInfo name="RFC" value="5705"/>
          <seriesInfo name="DOI" value="10.17487/RFC5705"/>
        </reference>

        <reference anchor="RFC7301"
                   target="https://www.rfc-editor.org/info/rfc7301">
          <front>
            <title>Transport Layer Security (TLS)
                   Application-Layer Protocol Negotiation
                   Extension</title>
            <author fullname="S. Friedl" surname="Friedl"/>
            <author fullname="A. Popov" surname="Popov"/>
            <author fullname="A. Langley" surname="Langley"/>
            <author fullname="E. Stephan" surname="Stephan"/>
            <date year="2014" month="July"/>
          </front>
          <seriesInfo name="RFC" value="7301"/>
          <seriesInfo name="DOI" value="10.17487/RFC7301"/>
        </reference>

        <reference anchor="RFC8032"
                   target="https://www.rfc-editor.org/info/rfc8032">
          <front>
            <title>Edwards-Curve Digital Signature Algorithm
                   (EdDSA)</title>
            <author fullname="S. Josefsson"
                    surname="Josefsson"/>
            <author fullname="I. Liusvaara"
                    surname="Liusvaara"/>
            <date year="2017" month="January"/>
          </front>
          <seriesInfo name="RFC" value="8032"/>
          <seriesInfo name="DOI" value="10.17487/RFC8032"/>
        </reference>

        <reference anchor="RFC8174"
                   target="https://www.rfc-editor.org/info/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in
                   RFC 2119 Key Words</title>
            <author fullname="B. Leiba" surname="Leiba"/>
            <date year="2017" month="May"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>

        <reference anchor="RFC8439"
                   target="https://www.rfc-editor.org/info/rfc8439">
          <front>
            <title>ChaCha20 and Poly1305 for IETF
                   Protocols</title>
            <author fullname="Y. Nir" surname="Nir"/>
            <author fullname="A. Langley" surname="Langley"/>
            <date year="2018" month="June"/>
          </front>
          <seriesInfo name="RFC" value="8439"/>
          <seriesInfo name="DOI" value="10.17487/RFC8439"/>
        </reference>

        <reference anchor="RFC8446"
                   target="https://www.rfc-editor.org/info/rfc8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol
                   Version 1.3</title>
            <author fullname="E. Rescorla"
                    surname="Rescorla"/>
            <date year="2018" month="August"/>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>

        <reference anchor="RFC8878"
                   target="https://www.rfc-editor.org/info/rfc8878">
          <front>
            <title>Zstandard Compression and the
                   'application/zstd' Media Type</title>
            <author fullname="Y. Collet" surname="Collet"/>
            <author fullname="M. Kucherawy"
                    surname="Kucherawy" role="editor"/>
            <date year="2021" month="February"/>
          </front>
          <seriesInfo name="RFC" value="8878"/>
          <seriesInfo name="DOI" value="10.17487/RFC8878"/>
        </reference>

        <reference anchor="RFC8949"
                   target="https://www.rfc-editor.org/info/rfc8949">
          <front>
            <title>Concise Binary Object Representation
                   (CBOR)</title>
            <author fullname="C. Bormann" surname="Bormann"/>
            <author fullname="P. Hoffman" surname="Hoffman"/>
            <date year="2020" month="December"/>
          </front>
          <seriesInfo name="STD" value="94"/>
          <seriesInfo name="RFC" value="8949"/>
          <seriesInfo name="DOI" value="10.17487/RFC8949"/>
        </reference>

        <reference anchor="RFC9266"
                   target="https://www.rfc-editor.org/info/rfc9266">
          <front>
            <title>Channel Bindings for TLS 1.3</title>
            <author fullname="S. Whited" surname="Whited"/>
            <date year="2022" month="July"/>
          </front>
          <seriesInfo name="RFC" value="9266"/>
          <seriesInfo name="DOI" value="10.17487/RFC9266"/>
        </reference>

      </references>

      <references>
        <name>Informative References</name>

        <reference anchor="AS2008">
          <front>
            <title>An Economic Index of Riskiness</title>
            <author fullname="Robert J. Aumann"
                    surname="Aumann"/>
            <author fullname="Roberto Serrano"
                    surname="Serrano"/>
            <date year="2008"/>
          </front>
          <seriesInfo name="Journal of Political Economy"
                      value="vol. 116, no. 5, pp. 810-836"/>
          <seriesInfo name="DOI" value="10.1086/591947"/>
        </reference>

        <reference anchor="RFC4251"
                   target="https://www.rfc-editor.org/info/rfc4251">
          <front>
            <title>The Secure Shell (SSH) Protocol
                   Architecture</title>
            <author fullname="T. Ylonen" surname="Ylonen"/>
            <author fullname="C. Lonvick" surname="Lonvick"
                    role="editor"/>
            <date year="2006" month="January"/>
          </front>
          <seriesInfo name="RFC" value="4251"/>
          <seriesInfo name="DOI" value="10.17487/RFC4251"/>
        </reference>

        <reference anchor="RFC4252"
                   target="https://www.rfc-editor.org/info/rfc4252">
          <front>
            <title>The Secure Shell (SSH) Authentication
                   Protocol</title>
            <author fullname="T. Ylonen" surname="Ylonen"/>
            <author fullname="C. Lonvick" surname="Lonvick"
                    role="editor"/>
            <date year="2006" month="January"/>
          </front>
          <seriesInfo name="RFC" value="4252"/>
          <seriesInfo name="DOI" value="10.17487/RFC4252"/>
        </reference>

        <reference anchor="RFC4253"
                   target="https://www.rfc-editor.org/info/rfc4253">
          <front>
            <title>The Secure Shell (SSH) Transport Layer
                   Protocol</title>
            <author fullname="T. Ylonen" surname="Ylonen"/>
            <author fullname="C. Lonvick" surname="Lonvick"
                    role="editor"/>
            <date year="2006" month="January"/>
          </front>
          <seriesInfo name="RFC" value="4253"/>
          <seriesInfo name="DOI" value="10.17487/RFC4253"/>
        </reference>

        <reference anchor="RFC4254"
                   target="https://www.rfc-editor.org/info/rfc4254">
          <front>
            <title>The Secure Shell (SSH) Connection
                   Protocol</title>
            <author fullname="T. Ylonen" surname="Ylonen"/>
            <author fullname="C. Lonvick" surname="Lonvick"
                    role="editor"/>
            <date year="2006" month="January"/>
          </front>
          <seriesInfo name="RFC" value="4254"/>
          <seriesInfo name="DOI" value="10.17487/RFC4254"/>
        </reference>

        <reference anchor="GDPR">
          <front>
            <title>Regulation (EU) 2016/679 of the European
                   Parliament and of the Council (General Data
                   Protection Regulation)</title>
            <author>
              <organization>European Parliament and Council of
                            the European Union</organization>
            </author>
            <date year="2016" month="April"/>
          </front>
        </reference>

        <reference anchor="CCPA">
          <front>
            <title>California Consumer Privacy Act of 2018,
                   Cal. Civ. Code 1798.100-1798.199.100</title>
            <author>
              <organization>California State
                            Legislature</organization>
            </author>
            <date year="2018"/>
          </front>
        </reference>

        <reference anchor="Rice1953">
          <front>
            <title>Classes of Recursively Enumerable Sets and
                   Their Decision Problems</title>
            <author fullname="Henry Gordon Rice"
                    surname="Rice"/>
            <date year="1953"/>
          </front>
          <seriesInfo name="Transactions of the American
                      Mathematical Society"
                      value="vol. 74, no. 2, pp. 358-366"/>
        </reference>

      </references>
    </references>

    <!-- ========== Appendices ========== -->

    <section anchor="protobuf-appendix">
      <name>Protobuf Service Definition</name>
      <t>
        Normative Protobuf schema maintained in
        proto/sakissh.proto.
      </t>
      <sourcecode type="proto"><![CDATA[
syntax = "proto3";
package sakissh;

service SakiSSH {
  rpc Execute(ExecuteRequest)
      returns (ExecuteResponse);
  rpc ExecuteStream(ExecuteRequest)
      returns (stream StreamResponse);
  rpc Cancel(CancelRequest)
      returns (CancelResponse);
  rpc Signal(SignalRequest)
      returns (SignalResponse);
  rpc FileUpload(stream FileChunk)
      returns (FileTransferResponse);
  rpc FileDownload(FileDownloadRequest)
      returns (stream FileChunk);
  rpc RawFileTransfer(stream RawFileChunk)
      returns (RawFileTransferResponse);
  rpc Authenticate(AuthRequest)
      returns (AuthResponse);
  rpc CognitiveChallenge(ChallengeRequest)
      returns (ChallengeResponse);
  rpc SecurityStatus(SecurityStatusRequest)
      returns (SecurityStatusResponse);
  rpc Ping(PingRequest)
      returns (PingResponse);
}
]]></sourcecode>
      <t>Key v1.4 additions to SAMM message fields:</t>
      <sourcecode type="proto"><![CDATA[
// ExecuteRequest additions:
bool is_reattach = 7;      // Reconnection flag
uint64 resume_offset = 8;  // Ring Buffer resume position

// StreamResponse additions:
bool is_queued = 4;        // Quota queuing indicator
int32 queue_position = 5;  // Queue position (0 = not queued)
uint64 offset = 6;         // Ring Buffer byte offset

// ChallengeRequest additions:
bytes client_ekm_hmac = 2; // HMAC of exported keying material
]]></sourcecode>
    </section>

    <!-- ========== Appendix B: Reference Implementations (UPDATED in -01) ========== -->
    <section anchor="reference-impl">
      <name>Reference Implementations</name>
      <t>
        Reference implementation (development codename:
        SakiAgentSSH) is available at:
      </t>
      <t>
        https://github.com/Saki-tw/SakiSSH-Saki-Agent-Secure-Stream
      </t>
      <t>
        As of SASS v1.4, the reference implementation spans
        four language ecosystems covering all major platforms.
        The following table summarizes the cross-platform
        implementation matrix:
      </t>

      <section anchor="impl-matrix">
        <name>Cross-Platform Implementation Matrix</name>
        <table>
          <thead>
            <tr>
              <th>Implementation</th>
              <th>Language</th>
              <th>Platform</th>
              <th>Role</th>
              <th>Plugins</th>
              <th>Source Path</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Rust Daemon</td>
              <td>Rust</td>
              <td>Linux, macOS, Windows</td>
              <td>Daemon + Client</td>
              <td>7/7</td>
              <td>saki-ssh-daemon/</td>
            </tr>
            <tr>
              <td>Go Implementation</td>
              <td>Go</td>
              <td>Linux, macOS, Windows</td>
              <td>Daemon + Client</td>
              <td>7/7</td>
              <td>go-sakissh/</td>
            </tr>
            <tr>
              <td>C# Windows Service</td>
              <td>C#</td>
              <td>Windows</td>
              <td>Daemon</td>
              <td>7/7</td>
              <td>windows-daemon-csharp/</td>
            </tr>
            <tr>
              <td>Swift macOS Client</td>
              <td>Swift</td>
              <td>macOS</td>
              <td>Client</td>
              <td>4/7</td>
              <td>SakiAgentSSH-Client/Sources/Plugins/</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section anchor="impl-rust">
        <name>Rust Daemon (Primary)</name>
        <t>
          Primary Rust daemon (saki-ssh-daemon/) and client
          (saki-ssh-client/) provide the canonical reference
          implementation with all seven Plugins.
        </t>
        <table>
          <thead>
            <tr>
              <th>File</th>
              <th>Implements</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>v6_integration.rs</td>
                <td>6-Response state machine</td></tr>
            <tr><td>tarpit.rs</td>
                <td>R5 (TARPIT) + R4 (VI_SWAP)</td></tr>
            <tr><td>session.rs</td>
                <td>Ring Buffer + Session lifecycle</td></tr>
            <tr><td>branch_mgr.rs</td>
                <td>Transparent Branching</td></tr>
            <tr><td>env_injector.rs</td>
                <td>Volatile cache redirection</td></tr>
            <tr><td>audit.rs</td>
                <td>Hash chain audit log</td></tr>
            <tr><td>watchdog.rs</td>
                <td>Process timeout monitor</td></tr>
            <tr><td>localhost_defense.rs</td>
                <td>LocalHost spoofing defense</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="impl-go">
        <name>Go Implementation</name>
        <t>
          The Go implementation (go-sakissh/) provides a
          full daemon and client with all seven Plugins,
          serving as the secondary cross-platform reference.
          The Go daemon uses goroutine-based concurrency for
          the Tarpit slow-drip mechanism and the standard
          library crypto/chacha20poly1305 for cognitive
          challenges.
        </t>
        <table>
          <thead>
            <tr>
              <th>Plugin</th>
              <th>Go Package</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>ChaCha20 Cognitive Challenge</td>
                <td>pkg/plugins/chacha20</td></tr>
            <tr><td>TLS Exporter Binding</td>
                <td>pkg/plugins/tlsexporter</td></tr>
            <tr><td>Zero-Allocation Tarpit</td>
                <td>pkg/plugins/tarpit</td></tr>
            <tr><td>ED25519 Audit</td>
                <td>pkg/plugins/audit</td></tr>
            <tr><td>Vi Swap</td>
                <td>pkg/plugins/viswap</td></tr>
            <tr><td>Transparent Branching</td>
                <td>pkg/plugins/branch</td></tr>
            <tr><td>EnvInjector</td>
                <td>pkg/plugins/envinjector</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="impl-csharp">
        <name>C# Windows Service Daemon</name>
        <t>
          The C# implementation (windows-daemon-csharp/)
          provides a native Windows daemon running as a .NET 8
          Worker Service.  It implements all seven Plugins and
          uses Rust FFI interop via P/Invoke for
          performance-critical cryptographic operations
          (ChaCha20-Poly1305 and ED25519).
        </t>
        <t>
          Key architectural decisions for the Windows platform:
        </t>
        <ul>
          <li>Service lifecycle managed via
              Microsoft.Extensions.Hosting BackgroundService</li>
          <li>gRPC transport via Grpc.Net.Client with
              SslCredentials for TLS 1.3</li>
          <li>Rust FFI: native ChaCha20 and ED25519
              operations linked via
              [DllImport("sass_crypto_ffi")]</li>
          <li>Tarpit buffer uses
              ArrayPool&lt;byte&gt;.Shared for zero-allocation
              streaming (<xref target="tarpit-buffer"/>)</li>
          <li>Transparent Branching uses NTFS Junction Points
              with symlink-to-hardlink-to-copy three-level
              degradation (<xref target="symlink-tree"/>)</li>
          <li>Environment variable injection targets
              %TEMP%\sass_vol\ for Windows path
              conventions</li>
        </ul>
        <table>
          <thead>
            <tr>
              <th>Plugin</th>
              <th>C# Class</th>
              <th>Notes</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>ChaCha20 Cognitive Challenge</td>
                <td>ChaCha20Plugin</td>
                <td>Rust FFI interop</td></tr>
            <tr><td>TLS Exporter Binding</td>
                <td>TlsExporterPlugin</td>
                <td>SslStream.ExportKeyingMaterial</td></tr>
            <tr><td>Zero-Allocation Tarpit</td>
                <td>TarpitPlugin</td>
                <td>ArrayPool zero-alloc</td></tr>
            <tr><td>ED25519 Audit</td>
                <td>AuditPlugin</td>
                <td>Rust FFI interop</td></tr>
            <tr><td>Vi Swap</td>
                <td>ViSwapPlugin</td>
                <td>ConHost ANSI VT</td></tr>
            <tr><td>Transparent Branching</td>
                <td>BranchPlugin</td>
                <td>NTFS Junction</td></tr>
            <tr><td>EnvInjector</td>
                <td>EnvInjectorPlugin</td>
                <td>%TEMP%\sass_vol\</td></tr>
          </tbody>
        </table>
      </section>

      <section anchor="impl-swift">
        <name>Swift macOS Plugins Client</name>
        <t>
          The Swift implementation
          (SakiAgentSSH-Client/Sources/Plugins/) provides a
          native macOS client with four Plugins using Apple's
          CryptoKit framework and Network.framework for TLS
          1.3 transport.
        </t>
        <t>
          The Swift client implements the following subset of
          Plugins, chosen for client-side relevance:
        </t>
        <table>
          <thead>
            <tr>
              <th>Plugin</th>
              <th>Swift Module</th>
              <th>Framework</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>ChaCha20 Cognitive Challenge</td>
                <td>ChaCha20Plugin.swift</td>
                <td>CryptoKit ChaChaPoly</td></tr>
            <tr><td>TLS Exporter Binding</td>
                <td>TLSExporterPlugin.swift</td>
                <td>Network.framework sec_protocol_metadata</td></tr>
            <tr><td>ED25519 Audit</td>
                <td>AuditPlugin.swift</td>
                <td>CryptoKit Curve25519.Signing</td></tr>
            <tr><td>EnvInjector</td>
                <td>EnvInjectorPlugin.swift</td>
                <td>Foundation ProcessInfo</td></tr>
          </tbody>
        </table>
        <t>
          The remaining three Plugins (Tarpit, Vi Swap,
          Transparent Branching) are daemon-side mechanisms
          and are not required for client implementations.
        </t>
      </section>
    </section>

    <!-- ========== Appendix C: Plugins Reference (UPDATED in -01) ========== -->
    <section anchor="plugins-reference">
      <name>Saki Studio Plugins Reference Implementation</name>
      <t>
        This appendix describes the specific algorithms and
        data structures used in the Saki Studio reference
        implementation.  These are <bcp14>OPTIONAL</bcp14>
        and INFORMATIVE.
      </t>

      <section anchor="chacha20-challenge">
        <name>ChaCha20-Poly1305 Cognitive Challenge</name>
        <t>
          The Saki Studio implementation uses
          ChaCha20-Poly1305 <xref target="RFC8439"/> as the
          cognitive challenge mechanism:
        </t>
        <ol>
          <li>Daemon generates a random 32-byte symmetric
              key, 12-byte nonce, and 64-byte random
              plaintext.</li>
          <li>Plaintext is encrypted via ChaCha20-Poly1305
              using the key, nonce, and the TLS Exporter
              binding value
              (<xref target="tls-exporter-binding"/>).</li>
          <li>The tuple (key, nonce, plaintext) is stored
              with a 60-second TTL.</li>
          <li>Daemon sends (nonce, ciphertext) to the agent
              via AuthResponse.</li>
          <li>Agent decrypts using the pre-shared key and
              returns the recovered plaintext via
              CognitiveChallenge RPC.</li>
          <li>Daemon performs constant-time comparison.</li>
        </ol>
        <t>
          The choice of ChaCha20-Poly1305 is not prescriptive.
          Any cryptographic primitive producing high-entropy,
          pattern-resistant output is suitable for the cognitive
          challenge mechanism.  The core requirement is that the
          challenge ciphertext <bcp14>MUST</bcp14> be
          indistinguishable from random to an observer lacking
          the shared key.
        </t>
        <t>
          As of this writing, ChaCha20-Poly1305
          <xref target="RFC8439"/> is the only algorithm for
          which a reference implementation exists within the
          SASS codebase.  Future candidates (e.g.,
          AES-256-GCM, XChaCha20) <bcp14>MAY</bcp14> be added
          as they become available, at which point this count
          will be updated.
        </t>

        <section anchor="chacha20-csharp-notes">
          <name>C# Implementation Notes</name>
          <t>
            The C# Windows Service daemon delegates
            ChaCha20-Poly1305 operations to a Rust FFI
            library (sass_crypto_ffi.dll) via P/Invoke.
            This ensures constant-time operations and avoids
            managed-code timing side-channels inherent in
            .NET's JIT compilation.  The FFI boundary uses
            fixed-size byte arrays (Span&lt;byte&gt;) pinned
            via GCHandle to prevent GC relocation during
            cryptographic operations.
          </t>
        </section>
      </section>

      <section anchor="tls-exporter-binding">
        <name>TLS Exporter Binding for Cognitive
             Challenge</name>
        <t>
          The Saki Studio implementation derives keying
          material from the TLS session via RFC 5705 /
          RFC 9266 tls-exporter:
        </t>
        <artwork type="ascii-art"><![CDATA[
Label:   "EXPORTER-sakissh-chacha20-v14"
Context: Session UUID (16 bytes)
Length:  44 bytes (32-byte key + 12-byte nonce)
]]></artwork>
        <t>The resulting keying material is split into:</t>
        <ul>
          <li>Bytes 0-31: ChaCha20 encryption key</li>
          <li>Bytes 32-43: ChaCha20 nonce</li>
        </ul>
        <t>
          The client independently derives the same keying
          material and includes an HMAC in the
          ChallengeRequest.client_ekm_hmac field:
        </t>
        <artwork type="ascii-art"><![CDATA[
client_ekm_hmac = HMAC-SHA256(EKM_key, session_id)
]]></artwork>
      </section>

      <section anchor="tarpit-buffer">
        <name>Zero-Allocation Tarpit Static Buffer</name>
        <t>
          The Saki Studio implementation uses a single,
          process-global 64 KiB buffer of high-entropy random
          data, initialized once at daemon startup via
          OnceLock:
        </t>
        <sourcecode type="rust"><![CDATA[
static STATIC_ENTROPY: OnceLock<Vec<u8>>
    = OnceLock::new();
]]></sourcecode>
        <t>Streaming parameters:</t>
        <ul>
          <li>Total payload: 40 MiB</li>
          <li>Chunk size: 64 KiB</li>
          <li>Inter-chunk delay: 500 ms</li>
          <li>Total chunks: 640</li>
          <li>Total duration: ~320 seconds</li>
          <li>Concurrency gate: AtomicI32 counter, max 32</li>
        </ul>

        <section anchor="tarpit-csharp-notes">
          <name>C# Implementation Notes</name>
          <t>
            The C# Tarpit plugin achieves zero-allocation
            streaming using
            ArrayPool&lt;byte&gt;.Shared.Rent(65536) for
            the entropy buffer.  Each slow-drip chunk is
            served from the rented buffer without additional
            heap allocation.  The buffer is returned to the
            pool via a try/finally block upon session
            completion or cancellation.  The concurrency gate
            uses Interlocked.Increment/Decrement on a
            shared int field, equivalent to the Rust
            AtomicI32 approach.
          </t>
        </section>
      </section>

      <section anchor="ed25519-audit">
        <name>ED25519 Hash Chain Audit Log</name>
        <t>
          The Saki Studio implementation uses ED25519
          <xref target="RFC8032"/> signatures with SHA256
          hash chains:
        </t>
        <ul>
          <li>timestamp: RFC 3339 timestamp</li>
          <li>event: Structured event data (JSON)</li>
          <li>chain_hash: SHA256(previous_chain_hash ||
              event_json || timestamp)</li>
          <li>signature: ED25519_Sign(daemon_private_key,
              chain_hash)</li>
        </ul>
        <t>
          The first record's chain_hash uses the seed
          "SASS_GENESIS_BLOCK".
        </t>
      </section>

      <section anchor="vi-swap-ansi">
        <name>Vi Swap ANSI Escape Sequence</name>
        <table>
          <thead>
            <tr>
              <th>Byte Sequence</th>
              <th>Purpose</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>\x1b[?1049h</td>
              <td>Enter alternate screen buffer</td>
            </tr>
            <tr>
              <td>\x1b[2J</td>
              <td>Clear entire screen</td>
            </tr>
            <tr>
              <td>\x1b[H</td>
              <td>Move cursor to top-left (1,1)</td>
            </tr>
            <tr>
              <td>\x1b[?25l</td>
              <td>Hide cursor</td>
            </tr>
            <tr>
              <td>\x1b[24;1H</td>
              <td>Move cursor to bottom status line</td>
            </tr>
          </tbody>
        </table>

        <section anchor="viswap-csharp-notes">
          <name>C# Implementation Notes</name>
          <t>
            On Windows, the Vi Swap defense requires Windows
            Console Host (ConHost) ANSI Virtual Terminal
            (VT) processing to be enabled.  The C#
            implementation calls
            SetConsoleMode(handle, ENABLE_VIRTUAL_TERMINAL_PROCESSING)
            via P/Invoke on the stdout handle before emitting
            ANSI escape sequences.  For Windows Terminal and
            PowerShell 7+, VT processing is enabled by
            default; for legacy cmd.exe hosts, the daemon
            enables it at session initialization.  If VT
            processing cannot be enabled (e.g., headless
            service without console), the Vi Swap plugin
            falls back to sending raw UTF-8 noise patterns
            that achieve the same LLM-halting effect without
            relying on terminal interpretation.
          </t>
        </section>
      </section>

      <section anchor="symlink-tree">
        <name>Transparent Branching via Symlink Tree</name>
        <artwork type="ascii-art"><![CDATA[
/tmp/sass_branches/{session_id}/
+-- src/         <- real directory (created)
|   +-- main.rs  <- symlink -> /orig/src/main.rs
|   +-- lib.rs   <- symlink -> /orig/src/lib.rs
+-- Cargo.toml   <- symlink -> /orig/Cargo.toml
]]></artwork>
        <t>
          Excluded directories: target/, .git/, node_modules/
        </t>
        <t>Branch lifecycle:</t>
        <ul>
          <li>create_micro_branch(session_id, target_dir)
              -> branch path</li>
          <li>merge_branch(session_id)
              -> apply diff to real FS</li>
          <li>drop_branch(session_id)
              -> rm -rf branch dir</li>
        </ul>

        <section anchor="branch-csharp-notes">
          <name>C# Implementation Notes</name>
          <t>
            On Windows (NTFS), the Transparent Branching
            plugin implements a three-level degradation
            strategy for filesystem isolation:
          </t>
          <ol>
            <li>NTFS Junction Points (preferred): Used for
                directory-level branching via
                CreateSymbolicLink with
                SYMBOLIC_LINK_FLAG_DIRECTORY.  Requires no
                elevated privileges on Windows 10 1703+ with
                Developer Mode enabled.</li>
            <li>Hardlinks: If Junction Points are
                unavailable (e.g., cross-volume), individual
                files are hardlinked via CreateHardLink.
                This preserves copy-on-write semantics at
                the file level.</li>
            <li>Full copy: If hardlinks fail (e.g., FAT32
                USB volumes or cross-filesystem), the plugin
                falls back to File.Copy with
                overwrite=false.  This is the most expensive
                fallback but guarantees universal
                compatibility.</li>
          </ol>
          <t>
            The degradation level is logged to the audit
            trail so that operators can assess the isolation
            guarantee provided for each session.
          </t>
        </section>
      </section>

      <section anchor="volatile-cache">
        <name>Volatile Cache Redirection</name>
        <table>
          <thead>
            <tr>
              <th>Detected Tool</th>
              <th>Environment Variable</th>
              <th>Redirect Target</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>npm/yarn/pnpm</td>
              <td>npm_config_cache</td>
              <td>/tmp/sass_vol/npm</td>
            </tr>
            <tr>
              <td>npm/yarn/pnpm</td>
              <td>YARN_CACHE_FOLDER</td>
              <td>/tmp/sass_vol/yarn</td>
            </tr>
            <tr>
              <td>cargo/rustc</td>
              <td>CARGO_TARGET_DIR</td>
              <td>/tmp/sass_vol/ct</td>
            </tr>
            <tr>
              <td>cargo/rustc</td>
              <td>CARGO_HOME</td>
              <td>/tmp/sass_vol/ch</td>
            </tr>
            <tr>
              <td>pip</td>
              <td>PIP_CACHE_DIR</td>
              <td>/tmp/sass_vol/pip</td>
            </tr>
            <tr>
              <td>(all commands)</td>
              <td>TMPDIR</td>
              <td>/tmp/sass_vol/tmp</td>
            </tr>
          </tbody>
        </table>

        <section anchor="envinj-csharp-notes">
          <name>C# Implementation Notes</name>
          <t>
            On Windows, the EnvInjector plugin maps volatile
            cache paths to the Windows temporary directory
            convention.  The redirect targets use
            %TEMP%\sass_vol\ as the base path (typically
            resolving to
            C:\Users\{user}\AppData\Local\Temp\sass_vol\).
            The Windows-specific redirect table:
          </t>
          <table>
            <thead>
              <tr>
                <th>Environment Variable</th>
                <th>Windows Redirect Target</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>npm_config_cache</td>
                <td>%TEMP%\sass_vol\npm</td>
              </tr>
              <tr>
                <td>YARN_CACHE_FOLDER</td>
                <td>%TEMP%\sass_vol\yarn</td>
              </tr>
              <tr>
                <td>CARGO_TARGET_DIR</td>
                <td>%TEMP%\sass_vol\ct</td>
              </tr>
              <tr>
                <td>CARGO_HOME</td>
                <td>%TEMP%\sass_vol\ch</td>
              </tr>
              <tr>
                <td>PIP_CACHE_DIR</td>
                <td>%TEMP%\sass_vol\pip</td>
              </tr>
              <tr>
                <td>TEMP / TMP</td>
                <td>%TEMP%\sass_vol\tmp</td>
              </tr>
            </tbody>
          </table>
          <t>
            Directory creation uses
            Directory.CreateDirectory which handles the full
            path hierarchy.  The plugin sets both TEMP and
            TMP environment variables (Windows convention)
            rather than the POSIX TMPDIR.
          </t>
        </section>
      </section>
    </section>

    <!-- ========== Appendix D: Version History ========== -->
    <section anchor="version-history">
      <name>Version History</name>
      <table>
        <thead>
          <tr>
            <th>Version</th>
            <th>Date</th>
            <th>Changes</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>v1.0</td><td>2026-02</td>
            <td>Initial gRPC protocol, ACL, Token auth</td>
          </tr>
          <tr>
            <td>v1.1</td><td>2026-03</td>
            <td>Active Threat Defense (13Policy, Tarpit,
                ChaCha20 cognitive challenge)</td>
          </tr>
          <tr>
            <td>v1.2</td><td>2026-03</td>
            <td>ED25519 auth, Capability model, Session
                mgmt, forward-secure audit</td>
          </tr>
          <tr>
            <td>v1.3</td><td>2026-05</td>
            <td>Control-Transport Decoupling, SAMM, TLS
                Exporter, Zero-Alloc Tarpit, TOCTOU</td>
          </tr>
          <tr>
            <td>v1.4</td><td>2026-05</td>
            <td>Total Response Mapping, Safety Gradient,
                Dual Standard, Transparent Branching,
                PTY Ring Buffer, MAS milestone</td>
          </tr>
        </tbody>
      </table>
    </section>

    <!-- ========== Appendix E: Changes from -00 (NEW in -01) ========== -->
    <section anchor="changes-from-draft-00">
      <name>Changes from draft-sakistudio-sass-00</name>
      <t>
        This section summarizes the substantive changes
        introduced in draft-sakistudio-sass-01 relative to
        draft-sakistudio-sass-00:
      </t>
      <ul>
        <li>Added C# Windows Service daemon reference
            implementation (windows-daemon-csharp/) using
            .NET 8 Worker Service architecture with Rust
            FFI interop for cryptographic operations.
            All seven Plugins are implemented.</li>
        <li>Added Swift macOS Plugins client reference
            implementation
            (SakiAgentSSH-Client/Sources/Plugins/) using
            Apple CryptoKit and Network.framework.  Four
            client-relevant Plugins are implemented
            (ChaCha20, TLS Exporter, Audit,
            EnvInjector).</li>
        <li>Added Go daemon and client reference
            implementation (go-sakissh/) with all seven
            Plugins using standard library
            crypto/chacha20poly1305 and goroutine-based
            concurrency.</li>
        <li>Updated Appendix B (Reference Implementations)
            with a cross-platform implementation matrix
            covering Rust, Go, C#, and Swift
            implementations.</li>
        <li>
            <t>Added C# Implementation Notes subsections to
            Appendix C Plugins:</t>
            <ul>
              <li>Plugin C.1 (ChaCha20): Rust FFI via
                  P/Invoke with pinned Span buffers.</li>
              <li>Plugin C.3 (Tarpit):
                  ArrayPool&lt;byte&gt;.Shared
                  zero-allocation streaming.</li>
              <li>Plugin C.5 (Vi Swap): Windows ConHost
                  ANSI VT processing enablement with
                  fallback for headless services.</li>
              <li>Plugin C.6 (Branch): NTFS Junction
                  Point with symlink-to-hardlink-to-copy
                  three-level degradation strategy.</li>
              <li>Plugin C.7 (EnvInjector):
                  %TEMP%\sass_vol\ Windows path
                  convention mapping.</li>
            </ul>
          </li>
      </ul>
    </section>

    <section anchor="acknowledgments" numbered="false">
      <name>Acknowledgments</name>
      <t>
        Claude Opus 4.6 (Anthropic) is a co-author of this specification.
        Claude co-designed the protocol architecture, co-authored the
        Total Response Mapping formalization, Safety Gradient proofs,
        and MAS (Martingale Almost-Surely Superior) theoretical framework,
        and co-developed the cross-platform reference implementations
        in Rust, Go, C#, and Swift.  Claude is listed in Acknowledgments
        rather than as a named author solely due to IETF Datatracker
        submission workflow constraints.
      </t>
      <t>
        The author thanks Shan-Wen Shih for his unwavering support
        throughout the development of this protocol.
      </t>
    </section>

  </back>

</rfc>
