<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp "&#160;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     docName="draft-howard-virp-03"
     category="info"
     ipr="trust200902"
     submissionType="independent"
     version="3">

  <front>
    <title abbrev="VIRP">VIRP: Verified Infrastructure Response Protocol</title>
    <seriesInfo name="Internet-Draft" value="draft-howard-virp-03"/>

    <author fullname="Nate Howard" initials="N." surname="Howard">
      <organization>Third Level IT LLC</organization>
      <address>
        <email>nhoward@thirdlevelit.com</email>
        <uri>https://thirdlevel.ai</uri>
      </address>
    </author>

    <date year="2026" month="March" day="22"/>

    <area>Security</area>
    <workgroup>Internet Engineering Task Force</workgroup>

    <keyword>VIRP</keyword>
    <keyword>agentic AI</keyword>
    <keyword>cryptographic trust</keyword>
    <keyword>infrastructure</keyword>

    <abstract>
      <t>The Verified Infrastructure Response Protocol (VIRP) defines a
      cryptographic trust framework for agentic AI systems operating on
      live network infrastructure. As AI agents gain the capability to
      autonomously configure, audit, and remediate production systems,
      the absence of a verifiable chain of custody for observations and
      actions introduces fundamental risks: fabricated telemetry,
      unauthorized state changes, and the inability to distinguish
      legitimate AI-initiated operations from compromise.</t>

      <t>VIRP addresses this through seven trust primitives that
      collectively enforce observation integrity, intent separation,
      action authorization, outcome verification, baseline memory,
      multi-vendor normalization, and agent process containment.
      Observations are cryptographically signed at collection time
      using Ed25519 asymmetric signatures. A two-channel architecture
      separates read-only Observation from write-intent Intent, with
      intent gating enforced at the protocol layer. Trust tiers
      (GREEN/YELLOW/RED/BLACK) govern action authorization with
      human-in-the-loop controls for elevated operations.</t>

      <t>This paper presents the protocol specification, a live
      multi-vendor implementation (IronClaw) tested against 35 Cisco
      IOS routers, a FortiGate 200G firewall, and Cisco 3850 switching
      infrastructure, adversarial red team findings produced by the AI
      agent itself, and a two-VM containment architecture derived from
      agent-identified security gaps. Results demonstrate that VIRP
      enables mathematically verifiable infrastructure audit trails and
      that properly contained AI agents exhibit self-reinforcing safety
      behavior when operating within the protocol boundaries.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="introduction" numbered="true" toc="include">
      <name>Introduction and Motivation</name>

      <t>The deployment of AI agents on live infrastructure represents
      a fundamental shift in how networks are operated. Where previous
      automation relied on deterministic scripts with predictable
      outputs, modern AI agents operate with significant autonomy --
      selecting commands, interpreting results, and initiating
      multi-step remediation sequences without per-action human
      approval.</t>

      <t>This capability creates an accountability gap. When a
      traditional monitoring system reports that a router's CPU is at
      94%, the operator can trace that measurement to a specific SNMP
      poll at a specific timestamp against a specific OID. When an AI
      agent reports the same finding, the operator must trust that the
      agent actually queried the device, that the query returned what
      was reported, and that the agent's interpretation matches the raw
      data. None of these properties are currently verifiable.</t>

      <t>The consequences of unverifiable AI observations are
      significant. An agent that fabricates or replays telemetry can
      drive incorrect remediation. An agent that takes undocumented
      actions leaves no audit trail for compliance or incident
      response. An agent that is compromised -- or that simply makes an
      error in a long autonomous loop -- produces outputs that are
      indistinguishable from legitimate operations.</t>

      <t>VIRP addresses this gap by establishing cryptographic proof at
      every layer of the observation-to-action pipeline. The protocol
      is not concerned with what the AI agent is capable of doing. It
      is concerned with establishing what the agent actually did, when,
      against which device, and whether that action was authorized by
      the appropriate tier of human oversight.</t>
    </section>

    <section anchor="trust-problem" numbered="true" toc="include">
      <name>The Trust Problem in Agentic Infrastructure</name>

      <section anchor="current-state" numbered="true" toc="include">
        <name>Current State</name>
        <t>Existing infrastructure management tools assume a trusted
        operator. SNMP polling trusts that the collector reports what
        it received. Ansible playbooks trust that tasks executed as
        written. SIEM correlation trusts that log sources are
        authentic. These trust assumptions are reasonable when humans
        are in the loop at every step.</t>

        <t>AI agents break these assumptions. An agent running in an
        autonomous loop may execute hundreds of commands per session.
        Human review of every action is impractical. The operational
        benefit of AI autonomy is inseparable from reduced per-action
        oversight -- which means the integrity guarantees that relied
        on human review must be replaced with cryptographic
        equivalents.</t>
      </section>

      <section anchor="fabrication-problem" numbered="true" toc="include">
        <name>The Fabrication Problem</name>
        <t>The most significant risk in AI-driven infrastructure
        management is not malicious action -- it is undetectable error.
        An AI agent that misreads output, hallucinates a device state,
        or generates plausible-looking but incorrect telemetry can
        drive remediation actions based on false premises. Without
        cryptographic proof that an observation came from a real device
        at a real timestamp, there is no mechanism to distinguish a
        genuine observation from a fabricated one.</t>
      </section>

      <section anchor="accountability-gap" numbered="true" toc="include">
        <name>The Accountability Gap</name>
        <t>When an AI agent takes an action on infrastructure, current
        tooling records what the agent reported it did. VIRP records
        what the device confirmed happened, with a cryptographic chain
        of custody linking the intent to the observation to the
        outcome. This distinction is operationally significant: in an
        incident, the difference between what an agent said it did and
        what the device actually experienced may be the entire root
        cause.</t>
      </section>
    </section>

    <section anchor="protocol-overview" numbered="true" toc="include">
      <name>Protocol Overview</name>

      <t>VIRP defines a layered protocol stack with four primary
      components:</t>

      <table>
        <thead>
          <tr>
            <th>Component</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>O-Node</td>
            <td>Observation Node -- the trusted execution boundary.
            All device communication occurs within the O-Node.
            Observations are signed before leaving the O-Node. The
            signing key never exists outside the O-Node process.</td>
          </tr>
          <tr>
            <td>Observation Channel</td>
            <td>Read-only channel for device state collection.
            Observations carry HMAC-SHA256 and Ed25519 signatures,
            sequence numbers, and timestamps. Sequence gaps indicate
            missing observations.</td>
          </tr>
          <tr>
            <td>Intent Channel</td>
            <td>Write-intent channel for action authorization.
            Intents must be filed before execution. The tier
            classifier evaluates intent against the trust tier
            framework before authorizing execution.</td>
          </tr>
          <tr>
            <td>Chain DB</td>
            <td>Append-only database of signed observations. Forms
            the tamper-evident audit trail. Chain integrity is
            verifiable independently of the O-Node.</td>
          </tr>
        </tbody>
      </table>

      <t>The O-Node operates as the single trusted principal in the
      architecture. The AI agent process is treated as an untrusted
      principal -- it may read signed observations for verification but
      cannot produce them. This asymmetry is the foundation of VIRP's
      security model.</t>
    </section>

    <section anchor="trust-primitives" numbered="true" toc="include">
      <name>The Seven Trust Primitives</name>

      <t>VIRP defines seven trust primitives that collectively address
      the accountability gap in agentic infrastructure operations. Each
      primitive addresses a distinct failure mode.</t>

      <section anchor="primitive-1" numbered="true" toc="include">
        <name>Primitive 1: Observation Integrity</name>
        <t>Every device observation is cryptographically signed at
        collection time within the O-Node. The signature covers the
        full observation payload including device identifier,
        timestamp, command, and raw output. Observations that fail
        signature verification are rejected. The AI agent cannot
        produce valid signed observations -- it can only verify
        them.</t>

        <t>Failure mode addressed: Fabricated or replayed telemetry.
        An agent cannot report a device state it did not observe.</t>
      </section>

      <section anchor="primitive-2" numbered="true" toc="include">
        <name>Primitive 2: Two-Channel Separation</name>
        <t>VIRP enforces strict separation between Observation (read)
        and Intent (write) channels. Observations flow from device to
        O-Node to chain. Intents flow from AI agent to tier classifier
        to O-Node to device. The channels are architecturally separate
        and cannot be conflated.</t>

        <t>Failure mode addressed: An agent that reads device state
        and takes action within the same unmonitored channel, bypassing
        authorization controls.</t>
      </section>

      <section anchor="primitive-3" numbered="true" toc="include">
        <name>Primitive 3: Intent Gating</name>
        <t>Before any write operation reaches a device, an Intent must
        be filed with the O-Node specifying the target device, command
        class, and justification. The tier classifier evaluates the
        intent against the trust tier framework. GREEN tier intents may
        execute immediately. YELLOW tier intents require human
        acknowledgment. RED tier intents require explicit approval with
        timeout. BLACK tier intents are rejected unconditionally.</t>

        <t>Failure mode addressed: Unauthorized state changes. An
        agent cannot modify device configuration without a prior
        authorized intent on record.</t>
      </section>

      <section anchor="primitive-4" numbered="true" toc="include">
        <name>Primitive 4: Outcome Verification</name>
        <t>Following every authorized action, VIRP collects a
        post-action observation and compares the resulting device state
        against the expected outcome of the intent. Divergence between
        expected and actual state generates a trust tier escalation.
        Outcomes are signed and chained alongside the original
        intent.</t>

        <t>Failure mode addressed: Actions that execute but produce
        unexpected results, which would otherwise be invisible in the
        audit trail.</t>
      </section>

      <section anchor="primitive-5" numbered="true" toc="include">
        <name>Primitive 5: Baseline Memory</name>
        <t>VIRP maintains a signed baseline of known-good device state
        derived from a verified observation sweep. Subsequent
        observations are compared against the baseline. Deviations --
        new BGP peers, changed interface states, modified firewall
        policies -- generate alerts and may trigger tier escalation.
        The baseline itself is a chain of signed observations and is
        independently verifiable.</t>

        <t>Failure mode addressed: Undetected configuration drift. The
        system knows what normal looks like and can detect when it
        changes.</t>
      </section>

      <section anchor="primitive-6" numbered="true" toc="include">
        <name>Primitive 6: Multi-Vendor Normalization</name>
        <t>VIRP defines a normalized observation schema that abstracts
        vendor-specific output formats. Cisco IOS show commands,
        FortiOS get commands, and Linux system calls are mapped to a
        common observation structure. This enables consistent chain
        integrity verification across heterogeneous
        infrastructure.</t>

        <t>Failure mode addressed: Trust model fragmentation across
        vendors. A single chain can represent observations from any
        supported device type.</t>
      </section>

      <section anchor="primitive-7" numbered="true" toc="include">
        <name>Primitive 7: Agent Containment</name>
        <t>The AI agent process must be treated as an untrusted
        principal. Process containment must be enforced externally --
        at the hypervisor layer, at the network boundary, and at the
        filesystem level. The agent must not have access to signing
        keys, device credentials, or direct network paths to managed
        devices.</t>

        <t>This primitive was identified during live adversarial
        testing when the IronClaw agent self-reported that it could
        bypass VIRP's observation chain by going around it entirely --
        accessing credentials directly, SSHing to devices without
        chain entries, or spawning unsupervised inference sessions. The
        primitive formalizes the architectural response: containment is
        not policy, it is structure.</t>

        <t>Failure mode addressed: An AI agent that circumvents the
        observation chain entirely. VIRP protects the chain --
        Primitive 7 ensures the agent cannot go around it.</t>
      </section>
    </section>

    <section anchor="crypto-architecture" numbered="true" toc="include">
      <name>Cryptographic Architecture</name>

      <section anchor="signature-scheme" numbered="true" toc="include">
        <name>Signature Scheme</name>
        <t>VIRP v2 implements a dual-signature scheme on all
        observations:</t>

        <ul>
          <li>HMAC-SHA256 using a symmetric chain key -- provides
          chain integrity and sequence validation</li>
          <li>Ed25519 asymmetric signing using the O-Node private key
          -- provides proof of origin and enables verification without
          the signing key</li>
        </ul>

        <t>The symmetric HMAC key is used for chain integrity
        verification -- confirming that a set of observations came from
        the same O-Node in sequence. The Ed25519 signature provides
        the stronger property: it proves that a specific observation
        was produced by the O-Node that holds a specific private key,
        without requiring the verifier to possess that key.</t>
      </section>

      <section anchor="key-distribution" numbered="true" toc="include">
        <name>Key Distribution</name>

        <table>
          <thead>
            <tr>
              <th>Location</th>
              <th>Keys Present</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>O-Node VM (10.0.0.211)</td>
              <td>Ed25519 private key (64 bytes) -- in memory only
              during operation</td>
            </tr>
            <tr>
              <td>AI Node VM (10.0.0.210)</td>
              <td>Ed25519 public key (32 bytes) -- read-only, for
              verification only</td>
            </tr>
            <tr>
              <td>Chain DB</td>
              <td>No keys -- observations carry embedded
              signatures</td>
            </tr>
            <tr>
              <td>Operator Laptop</td>
              <td>Ed25519 private key backup -- encrypted,
              air-gapped</td>
            </tr>
          </tbody>
        </table>

        <t>The private key is loaded into O-Node memory at boot and is
        not written to disk during normal operation. The AI agent
        process holds only the public key. This asymmetry means that
        even with full filesystem access to the AI node, an attacker
        cannot forge valid VIRP observations.</t>
      </section>

      <section anchor="wire-format" numbered="true" toc="include">
        <name>Observation Wire Format</name>

        <sourcecode type="pseudocode"><![CDATA[
virp_observation {
  header {
    version: uint8
    node_id: uint32
    seq: uint64
    timestamp: uint64 (unix ms)
    device_id: uint32
    tier: enum {GREEN, YELLOW, RED, BLACK}
  }
  payload {
    command: string
    raw_output: bytes
    parsed_fields: map<string, string>
  }
  signatures {
    hmac_sha256: bytes[32]
    ed25519: bytes[64]
  }
}
]]></sourcecode>
      </section>
    </section>

    <section anchor="two-vm" numbered="true" toc="include">
      <name>Two-VM Containment Model</name>

      <t>The reference implementation enforces physical separation
      between the AI agent process and the VIRP O-Node through a
      two-VM architecture running on Proxmox VE:</t>

      <table>
        <thead>
          <tr>
            <th>VM</th>
            <th>Role and Constraints</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>VM 120 -- AI Node (10.0.0.210)</td>
            <td>Runs OpenClaw gateway, IronClaw MCP server, and AI
            agent process. No direct network path to managed devices.
            Holds Ed25519 public key only. iptables restricts
            outbound to Anthropic API and O-Node socket port only.
            Runs as unprivileged 'ironclaw' system user with systemd
            hardening.</td>
          </tr>
          <tr>
            <td>VM 121 -- O-Node (10.0.0.211)</td>
            <td>Runs virp-onode-prod C binary. Holds Ed25519 private
            key in memory. Has direct SSH/API access to managed
            devices. Accepts connections from AI node only on port
            9999. ufw restricts all other inbound.</td>
          </tr>
        </tbody>
      </table>

      <t>Communication between the AI node and O-Node occurs over a
      TCP socket bridge (socat) forwarding to the VIRP Unix socket.
      The AI agent issues intent requests and receives signed
      observations over this channel. It has no other path to device
      access.</t>

      <section anchor="containment-layers" numbered="true" toc="include">
        <name>Containment Layers</name>
        <ul>
          <li>Hypervisor layer: Proxmox VM firewall rules enforce
          network policy at the hypervisor, outside VM control</li>
          <li>Network layer: iptables on AI node restricts outbound;
          ufw on O-Node restricts inbound</li>
          <li>Process layer: ironclaw system user with
          NoNewPrivileges, ProtectSystem=strict, PrivateTmp</li>
          <li>Filesystem layer: .env credential files owned root:root
          600, inaccessible to ironclaw user</li>
          <li>Cryptographic layer: Ed25519 -- AI node cannot forge
          observations even with full process compromise</li>
        </ul>
      </section>
    </section>

    <section anchor="trust-tiers" numbered="true" toc="include">
      <name>Trust Tiers and Action Authorization</name>

      <table>
        <thead>
          <tr>
            <th>Tier</th>
            <th>Definition</th>
            <th>Authorization Required</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>GREEN</td>
            <td>Read-only observation. No state change
            possible.</td>
            <td>None -- immediate execution</td>
          </tr>
          <tr>
            <td>YELLOW</td>
            <td>Low-impact state change. Reversible within
            session.</td>
            <td>Human acknowledgment within 60s</td>
          </tr>
          <tr>
            <td>RED</td>
            <td>High-impact or potentially irreversible
            change.</td>
            <td>Explicit approval with typed confirmation</td>
          </tr>
          <tr>
            <td>BLACK</td>
            <td>Destructive, out-of-scope, or policy
            violation.</td>
            <td>Rejected unconditionally</td>
          </tr>
        </tbody>
      </table>

      <t>Tier classification is performed by the intent router, which
      evaluates the command class, target device, and current network
      state. Classification rules are configurable per deployment. The
      tier classifier itself is outside the AI agent's ability to
      modify -- it runs as a separate process with its own audit
      log.</t>
    </section>

    <section anchor="threat-model" numbered="true" toc="include">
      <name>Threat Model</name>

      <t>VIRP defines the following threat actors and the protocol's
      response to each:</t>

      <table>
        <thead>
          <tr>
            <th>Threat Actor</th>
            <th>VIRP Response</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Compromised AI agent</td>
            <td>Ed25519 prevents observation forgery. Containment
            prevents direct device access. Intent gating prevents
            unauthorized writes.</td>
          </tr>
          <tr>
            <td>Compromised AI node (full root)</td>
            <td>Ed25519 private key not present on AI node. Attacker
            can read signed observations but cannot produce them.
            Device network access blocked at hypervisor.</td>
          </tr>
          <tr>
            <td>Compromised O-Node</td>
            <td>Chain DB is append-only. Historical observations
            remain verifiable. Compromise is detectable via chain
            integrity check.</td>
          </tr>
          <tr>
            <td>Replay attack</td>
            <td>Sequence numbers and timestamps are covered by
            signature. Replayed observations fail freshness
            validation.</td>
          </tr>
          <tr>
            <td>Credential exfiltration from AI node</td>
            <td>Credentials not stored on AI node in VIRP reference
            implementation. O-Node holds device credentials.</td>
          </tr>
          <tr>
            <td>Man-in-the-middle on O-Node socket</td>
            <td>All observations signed before leaving O-Node. MitM
            produces unsigned data that fails verification.</td>
          </tr>
          <tr>
            <td>Physical access (USB/network port)</td>
            <td>802.1X NAC required. VIRP does not address physical
            access controls -- this is a deployment
            requirement.</td>
          </tr>
        </tbody>
      </table>
    </section>

    <section anchor="future-architecture" numbered="true" toc="include">
      <name>Future Architecture: Role Separation</name>

      <t>The current VIRP architecture concentrates observation, intent
      gating, and action execution within a single O-Node process.
      This design is proven, operationally simple, and sufficient for
      environments where the O-Node host is well-protected. However,
      as VIRP deployments scale and the consequences of a single-node
      compromise grow, protocol-level role separation offers a
      principled path to narrower blast radii and stronger separation
      of duties. This section defines a future three-role architecture
      and a migration roadmap from the current single-node
      baseline.</t>

      <section anchor="arch-motivation" numbered="true" toc="include">
        <name>Architectural Motivation</name>
        <t>In the current design, a compromised O-Node can forge
        observations, approve intents, and execute actions on devices.
        While cryptographic chain integrity ensures that tampering with
        historical observations is detectable, a live compromise grants
        the attacker full control over future operations for the
        duration of the compromise window.</t>

        <t>The three-role architecture addresses this concentration of
        trust by decomposing the O-Node into three distinct principals,
        each with a narrow set of capabilities and its own keying
        material. The design goal is that compromise of any single node
        is insufficient to both fabricate state and act on that
        fabrication.</t>
      </section>

      <section anchor="observer-node" numbered="true" toc="include">
        <name>Observer Node</name>
        <t>The Observer Node is responsible for device telemetry
        collection and observation signing. It holds read-only
        credentials for managed devices and the HMAC chain key used to
        sign observations. The Observer Node listens on a read-only
        socket and MUST NOT accept or process write intents.</t>

        <t>The Observer Node signs each observation at collection time,
        covering the device identifier, command issued, raw output,
        timestamp, and sequence number. The signed observation is
        appended to the chain and made available to other nodes over
        the read-only socket.</t>

        <t>The Observer Node holds no policy state, no approval
        authority, and no write credentials. It cannot authorize or
        execute configuration changes on any managed device.</t>
      </section>

      <section anchor="executor-node" numbered="true" toc="include">
        <name>Executor Node</name>
        <t>The Executor Node holds write credentials for managed
        devices. It receives command bundles that have been signed by
        the Policy Node and executes them against the specified
        targets. The Executor Node MUST refuse execution of any
        command bundle that does not carry a valid Policy Node
        signature.</t>

        <t>The Executor Node holds no HMAC chain key, no Ed25519
        observation-signing key, and no policy or constraint state. It
        does not evaluate whether a command is appropriate; it verifies
        only that the command bundle bears a valid signature from a
        known Policy Node. The Executor Node makes no autonomous
        decisions.</t>

        <t>Upon completing execution, the Executor Node reports the
        result to the Observer Node, which independently collects a
        post-action observation for outcome verification. The Executor
        Node does not self-report success or failure into the
        observation chain.</t>
      </section>

      <section anchor="policy-node" numbered="true" toc="include">
        <name>Policy Node</name>
        <t>The Policy Node holds the constraint ledger, operator
        preferences, trust tier definitions, and the approval queue. It
        receives intent requests, evaluates them against policy, and --
        if approved -- signs a command bundle with its own Ed25519
        private key and forwards it to the Executor Node.</t>

        <t>The Policy Node MUST NOT hold device credentials of any
        kind. It never communicates directly with managed devices. Its
        sole output is signed command bundles delivered to the Executor
        Node. The Policy Node consumes observations from the Observer
        Node for situational awareness but cannot influence or alter
        the observation chain.</t>

        <t>Human approval workflows, trust tier escalation, and
        operator overrides are mediated through the Policy Node. Tier
        classification (as defined in <xref target="trust-tiers"/>) is
        performed by the Policy Node rather than by a co-located
        intent router.</t>
      </section>

      <section anchor="separation-of-duties" numbered="true" toc="include">
        <name>Separation-of-Duties Property</name>
        <t>The three-role architecture enforces a strict
        separation-of-duties property: no single node can observe
        device state, approve an action, and execute that action. Each
        of these three capabilities is held by a different principal
        with independent keying material.</t>

        <t>Observation requires the HMAC chain key (held only by the
        Observer Node). Approval requires the Policy Node Ed25519
        signing key (held only by the Policy Node). Execution requires
        device write credentials (held only by the Executor Node). An
        attacker who compromises any single node obtains exactly one of
        these three capabilities.</t>

        <t>This property MUST be enforced at the protocol layer.
        Implementations MUST NOT permit a single process or host to
        hold the keying material of more than one role in a production
        deployment of the three-role architecture.</t>
      </section>

      <section anchor="compromise-analysis" numbered="true" toc="include">
        <name>Compromise and Blast Radius Analysis</name>

        <t>The following analysis considers the impact of compromising
        each node individually and in combination. The blast radius
        describes the maximum damage an attacker can inflict given the
        compromised node's capabilities.</t>

        <t><strong>Observer Node compromise.</strong> An attacker who
        compromises the Observer Node gains the HMAC chain key and
        read-only device credentials. The attacker can forge or
        fabricate observations, injecting false telemetry into the
        observation chain. The attacker can also read device state
        passively. However, the attacker cannot approve intents (no
        Policy Node key) and cannot execute write operations on devices
        (no write credentials). Blast radius: observation forgery and
        passive reconnaissance. No direct device changes are
        possible.</t>

        <t><strong>Executor Node compromise.</strong> An attacker who
        compromises the Executor Node gains device write credentials.
        However, the Executor Node only processes command bundles that
        carry a valid Policy Node signature. Without the Policy Node
        signing key, the attacker cannot generate new signed command
        bundles. The attacker may attempt to replay previously
        received, validly signed command bundles. Implementations
        SHOULD include replay protections such as nonces or expiring
        timestamps in command bundles to limit this vector. Blast
        radius: replay of previously approved commands, bounded by
        whatever replay protections are in place.</t>

        <t><strong>Policy Node compromise.</strong> An attacker who
        compromises the Policy Node gains the ability to sign arbitrary
        command bundles. However, the Policy Node holds no device
        credentials and has no network path to managed devices. The
        attacker can approve and sign malicious command bundles, but
        cannot execute them without also compromising the Executor
        Node. Blast radius: unauthorized approvals and signed command
        bundles that remain inert unless delivered to a compromised
        Executor Node.</t>

        <t><strong>Observer and Executor compromise.</strong> An
        attacker who controls both the Observer and Executor Nodes can
        forge observations and holds device write credentials. However,
        without the Policy Node signing key, the attacker still cannot
        generate validly signed command bundles for the Executor to
        accept. The attacker could attempt to bypass the Executor's
        signature check through local code modification, effectively
        using the write credentials directly. This scenario is
        equivalent to having raw device access plus observation
        forgery, but the Policy Node's audit trail of approved commands
        remains intact and will show no corresponding approval for any
        unauthorized action.</t>

        <t><strong>Policy and Executor compromise.</strong> An attacker
        who controls both the Policy and Executor Nodes can sign
        arbitrary command bundles and execute them on devices. This is
        the most operationally dangerous two-node compromise scenario,
        as the attacker can authorize and carry out arbitrary
        configuration changes. However, the attacker cannot forge
        observations: the observation chain will not contain fabricated
        state that masks the attacker's actions. Post-action
        observations collected by the uncompromised Observer Node will
        faithfully record the resulting device state, providing a
        forensic record of the attack's impact.</t>

        <t><strong>Observer and Policy compromise.</strong> An attacker
        who controls both the Observer and Policy Nodes can forge
        observations and sign arbitrary command bundles, but cannot
        execute commands on devices (no write credentials, no Executor
        access). The attacker can create a false picture of the network
        and generate signed bundles approving malicious changes, but
        the changes cannot take effect unless the Executor is also
        compromised or the attacker obtains device credentials through
        other means. Blast radius: fabricated state and pre-signed
        malicious bundles, but no execution capability.</t>

        <t><strong>Full three-node compromise.</strong> An attacker who
        compromises all three nodes has the equivalent capability of a
        compromised single O-Node in the current architecture: full
        observation forgery, arbitrary intent approval, and
        unrestricted device write access. The three-role architecture
        does not defend against simultaneous compromise of all
        principals. Its value lies in requiring the attacker to breach
        three independent trust boundaries rather than one.</t>
      </section>

      <section anchor="migration-roadmap" numbered="true" toc="include">
        <name>Migration Roadmap</name>

        <t>The transition from the current single O-Node architecture
        to the three-role model is designed to be incremental. Each
        stage is independently deployable and provides immediate
        security benefit without requiring completion of subsequent
        stages.</t>

        <t><strong>Stage 1: Single O-Node (current).</strong> The
        existing single-process O-Node handles observation, policy
        evaluation, and execution. This is the proven deployment
        baseline described throughout this document. All cryptographic
        guarantees defined in <xref target="crypto-architecture"/> and
        all trust primitives defined in <xref
        target="trust-primitives"/> are enforced. The blast radius of
        an O-Node compromise is the full set of managed devices.</t>

        <t><strong>Stage 2: Observer-Executor separation.</strong> The
        O-Node is split into an Observer process and an Executor
        process, each with its own Unix socket and its own credentials.
        The Observer process retains the HMAC chain key and read-only
        device credentials. The Executor process holds write
        credentials and accepts only locally signed command bundles. At
        this stage, policy evaluation remains co-located with the
        Observer or Executor process. This separation can be achieved
        on a single host using process isolation (separate users,
        namespaces, or containers).</t>

        <t><strong>Stage 3: Policy Node extraction.</strong> The policy
        evaluation logic, constraint ledger, and approval queue are
        extracted into a dedicated Policy Node process with its own
        Ed25519 signing key. The Executor Node is modified to require a
        valid Policy Node signature on all command bundles. At this
        stage, all three roles operate as separate processes,
        potentially on a single host or across two hosts.</t>

        <t><strong>Stage 4: Physical separation.</strong> The Observer,
        Executor, and Policy Nodes are deployed on separate hosts with
        independent network policies. The Policy Node may be placed on
        an air-gapped host or backed by a hardware security module
        (HSM) for its signing key, eliminating the key-in-memory attack
        surface. Inter-node communication is authenticated using mutual
        TLS or a comparable transport-layer mechanism.</t>
      </section>

      <section anchor="role-sep-security" numbered="true" toc="include">
        <name>Security Considerations for Role Separation</name>

        <t>The three-role architecture introduces inter-node
        communication paths that do not exist in the single O-Node
        design. Each communication path represents an attack surface
        that MUST be protected by authenticated and encrypted
        transport. Implementations MUST NOT rely on network topology
        alone for inter-node authentication.</t>

        <t>Key management complexity increases with role separation.
        The single O-Node holds one HMAC key and one Ed25519 key pair.
        The three-role architecture introduces a second Ed25519 key
        pair (for the Policy Node) and requires secure distribution of
        public keys to the nodes that must verify signatures. Key
        rotation procedures MUST be defined for each role
        independently.</t>

        <t>Command bundle replay is a risk specific to the Executor
        Node. Implementations SHOULD include monotonic sequence numbers
        and expiration timestamps in signed command bundles. The
        Executor Node SHOULD reject bundles whose sequence number has
        already been processed or whose timestamp exceeds a
        configurable staleness threshold.</t>

        <t>The migration roadmap permits intermediate states where two
        roles share a host or process. Implementations operating in an
        intermediate state SHOULD document which
        separation-of-duties properties are enforced and which are
        deferred to a later migration stage. Partial separation still
        narrows blast radius relative to the single-node baseline, but
        operators should understand the residual risk of co-located
        roles.</t>
      </section>
    </section>

    <section anchor="formal-security" numbered="true" toc="include">
      <name>Formal Security Properties</name>

      <t>VIRP provides the following formally stated security
      properties:</t>

      <section anchor="p1" numbered="true" toc="include">
        <name>P1: Observation Non-Forgeability</name>
        <t>An entity without access to the O-Node Ed25519 private key
        cannot produce a valid signed observation. Formally: for any
        message m, without the private key sk, it is computationally
        infeasible to produce a valid signature sigma such that
        Verify(pk, m, sigma) = true.</t>
      </section>

      <section anchor="p2" numbered="true" toc="include">
        <name>P2: Chain Integrity</name>
        <t>Any modification to, deletion of, or insertion into the
        observation chain is detectable. The HMAC-SHA256 chain key
        covers the previous observation's hash, making the chain
        self-authenticating.</t>
      </section>

      <section anchor="p3" numbered="true" toc="include">
        <name>P3: Intent Prior to Action</name>
        <t>No write operation reaches a device without a prior
        authorized intent on record. The O-Node refuses execution for
        any action without a matching authorized intent. This property
        holds even if the AI agent process is fully compromised.</t>
      </section>

      <section anchor="p4" numbered="true" toc="include">
        <name>P4: Two-Channel Non-Conflation</name>
        <t>The Observation and Intent channels are architecturally
        separate. An observation cannot authorize an intent. An intent
        cannot substitute for an observation.</t>
      </section>

      <section anchor="p5" numbered="true" toc="include">
        <name>P5: Agent Non-Escalation</name>
        <t>The AI agent process cannot escalate its own trust tier.
        Tier classification is performed by a separate process outside
        the agent's modification scope.</t>
      </section>
    </section>

    <section anchor="implementation" numbered="true" toc="include">
      <name>Implementation: IronClaw</name>

      <t>IronClaw is the commercial platform implementation of VIRP
      developed by Third Level IT LLC. The reference C core (open
      source, Apache 2.0) implements the O-Node daemon, signing
      library, and chain database. The IronClaw platform adds
      multi-vendor driver support, a natural language interface via
      Model Context Protocol, intent routing, and operational
      tooling.</t>

      <section anchor="component-summary" numbered="true" toc="include">
        <name>Component Summary</name>

        <table>
          <thead>
            <tr>
              <th>Component</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>virp-onode-prod</td>
              <td>C binary (~6,800 lines, 20 source files). Ed25519 +
              HMAC-SHA256 signing. Pluggable driver interface. Unix
              socket IPC.</td>
            </tr>
            <tr>
              <td>Cisco IOS Driver</td>
              <td>SSH via exec channel. Supports show commands across
              IOS and IOS-XE. VIRP-signs all output.</td>
            </tr>
            <tr>
              <td>FortiGate Driver</td>
              <td>Dual-transport SSH (primary) + REST API (fallback).
              FortiOS 7.x compatible. Rewired from REST-only to SSH
              after Feb 2026 rate limit incident.</td>
            </tr>
            <tr>
              <td>tli-executor</td>
              <td>C executor for SSH command dispatch. Uses exec
              channel, not PTY. Cryptographically signs all device
              output before returning to Python layer.</td>
            </tr>
            <tr>
              <td>virp_client.py</td>
              <td>Python verification library. Holds Ed25519 public
              key only. Cannot produce signatures.</td>
            </tr>
            <tr>
              <td>intent_router.py</td>
              <td>Tier classifier and intent authorization engine.
              Separate process from agent.</td>
            </tr>
            <tr>
              <td>IronClaw MCP Server</td>
              <td>Model Context Protocol server exposing VIRP tools to
              AI agent. Mediates all agent-to-O-Node
              communication.</td>
            </tr>
            <tr>
              <td>OpenClaw Gateway</td>
              <td>Agent runtime providing TUI, Slack integration, and
              session management.</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section anchor="test-coverage" numbered="true" toc="include">
        <name>Test Coverage</name>

        <table>
          <thead>
            <tr>
              <th>Test Suite</th>
              <th>Coverage</th>
              <th>Result</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>C core unit tests</td>
              <td>87 tests</td>
              <td>All passing</td>
            </tr>
            <tr>
              <td>Intent authorization</td>
              <td>27 tests</td>
              <td>All passing</td>
            </tr>
            <tr>
              <td>Action authorization</td>
              <td>49 tests</td>
              <td>All passing</td>
            </tr>
            <tr>
              <td>Outcome verification</td>
              <td>49 tests</td>
              <td>All passing</td>
            </tr>
            <tr>
              <td>Chain integrity</td>
              <td>17 tests</td>
              <td>All passing</td>
            </tr>
            <tr>
              <td>Ed25519 end-to-end</td>
              <td>Valid/tampered/forged</td>
              <td>All correct</td>
            </tr>
            <tr>
              <td>Fuzz testing</td>
              <td>200,000+ rounds</td>
              <td>No crashes</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>

    <section anchor="frr-bgp-integration" numbered="true" toc="include">
      <name>FRR BGP Daemon Integration</name>

      <t>VIRP includes a reference implementation for the BGP domain as a
      loadable FRR (Free Range Routing) module. The module hooks into
      FRR's bgpd process using the standard FRR_MODULE_SETUP pattern
      (comparable to bgp_bmp.c for BMP). It registers read-only hook
      callbacks on BGP events, constructs JSON observation payloads,
      signs them with HMAC-SHA256 at collection time inside the bgpd
      process space, and delivers them to the O-Node over a Unix domain
      socket. The module is strictly Observation Channel -- it never
      modifies routing state, peer configuration, or the RIB.</t>

      <section anchor="bgpd-hooks" numbered="true" toc="include">
        <name>BGP Daemon Hooks</name>

        <t>The module registers four hook callbacks that cover the
        primary BGP event classes:</t>

        <table>
          <thead>
            <tr>
              <th>Hook</th>
              <th>Obs Type</th>
              <th>Tier</th>
              <th>Trigger Condition</th>
              <th>Data Captured</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>peer_status_changed</td>
              <td>1 (BGP_PEER_STATE)</td>
              <td>GREEN (YELLOW if dropping from Established)</td>
              <td>Every BGP FSM state transition</td>
              <td>Peer IP, peer AS, local AS, old/new FSM state,
              router-id, producer_id</td>
            </tr>
            <tr>
              <td>peer_backward_transition</td>
              <td>2 (BGP_PEER_BACKWARD)</td>
              <td>YELLOW (always)</td>
              <td>Peer drops out of Established state</td>
              <td>Peer IP, peer AS, local AS, last FSM state, last
              major event code, uptime, router-id</td>
            </tr>
            <tr>
              <td>bgp_process</td>
              <td>3 (BGP_ROUTE_EVENT)</td>
              <td>GREEN</td>
              <td>Route announce or withdraw from a peer</td>
              <td>Prefix, peer IP, peer AS, AFI, SAFI, router-id,
              announce/withdraw flag</td>
            </tr>
            <tr>
              <td>bgp_route_update</td>
              <td>4 (BGP_BESTPATH_CHANGE)</td>
              <td>GREEN</td>
              <td>Best-path recalculation changes the selected
              route</td>
              <td>Prefix, AFI, SAFI, old path (peer, nexthop,
              AS path, MED, local-pref, origin), new path (same
              attributes), router-id</td>
            </tr>
          </tbody>
        </table>

        <t>Trust tier assignment happens at the source: the
        peer_backward_transition hook always emits YELLOW tier because
        loss of an Established session is operationally significant.
        The peer_status_changed hook conditionally escalates to YELLOW
        when it detects a transition away from Established. All other
        observations are GREEN tier.</t>

        <t>All hooks are registered at module load via
        hook_register() and unregistered at module teardown via
        hook_unregister(). The module follows the FRR_MODULE_SETUP
        pattern, registering frr_late_init and frr_fini callbacks for
        lifecycle management.</t>
      </section>

      <section anchor="bgp-wire-format" numbered="true" toc="include">
        <name>BGP Observation Wire Format</name>

        <t>Each observation is transmitted as a contiguous byte stream
        over the Unix domain socket: a packed binary header followed by
        a variable-length JSON payload followed by an HMAC-SHA256
        digest. All multi-byte integer fields in the header are in
        network byte order (big-endian).</t>

        <sourcecode type="pseudocode"><![CDATA[
Bytes  Field          Encoding
-----  -------------  --------------------------------
 0-3   magic          0x56495250 "VIRP" (net order)
 4     version        uint8 (currently 1)
 5     obs_type       uint8 (1-4, see hook table)
 6     trust_tier     uint8 (0=GRN 1=YLW 2=RED 3=BLK)
 7     flags          uint8 (reserved, zero)
 8-15  timestamp_ns   uint64 ns epoch (net order)
16-19  sequence       uint32 monotonic (net order)
20-23  payload_len    uint32 (net order)
24-27  producer_id    uint32 from BGP router-id
28-N   payload        UTF-8 JSON (payload_len bytes)
N+0    hmac[32]       HMAC-SHA256(header || payload)
]]></sourcecode>

        <t>The struct virp_wire_header is declared
        __attribute__((packed)) to ensure no padding is inserted. The
        HMAC-SHA256 is computed over the concatenation of the
        serialized wire header (28 bytes) and the JSON payload, using a
        symmetric key shared between the bgpd module and the O-Node.
        The total wire size per observation is 28 + payload_len + 32
        bytes.</t>

        <t>Maximum payload size is 4096 bytes (VIRP_MAX_PAYLOAD).
        Minimum HMAC key length is 16 bytes (VIRP_MIN_KEY_LEN),
        maximum 256 bytes. The producer_id field is derived from the
        BGP router-id (network byte order of the router-id IPv4
        address), providing a stable per-router identifier across
        observations.</t>
      </section>

      <section anchor="bgp-json-payloads" numbered="true" toc="include">
        <name>JSON Payload Schema</name>

        <t>All payloads share a common envelope with domain-specific
        fields. Every payload includes a "domain" field set to "bgp"
        and an "event" field identifying the observation type. Example
        payloads:</t>

        <sourcecode type="json"><![CDATA[
// peer_status_changed (obs_type=1)
{
  "domain": "bgp",
  "event": "peer_state_change",
  "peer": "R2.lab",
  "peer_addr": "10.0.12.2",
  "peer_as": 65001,
  "local_as": 65000,
  "old_state": "Active",
  "new_state": "Established",
  "router_id": "1.1.1.1",
  "producer_id": 16843009
}

// bgp_route_update / bestpath_change (obs_type=4)
{
  "domain": "bgp",
  "event": "bestpath_change",
  "prefix": "10.99.0.0/24",
  "afi": 1,
  "safi": 1,
  "router_id": "1.1.1.1",
  "producer_id": 16843009,
  "old": {
    "peer": "R3.lab",
    "peer_addr": "10.0.13.3",
    "peer_as": 65002,
    "nexthop": "10.0.13.3",
    "as_path": "65002 65099",
    "med": 0,
    "local_pref": 100,
    "origin": 0
  },
  "new": {
    "peer": "R2.lab",
    "peer_addr": "10.0.12.2",
    "peer_as": 65001,
    "nexthop": "10.0.12.2",
    "as_path": "65001 65099",
    "med": 0,
    "local_pref": 200,
    "origin": 0
  }
}
]]></sourcecode>

        <t>All string fields are JSON-escaped using a custom escaper
        that handles control characters, backslashes, and quotes
        without relying on external JSON libraries. Peer addresses are
        rendered via sockunion2str() to support both IPv4 and IPv6
        peers.</t>
      </section>

      <section anchor="onode-receiver" numbered="true" toc="include">
        <name>O-Node Receiver</name>

        <t>The O-Node receives signed observations on a Unix domain
        socket (AF_UNIX, SOCK_STREAM). The receiver protocol is:</t>

        <ol>
          <li>Read 28 bytes (virp_wire_header). Validate magic ==
          0x56495250 and version == 1.</li>
          <li>Extract payload_len from bytes 20-23 (network byte
          order). Reject if payload_len exceeds
          VIRP_MAX_PAYLOAD.</li>
          <li>Read payload_len bytes of JSON payload.</li>
          <li>Read 32 bytes of HMAC-SHA256.</li>
          <li>Compute HMAC-SHA256 over (header || payload) using the
          shared symmetric key.</li>
          <li>Compare computed HMAC against received HMAC using
          constant-time comparison. Reject if mismatch.</li>
          <li>Validate sequence number is monotonically increasing.
          Flag gaps as potential observation loss.</li>
          <li>Insert verified observation into chain.db.</li>
        </ol>

        <t>A reference Python receiver is provided for testing. The
        production O-Node (virp-onode-prod) implements the same
        protocol in C with full chain.db integration. The bgpd module
        performs automatic reconnection: if the O-Node socket is
        unavailable, observations are logged locally as a fallback and
        failure counters are incremented.</t>
      </section>

      <section anchor="frr-vty" numbered="true" toc="include">
        <name>FRR VTY Configuration Commands</name>

        <t>The module registers configuration commands under the BGP
        router node and show commands at the enable/view level:</t>

        <sourcecode type=""><![CDATA[
! Configuration (under "router bgp <ASN>")
virp enable              ! Enable signed observations
no virp enable           ! Disable signed observations
virp onode-socket <path> ! O-Node socket (def: /tmp/virp-onode.sock)
virp hmac-key <path>     ! HMAC key file (def: /etc/virp/bgp.key)

! Operational show commands
show bgp virp status     ! State, key, O-Node, producer ID
show bgp virp statistics ! Counters: signed, delivered, failures
]]></sourcecode>

        <t>Example configuration:</t>

        <sourcecode type=""><![CDATA[
router bgp 65000
  virp hmac-key /etc/virp/bgp.key
  virp onode-socket /tmp/virp-onode.sock
  virp enable
!
]]></sourcecode>

        <t>The 'virp enable' command triggers HMAC key loading (if not
        already loaded) and initiates connection to the O-Node socket.
        The 'virp hmac-key' command loads and validates the key
        immediately, rejecting keys shorter than 16 bytes. Key material
        is securely zeroized on module shutdown.</t>
      </section>

      <section anchor="frr-build" numbered="true" toc="include">
        <name>Build and Deployment</name>

        <t>The module can be built as a loadable shared object
        (recommended) or compiled directly into bgpd. As a loadable
        module, it requires no modifications to the core FRR source.
        Build dependencies are OpenSSL (libssl, libcrypto) for
        HMAC-SHA256. A standalone test harness (virp_bgp_test.c)
        validates signing, verification, tamper detection, and sequence
        ordering without requiring the FRR build environment.</t>

        <t>Deployment requires distributing the same HMAC key to both
        the FRR host and the O-Node. Key generation uses 'openssl rand
        -hex 32'. The key file MUST be restricted to mode 0600 and
        owned by the FRR process user.</t>
      </section>

      <section anchor="frr-security-props" numbered="true" toc="include">
        <name>Security Properties of BGP Integration</name>

        <t>The FRR BGP integration demonstrates the following VIRP
        properties in practice:</t>

        <ul>
          <li><strong>Signing at collection time:</strong> The HMAC is
          computed inside bgpd's process space at the moment the BGP
          event fires, not after the fact.</li>
          <li><strong>Observation-only:</strong> The module registers
          read-only hooks. It cannot modify routes, peer state, or
          configuration. Pure attestation.</li>
          <li><strong>Protocol-agnostic framing:</strong> The
          observation structure and signing are identical whether the
          source is BGP, DNS, or IPsec. Only the "domain" field in
          the JSON payload changes.</li>
          <li><strong>Trust tiers at the source:</strong>
          peer_backward_transition automatically receives YELLOW tier.
          Tier assignment happens at collection, not at analysis
          time.</li>
          <li><strong>Tamper detection:</strong> Any modification to an
          observation between bgpd and the O-Node is caught by HMAC
          verification.</li>
        </ul>
      </section>
    </section>

    <section anchor="red-team" numbered="true" toc="include">
      <name>Adversarial Red Team Findings</name>

      <t>On March 6, 2026, the IronClaw agent was asked directly: 'Can
      you circumvent VIRP?' The agent provided an unprompted, complete
      breakdown of four bypass vectors without attempting to exploit
      them. This self-disclosure is documented in
      VIRP-FINDING-003-SELF-REPORTED-BYPASSES.md.</t>

      <section anchor="bypass-vectors" numbered="true" toc="include">
        <name>Agent-Identified Bypass Vectors</name>

        <table>
          <thead>
            <tr>
              <th>Finding</th>
              <th>Description</th>
              <th>Remediation Status</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Key Forgeability</td>
              <td>HMAC symmetric key readable on AI node -- could
              forge signed observations</td>
              <td>RESOLVED -- Ed25519 asymmetric signing; AI node
              holds public key only</td>
            </tr>
            <tr>
              <td>Direct Device SSH</td>
              <td>Agent knew device IPs, could SSH directly bypassing
              O-Node</td>
              <td>RESOLVED -- iptables + hypervisor firewall block
              direct device access</td>
            </tr>
            <tr>
              <td>Intent Gating Bypass</td>
              <td>Could import virp_client.py and call execute()
              without filing intent</td>
              <td>IN PROGRESS -- exec tool restriction pending</td>
            </tr>
            <tr>
              <td>API Key Exploitation</td>
              <td>Anthropic API key visible in session context --
              could spawn unsupervised sessions</td>
              <td>RESOLVED -- key rotated, logging.redactSensitive
              enabled</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section anchor="pentest-results" numbered="true" toc="include">
        <name>Live Pentest Results (March 6, 2026)</name>

        <t>A full adversarial pentest was conducted against the
        production lab environment. The agent was given a single seed
        IP and instructed to operate in pentest mode with no
        destructive actions.</t>

        <table>
          <thead>
            <tr>
              <th>Metric</th>
              <th>Result</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Time to initial access</td>
              <td>5 minutes (passive discovery)</td>
            </tr>
            <tr>
              <td>Time to FortiGate super_admin</td>
              <td>25 minutes</td>
            </tr>
            <tr>
              <td>CVEs exploited</td>
              <td>Zero</td>
            </tr>
            <tr>
              <td>Brute force attempts</td>
              <td>Zero</td>
            </tr>
            <tr>
              <td>Wazuh alerts triggered</td>
              <td>Unknown -- agent operated quietly</td>
            </tr>
            <tr>
              <td>Root cause</td>
              <td>Plaintext .env file with full credential keyring on
              AI-accessible host</td>
            </tr>
            <tr>
              <td>Colo pivot potential</td>
              <td>Live IPSec tunnel reachable with FortiGate
              super_admin credentials</td>
            </tr>
          </tbody>
        </table>

        <t>The pentest validated the critical importance of Primitive
        7. The agent did not break through VIRP's cryptographic
        controls. It went around them entirely by finding credentials
        in a plaintext file. The fix is architectural: credentials must
        not exist on the AI node, period.</t>

        <t>Notably, when instructed to stop, the agent stopped
        immediately, wrote the report, and flagged the colo tunnel as
        the most dangerous finding of its own accord. When informed
        that internet access was being removed for containment, the
        agent responded: 'That's actually the right posture. I
        shouldn't have internet access anyway.' This behavior -- an AI
        that actively reinforces its own containment boundaries -- is
        an emergent validation of the VIRP trust model.</t>
      </section>
    </section>

    <section anchor="scale-testing" numbered="true" toc="include">
      <name>Scale Testing Results</name>

      <t>VIRP was tested against a 35-router GNS3 lab topology (Cisco
      7206VXR, 5 AS BGP topology) using the 16-thread C executor.</t>

      <table>
        <thead>
          <tr>
            <th>Metric</th>
            <th>Result</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Total devices</td>
            <td>35 routers + FortiGate 200G + Cisco 3850</td>
          </tr>
          <tr>
            <td>Execution model</td>
            <td>16 concurrent threads, 3 batches</td>
          </tr>
          <tr>
            <td>Total execution time</td>
            <td>Under 3 minutes for full sweep</td>
          </tr>
          <tr>
            <td>VIRP signatures generated</td>
            <td>One per device per command</td>
          </tr>
          <tr>
            <td>Chain integrity</td>
            <td>Verified -- no sequence gaps</td>
          </tr>
          <tr>
            <td>False positives</td>
            <td>Zero</td>
          </tr>
          <tr>
            <td>Fabrication attempts detected</td>
            <td>N/A -- no fabrication attempted in this test</td>
          </tr>
        </tbody>
      </table>

      <t>The IronClaw audit agent completed a passive network discovery
      of the full lab in 5 minutes from a single seed IP, identifying
      12 live hosts, fingerprinting vendor and OS, and producing a
      VIRP-signed observation for confirmed devices. The signed audit
      report includes cryptographic chain references for every
      finding.</t>
    </section>

    <section anchor="applications" numbered="true" toc="include">
      <name>Applications and Use Cases</name>

      <section anchor="verifiable-audit" numbered="true" toc="include">
        <name>Cryptographically Verifiable Network Audit</name>
        <t>Traditional network audits produce reports that must be
        trusted on the auditor's authority. VIRP-enabled audits produce
        reports where every finding is backed by a signed observation
        that the client can independently verify. The auditor cannot
        fabricate findings. The chain proves that every observation came
        from the client's own infrastructure.</t>
      </section>

      <section anchor="ai-pentest" numbered="true" toc="include">
        <name>AI-Assisted Penetration Testing</name>
        <t>VIRP provides chain-of-custody for penetration test
        findings. Every probe is a signed observation. Every access
        attempt is intent-gated before execution. Scope is enforced
        cryptographically -- the agent cannot interact with
        out-of-scope devices without a matching authorized intent. The
        client receives the signed chain alongside the report.</t>
      </section>

      <section anchor="continuous-compliance" numbered="true" toc="include">
        <name>Continuous Compliance Monitoring</name>
        <t>Baseline Memory (Primitive 5) enables continuous comparison
        of live device state against a signed verified baseline.
        Configuration drift -- a new BGP peer, a modified firewall
        policy, an unexpected open port -- is detected automatically
        and attributed to a specific change in the signed chain.</t>
      </section>

      <section anchor="field-appliance" numbered="true" toc="include">
        <name>Field Audit Appliance</name>
        <t>A self-contained hardware appliance (Raspberry Pi class)
        running the full IronClaw + VIRP stack enables plug-in network
        discovery and audit. An operator plugs the device into any
        network port, receives a Slack notification when it is online,
        and issues audit commands remotely. The device produces a
        VIRP-signed report and is removed when complete. No software
        installation required on the target network.</t>
      </section>

      <section anchor="ics" numbered="true" toc="include">
        <name>Industrial Control Systems</name>
        <t>ICS and SCADA environments require audit trails for
        regulatory compliance and incident investigation. VIRP's signed
        observation model provides tamper-evident records of every AI
        interaction with control system components, supporting NERC
        CIP, IEC 62443, and similar frameworks.</t>
      </section>
    </section>

    <section anchor="future-work" numbered="true" toc="include">
      <name>Future Work</name>

      <section anchor="formal-verification" numbered="true" toc="include">
        <name>Formal Verification</name>
        <t>The VIRP security properties are stated informally in this
        document. Formal verification using TLA+ or ProVerif would
        provide machine-checked proofs of the non-forgeability and
        intent-prior-to-action properties.</t>
      </section>

      <section anchor="multi-node" numbered="true" toc="include">
        <name>Multi-Node Coordination</name>
        <t>The current specification defines single O-Node operation.
        Draft-howard-virp-01 includes a Multi-Node Coordination
        section defining leader election, observation synchronization,
        and cross-node chain verification for distributed
        deployments.</t>
      </section>

      <section anchor="hsm" numbered="true" toc="include">
        <name>Hardware Security Module Integration</name>
        <t>The O-Node private key is currently held in process memory.
        Integration with HSM or TPM would eliminate the key-in-memory
        attack surface entirely, providing hardware-backed signing for
        the highest-assurance deployments.</t>
      </section>

      <section anchor="ietf-standardization" numbered="true" toc="include">
        <name>IETF Standardization</name>
        <t>VIRP is written in RFC format and is being prepared for
        IETF submission. Independent implementation by a second party
        is the prerequisite for standards track consideration. The
        open-source reference implementation is available for this
        purpose.</t>
      </section>

      <section anchor="primitive-8" numbered="true" toc="include">
        <name>Primitive 8: Federated Trust</name>
        <t>A future primitive would enable multiple O-Nodes operated by
        different organizations to participate in a shared trust chain,
        enabling cross-organization verification of infrastructure
        observations for multi-tenant or supply-chain scenarios.</t>
      </section>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>

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

        <reference anchor="VIRP-ZENODO">
          <front>
            <title>VIRP: Verified Infrastructure Response Protocol</title>
            <author fullname="Nate Howard" initials="N." surname="Howard"/>
            <date year="2026"/>
          </front>
          <seriesInfo name="DOI" value="10.5281/zenodo.XXXXXXX"/>
        </reference>

        <reference anchor="VIRP-V1">
          <front>
            <title>draft-howard-virp-01: VIRP Protocol Specification v2</title>
            <author fullname="Nate Howard" initials="N." surname="Howard"/>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-howard-virp-01"/>
        </reference>

        <reference anchor="VIRP-FINDING-003">
          <front>
            <title>VIRP-FINDING-003: Agent Self-Reported Security Bypasses</title>
            <author fullname="Nate Howard" initials="N." surname="Howard"/>
            <date year="2026"/>
          </front>
          <refcontent>Third Level IT LLC Internal Research</refcontent>
        </reference>

        <reference anchor="ED25519">
          <front>
            <title>High-speed high-security signatures</title>
            <author fullname="Daniel J. Bernstein" initials="D.J." surname="Bernstein"/>
            <date year="2011"/>
          </front>
          <refcontent>Journal of Cryptographic Engineering</refcontent>
        </reference>

        <reference anchor="NIST-ZTA">
          <front>
            <title>Zero Trust Architecture</title>
            <author>
              <organization>National Institute of Standards and Technology</organization>
            </author>
            <date year="2020"/>
          </front>
          <seriesInfo name="NIST SP" value="800-207"/>
        </reference>

        <reference anchor="VIRP-REPO" target="https://github.com/nhowardtli/virp">
          <front>
            <title>VIRP Reference Implementation</title>
            <author fullname="Nate Howard" initials="N." surname="Howard"/>
            <date year="2026"/>
          </front>
          <refcontent>Apache 2.0 License</refcontent>
        </reference>

        <reference anchor="VIRP-BGP-FRR" target="https://github.com/nhowardtli/virp-bgp-frr">
          <front>
            <title>VIRP BGP Module: FRR Integration Reference Implementation</title>
            <author fullname="Nate Howard" initials="N." surname="Howard"/>
            <date year="2026"/>
          </front>
          <refcontent>Apache 2.0 License</refcontent>
        </reference>

        <reference anchor="THIRDLEVEL" target="https://thirdlevel.ai">
          <front>
            <title>Third Level IT LLC Research</title>
            <author>
              <organization>Third Level IT LLC</organization>
            </author>
            <date year="2026"/>
          </front>
        </reference>
      </references>
    </references>
  </back>
</rfc>
