Skip to content

Stack

Technology and rationale

Status: Bootstrapping. Record path and Registry write surface are live; UI shell under Quinoa. Version: 0.3 Date: 2026-08-12

Every choice here has to survive the question why not the boring option? Where the boring option wins, we take it.

Two deployables, two Quarkus lines

Kogito 10.2.0 pins Quarkus 3.27.2. Bundling DMN into the record server would force the whole platform onto that older line. So Kovent is deliberately two artefacts:

Deployable Quarkus Role
kovent-server 3.38.1 Record path — Registry, Strata, Seal, Cadence, Bench, Prism, Docket, Projections, Quinoa UI
kovent-automation 3.27.2 (via fords-automation-platform) Assay decision host — Kogito DMN/BPMN, worksheets, decision audit

Assay in kovent-server calls kovent-automation over REST. That is the one place we accept a network hop in the write path, and it is forced by the platform version conflict rather than by a taste for microservices.

Fordsworth standard extensions on the server line: fords-scheduler (Cadence deadlines) and fords-comm (reminders and outcome notices). Both independently number Flyway migrations from V1.0.0, so each gets its own Postgres schema, its own named Flyway configuration, and its own schema_history table — see KD-011. fords-automation stays on the automation line only.

Runtime

Layer Technology Rationale
Compute Quarkus 3.38.1 (server), GraalVM native image Sub-second start, ~64 MB resident. A supervisor's dashboard should not wait on a JVM warming up, and a regulator's infrastructure budget is not elastic.
Reactive core Mutiny Non-blocking IO on the write path. Validation fan-out over dozens of rules must not hold a thread each.
Decision rules Kogito DMN 10.2.0 on kovent-automation Validation and prudential computation as decision tables a supervisor can read. Hosted via fords-automation-platform so the version pin stays off the record path.
Workflow Kogito BPMN on kovent-automation Review and enforcement lifecycles that need long-running process state. Hand-rolled state machines here become the thing nobody dares change.
Scheduling fords-scheduler (Quartz, clustered JDBC, own scheduler schema) Cadence materialises obligations and escalates lapsed deadlines once per cluster, not once per node.
Communications fords-comm (own comm schema) Reminders and outcome notices.
Web tier Quarkus REST (JAX-RS) + Quinoa Quinoa serves the front-end from the same artefact, so there is one origin and no CORS story for the UI.
Front-end Angular 22 + Tailwind 4 + Lucide (src/main/webui) One SPA under Quinoa. Signals and Signal Forms; no NgRx or UI kit on bootstrap. The design system is prototyped in Next.js for velocity; production tokens and screens land in Angular. Conventions: Front-end.

Data

Concern Technology Rationale
System of record PostgreSQL Returns are template-shaped, so submitted values live in jsonb keyed by field id and validated against the template version. Structural data — licences, obligations, cases, audit — is fully typed and constrained.
Current state Redis Hydrated current submission documents and idempotency keys. A read of "the return as it stands" must not reassemble versions on every request.
Events Kafka via transactional outbox The outbox keeps event emission in the same transaction as the state change, so a projection can never diverge from the record that caused it.
Documents S3-compatible object store Attachments are content-addressed and checksummed. The checksum goes in the audit trail; the bytes do not go in the database.
Search PostgreSQL full-text Sufficient for firm and return lookup at supervisory scale. Revisit only if measurement demands it.
Analytics Projection tables in PostgreSQL Flattened, typed, denormalised read models. Separate schema, separate credentials, no writes.

Why jsonb for submitted values

This is the load-bearing data decision, so it gets argued rather than asserted.

A configurable return template means the column set is not known at build time. The three options:

Option Verdict
A table per return type, generated by DDL Rejected. Migrations become a runtime concern and thirty returns become thirty schemas that drift.
Entity-attribute-value rows Rejected. Every read becomes a pivot, and the query plans get ugly fast.
jsonb document per submission, validated against the template version Chosen. One shape, indexable with expression indexes on the fields that matter, and the template version is the schema.

The cost is that jsonb will not enforce field types — so Assay validates on write and the write is rejected if the document does not conform to its template version. The schema guarantee moves from the database to an engine we control and can cite. Projections then flatten the fields analysts actually query into typed columns, so reporting gets real types and real indexes.

Platform

Concern Technology Rationale
Identity OIDC (Keycloak), per-firm realms or groups Firms authenticate as their own tenant. Maker and approver are distinct roles, not a flag on a user.
Authorisation Attribute-based, evaluated per firm and return A firm user may only see obligations for licences they are mandated to act on.
Observability OpenTelemetry, Micrometer, structured JSON logs Trace a submission from portal to projection through one trace id.
Deployment OCI containers, Kubernetes or plain hosts Native images run anywhere. No requirement for a managed platform the regulator cannot procure.
Docs MkDocs Material, Cloudflare Pages This site. See Publish docs.

What we are deliberately not doing

Not doing Why
Microservices per engine Engine boundaries are module boundaries first. The only extra deployable is kovent-automation, forced by Kogito's Quarkus pin — not a taste for distribution.
Embedding Kogito in kovent-server Would pin the record path to Quarkus 3.27.2 and fight every Quarkus upgrade thereafter.
An event-sourced write model Append-only versioning gives us the audit properties we need without the replay complexity. Revisit if a real requirement demands it.
A rules DSL of our own DMN is a standard with tooling and a specification. Ours would have neither.
Excel as an integration contract Excel import is a convenience for firms. It is never the source of truth; the template is.
A React production front-end The prototype is React for speed of design. The product UI is Angular under Quinoa.