Skip to content

Kovent Architecture Doctrine

The laws

Status: Locked. Version: 0.1 Date: 2026-08-11

This document states the architecture of Kovent. It is written to survive scrutiny from principal engineers, database specialists, auditors, and a regulator's legal team. It states what is required, how it is enforced, and where the hard problems are.

Ten laws. Each has a mechanism, because a principle with no enforcement is a preference.


1. Templates are data

No return may be hard-coded. A return's sections, fields, data types, formulas, validation rules, thresholds, attachment requirements, and reviewer checklist are configuration held in Return Studio and versioned with effective dates.

Mechanism. There is no code path that names a specific return. The submission API accepts (templateCode, templateVersion, values). A build-time check fails the pipeline if a return code appears as a literal outside test fixtures and seed configuration.

Consequence. Adding R31 is configuration plus a spec page. It is not a release.


2. Nothing is overwritten

Submissions, decisions, scores, and configuration are append-only. An amendment or resubmission creates a new version and the prior version remains addressable forever.

Mechanism. Strata holds submissions as immutable rows keyed by (obligationId, version). There is no UPDATE statement against a submitted return. The "current" version is a pointer, and moving the pointer is itself a sealed event.

Consequence. "What did the firm tell us on 11 August, before the query?" is a query, not an archaeology project.


3. Every rule cites its authority

A validation result carries the directive, statutory instrument, or template rule it derives from. A rule with no citation is a defect, not a feature.

Mechanism. The rule definition in Return Studio has a mandatory citation field. Assay propagates it into every result. The reviewer UI renders it next to the finding, and the query raised from that finding quotes it to the firm.

Consequence. A rejection is defensible on its face. The firm is told which instrument it fell short of, not merely that a number looked wrong.


4. Computed figures are never typed

If the platform can derive a figure, the firm cannot enter it. Capital surplus, early warning ratio, totals, and variances are computed from inputs.

Mechanism. Template fields are declared input or derived. The submission API rejects any document containing a value for a derived field. The UI marks these sections platform-derived and renders them read-only.

Consequence. Arithmetic disputes disappear. A disagreement becomes a disagreement about inputs or about the formula — both of which are visible and versioned.


5. Every state change is sealed

Actor, timestamp, action, reason, prior state hash, and new state hash — for every transition across every engine.

Mechanism. Seal writes a hash-chained append-only log. Each entry includes the hash of its predecessor, so removal or alteration of any entry breaks the chain and is detectable. Entries are written in the same transaction as the state change they describe.

Consequence. The audit trail is legally defensible by construction rather than by policy. A regulator can prove the record was not edited after the fact.


6. Maker-checker is structural

The user who prepares a return cannot be the user who certifies it. The reviewer who raises a query is not blocked from deciding, but a decision above a configured materiality requires a second supervisor.

Mechanism. Enforced in the engine, not the UI. The certify endpoint rejects a request where certifierId == preparerId. Roles are distinct grants in the identity provider, not a boolean on a user record.

Consequence. The control cannot be bypassed by calling the API directly, which is exactly the attack an auditor will ask about.


7. Reading never blocks writing

Dashboards, heatmaps, sector analytics, and export packs are served from Projections, never from the write path.

Mechanism. State changes emit events through a transactional outbox. Projection consumers build denormalised read models in a separate schema with read-only credentials. A slow analytical query cannot lock a submission.

Consequence. Quarter-end is the moment when every firm files and every supervisor runs reports. Those two activities must not contend.

Cost, stated plainly. Projections are eventually consistent, typically sub-second. Any screen where staleness is unacceptable — the return the reviewer is deciding on right now — reads the record directly. We choose per screen, and the choice is documented on the screen's spec.


8. Time is explicit and bi-temporal

Two clocks, always distinguished: business time (the period a figure describes, when a deadline falls, when a licence takes effect) and system time (when we learned it).

Mechanism. Records carry effectiveFrom/effectiveTo and recordedAt. Queries state which clock they mean. Template versions have effective dates, so a return for Q1 is validated by the rules that were in force in Q1 — not by today's rules.

Consequence. "Show me the sector's capital position as we understood it in June" and "as we understand it now" are both answerable, and they are different answers. Retrospective re-validation against current rules is possible but is always an explicit, labelled operation.


9. Deadlines are computed, not stored

A due date is derived from the obligation: licence category, template frequency, period end, notice period, and the working-day calendar including public holidays.

Mechanism. Cadence computes and materialises obligations on a schedule and on change. Calendars and adjustment policy are configuration. A holiday added in Return Studio shifts every affected obligation, and the shift is sealed.

Consequence. Late is a fact the platform asserts, with the calendar arithmetic shown. It is not a supervisor's recollection, and it survives a challenge over a public holiday.


10. Risk scores are explainable

A score is never a bare number. It decomposes into weighted, named drivers, each traceable to the submission, breach, or finding that produced it.

Mechanism. Prism stores the driver breakdown alongside the score, with the model version and weights used. A supervisor may override a rating; the override requires a reason and never deletes the computed score.

Consequence. A firm can be told why it is rated high risk. A supervisor can defend the rating at a hearing. Model changes are visible as model changes, not as unexplained score drift.


The write path

Every command follows this path. It is the most important flow in the system.

[Command — submit / certify / decide / score]
[Idempotency check] ────────► key seen? ──► return prior result
[Authorise] ────────────────► actor mandated for this firm + return?
        │                     maker ≠ checker where required
[Resolve template version] ─► the version in force for the period
[Conformance check] ────────► document matches template shape?
        │                     no values for derived fields?
[Assay: validate + compute] ► DMN rules, each with a citation
[Strata: append version] ───► immutable row, current pointer moved
[Seal: chain entry] ────────► same transaction as the append
[Outbox: enqueue events] ───► same transaction again
        ═══ transaction commits here ═══
[Kafka] ──► Prism (rescore) ──► Bench (queue) ──► Projections (read models)

Everything above the commit line is one transaction. Everything below is asynchronous. The boundary is deliberate and is the reason a projection can never claim something the record does not contain.

Multi-tenancy

Kovent is built for SECZim first and for configurable supervisor deployments after. A tenant is a supervisory authority, not a firm.

  • Tenant is a first-class column on every table, enforced by row-level security
  • Return catalogues, calendars, thresholds, and scoring models are per tenant
  • A firm belongs to exactly one tenant; cross-border data sharing is an integration, not a join
  • The Zimbabwe deployment ships with the SECZim catalogue as seed configuration, not as code

Known hard problems

Stated rather than hidden. These are where the design will be tested.

Problem Current thinking
Template migration A firm holds a draft against v2.3 when v2.4 takes effect. Drafts pin their version; the firm is prompted to migrate, and the migration is a diff it must accept. Unresolved: whether a supervisor can force migration mid-period.
Cross-return consistency R02 must agree with R01 for the same period. Cross-return rules need both returns present, which means validation is partly deferred and re-run on arrival of the second. Design not finalised.
Retrospective rule changes If a threshold was wrong, does the supervisor re-validate accepted returns? Technically yes via re-run against a chosen version. Policy question, deliberately left to the supervisor with the result labelled.
Penalty computation Requirement calls for configurable penalty hooks. Penalties are legally sensitive and jurisdiction-specific; Kovent computes a recommendation and never issues automatically.
Excel round-trip fidelity Firms will want to prepare in Excel. Import must map to template fields and reject on mismatch rather than coercing. The failure mode to avoid is silent coercion.
jsonb query performance at scale Mitigated by expression indexes and projections, but unproven. Needs load testing against a realistic catalogue before we commit.
  • Manifesto — the claims these laws enforce
  • Stack — the technology, with the jsonb argument in full
  • Engines — where each law is implemented
  • Submission lifecycle — the laws seen from the firm's side