ADR 0004: Mandatory parents — the log is a Merkle DAG

Decision

Every event carries :event/parents: the set of head event ids the actor observed when minting. :ticket/create is the unique root with #{}; for every other event type an empty parent set is a mint-time error. Since parents are inside the content-addressed, signed region, the log is a Merkle DAG: one head hash commits to the entire history.

Context

Parents are not metadata — they change what kind of object the log is: without them, an append-only collection of claims; with them, an authenticated history graph where every claim carries what its author knew. Parents were originally optional “Phase 1” metadata. Review of the axes showed that optionality here is ambiguity, not flexibility, and that mandatory parents simplify or strengthen nearly every other axis simultaneously:

What “observed” means, operationally. The minting layer must track known heads; :event/parents states “I created this event knowing exactly these heads.” Creating an event while offline or behind is not an error — a newer head existing elsewhere is precisely the distributed model, and the resulting structural concurrency is honest. The error is pretending no head existed: an empty parent set on a non-root event is a lie about what the actor knew, which is why it is rejected at mint time rather than tolerated as a degenerate case.

Consequences

see history · edit this page