Decision log¶
Status: Living document. Append only — a superseded decision is marked, never deleted. Version: 0.1 Date: 2026-08-11
One row per decision. A decision recorded here has been made; an open question lives on the relevant engine or spec page until it becomes one of these.
KD-001 — Return templates are configuration, not code¶
Date: 2026-08-11 · Status: Accepted
Context. The requirement asks for a return-template engine so the supervisor can add, retire, or amend templates without a redevelopment cycle. The alternative is a screen and a model per return.
Decision. No return may be hard-coded. Templates, fields, formulas, rules, checklists, and due-date policy are versioned configuration in Return Studio.
Consequences. The UI must render any template generically, which is harder than thirty bespoke screens and is the reason Phase A exists to falsify it early. Field-level type safety moves from the database to Assay.
Rejected. A screen per return — fails the core premise. A code-generation approach that emits a module per template — moves the release cycle rather than removing it.
KD-002 — Submitted values stored as jsonb, validated against the template version¶
Date: 2026-08-11 · Status: Accepted
Context. A configurable template means the column set is unknown at build time.
Decision. One jsonb document per submission, keyed by field id, conformance-checked against its
template version on write. Analysts read flattened typed columns from
Projections.
Consequences. The database will not enforce field types, so the write path must. Expression indexes cover hot fields. Performance is an assumption until load-tested — an explicit roadmap gate.
Rejected. A table per return type generated by DDL — migrations become a runtime concern. Entity-attribute-value — every read becomes a pivot. Full argument in the stack.
KD-003 — Validation and computation as Kogito DMN¶
Date: 2026-08-11 · Status: Accepted
Context. Validation rules and prudential formulas change with directives and are the part of the system least appropriate for developers to own.
Decision. Rules compile to DMN decision tables executed by Kogito. The requirement's worked examples become test fixtures.
Consequences. A standard with tooling and a specification, readable by the supervisor who wrote the directive. Adds Kogito to the runtime. How much FEEL a supervisor authors directly versus through a builder UI is unresolved and determines how real the no-code promise is.
Rejected. Rules in Java — every threshold change becomes a release. A bespoke rule DSL — ours would have neither tooling nor a specification.
KD-004 — Append-only versioning rather than event sourcing¶
Date: 2026-08-11 · Status: Accepted
Context. The requirement demands a legally defensible trail and that resubmissions retain original version history.
Decision. Submissions and decisions are append-only versioned rows in Strata, with a current-version pointer. Not an event-sourced aggregate.
Consequences. We get the audit properties without replay complexity, and the current state is a row rather than a fold. Revisit only if a requirement genuinely needs temporal replay.
Rejected. Event sourcing — the audit benefit is available more cheaply and the operational cost is real. Soft deletes and status flags — insufficient for evidence.
KD-005 — Audit trail is hash-chained, in-transaction, and owned by an engine¶
Date: 2026-08-11 · Status: Accepted
Context. "Legally defensible" has to mean something a firm's counsel cannot dismiss.
Decision. Seal writes hash-chained entries in the same transaction as the state change, with periodic publication of the chain head.
Consequences. Alteration becomes demonstrable rather than deniable. Storage growth is linear and permanent — pruning is not available by design. Chaining alone does not stop a privileged actor rewriting from the point of alteration forward, which is why the published head is the anchor.
Rejected. An append-only table alone — protects against accident, not against a privileged actor. A logging library per engine — produces a log, not evidence, and cannot prove its own integrity.
KD-006 — Penalties are recommended, never issued automatically¶
Date: 2026-08-11 · Status: Accepted
Context. The requirement asks for configurable penalty parameters and calculation hooks.
Decision. Kovent computes a recommendation showing the parameters and facts relied on. A human issues.
Consequences. Slower, and correct. An automatically issued penalty is an administrative act taken by software, which a firm will challenge on process grounds before arguing the merits. Supervisory discretion is part of the legal framework, not a gap to automate.
Rejected. Automatic penalty issuance on overdue status.
KD-007 — Production front-end is web components, prototype is React¶
Date: 2026-08-11 · Status: Accepted
Context. The design system needed to move fast; the product needs a ten-year life.
Decision. The design system and prototype are Next.js and Tailwind. The production UI is web components with lit-html, served by Quinoa. Tokens in the prototype are the source of truth for both.
Consequences. Two expressions of the system, with drift risk mitigated by sharing token values —
this documentation site uses the same oklch values for the same reason. A framework rewrite in
year four is avoided.
Rejected. React in production — a supervisory tool should not inherit a framework's churn. Skipping the prototype — design velocity would have collapsed.
KD-008 — Engine boundaries are modules, not services¶
Date: 2026-08-11 · Status: Accepted
Context. Ten engines invites a service per engine.
Decision. One deployable. Engines are business components with boundary, control, and entity layers, enforced by package structure and build-time dependency rules.
Consequences. Transactional integrity across the write path is straightforward, which matters because Seal and the outbox must commit with the state change. Extraction later is possible because the boundaries are already explicit. A regulator does not need a distributed systems problem on day one.
Rejected. Microservice per engine — a distributed transaction problem in exchange for scaling we have no evidence of needing.
KD-009 — Documentation is MkDocs Material on Cloudflare Pages¶
Date: 2026-08-11 · Status: Accepted
Context. Kovent needs a browsable source of truth, matching how Limen publishes.
Decision. Markdown in docs/, MkDocs Material, strict build as a CI gate, Cloudflare Pages
deploying main to docs.kovent.fordsworth.com.
Consequences. Docs live in the same pull request as the change they describe. A broken internal link fails the build. See Publish docs.
Rejected. A wiki — drifts from the code and has no review gate. Docs in the design-system app — couples documentation to a prototype's lifecycle.
KD-010 — Three validation severities, not two¶
Date: 2026-08-11 · Status: Accepted
Context. A binary pass/fail model forces a choice between blocking honest disclosure and letting real breaches through.
Decision. FAIL blocks acceptance, ADVISORY flags without blocking, INFO records context. A
reported capital deficit is ADVISORY; a missing explanation for it is FAIL.
Consequences. Reviewers keep trust in the gate, because the gate only fires on genuine process failures. Spec authors must choose severity deliberately — guidance here.
Rejected. Binary pass/fail — over-blocking trains reviewers to override, and an override habit is worse than no gate.