Get started
PROTOCOLSTABLEOPEN SPEC

Write-once Append-only Receipt Digests

Content-free hash-chain witnesses for AEE, AOCL, and VOLT events. Tamper-evident receipts that prove the record of an event is intact, and when it was made, without storing what it said.

WARD protocol explainer. Content-free hash-chain witnessing, open specification.

SHA-256
Hash Chains
6 Sinks
External Publication
RFC 3161
Timestamp Authority
Content-Free
By Design

Why WARD?

VOLT records what happened. WARD witnesses that it was recorded. WARD produces tamper-evident receipts — hash-chain entries that reference events by ID and payload hash, but never store the event content.

✗ Evidence can be rewritten wholesale
✓ WARD chain hashes detect any modification
✗ No independent proof events existed
✓ Signed tips published to external sinks
✗ Witnessing stores sensitive content
✓ Content-free by design — only hashes and IDs
✗ Single chain, single point of failure
✓ Meta-chains witness tips from multiple chains

What stops an agent going around this?

The honest line on the homepage invites this question, so here is the answer in full, layer by layer.

Reach: what Quox holds, the agent never holds. Credentials live in the vault, not in the agent. When a tool call needs a key or a token, the platform resolves it server-side and makes the call; the model receives the result, never the secret.

Host access works the same way: QuoxBastion holds the keys and speaks to named hosts on the agent's behalf. This claim is scoped to what you place in Quox's custody: a secret that reaches an agent through some other channel, a prompt, a file, an environment variable, was never inside the boundary, and the edge below is about exactly that.

Breadth: inside its reach, an agent acts within a scope, not a blank cheque. Governed execution is deny-by-default: the tools an agent may call are the tools you named, risky steps wait for a human in the approval inbox, and a refusal is recorded exactly like a success.

Within Quox-mediated execution, an action cannot skip the approval and recording controls: the same door that runs it is the door that writes it down.

The edge, stated plainly: the boundary is as wide as what you place behind it. A credential handed to an agent directly, outside Quox, is outside the record, and no product can honestly claim otherwise.

That is a deployment choice, not a technical footnote: put the credentials that matter behind the vault and the path around governance is not a disobedient agent, it is a human deciding to arm one. WARD will not have seen it, and WARD will never pretend it did.

One precision note for auditors, since it is the next question: the chain is tamper-evident proof that Quox recorded the governed request, decision and result, in sequence, unmodified since. It does not independently prove an external system's final state; pair it with that system's own records when the question is "and did the world change accordingly".

Payloads are encrypted at rest and only their hashes ride the chain, so verifying payload content requires the operator's decryption; verifying the integrity of the record itself can be done without trusting us. The full construction is below on this page.

The longer version, including why we answer this in public: What Stops an AI Agent Going Around Its Governance?

Content-free design

WARD's defining property: entries reference source events only by identifier and payload hash. No message content, no payloads, no secrets, no PII.

// What WARD stores (receipt)
{ source_kind: "AEE",
source_id: "ENV_20260308_A1B2C3",
payload_hash: "a1b2c3...64 hex chars",
chain_hash: "linked to previous entry" }
// What WARD does NOT store
// No message text, no payloads, no attachments, no secrets

This separation means WARD databases can be shared, audited, and published without leaking operational data. The content lives in VOLT; the proof of existence lives in WARD.

Chain structure

Every WARD chain starts with a deterministic genesis hash derived from the chain ID. Each entry links to its predecessor via chain_hash, forming an append-only sequence.

genesis_hash = SHA-256("WARD-GENESIS|" + chain_id)
chain_hash = SHA-256(prev_chain_hash | chain_id | seq | ward_entry_id | timestamp | source_kind | source_id | payload_hash)
genesisentry #1entry #2entry #3...head

Chain IDs follow a scoping convention: ward:org/quox/env/production, ward:meta/quox-global. Each entry includes 11 required fields and 3 optional fields.

Source kinds

WARD defines five source kinds, covering the full Quox protocol family and external events:

AEEAgent Envelope Exchange message
AOCLOrchestration control layer decision
VOLTEvidence ledger event or bundle
WARDTip from another chain (meta-chain)
EXTERNALAny non-Quox event (webhooks, external logs)

Implementations must reject entries with unrecognised source kinds. Different chains may independently witness the same source event, but within a single chain the combination of (chain_id, source_kind, source_id) must be unique.

Verification

A WARD verifier walks the chain in 5 steps, producing an INTACT, BROKEN, or PARTIAL result:

1
Genesis
Verify first entry links to the computed genesis hash for the chain ID
2
Chain Hashes
Recompute each entry's chain_hash from its inputs and confirm it matches
3
Linkage
Verify each entry's prev_chain_hash matches the previous entry's chain_hash
4
Ordering & Uniqueness
Confirm seq starts at 1, increments by 1, no gaps, no duplicate sources
5
Tips & Signatures
Verify tip chain hashes match entries, validate Ed25519 signatures if present

Failure codes

GENESIS_MISMATCHGenesis hash does not match chain ID
CHAIN_HASH_MISMATCHRecomputed chain_hash does not match stored value
CHAIN_LINK_BROKENEntry does not link to its predecessor
SEQ_INVALIDSequence numbers are not monotonically increasing
DUPLICATE_SOURCESame source event witnessed twice in one chain
TIP_MISMATCHTip hash does not match the entry at that sequence
TIP_SIGNATURE_INVALIDEd25519 signature on tip does not verify

Exit codes: 0 = INTACT, 1 = BROKEN, 2 = ERROR, 3 = PARTIAL.

Tips & signing

Tips are periodic checkpoints that snapshot chain state at a given sequence number. They provide anchoring points for external verification.

Periodic creation

Create tips every N entries, at time boundaries, or before sealing a chain.

Ed25519 signing

Sign tips with Ed25519 for non-repudiation. Signature is over the tip_chain_hash hex bytes.

External sinks

Publish signed tips to Gitea tags, S3 Object Lock, or any append-only store. The sink_ref field records where.

Conformance levels

WARD defines three conformance levels, each building on the previous:

WARD-WWitness

Produces valid ward entries with correct hashing and uniqueness enforcement

  • SHA-256 chain hashing
  • Genesis hash computation
  • Uniqueness constraint
  • Content-free by design
WARD-VVerifier

Independently validates any WARD chain and produces verification results

  • 5-step verification algorithm
  • 7 failure reason codes
  • INTACT / BROKEN / PARTIAL results
WARD-TTipper

Creates periodic checkpoints with optional Ed25519 signing and external sink publishing

  • Tip creation at chain head
  • Optional Ed25519 signing
  • Optional sink publishing (Gitea, S3)

Threat model

WARD provides tamper-evidence, not tamper-prevention. An adversary with full host access can destroy data, but they cannot modify the chain without detection.

T1Entry deletionChain hash breaks at gap — verifier detects missing sequence
T2Entry modificationRecomputed chain_hash will not match stored value
T3Entry insertionprev_chain_hash will not match surrounding entries
T4Entry reorderingSequence numbers + chain hash linkage enforced
T5Full chain fabricationSigned tips published to external sinks provide independent anchoring
T6Content leakage via WARDContent-free by design — only hashes and identifiers stored
T7Selective witnessingCoverage metrics: compare envelope count vs chain entry count
T8Full host compromiseExternal sink tips survive host destruction; meta-chain witnesses survive single-chain loss

Meta-chains

A meta-chain is a WARD chain that witnesses tips from other WARD chains, creating a chain-of-chains. This provides a single point of verification for an entire deployment.

ward:org/quox/env/production ── tip #42 ──┐
ward:org/quox/env/staging ── tip #18 ──┤
ward:org/quox/env/dev ── tip #7 ──┤
└───▶ ward:meta/quox-global
source_id format: "ward:org/quox/env/production::42" (double colon)

One signed meta-chain tip proves the state of all sub-chains at that point in time — without publishing individual tips for each.

External Publication

WARD tips are signed checkpoints — but without external publication, they exist only in the local database. External publication sends signed tip hashes to independent third-party systems, proving the chain state existed at a specific time without trusting Quox.

Pluggable Sink Architecture

WARD uses a pluggable sink registry. Each sink is a backend that receives signed tips. Multiple sinks can be active simultaneously — a tip published to both RFC 3161 TSA and GitHub has two independent proof sources.

RFC 3161 TSA
Default. Internet standard timestamp.
DEFAULT (zero config)
GitHub
Annotated tags in a repo.
GitLab
Tags via GitLab API.
S3 Object Lock
WORM storage in AWS.
Webhook
POST to any URL.
Gitea
Tags in Gitea repos.

RFC 3161 Timestamps

The default sink sends each tip's tip_chain_hash to an RFC 3161 Time Stamping Authority (TSA). The TSA returns a cryptographic timestamp receipt (tsr_base64) proving the hash existed at that exact moment. This is an internet standard — any auditor can verify with openssl ts -verify.

Default TSA: freetsa.org (free, public, no account needed). Override with WARD_TSA_URL for private TSA servers.

Sink Configuration

SinkRequired Env Varssink_ref Format
TSA(none — default on)tsa:freetsa.org#<seq>
GitHubWARD_GITHUB_TOKEN, _OWNER, _REPOgithub:owner/repo#tag
GitLabWARD_GITLAB_TOKEN, _PROJECT_IDgitlab:project#tag
S3WARD_S3_BUCKETs3://bucket/ward/<chain>/<seq>.json
WebhookWARD_WEBHOOK_URLwebhook:<hash>#<seq>
GiteaWARD_GITEA_URL, _TOKENgitea:owner/repo#tag

Public Verification Endpoint

Any third party can verify a WARD chain's integrity without authentication:

GET /public/verify/ward/<chain_id>

Response:
{
  "status": "INTACT",
  "entry_count": 30787,
  "tips_verified": 307,
  "signatures_verified": 307,
  "sinks_published": { "tsa": 307 },
  "public_key_pem": "-----BEGIN PUBLIC KEY-----\n..."
}

Rate-limited to 10 requests per minute per IP. Give your auditor this URL — they verify the chain without a Quox account.

Visual Overview

Publishing Backfill

Existing tips that were created before external publication was enabled can be backfilled:

POST /ward/tips/publish-all
{ "chain_id": "ward:org/quox/env/production" }

→ { "ok": true, "published": 307, "total_unpublished": 307 }

Open Specification

WARD completes the Quox protocol family as the fourth open specification, alongside AEE, AOCL, and VOLT. The specification covers 22 sections including chain structure, cryptographic primitives, verification algorithm, conformance levels, and threat model. It is a live IETF Internet-Draft (draft-cowles-ward-00), filed 2026-08-31.

1,626 lines of xml2rfc v3 XML. Normative references: RFC 2119, 8174, 8259, 3629, 6234. Informative references: RFC 8032, 9562, and the three companion Quox protocol specifications.

From the blog