Skip to main content

Write-once Append-only Receipt Digests (WARD): A Content-Free Hash-Chain Witnessing Protocol for Agentic AI Systems
draft-cowles-ward-00

Document Type Active Internet-Draft (individual)
Author Adam Cowles
Last updated 2026-08-31
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-cowles-ward-00
Independent Submission                                         A. Cowles
Internet-Draft                                                  Quox Ltd
Intended status: Experimental                             31 August 2026
Expires: 4 March 2027

Write-once Append-only Receipt Digests (WARD): A Content-Free Hash-Chain
               Witnessing Protocol for Agentic AI Systems
                          draft-cowles-ward-00

Abstract

   Write-once Append-only Receipt Digests (WARD) defines a minimal,
   interoperable protocol for producing tamper-evident, content-free
   hash-chain witnesses over events from agentic AI systems.  WARD
   observes events from companion protocols (Agent Envelope Exchange
   (AEE) messages, Agent Orchestration Control Layers (AOCL) decisions,
   and Verifiable Operations Ledger and Trace (VOLT) evidence records)
   and produces cryptographically linked receipts that prove specific
   events existed at specific points in time, without storing any event
   content.

   WARD entries record only source identifiers and payload hashes, never
   raw payloads, secrets, or personally identifiable information.
   Entries are linked via SHA-256 hash chains anchored by deterministic
   genesis hashes.  Periodic checkpoints called "tips" may be signed
   with Ed25519 and published to external append-only stores (sinks) for
   independent verification.  A meta-chain pattern allows witnessing
   tips from multiple sub-chains, providing deployment-wide integrity
   from a single verification point.

   The protocol is designed as a passive observer: witnessing never
   blocks, delays, or modifies the source event pipeline.  WARD failures
   are logged but never disrupt AEE transport, AOCL decisions, or VOLT
   recording.  This fire-and-forget integration model ensures that
   witnessing adds tamper-evidence guarantees without introducing
   operational risk.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

Cowles                    Expires 4 March 2027                  [Page 1]
Internet-Draft                WARD Protocol                  August 2026

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 4 March 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Conventions and Definitions . . . . . . . . . . . . . . . . .   4
   3.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   5
   4.  Design Constraints  . . . . . . . . . . . . . . . . . . . . .   5
     4.1.  Content-Free by Design  . . . . . . . . . . . . . . . . .   5
     4.2.  One-Way Observation . . . . . . . . . . . . . . . . . . .   6
     4.3.  Minimal Schema, Extensible Evolution  . . . . . . . . . .   6
     4.4.  Deterministic and Reproducible  . . . . . . . . . . . . .   6
   5.  Transport and Encoding  . . . . . . . . . . . . . . . . . . .   6
   6.  Canonicalization  . . . . . . . . . . . . . . . . . . . . . .   6
   7.  Cryptographic Primitives  . . . . . . . . . . . . . . . . . .   8
     7.1.  Hash Algorithm  . . . . . . . . . . . . . . . . . . . . .   8
     7.2.  Hash Encoding . . . . . . . . . . . . . . . . . . . . . .   8
     7.3.  Genesis Hash  . . . . . . . . . . . . . . . . . . . . . .   8
     7.4.  Chain Hash  . . . . . . . . . . . . . . . . . . . . . . .   8
     7.5.  Signatures  . . . . . . . . . . . . . . . . . . . . . . .   9
   8.  Identifiers and Time  . . . . . . . . . . . . . . . . . . . .   9
     8.1.  Identifiers . . . . . . . . . . . . . . . . . . . . . . .   9
     8.2.  Timestamps  . . . . . . . . . . . . . . . . . . . . . . .  10
   9.  Ward Entry Schema . . . . . . . . . . . . . . . . . . . . . .  10
     9.1.  Required Fields . . . . . . . . . . . . . . . . . . . . .  10
     9.2.  Optional Fields . . . . . . . . . . . . . . . . . . . . .  11
     9.3.  Entry Example . . . . . . . . . . . . . . . . . . . . . .  12
     9.4.  Uniqueness Constraint . . . . . . . . . . . . . . . . . .  12
     9.5.  Sequence Ordering . . . . . . . . . . . . . . . . . . . .  13
   10. Source Kinds  . . . . . . . . . . . . . . . . . . . . . . . .  13
   11. Ward Chain Descriptor . . . . . . . . . . . . . . . . . . . .  13
   12. Tips and Checkpointing  . . . . . . . . . . . . . . . . . . .  14

Cowles                    Expires 4 March 2027                  [Page 2]
Internet-Draft                WARD Protocol                  August 2026

     12.1.  Tip Schema . . . . . . . . . . . . . . . . . . . . . . .  14
     12.2.  When to Create Tips  . . . . . . . . . . . . . . . . . .  15
     12.3.  Tip Signing  . . . . . . . . . . . . . . . . . . . . . .  15
     12.4.  Tip Sinks  . . . . . . . . . . . . . . . . . . . . . . .  16
     12.5.  Tip Example  . . . . . . . . . . . . . . . . . . . . . .  16
   13. Witnessing Rules  . . . . . . . . . . . . . . . . . . . . . .  17
     13.1.  What to Witness  . . . . . . . . . . . . . . . . . . . .  17
     13.2.  What NOT to Witness  . . . . . . . . . . . . . . . . . .  17
     13.3.  Witness Timing . . . . . . . . . . . . . . . . . . . . .  18
     13.4.  Selective Witnessing . . . . . . . . . . . . . . . . . .  18
     13.5.  Per-Protocol Witnessing Guidance . . . . . . . . . . . .  18
   14. Chain Lifecycle . . . . . . . . . . . . . . . . . . . . . . .  18
     14.1.  Chain Creation . . . . . . . . . . . . . . . . . . . . .  18
     14.2.  Appending Entries  . . . . . . . . . . . . . . . . . . .  19
     14.3.  Chain Sealing  . . . . . . . . . . . . . . . . . . . . .  19
   15. Meta-Chain Pattern  . . . . . . . . . . . . . . . . . . . . .  19
     15.1.  How Meta-Chains Work . . . . . . . . . . . . . . . . . .  19
     15.2.  Meta-Chain Source Identifier Format  . . . . . . . . . .  20
     15.3.  Why Meta-Chains Exist  . . . . . . . . . . . . . . . . .  20
   16. Verification  . . . . . . . . . . . . . . . . . . . . . . . .  20
     16.1.  What Verification Guarantees . . . . . . . . . . . . . .  20
     16.2.  What Verification Does NOT Guarantee . . . . . . . . . .  21
     16.3.  Verification Algorithm . . . . . . . . . . . . . . . . .  21
     16.4.  Failure Reason Codes . . . . . . . . . . . . . . . . . .  22
     16.5.  Verification Result Statuses . . . . . . . . . . . . . .  23
     16.6.  Verification Result Examples . . . . . . . . . . . . . .  24
     16.7.  CLI Exit Codes . . . . . . . . . . . . . . . . . . . . .  24
   17. Conformance Levels  . . . . . . . . . . . . . . . . . . . . .  25
     17.1.  WARD-W (Witness) . . . . . . . . . . . . . . . . . . . .  25
     17.2.  WARD-V (Verifier)  . . . . . . . . . . . . . . . . . . .  25
     17.3.  WARD-T (Tipper)  . . . . . . . . . . . . . . . . . . . .  25
   18. Storage Guidance  . . . . . . . . . . . . . . . . . . . . . .  25
     18.1.  SQLite (Single-Node) . . . . . . . . . . . . . . . . . .  25
     18.2.  PostgreSQL (Multi-Node)  . . . . . . . . . . . . . . . .  26
   19. Threat Model  . . . . . . . . . . . . . . . . . . . . . . . .  26
     19.1.  Threats WARD Mitigates . . . . . . . . . . . . . . . . .  26
     19.2.  Threats WARD Does Not Fully Mitigate . . . . . . . . . .  27
   20. Compatibility with AEE, AOCL, and VOLT  . . . . . . . . . . .  27
   21. Security Considerations . . . . . . . . . . . . . . . . . . .  28
   22. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  29
   23. References  . . . . . . . . . . . . . . . . . . . . . . . . .  30
     23.1.  Normative References . . . . . . . . . . . . . . . . . .  30
     23.2.  Informative References . . . . . . . . . . . . . . . . .  30
   Appendix A.  Legacy Version 0.1 Chain Hash  . . . . . . . . . . .  31
   Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . .  32
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  32

Cowles                    Expires 4 March 2027                  [Page 3]
Internet-Draft                WARD Protocol                  August 2026

1.  Introduction

   Evidence systems for autonomous AI agents need an independent
   witness.  Even a well-designed audit trail, such as the hash-chained
   traces produced by the VOLT protocol [VOLT], can be rewritten if an
   attacker controls the host and no external checkpoints exist.
   Operators need a way to answer questions such as:

   *  "Was this AEE envelope witnessed before it was disputed?"

   *  "Does the AOCL decision hash match what was recorded at the time?"

   *  "Has anyone tampered with the VOLT evidence bundle since it was
      created?"

   *  "Can we prove chain state at a point in time to an external
      auditor?"

   WARD answers these questions without storing a single byte of event
   content.  It maintains a separate, content-free hash chain that
   observes events from the Agent Envelope Exchange (AEE) [AEE], Agent
   Orchestration Control Layers (AOCL) [AOCL], and VOLT [VOLT]
   protocols, producing tamper-evident receipts that can be verified
   independently.

   The key design principle is separation of concerns.  AEE defines how
   agents communicate.  AOCL defines how they are controlled.  VOLT
   proves what happened.  WARD proves that the proof has not been
   tampered with.  Each protocol operates independently; WARD adds a
   witnessing layer without requiring changes to the protocols it
   observes.

   WARD is intentionally minimal.  A conformant witness implementation
   requires only SHA-256 hashing, append-only storage, and the ability
   to receive (source_kind, source_id, payload_hash) tuples.  Optional
   features (Ed25519 tip signing, external sink publication, and meta-
   chains) provide progressively stronger guarantees for deployments
   that require them.

2.  Conventions and Definitions

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in BCP
   14 [RFC2119] [RFC8174] when, and only when, they appear in ALL
   CAPITALS, as shown here.

Cowles                    Expires 4 March 2027                  [Page 4]
Internet-Draft                WARD Protocol                  August 2026

3.  Terminology

   Witness  The act of observing a source event and recording a content-
      free receipt.

   Ward Entry  A single receipt in the chain, referencing a source event
      by kind, identifier, and payload hash, but never storing the
      source content.

   Ward Chain  An append-only sequence of ward entries linked by chain
      hashes.

   Chain Hash  A deterministic SHA-256 hash linking each entry to its
      predecessor, computed over the canonical JSON of the entry's hash
      body.

   Genesis Hash  A deterministic SHA-256 hash derived from the chain
      identifier, anchoring the chain's origin.

   Tip  A periodic checkpoint summarizing chain state at a given
      sequence number.  Tips may be signed and published to external
      sinks.

   Meta-chain  A WARD chain that witnesses tips from other WARD chains,
      creating a chain-of-chains.

   Source Event  The AEE envelope, AOCL decision, VOLT transition, or
      external event being witnessed.

   Payload Hash  The SHA-256 digest of the source event's canonical
      content, computed by the caller and passed to WARD.

   Sink  An external append-only store where tips are published (e.g.,
      Gitea signed tags, S3 Object Lock).

   Source Kind  An enumerated value identifying the type of source
      event: AEE, AOCL, VOLT, WARD, or EXTERNAL.

4.  Design Constraints

4.1.  Content-Free by Design

   Ward entries MUST NOT store source event content, payloads, or
   attachments.  Ward entries MUST reference source events only by
   identifier and payload hash.  This constraint is non-negotiable and
   constitutes WARD's defining property.  An implementation that stores
   event content is not a WARD implementation.

Cowles                    Expires 4 March 2027                  [Page 5]
Internet-Draft                WARD Protocol                  August 2026

4.2.  One-Way Observation

   WARD MUST be a passive observer.  Witnessing MUST NOT block, delay,
   or modify the source event pipeline.  WARD failures MUST NOT disrupt
   AEE transport, AOCL decisions, or VOLT recording.  This fire-and-
   forget integration model ensures that witnessing adds guarantees
   without introducing operational risk.

4.3.  Minimal Schema, Extensible Evolution

   Every ward entry MUST include a ward_version field.  Unknown fields
   MUST be ignored by verifiers to ensure forward compatibility.
   Breaking changes MUST increment ward_version; while the major version
   is 0, a minor increment MAY be a breaking change (the standard pre-
   1.0 convention).  The ward_version value stored in each entry selects
   the chain hash scheme a verifier MUST apply to that entry (see
   Section 7.4).

4.4.  Deterministic and Reproducible

   All hashes MUST be deterministically reproducible from the same
   inputs.  No randomness is permitted in hash computation; only
   identifier generation may use random sources.

5.  Transport and Encoding

   Ward entries are JSON objects [RFC8259].  All JSON MUST be encoded as
   UTF-8 [RFC3629].  The storage format is implementation-defined;
   common choices include SQLite rows, PostgreSQL tables, and NDJSON
   files.

   WARD does not define a transport protocol.  Implementations receive
   source event references via implementation-specific mechanisms
   (function calls, IPC, HTTP endpoints, message queues).  The protocol
   specifies only the data model, hash computation, and verification
   algorithm.

6.  Canonicalization

   This section normatively defines canonicalization profile WARD-CANON-
   1, used for every hash computed by this specification.  It aligns
   with the VOLT protocol's canonicalization [VOLT], but this document
   is authoritative for WARD.  An implementation MUST produce canonical
   byte representations as follows:

   1.  Serialize as JSON [RFC8259] with UTF-8 encoding [RFC3629] and no
       insignificant whitespace, using minimal string escaping: escape
       only the characters JSON requires (quotation mark, reverse

Cowles                    Expires 4 March 2027                  [Page 6]
Internet-Draft                WARD Protocol                  August 2026

       solidus, and control characters U+0000 to U+001F, using the two-
       character forms where defined and otherwise \u00xx with lowercase
       hexadecimal digits).  Every other character, including /, MUST
       appear literally as UTF-8; optional escapes such as \/ are non-
       canonical and MUST NOT be produced.  This makes the serialization
       of any given string unique.

   2.  Object keys MUST be sorted lexicographically by their UTF-8 byte
       sequences, compared byte by byte as unsigned values, at every
       nesting level.  This differs from UTF-16 code-unit order for
       supplementary-plane characters (U+E000 sorts before U+10000 in
       UTF-8 byte order); sorting by a language's native string
       comparison is not conformant unless it matches UTF-8 byte order.

   3.  Strings MUST be well-formed Unicode (no unpaired surrogates) and
       MUST already be in Normalization Form C.  Canonicalization MUST
       reject, not repair, a string that is not well-formed or not in
       NFC, so the stored form and the hashed form are byte-identical
       and two visually identical but differently-normalized identifiers
       cannot silently hash to the same commitment.

   4.  Integers MUST be within the range +/-(2^53 - 1) and serialized in
       exact decimal form: no leading zeros, no plus sign, no fraction
       part, no exponent.  Values outside that range, and non-integer
       numbers, MUST be rejected wherever this specification calls for
       an integer.

   5.  A parser feeding canonicalization or verification MUST reject
       JSON objects containing duplicate member names; last-wins or
       first-wins acceptance would allow one byte sequence to carry two
       different assertions.

   Canonicalization is used when computing payload hashes over source
   events and when computing chain hashes over entry fields.  WARD's own
   hash bodies contain no non-integer numbers, and this profile
   deliberately defines no serialization for them: a caller computing a
   payload hash over a source event containing non-integer numbers MUST
   define and document its own canonical number form, and WARD treats
   the resulting payload hash as an opaque commitment either way.
   Future revisions that change any of these rules will define a new
   named profile; ward_version binds each entry to the profile in force
   when it was written.

Cowles                    Expires 4 March 2027                  [Page 7]
Internet-Draft                WARD Protocol                  August 2026

7.  Cryptographic Primitives

7.1.  Hash Algorithm

   All hashing in WARD v0.2 MUST use SHA-256 [RFC6234] [FIPS180-4].

7.2.  Hash Encoding

   Hash values MUST be encoded as lowercase hexadecimal strings of 64
   characters (256 bits).

7.3.  Genesis Hash

   The genesis hash anchors a chain's origin deterministically:

   genesis_hash = SHA-256("WARD-GENESIS|" + chain_id)

   The input is the literal UTF-8 string WARD-GENESIS| concatenated with
   the chain_id.  The genesis hash serves as prev_chain_hash for the
   first entry (seq = 1).  Unlike the chain hash, this construction is
   not exposed to delimiter ambiguity: the input has exactly one
   variable field after a fixed literal prefix, so no two distinct
   inputs can collide by boundary confusion.

7.4.  Chain Hash

   Each entry's chain_hash links it to its predecessor.  It is computed
   over the canonical JSON (see Section 6) of the entry's hash body: the
   ten required fields of the entry schema excluding chain_hash itself.

   hash_body  = { chain_id, issuer_id, payload_hash,
                  prev_chain_hash, seq, source_id, source_kind,
                  ward_entry_id, ward_version, witnessed_at }

   chain_hash = SHA-256(canonical_json(hash_body))

   The hash body MUST contain exactly these ten members: no extras, none
   absent, none null.  The seq value is hashed as a JSON integer, not a
   string.  Optional fields (source_ts, tags, sig) MUST NOT be included
   in the hash body; they are annotations, not commitments, and are not
   tamper-protected by the chain.

   Canonical JSON is used rather than delimiter concatenation because
   identifier fields carry no character-set restriction: with
   concatenation, a crafted identifier containing the delimiter
   character can make two distinct field tuples produce an identical
   hash input, so a single chain hash would commit to an ambiguous
   statement.  JSON string escaping makes field boundaries unambiguous

Cowles                    Expires 4 March 2027                  [Page 8]
Internet-Draft                WARD Protocol                  August 2026

   for every possible input.  A legacy concatenation scheme used by
   ward_version 0.1 deployments is preserved for verification only in
   Appendix A.

   Because ward_version is part of the hash body, the scheme an entry
   declares is itself tamper-protected: an attacker cannot downgrade an
   entry to the legacy scheme without breaking its hash.

7.5.  Signatures

   Signatures are OPTIONAL in WARD v0.2 but the schema reserves fields
   for them.  If used:

   *  The signature algorithm SHOULD be Ed25519 [RFC8032].

   *  Public key identifiers SHOULD be stable (DID or key fingerprint).

   *  Tips SHOULD be signed; individual entries MAY be signed.

   *  Signing every entry is permitted but not expected, as it is
      computationally expensive for most deployments.

   When signing a tip, the signature is computed over the raw UTF-8
   bytes of the tip_chain_hash hexadecimal string.

   Key resolution and trust are deployment-defined in this version.
   This specification does not define a key-resolution mechanism, trust
   anchor, or issuer-authorization rule for key_id: a verified signature
   therefore proves possession of whichever key the deployment resolved
   for that identifier, and nothing more.  Deployments MUST document how
   key_id values resolve to keys and which keys are authorized to sign
   for a chain's issuer, and auditors SHOULD treat signature-
   verification counts as meaningful only relative to that documented
   policy.

8.  Identifiers and Time

8.1.  Identifiers

   The ward_entry_id MUST be unique within a chain.  The chain_id MUST
   be unique within a deployment.  Identifiers SHOULD be UUIDv4
   [RFC9562] or ULID.

   Chain identifiers follow a scoping convention:

   *  Per organisation/environment: ward:org/<org>/env/<env>

   *  Meta-chain: ward:meta/<deployment>

Cowles                    Expires 4 March 2027                  [Page 9]
Internet-Draft                WARD Protocol                  August 2026

   Examples: ward:org/quox/env/production, ward:org/quox/env/staging,
   ward:meta/quox-global.

   A chain_id MUST NOT contain the sequence ::, which is reserved as the
   separator in meta-chain source_id values (Section 15.2).  Identifiers
   SHOULD be limited to printable ASCII without whitespace; with
   canonical-JSON hashing this is hygiene rather than a hashing-safety
   requirement.

8.2.  Timestamps

   The witnessed_at field MUST be an ISO 8601 timestamp with UTC offset
   Z, for example 2026-03-05T14:30:00.000Z.  This records when WARD
   observed the source event, not when the source event occurred.  The
   optional source_ts field MAY carry the source event's own timestamp
   for correlation.

9.  Ward Entry Schema

   A ward entry is a JSON object with 11 REQUIRED and 3 OPTIONAL fields.

9.1.  Required Fields

   The two field groups differ in trust, not just in cardinality.  Every
   required field except chain_hash is committed: it is inside the hash
   body of Section 7.4, so the chain proves it.  Every optional field is
   an uncommitted annotation: it can be altered later without breaking
   any hash, and no claim of the form "WARD says this event was tagged
   X" is ever valid.

Cowles                    Expires 4 March 2027                 [Page 10]
Internet-Draft                WARD Protocol                  August 2026

      +=================+=========+=================================+
      | Field           | Type    | Description                     |
      +=================+=========+=================================+
      | ward_version    | string  | Protocol version (e.g., "0.2"); |
      |                 |         | selects the chain hash scheme   |
      +-----------------+---------+---------------------------------+
      | ward_entry_id   | string  | Unique identifier within the    |
      |                 |         | chain                           |
      +-----------------+---------+---------------------------------+
      | chain_id        | string  | Identifies the chain this entry |
      |                 |         | belongs to                      |
      +-----------------+---------+---------------------------------+
      | seq             | integer | Monotonically increasing,       |
      |                 |         | starting at 1                   |
      +-----------------+---------+---------------------------------+
      | witnessed_at    | string  | ISO 8601 UTC timestamp of when  |
      |                 |         | WARD observed the event         |
      +-----------------+---------+---------------------------------+
      | source_kind     | string  | Enumerated source type (see     |
      |                 |         | Section 10)                     |
      +-----------------+---------+---------------------------------+
      | source_id       | string  | Identifier of the source event  |
      +-----------------+---------+---------------------------------+
      | payload_hash    | string  | SHA-256 hex of source event's   |
      |                 |         | canonical content               |
      +-----------------+---------+---------------------------------+
      | prev_chain_hash | string  | Previous entry's chain_hash, or |
      |                 |         | genesis_hash for seq=1          |
      +-----------------+---------+---------------------------------+
      | chain_hash      | string  | This entry's computed chain     |
      |                 |         | hash (see Section 7.4)          |
      +-----------------+---------+---------------------------------+
      | issuer_id       | string  | Identifier of the WARD instance |
      |                 |         | that created this entry         |
      +-----------------+---------+---------------------------------+

              Table 1: Ward Entry Required Fields (Committed)

9.2.  Optional Fields

           +===========+========+=============================+
           | Field     | Type   | Description                 |
           +===========+========+=============================+
           | source_ts | string | ISO 8601 UTC timestamp from |
           |           |        | the source event itself     |
           +-----------+--------+-----------------------------+
           | tags      | array  | String tags for filtering   |
           |           |        | and categorisation          |

Cowles                    Expires 4 March 2027                 [Page 11]
Internet-Draft                WARD Protocol                  August 2026

           +-----------+--------+-----------------------------+
           | sig       | string | Ed25519 signature over      |
           |           |        | chain_hash (base64)         |
           +-----------+--------+-----------------------------+

             Table 2: Ward Entry Optional Fields (Uncommitted
                               Annotations)

9.3.  Entry Example

   The hash values below are real: the payload hash is the SHA-256 of a
   canonical example envelope (reproduced in the protocol repository's
   examples directory), the previous chain hash is the chain's genesis
   hash, and the chain hash recomputes from this entry's hash body under
   Section 7.4.  Long values are folded per [RFC8792].

   NOTE: '\' line wrapping per RFC 8792

   {
     "ward_version": "0.2",
     "ward_entry_id": "01WARD-E001",
     "chain_id": "ward:org/quox/env/production",
     "seq": 1,
     "witnessed_at": "2026-03-05T14:30:00.000Z",
     "source_kind": "AEE",
     "source_id": "aee-env-550e8400",
     "payload_hash": "eead9b7ee8f898c3b17f5913989ab6d048f92a1368d27f\
   9b1fad15d7bb3f45d2",
     "prev_chain_hash": "4228bb654b660969b96b84d502e1615de0ac7bffaeb\
   37c52a7007b310127f481",
     "chain_hash": "6078eafecfd309ca8aa078f4d90017f17d65e53e1c9bdf8d\
   3ac068d05ce4a1b4",
     "issuer_id": "ward-issuer-prod-01"
   }

9.4.  Uniqueness Constraint

   Within a single chain, the combination of (chain_id, source_kind,
   source_id) MUST be unique.  A chain MUST NOT contain two entries
   witnessing the same source event.  Different chains MAY independently
   witness the same source event.

Cowles                    Expires 4 March 2027                 [Page 12]
Internet-Draft                WARD Protocol                  August 2026

9.5.  Sequence Ordering

   The seq field MUST start at 1 and increase monotonically by exactly
   1.  Gaps in seq MUST NOT occur.  Implementations MUST guarantee
   atomic, gap-free sequence assignment under concurrent access using a
   mechanism appropriate to their storage (database row or advisory
   locks, serializable transactions, or a single-writer process for
   file-based stores).

10.  Source Kinds

   WARD defines five source kinds:

    +==========+======================================================+
    | Kind     | Description                                          |
    +==========+======================================================+
    | AEE      | An AEE envelope (agent-to-agent message)             |
    +----------+------------------------------------------------------+
    | AOCL     | An AOCL decision or policy evaluation                |
    +----------+------------------------------------------------------+
    | VOLT     | A VOLT trace event or bundle commitment              |
    +----------+------------------------------------------------------+
    | WARD     | A WARD tip from another chain (meta-chain pattern)   |
    +----------+------------------------------------------------------+
    | EXTERNAL | Any non-protocol event (external audit log, webhook) |
    +----------+------------------------------------------------------+

                      Table 3: Source Kind Enumeration

   Implementations MUST reject entries with unrecognised source_kind
   values.

11.  Ward Chain Descriptor

   A ward chain descriptor is a convenience object for chain management
   with 7 REQUIRED fields.  It is not part of the hash chain itself.

Cowles                    Expires 4 March 2027                 [Page 13]
Internet-Draft                WARD Protocol                  August 2026

   +=================+=========+=======================================+
   | Field           | Type    | Description                           |
   +=================+=========+=======================================+
   | chain_id        | string  | Unique chain identifier               |
   +-----------------+---------+---------------------------------------+
   | genesis_hash    | string  | SHA-256 hex, computed                 |
   |                 |         | per Section 7.3                       |
   +-----------------+---------+---------------------------------------+
   | scope           | string  | Human-readable scope                  |
   |                 |         | description                           |
   +-----------------+---------+---------------------------------------+
   | created_at      | string  | ISO 8601 UTC timestamp                |
   |                 |         | of chain creation                     |
   +-----------------+---------+---------------------------------------+
   | entry_count     | integer | Total entries in the                  |
   |                 |         | chain                                 |
   +-----------------+---------+---------------------------------------+
   | head_seq        | integer | Sequence number of the                |
   |                 |         | latest entry                          |
   +-----------------+---------+---------------------------------------+
   | head_chain_hash | string  | Chain hash of the                     |
   |                 |         | latest entry                          |
   +-----------------+---------+---------------------------------------+

                   Table 4: Ward Chain Descriptor Fields

12.  Tips and Checkpointing

   A tip is a checkpoint summarizing chain state at a point in time.

12.1.  Tip Schema

        +================+=========+==============================+
        | Field          | Type    | Description                  |
        +================+=========+==============================+
        | tip_id         | string  | Unique tip identifier        |
        +----------------+---------+------------------------------+
        | chain_id       | string  | The chain being checkpointed |
        +----------------+---------+------------------------------+
        | tip_seq        | integer | The seq of the entry being   |
        |                |         | checkpointed                 |
        +----------------+---------+------------------------------+
        | tip_chain_hash | string  | Chain hash at tip_seq        |
        +----------------+---------+------------------------------+
        | entry_count    | integer | Entries in chain up to and   |
        |                |         | including tip_seq            |
        +----------------+---------+------------------------------+
        | created_at     | string  | ISO 8601 UTC timestamp       |

Cowles                    Expires 4 March 2027                 [Page 14]
Internet-Draft                WARD Protocol                  August 2026

        +----------------+---------+------------------------------+

                        Table 5: Tip Required Fields

         +==========+========+===================================+
         | Field    | Type   | Description                       |
         +==========+========+===================================+
         | sig      | string | Ed25519 signature over            |
         |          |        | tip_chain_hash (base64)           |
         +----------+--------+-----------------------------------+
         | key_id   | string | Stable identifier for signing     |
         |          |        | key; REQUIRED when sig is present |
         +----------+--------+-----------------------------------+
         | sink_ref | string | Reference to external sink        |
         |          |        | publication                       |
         +----------+--------+-----------------------------------+
         | notes    | string | Human-readable annotation         |
         +----------+--------+-----------------------------------+

                        Table 6: Tip Optional Fields

   Tips SHOULD be signed.  Unsigned tips provide checkpoint convenience
   but weaker non-repudiation guarantees.

12.2.  When to Create Tips

   Tips SHOULD be created:

   *  Periodically (e.g., every N entries or every T minutes)

   *  At significant boundaries (end of a workflow run, end of day)

   *  Before chain sealing

12.3.  Tip Signing

   Tips SHOULD be signed with Ed25519 [RFC8032].  The signature is
   computed over the raw UTF-8 bytes of the tip_chain_hash hexadecimal
   string.  A tip carrying sig MUST also carry key_id: a signature with
   no key identifier cannot be resolved and verified, so it would be an
   annotation posing as evidence.  The key_id value SHOULD be a stable
   public key identifier (DID or key fingerprint) to enable key lookup
   during verification.

Cowles                    Expires 4 March 2027                 [Page 15]
Internet-Draft                WARD Protocol                  August 2026

12.4.  Tip Sinks

   Tips MAY be published to external stores.  Sinks differ in what they
   actually guarantee, and a deployment SHOULD document which property
   each configured sink provides:

   *  *Git signed tags*: replication plus a signature.  A repository
      administrator can delete or replace tags, so this sink protects
      against attackers without that access; deletion is detectable only
      by a verifier who already knows the tip existed.

   *  *Object storage with immutable retention* (for example S3 Object
      Lock in compliance mode): genuine write-once retention for the
      configured period.

   *  *Trusted timestamping*: an RFC 3161 authority adds third-party
      time.

   *  *Transparency services*: append-only logs with third-party
      observability, such as services implementing the SCITT
      architecture [RFC9943].  WARD does not compete with transparency
      infrastructure; a tip is a natural signed statement to register in
      it, and defining such bindings is planned work.

   The sink_ref field records where the tip was published, for example
   gitea:owner/repo#ward-tip/prod/42.  Absence of an expected tip at its
   sink_ref is itself evidence and SHOULD surface as a verification
   warning, not be silently ignored.

12.5.  Tip Example

   This tip is real: tip_chain_hash is the head of the three-entry
   example chain in the protocol repository, and sig is a genuine
   Ed25519 signature over the raw UTF-8 bytes of that hash by a
   documentation key whose seed is published (SHA-256 of the string
   WARD-EXAMPLE-KEY-v0.2; public key pDN4/
   yZmzhkKfzDCHS5uc6seNgrcnei2+cJ3liDPwrc=), so both are independently
   verifiable.  That key is for documentation only: its private half is
   public by construction.  Long values are folded per [RFC8792].

Cowles                    Expires 4 March 2027                 [Page 16]
Internet-Draft                WARD Protocol                  August 2026

   NOTE: '\' line wrapping per RFC 8792

   {
     "tip_id": "tip-stg-002",
     "chain_id": "ward:org/quox/env/staging",
     "tip_seq": 3,
     "tip_chain_hash": "88893edd241f630801a44bb4b839f85200a1e47ac38b\
   5d6ec895c85e3a937791",
     "entry_count": 3,
     "created_at": "2026-03-05T15:01:00.000Z",
     "sig": "lHFDS97QRZSwAcmtxDyJxSNDutvZLJmcQIPyX4UeKYSPK+IsVie5xWQk\
   TOrfs0ioVmQHcUPTJpZOmtM0XIOCDA==",
     "key_id": "ed25519:sha256:765fe10404e81eb5",
     "sink_ref": "https://gitea.example.com/ward-tips/tags/stg-tip-002",
     "notes": "End-of-batch tip for staging, March 5 2026"
   }

13.  Witnessing Rules

13.1.  What to Witness

   WARD witnesses references, not content:

   *  For AEE: the envelope identifier and the SHA-256 of the canonical
      envelope JSON.

   *  For AOCL: the decision identifier and the SHA-256 of the canonical
      decision JSON.

   *  For VOLT: the event identifier or bundle commitment hash, and the
      SHA-256 of the relevant object.

   *  For WARD: a tip from a sub-chain (meta-chain pattern).

   *  For EXTERNAL: a caller-provided identifier and payload hash.

13.2.  What NOT to Witness

   WARD MUST NOT witness:

   *  Raw message content or payloads

   *  Secrets, tokens, or credentials

   *  Personally identifiable information (PII)

   *  Attachment contents (reference by hash only)

Cowles                    Expires 4 March 2027                 [Page 17]
Internet-Draft                WARD Protocol                  August 2026

13.3.  Witness Timing

   WARD SHOULD witness events as soon as possible after they occur.
   WARD MUST NOT block or delay source event processing.  If witnessing
   fails, the failure MUST be logged but MUST NOT affect the source
   pipeline.

13.4.  Selective Witnessing

   Implementations MAY witness a subset of source events based on
   configuration: by source kind, by event type (e.g., only AOCL
   denials), or by tag or scope.  Selective witnessing SHOULD be
   documented in the chain's scope field.

13.5.  Per-Protocol Witnessing Guidance

   *AEE Envelopes.* Witness after the envelope is persisted or
   delivered, not while in-flight.  The payload hash is computed over
   the whole canonical envelope JSON, including its payload fields, so
   any later modification of the stored envelope is detectable.  WARD
   stores only the hash; the envelope content itself never enters the
   ward entry.

   *AOCL Decisions.* Witness after the decision is finalised and
   persisted.  Both allow and deny decisions SHOULD be witnessed.
   Implementations MAY filter to witness only terminal decisions
   (completions, rejections, bypasses) and skip layer-start events,
   which are high volume and low signal.

   *VOLT Transitions.* Witness VOLT at boundaries, not every event: VOLT
   already chains events internally.  Witness after a bundle is
   finalised or a run is completed or failed.  Individual VOLT events
   MAY also be witnessed for higher-resolution audit trails.

   *EXTERNAL Events.* The caller provides both source_id and
   payload_hash.  WARD trusts the caller's hash; it does not verify
   against the source content because it never sees the content.  This
   allows anchoring non-protocol events such as external audit logs,
   webhooks, and compliance records.

14.  Chain Lifecycle

14.1.  Chain Creation

   1.  Choose a chain_id following the conventions in Section 8.1.

   2.  Compute genesis_hash per Section 7.3.

Cowles                    Expires 4 March 2027                 [Page 18]
Internet-Draft                WARD Protocol                  August 2026

   3.  Record the ward chain descriptor.

14.2.  Appending Entries

   1.  Receive a source event reference (kind, identifier, payload
       hash).

   2.  Enforce the uniqueness constraint (Section 9.4).

   3.  Assign seq = previous seq + 1 (or 1 for the first entry).

   4.  Set prev_chain_hash to the previous entry's chain_hash (or
       genesis_hash for seq=1).

   5.  Compute chain_hash per Section 7.4.

   6.  Persist the ward entry.

   7.  Update the chain descriptor (entry_count, head_seq,
       head_chain_hash).

14.3.  Chain Sealing

   A chain MAY be sealed (made immutable).  Sealing MUST create and sign
   a final tip covering the whole chain, and SHOULD publish that tip to
   an external sink; without external publication, the seal proves
   nothing to a party who does not already trust the store.  Sealed
   chains MUST NOT accept new entries.

   Chain lifecycle states are: active (accepting entries), sealed (final
   tip signed, no new entries), and archived (moved to cold storage).

15.  Meta-Chain Pattern

   A meta-chain is a WARD chain that witnesses tips from other WARD
   chains, creating a chain-of-chains.

15.1.  How Meta-Chains Work

   1.  Create a meta-chain with identifier following
       ward:meta/<deployment>.

   2.  When a sub-chain creates a tip, witness it in the meta-chain with
       source_kind = WARD, source_id = <sub_chain_id>::<tip_seq>, and
       payload_hash = SHA-256 of the canonical tip JSON.

Cowles                    Expires 4 March 2027                 [Page 19]
Internet-Draft                WARD Protocol                  August 2026

15.2.  Meta-Chain Source Identifier Format

   The double colon (::) separates the sub-chain identifier from the tip
   sequence number:

   ward:org/quox/env/production::42

   This means: "tip at sequence 42 from chain ward:org/quox/env/
   production".  The double colon is chosen to avoid ambiguity with
   single colons in chain identifiers.

   Normative grammar: for entries with source_kind WARD, the source_id
   MUST consist of the sub-chain identifier, then ::, then the tip
   sequence as a positive decimal integer with no leading zeros.
   Because a chain identifier MUST NOT contain :: (Section 8.1),
   splitting on the first occurrence of :: is unambiguous.  A consumer
   MUST reject a WARD-kind source_id that does not match this grammar,
   including values where the separator region contains three or more
   consecutive colons.

15.3.  Why Meta-Chains Exist

   Meta-chains provide:

   *  A single chain-of-chains for a deployment

   *  Cross-chain integrity verification

   *  A single tip to publish externally instead of one per sub-chain

   *  Compact proof that multiple chains existed at a point in time

16.  Verification

16.1.  What Verification Guarantees

   A successful verification proves:

   *  The genesis hash is correctly derived from the chain identifier.

   *  Every entry's chain hash recomputes correctly from its inputs.

   *  Each entry links correctly to its predecessor.

   *  Sequence numbers are monotonically increasing with no gaps.

   *  No duplicate source events exist within the chain.

Cowles                    Expires 4 March 2027                 [Page 20]
Internet-Draft                WARD Protocol                  August 2026

   *  Tips reference valid chain state.

   *  Signatures (if present) are valid.

   In short: the chain has integrity and no entries have been modified,
   inserted, or deleted.

16.2.  What Verification Does NOT Guarantee

   Verification does not prove:

   *  The source events were truthful.

   *  The issuer was uncompromised when it created entries.

   *  The payload hashes correspond to events that still exist.

   *  The witnessed events were complete (coverage is an integration
      concern).

   WARD is a tamper-evidence protocol, not an oracle.

16.3.  Verification Algorithm

   A WARD verifier MUST execute the following six steps in order:

   *Step 0: Validate Entry Well-Formedness.* Before any hash is
   recomputed, parse each entry with a JSON parser that rejects
   duplicate member names (Section 6), validate it against the entry
   schema (all eleven required fields present, correct types, hash
   fields 64-character lowercase hexadecimal, seq within [1, 2^53 - 1],
   no null hash-body members), and, for entries declaring version 0.2 or
   later, confirm every hash-body string is well-formed Unicode in NFC
   and that chain_id does not contain :: (version 0.1 entries predate
   those rules: a violation there MUST produce a warning, not a
   failure).  Any failure produces failure code SCHEMA_INVALID.
   Skipping this step and verifying hashes alone can "verify" an entry
   whose displayed fields differ from its hashed fields.

   *Step 1: Validate Genesis.* Compute expected_genesis = SHA-256("WARD-
   GENESIS|" + chain_id).  Read the first entry (seq=1).  Confirm that
   the entry's prev_chain_hash equals expected_genesis.  Mismatch
   produces failure code GENESIS_MISMATCH.

   *Step 2: Validate Chain Hashes.* For each entry in sequence order,
   select the hash scheme from the entry's ward_version: "0.2" uses the
   canonical-JSON hash body of Section 7.4; "0.1" uses the legacy
   concatenation of Appendix A; any other value produces failure code

Cowles                    Expires 4 March 2027                 [Page 21]
Internet-Draft                WARD Protocol                  August 2026

   CHAIN_HASH_MISMATCH with a detail naming the unrecognized version.
   Recompute chain_hash under that scheme and confirm it equals the
   stored value; mismatch produces CHAIN_HASH_MISMATCH.  Declared
   ward_version values MUST be non-decreasing in seq order, compared
   numerically as (major, minor); an entry declaring a lower version
   than any earlier entry produces failure code VERSION_DOWNGRADE.  This
   makes "no new legacy entries" enforceable from stored data for
   upgraded chains.  For a chain that has never upgraded, a verifier
   reading stored data cannot distinguish a legacy entry appended
   recently from one appended before the current version existed; the
   mitigation, as for any append to a compromised chain, is externally
   published signed tips, which bound the exposure to entries after the
   most recent tip.  If a version 0.1 entry's ward_entry_id or source_id
   contains the | character, the verifier MUST append a warning to the
   result (delimiter-injection exposure, Appendix A).

   *Step 3: Validate Chain Linkage.* For each entry where seq > 1,
   confirm that the entry's prev_chain_hash equals the chain_hash of the
   entry with seq - 1.  Mismatch produces failure code
   CHAIN_LINK_BROKEN.

   *Step 4: Validate Ordering and Uniqueness.* Confirm seq starts at 1,
   increases monotonically by 1 with no gaps, and that no duplicate
   (chain_id, source_kind, source_id) tuples exist.  Sequence violation
   produces SEQ_INVALID; duplicate source produces DUPLICATE_SOURCE.

   *Step 5: Validate Tips.* For each tip, locate the entry at tip_seq
   and confirm tip_chain_hash equals that entry's chain_hash.  If sig is
   present, resolve key_id to a public key using the deployment's
   documented key-resolution policy (key resolution and trust are
   deployment-defined, see Section 7.5) and verify the Ed25519 signature
   over the tip_chain_hash hex bytes.  A valid signature proves
   possession of the resolved key, not that the key was authorized.
   Hash mismatch produces TIP_MISMATCH; signature failure produces
   TIP_SIGNATURE_INVALID.

16.4.  Failure Reason Codes

      +=======================+=====================================+
      | Code                  | Meaning                             |
      +=======================+=====================================+
      | SCHEMA_INVALID        | Entry failed Step 0 well-formedness |
      |                       | validation (schema, duplicate       |
      |                       | members, non-NFC strings, reserved  |
      |                       | "::" in chain_id)                   |
      +-----------------------+-------------------------------------+
      | VERSION_DOWNGRADE     | An entry declares a lower           |
      |                       | ward_version than an earlier entry  |

Cowles                    Expires 4 March 2027                 [Page 22]
Internet-Draft                WARD Protocol                  August 2026

      |                       | (version monotonicity)              |
      +-----------------------+-------------------------------------+
      | GENESIS_MISMATCH      | Computed genesis hash does not      |
      |                       | match entry seq=1 prev_chain_hash   |
      +-----------------------+-------------------------------------+
      | CHAIN_HASH_MISMATCH   | Recomputed chain_hash does not      |
      |                       | match stored value                  |
      +-----------------------+-------------------------------------+
      | CHAIN_LINK_BROKEN     | Entry's prev_chain_hash does not    |
      |                       | match previous entry's chain_hash   |
      +-----------------------+-------------------------------------+
      | SEQ_INVALID           | Sequence numbers are not            |
      |                       | monotonically increasing from 1     |
      +-----------------------+-------------------------------------+
      | DUPLICATE_SOURCE      | Same (chain_id, source_kind,        |
      |                       | source_id) appears more than once   |
      +-----------------------+-------------------------------------+
      | TIP_MISMATCH          | Tip's chain_hash does not match the |
      |                       | entry at tip_seq                    |
      +-----------------------+-------------------------------------+
      | TIP_SIGNATURE_INVALID | Tip signature does not verify       |
      |                       | against the declared key            |
      +-----------------------+-------------------------------------+
      | INCOMPLETE_CHAIN      | (PARTIAL) Chain verified up to a    |
      |                       | point, but later entries are        |
      |                       | unavailable                         |
      +-----------------------+-------------------------------------+

                    Table 7: Verification Failure Codes

   All codes except INCOMPLETE_CHAIN accompany the BROKEN status;
   INCOMPLETE_CHAIN accompanies PARTIAL.  Implementations MAY define
   additional reason codes; a consumer that encounters an unknown code
   MUST treat it according to the status field, never as a success.

16.5.  Verification Result Statuses

          +=========+==========================================+
          | Status  | Meaning                                  |
          +=========+==========================================+
          | INTACT  | Chain verified successfully: all hashes, |
          |         | linkage, ordering, and tips are correct  |
          +---------+------------------------------------------+
          | BROKEN  | Verification failed: at least one check  |
          |         | did not pass                             |
          +---------+------------------------------------------+
          | PARTIAL | Chain is valid up to a point but         |
          |         | incomplete                               |

Cowles                    Expires 4 March 2027                 [Page 23]
Internet-Draft                WARD Protocol                  August 2026

          +---------+------------------------------------------+

                  Table 8: Verification Result Statuses

16.6.  Verification Result Examples

   The results below are illustrative: values in angle brackets are
   placeholders describing what belongs in each field, not computed
   hashes.  Fully real, recomputable example chains and verification
   results are published in the protocol repository's examples
   directory.

   INTACT result:

   {
     "status": "INTACT",
     "chain_id": "ward:org/quox/env/production",
     "ward_version": "0.2",
     "entry_count": 1042,
     "head_seq": 1042,
     "head_chain_hash": "d4e5f6a7b8c9d0e1...a1b2c3d4",
     "genesis_verified": true,
     "tips_verified": 3,
     "signatures_verified": 2,
     "warnings": []
   }

   BROKEN result:

   {
     "status": "BROKEN",
     "chain_id": "ward:org/quox/env/production",
     "reason": "CHAIN_HASH_MISMATCH",
     "details": {
       "seq": 417,
       "ward_entry_id": "01WARD-E417",
       "expected_chain_hash": "c3d4e5f6...recomputed",
       "found_chain_hash": "ff00ff00...stored"
     }
   }

16.7.  CLI Exit Codes

   Implementations providing a command-line verifier SHOULD use the
   following exit codes:

   *  0 = INTACT

Cowles                    Expires 4 March 2027                 [Page 24]
Internet-Draft                WARD Protocol                  August 2026

   *  1 = BROKEN (verification failed)

   *  2 = ERROR (storage not readable, invalid arguments)

   *  3 = PARTIAL (chain incomplete)

17.  Conformance Levels

17.1.  WARD-W (Witness)

   An implementation is WARD-W conformant if it:

   *  Produces ward entries matching Section 9

   *  Computes genesis_hash and chain_hash correctly per Section 7

   *  Enforces the uniqueness constraint per Section 9.4

   *  Respects content-free constraints per Section 4.1

17.2.  WARD-V (Verifier)

   An implementation is WARD-V conformant if it:

   *  Implements the six-step verification algorithm per Section 16.3

   *  Produces verification results with the defined status codes and
      failure reasons

17.3.  WARD-T (Tipper)

   An implementation is WARD-T conformant if it:

   *  Creates valid tips per Section 12.1

   *  Optionally signs tips with Ed25519

   *  Optionally publishes tips to external sinks

18.  Storage Guidance

   This section is non-normative.  It provides implementation guidance
   for common storage backends.

18.1.  SQLite (Single-Node)

   SQLite with WAL mode is the recommended storage for single-node
   deployments.  The following schema is suggested:

Cowles                    Expires 4 March 2027                 [Page 25]
Internet-Draft                WARD Protocol                  August 2026

   CREATE TABLE ward_entries (
       ward_entry_id TEXT PRIMARY KEY,
       chain_id      TEXT NOT NULL,
       seq           INTEGER NOT NULL,
       witnessed_at  TEXT NOT NULL,
       source_kind   TEXT NOT NULL
         CHECK (source_kind IN
           ('AEE','AOCL','VOLT','WARD','EXTERNAL')),
       source_id     TEXT NOT NULL,
       payload_hash  TEXT NOT NULL,
       prev_chain_hash TEXT NOT NULL,
       chain_hash    TEXT NOT NULL,
       issuer_id     TEXT NOT NULL,
       ward_version  TEXT NOT NULL DEFAULT '0.2',
       source_ts     TEXT,
       tags          TEXT,
       sig           TEXT,
       UNIQUE(chain_id, seq),
       UNIQUE(chain_id, source_kind, source_id)
   );

   Storage sizing is approximately 500 bytes per SQLite row including
   indexes; 10,000 entries require approximately 5 MB.

18.2.  PostgreSQL (Multi-Node)

   For multi-node or high-availability deployments, use the same schema
   with appropriate type mappings (UUID, BIGINT, TIMESTAMPTZ, JSONB).
   Implementations SHOULD configure append-only triggers to prevent
   UPDATE and DELETE on entry rows, ensuring the write-once property at
   the storage layer.

19.  Threat Model

19.1.  Threats WARD Mitigates

   *T1: Post-Hoc Tampering.* An attacker modifies a ward entry after it
   has been recorded.  The chain hash recomputation during verification
   detects the modification (CHAIN_HASH_MISMATCH).

   *T2: Entry Deletion.* An attacker removes an entry from the middle of
   the chain.  Chain linkage breaks at the entry after the gap
   (CHAIN_LINK_BROKEN) and the sequence gap is detected (SEQ_INVALID).

   *T3: Entry Insertion.* An attacker inserts a fabricated entry.
   Unless they rehash all subsequent entries, chain linkage breaks.  If
   they do rehash, signed tips published to external sinks detect the
   discrepancy.

Cowles                    Expires 4 March 2027                 [Page 26]
Internet-Draft                WARD Protocol                  August 2026

   *T4: Backdating.* An attacker assigns an earlier witnessed_at
   timestamp.  If tips are published to external sinks with their own
   timestamps, the inconsistency is detectable.  Without external sinks,
   backdating is harder to detect.

   *T5: Double-Witnessing.* An attacker attempts to witness the same
   source event twice.  The uniqueness constraint (chain_id,
   source_kind, source_id) prevents this at the storage layer.

19.2.  Threats WARD Does Not Fully Mitigate

   *T6: Compromised Issuer.* If the WARD issuer itself is compromised,
   the attacker can produce a valid but false chain with consistent
   hashes, or present an alternative branch (fork) built from the same
   predecessor entry while withholding the original; a verifier shown
   only one branch cannot detect the fork from chain data alone.
   Mitigation: signed tips published to external sinks prevent post-hoc
   modification and anchor the branch that existed at publication time;
   meta-chains from independent issuers provide cross-verification;
   periodic external audits detect inconsistencies.

   *T7: Pre-Witness Modification.* WARD witnesses what it receives.  If
   the source event is modified before WARD observes it, WARD cannot
   detect this.  Mitigation: VOLT's internal hash chain detects VOLT
   modifications; AEE carries envelope-level integrity; AOCL persists
   decisions before triggering WARD.  Defence in depth across all four
   protocols hardens the system.

   *T8: Key Theft.* An attacker who steals the Ed25519 signing key can
   forge tips.  Mitigation: store keys in HSM/TPM, implement key
   rotation schedules, maintain key revocation lists, and use separate
   keys per environment.

20.  Compatibility with AEE, AOCL, and VOLT

   WARD is designed as the fourth member of a family of complementary
   protocols for agentic AI governance:

   *  *AEE* [AEE]: message format and correlation for agent
      communication.

   *  *AOCL* [AOCL]: orchestration control layers for policy decisions,
      permissions, and human-in-the-loop gates.

   *  *VOLT* [VOLT]: evidence recording with hash-chained traces and
      exportable bundles.

Cowles                    Expires 4 March 2027                 [Page 27]
Internet-Draft                WARD Protocol                  August 2026

   *  *WARD*: content-free witnessing with hash-chain receipts, tips,
      and meta-chains.

   WARD and VOLT are complementary: VOLT records detailed trace events
   with payloads (the evidence layer), while WARD produces content-free
   hash-chain receipts (the witnessing layer).  WARD may witness VOLT
   events, but never stores VOLT payloads.  VOLT may reference WARD
   chain hashes as external integrity anchors.

   WARD witnesses AEE envelopes by identifier and hash but does not
   participate in AEE routing or transport.  WARD witnesses AOCL
   decisions by identifier and hash but does not evaluate policies or
   make control decisions.

21.  Security Considerations

   WARD provides tamper-evidence guarantees for hash-chain integrity.
   It does not provide confidentiality, access control, or
   authentication of source events.  The following considerations apply
   to deployments.

   *Hash Chain Integrity.* WARD's core security property derives from
   SHA-256 hash chaining.  Each entry's chain_hash depends on all
   preceding entries via the prev_chain_hash linkage.  Modifying any
   entry invalidates all subsequent chain hashes, making tampering
   detectable.  This property holds as long as SHA-256 remains preimage
   and collision resistant [RFC6234].

   *Hash-Input Unambiguity.* The integrity property additionally
   requires that no two distinct field tuples produce the same hash
   input.  The canonical-JSON hash body of Section 7.4 guarantees this
   by construction: JSON string escaping makes field boundaries
   unambiguous for every possible identifier value.  The legacy version
   0.1 scheme (Appendix A) lacked this property: because identifiers
   carried no character-set restriction, a crafted identifier containing
   the | delimiter could make two distinct tuples hash identically, so a
   chain hash could commit to an ambiguous statement.  Verifiers surface
   a warning when legacy entries contain the delimiter character in an
   identifier field.  Optional fields are outside the hash body in both
   schemes and MUST NOT be relied upon for any security-relevant
   purpose.

   *Genesis Trust Anchor.* The genesis hash is deterministically derived
   from the chain_id.  Any party with knowledge of the chain_id can
   independently compute the expected genesis hash and verify the
   chain's origin.  There is no secret material in the genesis
   computation.

Cowles                    Expires 4 March 2027                 [Page 28]
Internet-Draft                WARD Protocol                  August 2026

   *Content-Free Privacy.* WARD's content-free design ensures that ward
   entries and chains do not leak source event content.  However,
   metadata (source identifiers, timestamps, source kinds, and payload
   hashes) may reveal operational patterns.  Deployments that require
   metadata privacy should apply additional protections at the
   integration layer.

   *Confirmation Attacks on Low-Entropy Content.* Content-free does not
   mean information-free.  A payload hash is an unsalted commitment: an
   attacker who can enumerate the plausible source contents (for example
   a decision field whose only values are approved, denied, or pending)
   can hash each candidate and confirm which one was witnessed.  Payload
   hashes over low-entropy or predictable source events permit this by
   construction.  Where it matters, callers SHOULD fold caller-held
   randomness or unpredictable identifiers into the canonical source
   content before hashing; a first-class blinded commitment profile is a
   candidate for a future revision.

   *Tip Signing and External Sinks.* Without signed tips published to
   external stores, an attacker who controls the WARD storage can
   rewrite the entire chain with consistent hashes.  Signed tips
   published to external sinks of documented strength (see Section 12.4)
   create anchors that make full chain rewrites detectable.  Deployments
   requiring strong non-repudiation SHOULD sign all tips and publish
   them to at least one external sink.

   *Key Management.* Ed25519 signing keys used for tips are high-value
   assets.  Compromise of a signing key allows an attacker to forge
   tips.  Implementations SHOULD store signing keys in hardware security
   modules, implement key rotation schedules, and maintain revocation
   lists.  Separate keys SHOULD be used for separate environments.

   *Denial of Service.* An attacker who can submit arbitrary source
   event references may attempt to inflate the chain with spurious
   entries.  Implementations SHOULD rate-limit witness requests and
   validate that source references correspond to genuine events at the
   integration boundary.

   *Layered Defence.* WARD is most effective as part of a layered
   defence with AEE [AEE], AOCL [AOCL], and VOLT [VOLT].  No single
   protocol provides complete security; together they provide message
   integrity (AEE), policy enforcement (AOCL), evidence recording
   (VOLT), and tamper-evident witnessing (WARD).

22.  IANA Considerations

   This document has no IANA actions.

Cowles                    Expires 4 March 2027                 [Page 29]
Internet-Draft                WARD Protocol                  August 2026

23.  References

23.1.  Normative References

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/info/rfc2119>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/info/rfc8174>.

   [RFC8259]  Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
              Interchange Format", STD 90, RFC 8259,
              DOI 10.17487/RFC8259, December 2017,
              <https://www.rfc-editor.org/info/rfc8259>.

   [RFC3629]  Yergeau, F., "UTF-8, a transformation format of ISO
              10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
              2003, <https://www.rfc-editor.org/info/rfc3629>.

   [RFC6234]  Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms
              (SHA and SHA-based HMAC and HKDF)", RFC 6234,
              DOI 10.17487/RFC6234, May 2011,
              <https://www.rfc-editor.org/info/rfc6234>.

23.2.  Informative References

   [RFC8032]  Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
              Signature Algorithm (EdDSA)", RFC 8032,
              DOI 10.17487/RFC8032, January 2017,
              <https://www.rfc-editor.org/info/rfc8032>.

   [RFC8792]  Watsen, K., Auerswald, E., Farrel, A., and Q. Wu,
              "Handling Long Lines in Content of Internet-Drafts and
              RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020,
              <https://www.rfc-editor.org/info/rfc8792>.

   [RFC9943]  Birkholz, H., Delignat-Lavaud, A., Fournet, C., Deshpande,
              Y., and S. Lasker, "An Architecture for Trustworthy and
              Transparent Digital Supply Chains", RFC 9943,
              DOI 10.17487/RFC9943, June 2026,
              <https://www.rfc-editor.org/info/rfc9943>.

   [RFC9562]  Davis, K., Peabody, B., and P. Leach, "Universally Unique
              IDentifiers (UUIDs)", RFC 9562, DOI 10.17487/RFC9562, May
              2024, <https://www.rfc-editor.org/info/rfc9562>.

Cowles                    Expires 4 March 2027                 [Page 30]
Internet-Draft                WARD Protocol                  August 2026

   [AEE]      Cowles, A., "Agent Envelope Exchange (AEE): A Minimal JSON
              Envelope Format for Inter-Agent Communication", Work in
              Progress, Internet-Draft, draft-cowles-aee-01, 2026,
              <https://github.com/quoxai/aee>.

   [AOCL]     Cowles, A., "Agent Orchestration Control Layers (AOCL): A
              Multi-Layer Governance Framework for Agentic AI Systems",
              Work in Progress, Internet-Draft, draft-cowles-aocl-01,
              2026, <https://github.com/quoxai/aocl>.

   [VOLT]     Cowles, A., "Verifiable Operations Ledger and Trace (VOLT)
              Protocol", Work in Progress, Internet-Draft, draft-cowles-
              volt-01, 2026, <https://github.com/quoxai/volt>.

   [FIPS180-4]
              National Institute of Standards and Technology (NIST),
              "Secure Hash Standard (SHS)", FIPS 180-4, August 2015,
              <https://csrc.nist.gov/publications/detail/fips/180/4/
              final>.

Appendix A.  Legacy Version 0.1 Chain Hash

   Entries with ward_version "0.1" computed chain_hash by delimiter
   concatenation:

   chain_hash = SHA-256(
     prev_chain_hash + "|" +
     chain_id        + "|" +
     seq             + "|" +
     ward_entry_id   + "|" +
     timestamp       + "|" +
     source_kind     + "|" +
     source_id       + "|" +
     payload_hash
   )

   All values are UTF-8 strings concatenated with pipe (|) separators.
   The seq value is the decimal string representation of the sequence
   number with no leading zeros.  The timestamp value is the ISO 8601
   UTC string from the entry's witnessed_at field.  The issuer_id and
   ward_version fields are not part of the version 0.1 hash input.

   This scheme is deprecated for the reason described in Section 7.4 and
   in the Security Considerations: identifiers containing the |
   character make the hash input ambiguous.  Chains are append-only and
   are never rehashed, so verifiers MUST still implement this scheme to
   verify existing version 0.1 entries.  Writers MUST NOT create new
   version 0.1 entries; verifiers enforce this to the extent stored data

Cowles                    Expires 4 March 2027                 [Page 31]
Internet-Draft                WARD Protocol                  August 2026

   allows via the version-monotonicity rule of the verification
   algorithm (VERSION_DOWNGRADE), and MUST append a warning to the
   verification result when a version 0.1 entry's ward_entry_id or
   source_id contains the | character.

Acknowledgements

   The author thanks the early adopters and reviewers of the Quox
   protocol family (AEE, AOCL, VOLT, WARD) for their feedback on
   content-free witnessing design, hash chain construction, and the
   meta-chain pattern.

Author's Address

   Adam Cowles
   Quox Ltd
   London
   United Kingdom
   Email: adam@quox.ai
   URI:   https://quox.ai

Cowles                    Expires 4 March 2027                 [Page 32]