> ## Documentation Index
> Fetch the complete documentation index at: https://docs.visiqlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Audit Trail

> A cryptographically signed, independently verifiable audit trail for every governance decision.

Every tool-call authorization and every human adjudication emits a **record envelope**; retrieval verdicts emit envelopes when artifact signing is enabled for your organization. There is no additional code; the audit trail activates automatically from the same `visiq()` call.

Envelopes are persisted server-side, off the request path, and then cryptographically attested: each one receives an asynchronous Ed25519 receipt, is committed to a Merkle batch whose root is signed by an HSM-backed key and countersigned by an independent RFC 3161 timestamp authority, and takes its place in a hash-chained transparency log. [Decision Receipts](/record/receipts) covers the cryptography in depth.

***

## What gets recorded

Each decision produces one envelope. An action-governance denial looks like this:

```json theme={null}
{
  "id": "9f4c1a3e-8f2b-4c1d-9e5a-2b7c8d0f1a42",
  "source": "action",
  "vendor_id": "b2e6d0c4-5a1f-4e8b-9c3d-7f2a1b4c5d6e",
  "decision_id": "4d7a2c1b-3e5f-4a8c-b1d2-9e0f3a6c7b8d",
  "actor_id": "support-agent",
  "decision": "deny",
  "event": {
    "target_app": "stripe",
    "action": "issue_refund",
    "context": { "amount": 500, "currency": "USD" }
  },
  "attestation": {
    "reason": "Refunds over $250 require human approval",
    "rule_id": "8c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
    "mode": "enforce"
  },
  "emitted_at": "2026-07-03T17:22:41.118Z"
}
```

`source` tells you which subsystem produced the decision, and each source carries its own decision vocabulary:

| `source`    | Emitted for                                    | `decision` values                               |
| ----------- | ---------------------------------------------- | ----------------------------------------------- |
| `action`    | Every tool-call authorization                  | `permit`, `deny`, `approval_required`, `mask`   |
| `retrieval` | Every retrieval verdict                        | `allow`, `deny`, `redact`, `escalate`           |
| `hitl`      | Every human adjudication of a pending decision | `approved`, `rejected`, `dismissed`, `resolved` |

The `event` field holds what happened — the payload the cryptographic receipt later signs — and `attestation` holds the decision metadata, both shaped per source:

* **`action`** — `event: { target_app, action, context }`, `attestation: { reason, rule_id, mode }`. `mode` records the agent's mode at decision time — `enforce`, `monitor`, or `off` (an `off`-mode call is permitted without evaluation but still recorded).
* **`retrieval`** — `event: { operation, resource_type, resource_metadata }`, `attestation: { reason_code, reason, rule_id }`.
* **`hitl`** — `event: { hitl_item_id, category, target_app, action, context, allow_decision_id }`, `attestation: { responded_by, responded_at, ai_recommended_rule }`.

<Note>
  Human adjudications are first-class evidence. When a responder approves or rejects a held action, a separate `hitl` envelope records **who** responded and **when**, linked back to the originating decision via `decision_id` — and it receives its own cryptographic receipt like any other decision.
</Note>

At the moment an envelope is ingested, the database also pins a **content hash** over its `event` in a generated column the application cannot write. Verification later recomputes it, proving the record was not edited even in the window between ingest and signing.

***

## How records become tamper-evident

Persisting the envelope is step one. An asynchronous pipeline — entirely off the decision hot path, adding zero latency to your agents — turns each envelope into independently verifiable evidence:

1. **Ed25519 leaf receipt** — the envelope's `event` is canonicalized, hashed, and signed. The receipt (signature, public key, payload hash) is stored separately from the envelope it attests.
2. **Merkle batching** — a background worker gathers unbatched receipts and commits their leaf hashes to a single Merkle root.
3. **HSM root signature** — the root is signed once with an HSM-backed key in AWS KMS. The private key never leaves the HSM.
4. **RFC 3161 timestamp** — DigiCert's timestamp authority countersigns the root: an independent third party attests *when* the batch existed.
5. **Hash-chained checkpoints** — each signed batch commits to the previous batch's root, forming an append-only transparency log whose checkpoints are published to write-once (WORM) object storage as an external witness. Deleting, reordering, or backdating any batch breaks the chain detectably — even for VisIQ.

This is the Certificate Transparency model: one HSM signature and one third-party timestamp attest an entire batch, so 100% of records are signed and independently timestamped at any decision volume.

***

## Verify a record in one call

You don't hand-roll any cryptography. One request re-derives and re-checks the full attestation chain:

```bash theme={null}
curl "https://api.visiqlabs.com/record/envelopes/9f4c1a3e-8f2b-4c1d-9e5a-2b7c8d0f1a42/verify" \
  -H "Authorization: Bearer <management-token>"
```

It runs six independent checks and returns per-check evidence:

| Check              | Proves                                                                                                           |
| ------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `integrity`        | The envelope's `event` still hashes to the receipt's payload hash — the record was not altered since signing     |
| `leafSignature`    | The Ed25519 receipt signature verifies against the receipt's public key — this exact decision was signed         |
| `merkleInclusion`  | The receipt's leaf is committed to its batch's Merkle root via a recomputed inclusion proof                      |
| `kmsRootSignature` | The batch root's signature verifies — including a live AWS KMS round-trip confirming the HSM key produced it     |
| `timestamp`        | The RFC 3161 token verifies against DigiCert's certificate chain — a third party attests when the record existed |
| `ingestAnchor`     | The at-ingest content hash still matches — the record was not edited between ingest and signing                  |

`verified` is `true` only when every applicable check passes. A freshly emitted record reports `attestationStatus: "timestamp_pending"` until the next batch sweep commits it — typically within a minute or two.

The dashboard runs this same verification for you: every governed event row (**Harness → Runtime Enforcement**) carries a record pill, and clicking through opens the record's verification page with the full per-check breakdown.

***

## What the audit trail proves

| Question                                                | Evidence                                                                   |
| ------------------------------------------------------- | -------------------------------------------------------------------------- |
| Did the agent attempt this action?                      | `event` — tool name, arguments, target app                                 |
| Was the action authorized, and by what policy?          | `decision` plus `attestation.rule_id` and `attestation.mode`               |
| Who approved or rejected it?                            | The linked `hitl` envelope — `attestation.responded_by` and `responded_at` |
| When did it happen?                                     | `emitted_at`, countersigned by an independent RFC 3161 timestamp           |
| Has this record been tampered with?                     | The six-check verification above                                           |
| Is the history complete — nothing deleted or backdated? | The hash-chained checkpoint log (`GET /record/chain/consistency`)          |

***

## Consuming the trail

* **Dashboard** — **Harness → Runtime Enforcement** streams every governed event with its record attached; agent pages and the **Escalations** queue link to the same records.
* **Query APIs** — `GET /v1/allow/audit-log` and `GET /v1/recall/audit-log` return the paginated decision logs, filterable by agent, decision, and date range.
* **Log streaming** — stream decision envelopes and audit events to your SIEM. Datadog and Elasticsearch destinations are configured under **Settings → Log Streaming** (organization scope) or from the **Integration → Connectors** Log Streaming cards. Delivery is cursor-tracked: a failed batch is retried, never dropped.
* **Evidence packs** — export a signed, per-agent evidence bundle over a date range from the agent's dashboard page, sized for handing to an auditor.

<Note>
  Cryptographic receipt issuance is plan-dependent. On every plan, all decisions are still recorded in the queryable audit logs above.
</Note>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Decision Receipts" icon="file-signature" href="/record/receipts">
    The exact cryptography — canonicalization, signatures, Merkle proofs, timestamps — and how to verify offline.
  </Card>

  <Card title="Action Governance" icon="shield-check" href="/rules/action/introduction">
    How tool-call authorization decisions are made.
  </Card>

  <Card title="Retrieval Governance" icon="shield-halved" href="/rules/retrieval/introduction">
    How retrieval verdicts govern what context your agents see.
  </Card>

  <Card title="Platform Automation" icon="key" href="/automation/introduction">
    Authenticating scripts and CI against the management API.
  </Card>
</CardGroup>
