Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-037: Offline witness checkpoint + append-only consistency proof

Date: 2026-06-18 Status: Accepted Author: Rômulo Febasi

SYN-270. Closes the gap ADR-026/030 explicitly leave to remote comparison. Companion to ADR-026 (tamper-evident audit), ADR-030 (git substrate), ADR-035 (verify report). Grounds: docs/researchs/2026-06-16-provable-non-corruption-syn-verify.md (O3).


Context

ADR-026 makes the audit log tamper-evident (per-author hash-chain + a signed head checkpoint) and ADR-030 makes git the integrity substrate. Both note an honest ceiling: a lone local clone cannot detect its own owner’s rewrite: a force-push or a mid-log edit-then-recheckpoint: because the attacker controls every local artifact. ADR-026/030 leave that to a remote witness (a push-protected remote sees the old history).

The research (O3, after Go sumdb / Sigsum / RFC 9162 consistency proofs) identifies a local analogue: cache a signed tree-head and later prove the current state extends it. The verifier holding a prior checkpoint is the witness: exactly the offline single-user case.

Decision

syn audit witness emits a tiny ed25519-signed synapse.audit-witness/1 checkpoint: the git HEAD, and per author the segment size + a prefix_hash (sha256 over the canonical bytes of the first size entries), plus the total count and a timestamp. It is signed with the user’s existing identity (reuses the receipt/report signing path: no new crypto, no new deps). The user publishes it (commit it, post it, email it).

syn verify --since <witness> adds INV-12: prove the current audit history is an append-only extension of the witness,

  1. git ancestry (when versioned): HEAD is the witnessed commit or descends from it (gix rev-walk). A force-push that drops the witnessed commit fails here.
  2. segment prefix stability: for every witnessed segment, the current author segment has >= size entries and its first size entries re-hash to the witnessed prefix_hash. A truncation shrinks the count; a mid-log rewrite moves the hash. Either fails.

Both checks are offline and dep-free. The check runs over read_all (live + archive), so retention rotation does not weaken it.

Consequences

  • Improves: force-push / history-rewrite is now detectable locally, without a remote: the gap ADR-026/030 deferred. A published witness lets a third party hold the owner to their history (the witness property a remote used to be required for). Zero new dependencies.
  • Worsens / limits: still tamper-evident, not tamper-proof: the witness is only as trustworthy as where it was published. A witness an attacker can also rewrite (e.g. an unpublished local file they control) is no stronger than the chain it summarises; the value is in publishing it somewhere the owner cannot quietly change. verify surfaces this in the trust-root caveat.
  • Open: a future audit witness --publish could push the checkpoint to a conventional location (a gist, a transparency endpoint); deferred, the file
    • manual publication is enough for single-user and shared-git today.

Alternatives considered

  • Require a remote to detect rewrites (ADR-026/030 status quo). Works only online and only when a push-protected remote exists; the witness file gives the same property offline and for a third party.
  • Run a transparency log (Rekor/Trillian/Sigsum server). Rejected by the governing discipline (borrow the invariant, refuse the engine): a network service contradicts offline-first and single-user. The consistency proof is adopted; the server is not.
  • Byte-compare the whole audit file against a stored copy. Brittle across retention rotation and legitimate appends; the per-segment prefix hash + git ancestry is rotation-stable and proves the precise append-only property.
  • A Merkle tree over entries for inclusion proofs. Overkill for single-user (no third party requesting selective inclusion); a prefix hash over the witnessed range is sufficient and simpler.