The evidence spine

Enforcement happens on chain. What happens next — the record a supervisor reads, the case a firm keeps, the anchor a regulator can check — is this. Its property is not that it is tamper-proof, but that tampering is detectable by someone who does not trust the firm.

Three layers, and what each is for

The spine, from the record to the anchor
LayerHoldsWho can change it
Chain events IntentRecorded before the pass/fail branch, ActionHeld, Executed, HoldResolved Nobody. This is the authority
PostgreSQL The indexed record, case files, findings, disclosure requests The firm — which is exactly why the third layer exists
HCS topic An ordered, consensus-timestamped commitment per intent Nobody. Append-only, and the firm cannot rewrite what it published

The database is rebuildable from chain: npm run -w @amw/intent-log index reconstructs it from events. A firm that loses its spine loses nothing but time, and a firm that edits its spine fails verification against the topic.

The commitment

Each intent is hashed into one digest. The field list is deliberately the whole of what a case file later relies on — anything omitted could not be proven unchanged:

keccak256(abi.encode(
      actionId,      // uint256
      mandateHash,   // bytes32
      amountIn,      // uint256
      venueClass,    // uint8  — 1 primary, 2 secondary
      breachFlags,   // uint256 — the flag word
      occurredAt     // uint64  — block timestamp, seconds
    ))

What the topic publishes

A bare digest is an anchor nobody can interpret. Each message is a self-describing envelope, so a reader who finds the topic without finding this repository can still tell what it is, which system produced it, and exactly how to check a record they are later shown:

{
      "v": 1,
      "type": "amw.intent.commitment",
      "network": { "chain": 296, "guard": "0.0.10308333", "registry": "0.0.10308330" },
      "mandate": "0x2cb3ea1e…7a2b",
      "action": "50",
      "outcome": { "state": "held", "flags": "0x140", "clauses": ["3.4", "3.7"] },
      "digest": {
        "alg": "keccak256",
        "encoding": "abi",
        "fields": ["actionId", "mandateHash", "amountIn", "venueClass", "breachFlags", "occurredAt"],
        "value": "0x…"
      },
      "occurredAt": "2026-08-31T13:18:26Z"
    }

The line between published and withheld

This is a deliberate boundary, not an accident of implementation, and it is the reason a firm can run this without publishing its book:

Published on the topicKept in firm custody
That an intent existed, and its orderThe notional
Its consensus timestampThe counterparty and the venue address
Which mandate governed itThe agent's calldata
Whether the guard held it, and which clause classThe case file and its findings
The digest, and how to reproduce itEverything a competitor would want

A reader learns that supervision happened and can prove that a record they are shown is the record that was anchored. They learn nothing about the firm's positions. The detail reaches a supervisor through a disclosure request — and the request for evidence is itself evidence, written to an audit row before the record is released.

Verifying a disclosed record

Three steps, none of which require trusting the firm or us:

  1. Read the message at the sequence number cited (hcs:0.0.10309023/9) from the mirror node, and take its digest.value.
  2. Re-encode the six disclosed fields in the order the envelope names, and hash them.
  3. Compare. Equal means the record is the one anchored at that consensus timestamp; different means it changed after publication.
npm run -w @amw/intent-log gate3   # does exactly this, and prints each step

Or without installing anything: /console/verify takes the record you were shown, reads the message straight from Hedera's mirror node, recomputes the digest in your browser and puts the two hashes beside each other. Nothing on that page asks AMW. A console that was switched off, a server that lied and a firm that stopped answering would each leave the answer unchanged — which is the property that makes it a supervisor's tool rather than a firm's.

Older messages on a topic may be a bare 0x digest, written before the envelope existed. They are still valid anchors and still verify; the reader accepts both formats and says which it found.

Append-only, at the grant level

case_steps takes INSERT and nothing else — no UPDATE, no DELETE — enforced by PostgreSQL grants and a trigger rather than by application code that could be bypassed. A worker writes its step and cannot revise it. The trail of a halted investigation survives the halt, because a stopped case that erased itself would be indistinguishable from one that never ran.