
# Integrity Verification

Context Nest uses SHA-256 hash chains to make version history tamper-evident.

## Hash types

| Hash | Scope | What it proves |
|------|-------|----------------|
| `content_hash` | Single version | The document content hasn't changed |
| `chain_hash` | Version chain | No versions have been inserted, removed, or reordered |
| `checkpoint_hash` | Checkpoint | The checkpoint hasn't been modified |
| Cross-chain binding | Checkpoint ↔ document | Document chain hashes match what the checkpoint recorded |

## How chain hashes work

```
v1: chain_hash = SHA256(content_hash_v1)
v2: chain_hash = SHA256(chain_hash_v1 + content_hash_v2)
v3: chain_hash = SHA256(chain_hash_v2 + content_hash_v3)
```

Each version's chain hash depends on all previous versions. Changing any version invalidates all subsequent chain hashes.

## Verification

```bash
ctx verify          # Verify all hash chains
ctx verify --json   # JSON output for CI integration
```

Verification checks:
1. Each document's content hash matches the stored content.
2. Each chain hash is correctly derived from the previous chain hash + content hash.
3. Each checkpoint's document chain hashes match the actual document histories.

## Hardened tamper detection

Verification is hardened against the ways a history could be forged or silently degraded:

- **Torn seals** — a partially written version or checkpoint (from a crash or interrupted write) is flagged, not trusted as complete.
- **Tamper** — editing any stored version, hash, or checkpoint breaks the derived chain and is reported.
- **Races** — concurrent writes cannot leave the chain in a half-updated state that passes verification.
- **Rebuild-laundering** — a rebuilt checkpoint history is validated against the recorded per-document histories, so tampered content cannot be "washed" into an apparently valid chain by rebuilding.

### Missing change-log patch = hash mismatch

If a per-version change-log (unified diff) is **missing**, the affected version reconstructs to empty content, which no longer matches its recorded `content_hash`. This surfaces as a **`content_hash_mismatch`** failure rather than passing silently. A gap in the change-log chain is treated as tampering, not as an absent-but-fine version.

*Confirmed in the inspected build: an absent diff is read as `""`, hashes to the empty-content hash, and fails the `content_hash_mismatch` check.*

Verification reports these mismatch reasons: `content_hash_mismatch`, `chain_hash_mismatch`, `checkpoint_hash_mismatch`, and `cross_chain_mismatch`; a failure raises an `IntegrityError` (code `INTEGRITY_ERROR`).

## Server-side enforcement on governed remotes

On **governed remotes** (hosted nests), writes are routed through the governed write path so that every write is versioned and hash-chained server-side — a client cannot fabricate history that the server will accept. `ctx verify` on the client is a local check; the governed remote maintains the authoritative chain.

## CI integration

Run `ctx verify` in your CI pipeline to ensure vault integrity on every commit:

```yaml
# GitHub Actions example
- name: Verify vault integrity
  run: ctx verify
```

Verification is idempotent and read-only — it produces no file changes.
