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

# Hash Chains

> How SHA-256 hash chains provide tamper evidence

Every event in ProvenLog is cryptographically linked to the one before it, forming a hash chain. This makes tampering detectable — modifying any event breaks the chain from that point forward.

## How it works

Each event's hash is computed as:

```
hash = SHA-256(canonical_json(content_fields) || prev_hash)
```

* **Canonical JSON** — keys sorted alphabetically, deterministic serialization
* **Content fields** — all event data that matters for integrity
* **prev\_hash** — the hash of the previous event in the chain

## Content fields (included in hash)

These fields are included in the hash computation:

`id`, `schema_version`, `agent_id`, `session_id`, `source`, `action_type`, `action_name`, `action_input`, `action_output`, `action_status`, `error_message`, `timestamp`, `duration_ms`, `labels`, `metadata`, `capture_method`

## Excluded from hash

These fields are **not** included in the hash:

* `sequence` — server-assigned ordering
* `hash` — the computed value itself
* `prev_hash` — linked separately
* `validation_warnings` — quality metadata added by the pipeline

## Genesis hash

The first event in each chain uses a well-known zero hash as its `prev_hash`:

```
0000000000000000000000000000000000000000000000000000000000000000
```

## Per-agent chains

Each `agent_id` maintains an independent hash chain. This design avoids a single-threaded write bottleneck — agents don't block each other when writing events.

```
Agent A:  [E1] -> [E2] -> [E3] -> [E4]
Agent B:  [E1] -> [E2] -> [E3]
Agent C:  [E1] -> [E2] -> [E3] -> [E4] -> [E5]
```

## Server-authoritative sequencing

The SDK sends events with client-side timestamps. The **server** assigns:

* `sequence` — monotonically increasing within each agent's chain
* `hash` / `prev_hash` — computed server-side to maintain chain integrity

This ensures a single source of truth for ordering, even when events arrive out of order or from multiple SDK instances.

## Verification

Verification walks the chain from the genesis event and recomputes each hash:

```bash theme={null}
plog verify --agent-id my-agent
```

```python theme={null}
result = client.verify("my-agent")
# {"valid": True}
```

Verification is O(n) and detects both **modified events** (hash mismatch) and **missing events** (sequence gap).

## Timing-safe comparison

Hash comparisons use `crypto/subtle.ConstantTimeCompare` (Go) to prevent timing side-channel attacks.
