Back to docs
Implemented · May 2026

Attestation Protocol

Cryptographic proof that consequence evaluation happened. Non-repudiation for agent actions.

Status: Implemented
Implementations: TypeScript (primary), Go SDK (verified interoperable)
Features: Ed25519 signing, RFC 8785 canonicalization, cross-implementation verification

Problem Statement

RecourseOS evaluates consequences of actions before execution. But there's no way to prove that evaluation happened.

Today, an agent can claim "I checked with RecourseOS and it said allow" without verification. The agent might have:

  • Lied about checking
  • Hallucinated the response
  • Skipped evaluation entirely
  • Received a different verdict than claimed

Solution: Cryptographic Attestation

Attestations provide cryptographic proof that:

  1. 1. A specific input was evaluated
  2. 2. By a specific RecourseOS instance
  3. 3. At a specific time
  4. 4. Producing a specific verdict

The killer feature is non-repudiation: agents cannot claim they checked without producing a signed artifact from RecourseOS.

Attestation Schema

interface ConsequenceAttestation {
  // Protocol version
  version: 'recourse.attestation.v1';

  // What was evaluated
  input: {
    hash: string;                    // SHA-256 of canonical input
    source: 'terraform' | 'shell' | 'mcp';
    timestamp: string;               // ISO 8601, evaluation time
  };

  // Replay/freshness protection
  nonce: string;                     // Random 128-bit value, hex-encoded
  expires_at: string;                // ISO 8601, attestation validity window

  // The evaluation result
  evaluation: {
    riskAssessment: 'allow' | 'warn' | 'escalate' | 'block';
    worstTier: 1 | 2 | 3 | 4 | 5;
    reportHash: string;              // SHA-256 of full ConsequenceReport
    mutationCount: number;
    hasUnrecoverable: boolean;
  };

  // Who evaluated
  evaluator: {
    instanceId: string;              // Unique RecourseOS instance identifier
    version: string;                 // RecourseOS version
    publicKey: string;               // PEM-encoded public key
  };

  // Cryptographic binding
  signature: string;                 // Ed25519 signature over all fields
  signatureAlgorithm: 'Ed25519';
}

Key Management

Each key exists in exactly one of five states:

StateSigningVerificationDescription
pendingMUST NOTMUST failKey generated but not yet valid
activeMAYMUST succeedKey available for signing new attestations
deprecatedMUST NOTMUST succeedKey no longer signs but attestations remain verifiable
retiredMUST NOTMUST succeedKey permanently out of rotation
compromisedMUST NOTMUST failKey cannot be trusted

Verification Model

ModelDescriptionv1?
Inline (execution)Target system refuses to execute without attestationNo
Async (audit)Actions execute, attestations logged, audit laterPartial
HybridInline for high-stakes, async otherwiseFuture
Opt-in by agentAgent decides whether to verify before proceedingYes

Why opt-in by agent for v1: RecourseOS doesn't control terraform, kubectl, or AWS CLI. It doesinfluence agent behavior through MCP. The agent's decision loop is the boundary where RecourseOS has leverage.

Threat Model

What the protocol protects against

  • Agents that fabricate or hallucinate consequence reports
  • Compromised agents that bypass evaluation entirely
  • Audit trail tampering
  • Repudiation by agent operators

What it does NOT protect against

  • Compromised RecourseOS instances (attacker can sign anything)
  • Compromised signing keys
  • Coercion (operators can force specific verdicts)
  • Out-of-band actions that skip evaluation

Honest framing: The protocol provides integrity of the evaluation chain, not correctness of the evaluation itself.

Why Attestation Matters

The shift from advisory to verifiable changes RecourseOS's security posture:

Advisory (today)

Agent: "Should I delete this bucket?"
RecourseOS: "Block: unrecoverable data loss"
Agent: *deletes bucket anyway*
Audit log: *nothing*

Verifiable (with attestation)

Agent: "Should I delete this bucket?"
RecourseOS: ConsequenceReport + Attestation(block)
Agent: *attempts to delete*
CI system: "Show attestation"
Agent: *presents block attestation*
CI system: "Attestation says block. Denied."

The attestation protocol doesn't change how evaluation works. It changes whether evaluation matters.