Skip to content

06 — Architecture Proof

The pitch makes claims. This document says which of them the code actually enforces today, how a sceptic can verify each one in a few minutes, and which claims are still only claims.

Nothing here is aspirational. Every row in the table below corresponds to a passing test in backend/limen-server.

The rule this document exists to keep

A claim is either enforced by a mechanism a reviewer can attack, or it is listed as not yet built. There is no third category. "The application layer takes care of it" is not enforcement, because the next contributor is not bound by it.

What is enforced

Claim in the pitch Mechanism Where
No UPDATE on money, ever Postgres trigger raises an exception on UPDATE or DELETE of ledger_entry V1.0.0__versioned_truth.sql, AppendOnlyLedgerTest
No UPDATE on history, ever The same trigger on contract_version and decision_record V1.0.0__versioned_truth.sql
Exactly-once money movement Mandatory idempotency key, unique index, replay returns the original entry LedgerAppend, AppendOnlyLedgerTest
Correct the past without touching it New version branched off the version in force on the corrected date TimelineFork, BackdatedCorrectionTest
Ten years of consequences in one entry Replayed timeline priced per segment, compared to what was charged, difference appended once FinancialDelta, BackdatedCorrectionTest
Replay is honest Each replayed version re-priced with the schedule its source used, not today's ContractPricing.priceWith, BackdatedCorrectionTest
Reissue an old statement unchanged Bi-temporal read filtering on recordedAt ContractVersion.asKnownAt, BackdatedCorrectionTest
A policy is a document, not a join Whole snapshot as JSONB per version, cached in Redis under one key HotContractState, HotContractStateTest
Redis is an accelerator, not a truth Read-through from Postgres on miss HotContractState, HotContractStateTest
Reassign a book with one write Effective-dated edges; a move appends one edge PartyHierarchy, PartyNetworkTest
Answer last year's org chart Edge resolution takes an asOf PartyHierarchy, PartyNetworkTest
Rules are versioned data Rate schedules are immutable published resources; every priced figure records its version RateScheduleCatalog, PremiumDecision
Every number is explainable Decision outcome stored beside the money it justified DecisionTrail, decision_record
Events cannot disagree with state Event written as a row under Transactional.MANDATORY OutboxAppend
No month-end window Short-interval dispatch loop OutboxDispatch
One model for any risk Line of business is a ComponentType value and a rate schedule row, not a subsystem ComponentType, term-life-1.0.json

Verify it yourself

cd backend/limen-server
mvn test

Postgres 18 and Redis 7 start as containers, Flyway applies the schema including the triggers, and eleven tests run. There is no H2 and no in-memory substitute anywhere: a claim about what a database refuses to do cannot be tested against a different database.

The two tests worth reading first are AppendOnlyLedgerTest, which issues raw UPDATE and DELETE statements against the ledger and asserts the database refuses them, and BackdatedCorrectionTest, which is the scenario the platform is pitched on.

The scenario, end to end

A policy runs for nine months. A dependant that should have been covered from inception was never captured. In a legacy administration system this is a change request, a corrective script, a reconciliation and a maintenance window.

# 1. Quote. Components are priced against the current schedule and recorded as version one.
curl -sX POST localhost:8080/api/contracts -H 'Content-Type: application/json' -d '{
  "contractNumber": "LMN-2026-004471",
  "productRef": "TERM-LIFE",
  "currency": "ZAR",
  "effectiveAt": "2025-11-08T00:00:00Z",
  "parties": [{"partyReference": "PTY-1", "name": "Thandi Mokoena", "role": "POLICYHOLDER"}],
  "components": [{"componentReference": "CMP-LIFE", "componentType": "RISK_LIFE",
                  "sumAssured": 500000, "ratedAge": 34, "effectiveFrom": "2025-11-08"}]
}'

# 2. Put it in force. A transition is a new version, not a status column being overwritten.
curl -sX POST localhost:8080/api/contracts/LMN-2026-004471/activations \
  -H 'Content-Type: application/json' -d '{"effectiveAt": "2025-11-08T00:00:00Z"}'

# 3. Read it. One key lookup, one complete document, no assembly.
curl -s localhost:8080/api/contracts/LMN-2026-004471

# 4. Raise premium for a month, then take the money. Replay the same call and nothing moves twice.
curl -sX POST localhost:8080/api/ledger/contracts/LMN-2026-004471/premium-due \
  -H 'Content-Type: application/json' \
  -d '{"amount": 235.00, "period": "202511", "effectiveAt": "2025-11-08T00:00:00Z",
       "idempotencyKey": "LMN-2026-004471:202511"}'

# 5. The correction. Add the child from inception and replay everything since.
curl -sX POST localhost:8080/api/timelines/LMN-2026-004471/corrections \
  -H 'Content-Type: application/json' -d '{
  "action": "ADD",
  "componentReference": "CMP-FUNERAL-CHILD",
  "componentType": "RISK_FUNERAL",
  "sumAssured": 20000,
  "ratedAge": 8,
  "effectiveFrom": "2025-11-08",
  "effectiveAt": "2025-11-08T00:00:00Z",
  "reason": "child omitted at inception"
}'

The response to step five states the version it branched from, the versions the replay created, the number of periods covered, what should have been charged, what was charged, and the single difference posted. Then:

# The whole timeline, including the fork and the history it branched from.
curl -s localhost:8080/api/timelines/LMN-2026-004471

# The contract as it is understood today.
curl -s 'localhost:8080/api/timelines/LMN-2026-004471/as-at?effectiveAt=2025-11-08T00:00:00Z'

# The contract as it was understood before the correction arrived. The child is absent,
# because on that date the platform had not been told. This is the query that reissues an
# old statement unchanged, and the one an overwriting system cannot answer at all.
curl -s 'localhost:8080/api/timelines/LMN-2026-004471/as-at?effectiveAt=2025-11-08T00:00:00Z&knownAt=2026-08-01T00:00:00Z'

# Every entry, none of them edited. Balances derived by summing them.
curl -s localhost:8080/api/ledger/contracts/LMN-2026-004471/entries
curl -s localhost:8080/api/ledger/contracts/LMN-2026-004471/balances

# Every decision that shaped the contract, with the rule version behind each figure.
curl -s localhost:8080/api/decisions/contracts/LMN-2026-004471

Not yet built

Kept explicit so that absence is never mistaken for an oversight, and so nobody demonstrates a stub as a feature.

  • DMN engine. Rules are versioned data evaluated by a pure function today. Kogito or fords-automation plugs in behind RateScheduleCatalog and PremiumDecision. Held back because Kogito's release cadence trails Quarkus and the version pairing is a decision, not a detail.
  • Product factory. Component templates, product configuration and campaigns. A product component to be designed.
  • Scheduled milestones. Escalations, renewals, benefit expiries, pre-alerts. Belongs on fords-scheduler with fords-comm for delivery, hanging off the outbox loop that already runs.
  • Multi-tenancy and data residency. Cell-per-client is a deployment topology decision. It changes little in this code and guessing at it now would add noise.
  • CQRS read models. The snapshot document is sufficient at this size. Projections come when a real query load exists to shape them.
  • Claims, reinsurance, co-insurance, commission calculation, telemetry-driven pricing. Documented, not coded.
  • Native image and load numbers. The stack is native-ready. No latency figure should be quoted until it is measured.

The honest summary for a technical audience

What is different here is not the framework. It is that the platform has no way to overwrite a financial fact or a historical one, and that correcting the past is an ordinary, tested operation rather than an incident. Everything else in the architecture follows from those two properties, and both are enforced by the database rather than by discipline.