Skip to content

ADR-001: Core Domain Classification and the Mandatory Global Stream

Accepted — 2026-07-24 (decided 2026-07-23/24 by the maintainer, Tobias Brennecke)

The Git Event Store (GES) specification family — the core spec (docs/git-event-store-spec.md, v0.21.0) plus five claimed extensions (docs/extensions/: linkage.md, emmett-binding.md, stream-projections.md, stream-export.md, dcb.md) — has grown to the point where two coupled questions must be settled before implementation investment is ordered:

  1. Which of the product’s eleven bounded contexts are core domain, supporting, or generic? (Twelve classified units: the store-persistence context’s three modules — durable-writing as store-persistence itself, stream-naming, store-compacting — are classified individually.) Investment, modeling rigor, and build order follow from this classification, not from section order in the spec.
  2. Is the global stream (§20) mandatory for conformance, or a capability a store may decline? The spec historically framed the substrate and the global stream as two selectable configurations; that framing had already begun to dissolve in v0.21.0 (§1 now states one model: “the multi-master substrate carrying the global stream”).

The two questions are coupled because the answer to the first drives the second: a capability classified as the product’s differentiating core cannot simultaneously be something a conforming store is free to omit.

Grounding facts from the spec as it stands:

  • Every clone is an authority over its own visibility point (§5.5.1); a remote holds no intrinsic privilege — authority is a role assigned by convention (§2, “authoritative remote”; §20.5.1). A store with no remote is trivially its own sequencer (§12.3, §20).
  • The §21 alignment register records that every reference store — EventStoreDB, EventSourcingDB, Marten, Message DB — provides a global total order ($all, global stream position); GES treats deviation from that consensus as a cost requiring a substrate- or goal-based justification (§1).
  • The §10.4 rule already delegates the durable-write path to the git binary or libgit2 rather than reimplementing it — a deliberate refusal to invest where Git has already solved the problem.

Decision 1 — Core Domain Chart for the twelve bounded contexts

Section titled “Decision 1 — Core Domain Chart for the twelve bounded contexts”

The twelve bounded contexts of the GES spec garden are classified on a core domain chart (Nick Tune style), with two axes: business differentiation (does this capability make GES worth choosing over an established event store?) × model complexity (how much irreducible domain modeling does it demand?).

Bounded context Classification Rationale
stream-operations Core One-event-per-commit plus the ref CAS as the transaction boundary (§5.2, §5.5, C3, C7) is the invention. Highest differentiation, highest model complexity.
global-stream Core “Git substrate with a real global total order” (§20, C22) is the product’s differentiating bet. Dual view, provisional positions, fast-forward-only reconciliation are irreducible domain logic (§20.2–§20.7).
linkage Core Big-bet candidate: events↔code-commit linkage via the GES-Link trailer and side-effect-free shadow capture (extensions/linkage.md, C18/C19) is unique among event stores. Remains structurally optional as a claimed extension yet receives core-domain investment.
stream-replication Supporting Local/shared/incoming status, conflict-free union, same-stream rejection (§12, C11, C12) — necessary, but the semantics follow from Git’s push/fetch model rather than differentiating GES.
record-integrity Supporting Canonical JSON, event ids, the per-stream integrity chain (§6, §8, C4, C6) form the family’s Published Language: the interop surface every implementation must speak, with modest novel modeling.
dcb Supporting Conformist on the dcb.events vocabulary (extensions/dcb.md). Deliberately separate from global-stream: the global stream is useful without DCB, and the dependency is strictly one-way — DCB’s global enforcement requires an authority, never the reverse (E-18c-4, §20.9).
store-persistence Generic The spec’s §10.4 mandate — delegate the durable-write path to git/libgit2 — is the generic-subdomain move: buy Git’s mature fsync path, do not build one.
stream-naming Generic Reversible percent-encoding of UTF-8 names into ref components (§4, C2): a solved encoding problem, fully specified, no domain judgment left.
store-compacting Generic Snapshots, horizon truncation, GC hygiene (§13): established event-store and Git practice, applied.
stream-projections Generic Fold-based read models with a cursor ref (extensions/stream-projections.md): standard projection machinery.
stream-export Generic JSONL export via plumbing (extensions/stream-export.md, C21): a format conversion.
emmett-binding Generic Emmett is a consumer of GES, not its definition (§1, §10); the binding maps the framework-neutral core onto one framework’s interface (extensions/emmett-binding.md).

(shared-kernel — the §2/§2.1 ubiquitous language — is vocabulary shared across all contexts and sits outside the chart.)

Key insight this classification records: domain-coreness and conformance-mandatoriness are independent axes. linkage is a claimed extension — structurally optional, a store need not offer it (C18/C19 are “if offered”) — yet it is classified core domain and receives maximum modeling rigor, because it is where GES can be unique. Conversely, store-persistence is mandatory for every store yet generic: maximum delegation, minimum ceremony.

Investment ordering: build core first (stream-operations, then global-stream, then linkage), supporting next, generic last and by delegation wherever the spec already names the delegate.

Decision 2 — The global stream is mandatory for conformance

Section titled “Decision 2 — The global stream is mandatory for conformance”

Every conforming store maintains the global stream. This is conformance clause C22 (§16): dual view, sequencer designation, fast-forward-only reconciliation, satisfying the CB clauses of §20.11, with tests CB-a/b/c core-required. The §0.0 section directory states it directly: “the global stream (§20) is core-normative — every conforming store maintains it (C22).”

The decision chain, recorded here because the spec text shows only the end state:

  1. The dichotomy was dissolved. The spec originally framed the substrate and the global stream as two selectable configurations. The maintainer rejected that framing: a designated-sequencer topology is a special case of the multi-master substrate, not a second model beside it. Every clone is an authority over its own visibility point (§5.5.1); the local repository is an authority in itself; the sequencer is a role assigned to a remote by convention (§20.5.1), and a lone repository is trivially its own sequencer (§12.3). One model remains: the multi-master substrate carrying the global stream (§1).
  2. Core-domain classification drove rescoping. Once global-stream was classified core (Decision 1) — the differentiating bet, per the §21 cross-store consensus that every established event store provides a global order — it could no longer live among the claimable capabilities. It was moved into the core spec as §20.
  3. Rescoped core became mandatory. A core capability a store may decline still leaves “conformant” ambiguous, so the final step made it unconditional: C22, with CB-a/b/c core-required. The former non-goal N3 (“no global total order across streams”) was deleted — the non-goals are now N1 and N2 only (§1) — and the §21 register row for global order flipped to Aligned, converging with EventStoreDB, EventSourcingDB, Marten, and Message DB.

MVP consequence: the reference implementation’s MVP is a sequencer-claiming store by definition — a lone repository designating itself sequencer satisfies C22 trivially. Substrate-only operation is not a conformance target.

  1. Global stream as a claimable optional extension (the immediately prior state of the family). Rejected: it leaves “conformant” ambiguous about the product’s differentiator; it permits conformant stores that lack the one property every established event store in the §21 register provides; and it invites future readers — human and LLM — to treat the core capability as optional precisely because the document structure said so.

  2. Two co-equal operating configurations — the historical “Mode A / Mode B” framing, presenting the substrate and the global stream as parallel choices a store selects between. Rejected as false pretense: even a star topology’s center is an authority only by convention (§20.5.1); every clone retains authority over its own visibility point (§5.5.1), so the substrate never disappears beneath the sequenced view — the sequenced view is a special case of it. Presenting a dichotomy where the model has a hierarchy seeds misleading assumptions in every future reader, and the documents therefore keep none of the retired vocabulary.

  3. Substrate-only conformance with a synthetic or optional global order. Rejected: the documented problem class it creates — no sound $all enumeration, cross-clone timestamp unsoundness, projection-order caveats, no global DCB enforcement authority (E-18c-4) — outweighs the offline-write-distribution benefit it preserves. The CAP trade is instead confined to the sequencing window: offline appends remain first-class, locally visible and durable immediately, with provisional global stream positions until pushed (§20.3.2, §20.5.2).

  • Alignment with established-store consensus. The §21 register row for global order reads Aligned; GES no longer deviates on the one property all reference stores share.
  • Projections fold over a real order. Read models consume the global stream’s total order rather than a per-store approximation (§20.9).
  • DCB’s enforcement authority always exists. The consistency check runs against the sequencer’s consistent global stream; the conservative per-tag-anchor approximation is unnecessary where the sequencer serializes (§20.9, §18c via extensions/dcb.md).
  • One conformance story. C1–C22 with CB-a/b/c core-required; no conditional branch in what “conformant” means (§16, §20.11).
  • Investment ordering is decided. Implementation effort follows the chart: maximum rigor on stream-operations, global-stream, linkage; delegation and minimal ceremony on the generic contexts.
  • Substrate-only stores are non-conformant. A deployment that wants distributed offline writes with no designated sequencer cannot claim GES conformance.
  • Every store pays the dual-view append. Each event joins the global stream and its state stream in one atomic ref transaction (§20.4) — extra refs and commit objects per event, though each payload blob is stored exactly once via structural sharing (§20.2, CB-5).
  • Positions are provisional during the sequencing window. Consumers must not treat a global stream position as authoritative until the append is fast-forward-pushed (§20.3.2); unpushed appends may be rewritten by rebase, reassigning positions and SHAs, with the re-signing consequence that integrity anchors at the tip, snapshots, or tags rather than per-event signatures (§20.6, §20.7).
  • Hosted remotes weaken enforcement. A hosted authoritative remote (Codeberg, GitHub) cannot run the §15.1 pre-receive hook; sequencer enforcement there degrades to platform ref-protection plus convention, backed by integrity-chain verification (§8.3, §8.4) rather than server-side rejection.
  • Sole-sequencer unavailability halts authoritative writes. Until the authoritative remote is restored, appends stay local and provisional; highly-available sequencing would reintroduce consensus and is explicitly deferred (§20.10).

Git Event Store is an independent open specification for an event store that uses Git as its storage component. It is not affiliated with or endorsed by the Git Project or Software Freedom Conservancy. Git and the Git logo are either registered trademarks or trademarks of Software Freedom Conservancy, Inc., corporate home of the Git Project, in the United States and/or other countries.

Git Event Store is not affiliated with or endorsed by Kurrent, the maker of KurrentDB (formerly EventStoreDB). "Event store" is used here as the generic name of the event-sourcing storage pattern.