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.
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.
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.
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.
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 messageAOCLOrchestration control layer decisionVOLTEvidence ledger event or bundleWARDTip 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:
Failure codes
GENESIS_MISMATCHGenesis hash does not match chain IDCHAIN_HASH_MISMATCHRecomputed chain_hash does not match stored valueCHAIN_LINK_BROKENEntry does not link to its predecessorSEQ_INVALIDSequence numbers are not monotonically increasingDUPLICATE_SOURCESame source event witnessed twice in one chainTIP_MISMATCHTip hash does not match the entry at that sequenceTIP_SIGNATURE_INVALIDEd25519 signature on tip does not verifyExit 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:
Produces valid ward entries with correct hashing and uniqueness enforcement
- SHA-256 chain hashing
- Genesis hash computation
- Uniqueness constraint
- Content-free by design
Independently validates any WARD chain and produces verification results
- 5-step verification algorithm
- 7 failure reason codes
- INTACT / BROKEN / PARTIAL results
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 sequenceT2Entry modificationRecomputed chain_hash will not match stored valueT3Entry insertionprev_chain_hash will not match surrounding entriesT4Entry reorderingSequence numbers + chain hash linkage enforcedT5Full chain fabricationSigned tips published to external sinks provide independent anchoringT6Content leakage via WARDContent-free by design — only hashes and identifiers storedT7Selective witnessingCoverage metrics: compare envelope count vs chain entry countT8Full host compromiseExternal sink tips survive host destruction; meta-chain witnesses survive single-chain lossMeta-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.
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 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
| Sink | Required Env Vars | sink_ref Format |
|---|---|---|
| TSA | (none — default on) | tsa:freetsa.org#<seq> |
| GitHub | WARD_GITHUB_TOKEN, _OWNER, _REPO | github:owner/repo#tag |
| GitLab | WARD_GITLAB_TOKEN, _PROJECT_ID | gitlab:project#tag |
| S3 | WARD_S3_BUCKET | s3://bucket/ward/<chain>/<seq>.json |
| Webhook | WARD_WEBHOOK_URL | webhook:<hash>#<seq> |
| Gitea | WARD_GITEA_URL, _TOKEN | gitea: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
The fourth draft: WARD is at the IETF
The audit that found a real defect, the fix, and the filing.
Read the articleWe read the code behind a dozen self-improving agents
Nine of ten could not prove their own history was untampered. WARD exists for exactly this.
Read the articleBuilding the fourth protocol
Why evidence needs a witness that never sees the content.
Read the article