Audit Packs

Beta routes (v1.5.0); the pack format is stable.

An audit pack is one period of the evidence store, packed for an audit: a report a reader starts from, and a bundle a security team verifies on its own, years later, from the root key and the anchors it holds. The format is Audit Pack Format.

Audit packs need the evidence store (EVIDENCE_STORE=on, off by default). Without it POST /admin/evidence/audit-pack answers 404 evidence_store_disabled. A pack holds only the entry kinds your NA records: out-of-band records appear only with EVIDENCE_OUT_OF_BAND=on, remediations and reviews only with EVIDENCE_REMEDIATION=on, and grant records only with EVIDENCE_GRANTS=on.

What a pack holds

  • The range: every store entry between two anchors (the period you ask for, widened to the anchors around it): decisions, execution evidence, observations, break-glass records, judgements, quarantine entries, remediations, reviews, registry records, key successions and archives.

  • What the range’s records cite: each decision an execution rests on, each judgement’s subject and matched record, each remediation’s and review’s subject, the records the range’s chains continue from (so a pack that starts mid-store verifies its chains), the registries (executor, observer and operator keys, policy activations) and the latest retention checkpoint.

  • The trust material decisions rest on: the policy versions in force and bound, the attestations bound, the treaties and revocation feeds of their issuers.

  • The NA’s key history: the genesis block and every key succession.

  • checks.json (the NA’s own verification when it wrote the pack) and report.md: every change with how it was governed (governed_by) and its state, denials, remediations, reviews and their deciders, notices sent, break-glass uses, quarantined records, key successions and archives, totals, and the checks. Remediation states and notices are the NA’s operational records at pack time, kept in states.json, and the report says so. The report is rendered from the pack’s own files: a verifier renders it again and refuses a report that differs.

  • manifest.json: every file’s SHA-256, and the period you asked for (since, until), signed by the NA.

Writing a pack

A read-tier key is enough: a pack holds what the read routes serve, and an auditor should not need more than reading.

genesis-mesh audit pack --na https://na.example.org \
    --since 2026-01-01T00:00:00Z --until 2027-01-01T00:00:00Z \
    --out pack-2026 \
    --operator-key auditor.key --operator-key-id auditor

--from-sequence / --since choose the first entry (the range widens back to the anchor before it, or the store’s start); --until-sequence / --until the last anchor. Without them the pack runs from the store’s start to its latest anchor. Anchor first (evidence anchors fetch --anchor-now) so the period ends where you want it. A pack holds at most 50,000 entries (409 audit_pack_too_large): make several packs, each between two anchors; consecutive packs share an anchor. The command writes every file, reads the directory back and checks it against the manifest.

The route is POST /admin/evidence/audit-pack ({from_sequence | since, until_sequence | until}), answering {manifest, files}; 409 audit_pack_not_anchored when no anchor ends the range. Building a pack reads and verifies up to 50,000 entries, so the route has a rate limit of its own: NA_RATE_LIMIT_AUDIT_PACKS_PER_HOUR per client address (default 12; 429 beyond it). The NA records every pack it builds (its manifest’s digest and whether its own checks passed): only such a pack can be archived.

Storing packs

A pack holds metadata and actor identifiers (as sources reported them, never secret values): store packs with the access controls of your audit logs. Archived packs (see Audit and Retention) go to immutable storage.

Next

Verify the pack with the anchors you hold: Verifying a Pack. A second verifier, a Rust port of the reference verifier, is described in The Rust Verifier. Walkthrough: Verifying an Audit Pack runs both on one pack.