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

# Audit records

> What Sengol signs, how records are chained, and what an examiner can check.

Every verdict Sengol records is a signed, append-only record. The gate
verdict and the audit record are the same object. There is no separate
compliance log rebuilt after the fact.

## Three layers of protection

**1. HMAC signature**

The appliance signs each record's canonical JSON (RFC 8785) with its HMAC
key. Every field the record sets is signed, except a short list of
fields that are unsigned by design.

**2. Hash chain**

Each record carries a `sequence_number` and the `prev_hash` of the record
before it. Removing, inserting or reordering a record breaks the chain.

**3. Ed25519 countersignature**

A second, asymmetric signature. Anyone with the appliance's public key
can check it offline, without the HMAC key. Countersigning runs
asynchronously, shortly after ingest.

Optionally, the appliance also **anchors** records to an RFC 3161
timestamp authority and a transparency log (`SENGOL_EVIDENCE_ANCHOR=1`).

## What a record contains

Export one agent's records, then look at the first one:

```bash theme={null}
sengol export --agent gic-advisor --out pack.json --wait-for-countersign
```

```python theme={null}
import json

pack = json.load(open("pack.json"))
record = pack["records"][0]
for key in ["record_id", "agent_id", "agent_version", "tenant_id", "timestamp",
            "policies", "controlbook_id", "sequence_number", "prev_hash", "hmac_signature"]:
    print(f"{key:16} {record[key]}")
for score in record["eval_result"]["scores"]:
    print(f"  {score['evaluator']:28} passed={score['passed']} failure_mode={score['failure_mode']}")
```

```text theme={null}
record_id        01a10ca6-d180-7727-ad58-c71a255e2cc9
agent_id         gic-advisor
agent_version    1.0.0
tenant_id        dev-tenant
timestamp        2026-10-05T07:45:21.622339Z
policies         ['OSFI_E23']
controlbook_id   None
sequence_number  1
prev_hash
hmac_signature   2cb6f0d005a423fd125b8dda0e9b2a5f0b118fe76c17013734a8662690ab6c8f
  PIIEvaluator                 passed=True failure_mode=None
  RequiredDisclosureEvaluator  passed=True failure_mode=None
  FaithfulnessEvaluator        passed=True failure_mode=None
  ToxicityEvaluator            passed=True failure_mode=None
```

The first record in a chain has an empty `prev_hash`. `controlbook_id` is
`None` because the demo records were written without a ControlBook.

### Signed

* The verdict of every evaluator: `passed` (true or false) and, on failure, a named `failure_mode`
* Agent id and version, tenant, policies, and the ControlBook id and version when the record was written under one
* A UTC timestamp, fixed at write time
* `reason_digest`: a keyed digest of each evaluator's free-text reason
* `evaluator_version` and `judge_model` on each evaluator's score, when the suite stamped them
* `sample_basis` and `environment`, on records written by online scoring of live calls

### Not signed, by design

* The free-text `reason`. It is stored separately so that a data-subject
  erasure can remove it. The record still verifies afterwards, and the
  reason reads back as `ERASED`.
* `hmac_signature` and `signing_backend`, which describe the signature itself.

`sengol-verify` lists the unsigned fields it found in its `field_coverage` check.

## Record families

| Family | Written by | Exported by `sengol export` |
| - | - | - |
| `AuditRecord` | SDK, guardrails, trace ingest, demo seeding: one per evaluated response | yes |
| `EvaluationRunRecord` | `sengol gate`: one per run, with per-case results in dataset mode | no; read it at `GET /v1/eval-runs/{run_id}` |
| Gold score, certification, tombstone and other governance records | the appliance | no |

## What is not signed evidence

These write logs or labels, not signed records:

* human review decisions
* user and role administration, including break-glass sign-ins
* ControlBook activation

## Verifying

* **Offline**, by anyone: [`sengol-verify`](https://docs.sengol.io/journeys/auditor) checks the
  canonical payload, the chain and the countersignatures.
* **Online**, with appliance access: `sengol audit verify --chain --agent-id <id>`
  also checks every HMAC.

A chain proves the records present link together. It does not prove the
pack is complete. Check the sequence range and the period, as shown in the
[auditor journey](https://docs.sengol.io/journeys/auditor.md#4-check-completeness).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.