Skip to main content

The seven guarantees

Seven things are true of GreatBook’s ledger, and each one is true because something refuses to let it be false. This page is the spine the whole Capabilities tab hangs off. A guarantee that lives only in a document is a wish. Each row below names the place it is enforced, so it can be checked rather than believed.

The seven

The GL is the single source of truth

Every business event becomes a balanced journal entry, or it does not exist to the system. No derived balance is trusted unless it can be recomputed as a GROUP BY over the GL.Enforced by the absence of any stored balance column. Proved by the Close checksums, which tie each sub-ledger back to its GL control account.

Single-writer posting

There is exactly one function that writes to the ledger: LedgerService.post_entry(). Every router, agent node, MCP action and connector funnels through it. Validation happens inside the writer, before the write.Enforced by the writer owning the whole validate-then-write sequence. Proved by a static import check that no agent module can reach a writer, and by the engine’s own test suite exercising every refusal path.

Immutable, and corrections are reversals

Posted entries are never mutated or deleted. A correction is a new reversing entry. This is what preserves both the audit trail and the hash chain.Enforced by database triggers that reject an UPDATE on a posted entry, so the rule holds even against a direct SQL session. Proved by the Auditor recomputing the chain rather than trusting a stored flag.

Exact replay by source key

Every entry carries (org_id, source_type, source_id, entry_set). An exact replay returns the existing entry, while reuse of the key with different immutable request facts conflicts. This is what makes retries, replays and agent re-runs safe.Enforced by the idempotency lookup inside the writer, before the write. Proved by the duplicate double-post suite, which drives the same source twice and asserts one entry.

Dimensions on the line, not multiplied accounts

The chart stays lean, around 45 IFRS accounts. Per-supplier, per-customer, per-order and per-activity detail lives as dimensions on the journal line. This scales to thousands of counterparties without bloating the chart.Enforced by the writer requiring the Tier-1 dimensions before it will accept a line. Proved by the invariant tests that reject a line missing a required dimension.

A human gate precedes every agent-proposed ledger write

The graph pauses at a gate before posting. The human approves, edits or rejects, and the graph resumes from its checkpoint rather than re-running the pipeline.Enforced by the Bookkeeper’s durable pause, plus a posting mandate the browser cannot mint. Proved by the trust-boundary suite, which attempts the forgeries and asserts an empty ledger. Native subledger, reversal and system-origin events use their applicable canonical domain controls rather than invented intake identities.

Every correction is training data

At each gate the system captures {proposed, committed, reason}. That delta stream is the signal that lets a behaviour graduate from “ask every time” toward acting unattended.Enforced by the gate recording the decision alongside the proposal. Proved by the audit trail on every intake row, which carries the whole sequence.

The two things called “checks”, and why they are not the same

Two different mechanisms in this system are both “checks” in the code, and conflating them would blur the strongest claim the finance layer makes. The naming below is binding on every page in this documentation. A GL invariant is a precondition. An unbalanced entry, a two-sided line, a closed period or a missing Tier-1 dimension never reaches the database at all. It is a property of the writer. A Close checksum is a reconciliation. AP control against the AP sub-ledger, cross-foot, per-rail reconciliation against external evidence. It is a property of the whole book across seven sub-ledgers.
Calling the second set “invariants” would imply the system refuses a posting that would break a Close tie-out. It does not, and it should not: a broken tie-out is a finding for a human, not a rejected transaction. The canonical phrasing when both appear together is “18 GL invariants + 104 Close checksums”.

The 18 GL invariants

Validated inside LedgerService.post_entry(), before any write. On any failure the writer raises a typed error and writes nothing.
Invariants 12, 14 and 16 are what make the chain trustworthy rather than decorative. The checksum is taken over a canonical serialisation that sorts the lines and stringifies the decimals, so neither line order nor 10 versus 10.0000 can change a checksum. The advisory lock means two concurrent postings cannot both extend the chain from the same head.