Projects using TypeScript in SindhProjects using TypeScript in Sindh
Cover image for KovaRisk: When the Interface Knew
KovaRisk: When the Interface Knew More Than the System ────────────────────────────────────────── The Expert in the Room Compliance officers don't struggle to understand risk. They struggle to act on it fast enough. The team behind KovaRisk understood this precisely. They had spent years inside financial institutions watching the same dysfunction repeat: alerts buried in spreadsheets, investigations tracked in email threads, audit trails reconstructed after the fact. They knew what the interface needed to feel like because they'd lived with the one that didn't. So they built it. Fast. Exactly as they'd imagined it. What emerged was sharp: a risk monitoring dashboard with filterable alert feeds, entity profiles with 12-month risk trajectories, a rule engine with toggle controls, and an audit log that felt immutable. The scenario switcher let compliance teams stress-test different alert load states. The side panel made investigations feel contained and intentional. It looked like a system that had survived production. It hadn't been asked to yet. ────────────────────────────────────────── What Existed Was a Strong Interface - Not a System Every alert in KovaRisk was generated at startup. Every risk score was computed by a random seed function. Every status change - Investigating, Resolved, Escalated - lived in component state. Every timeline event was appended to an in-memory array. Every rule toggle disappeared on refresh. The audit log recorded nothing. The export downloaded a snapshot of what React was holding at that moment. The entity risk history was a curve drawn from a formula, not a record. The logic was there. But it had nowhere to live. A compliance officer investigating a high-risk wire transfer would open the side panel, read the plain-English rule explanation, mark the alert as Investigating, add an internal note - and lose every one of those actions the moment they refreshed the browser. No colleague could see what they'd done. No regulator could verify it had happened. In financial compliance, that's not a UX problem. It's a liability. The prototype validated the workflow brilliantly. It exposed exactly how a compliance team would move through their day. But three things were missing: a source of truth, a coordination layer, and a trail that could be audited under pressure. ────────────────────────────────────────── They Didn't Need More Features - They Needed a System Behind the Interface The team came with a clear idea and a working prototype. What they needed was the architecture that made the prototype a product - the layer that turned interface actions into durable facts. Not a rebuild. A foundation. ────────────────────────────────────────── The Layer That Made It Dependable Data Models: Giving State a Home The first thing to reconstruct was where the data should actually live. KovaRisk's frontend implied a clear schema - alerts, entities, rules, audit events - but none of it persisted. The production system needed a PostgreSQL core with five primary entities: • Alert — with foreign keys to Entity, Rule, Transaction, and a JSONB timeline column for ordered event history • Entity — with risk tier, jurisdiction metadata, and a one-to-many relationship to RiskScore snapshots • Rule — with active/disabled state, trigger thresholds, false-positive tracking, and a versioning mechanism so changes to rules didn't retroactively alter historical alerts • AuditEvent — append-only, with actor ID, action type, target reference, and a server-generated timestamp that clients cannot modify • InternalNote — owned by an alert, with authorship and a soft-delete flag to preserve compliance integrity Every status change, note, escalation, and flag the UI handled ephemerally became a write to this schema. The Alert Generation Engine: Replacing the Seed Function In the prototype, 85 alerts appeared because a loop ran 85 times at startup. In production, alerts are the output of a Transaction Monitoring Service - a background process that runs continuously against incoming transaction streams. This service: • Evaluates each transaction against every active Rule definition • Computes a risk score using rule weights, entity risk tier, jurisdiction flags, and behavioral baselines • Creates an Alert record only when a threshold is breached • Emits an event to a notification queue for high-risk triggers The rule engine the UI let users toggle wasn't decorative. Each rule mapped to an evaluation function in the monitoring service. Disabling a rule didn't just grey out a card - it removed it from the active evaluation set. Re-enabling it didn't retroactively generate alerts it would have caught; it resumed from the point of activation. That distinction mattered for regulatory defensibility. ────────────────────────────────────────── Async Workflows: The Operations the UI Implied But Couldn't Sustain Several interactions in the prototype implied workflows that couldn't complete synchronously. Escalation - When an alert was escalated, the UI changed a status badge. In production, escalation triggers a queue job that: notifies the senior compliance officer via a configured channel, creates a case record linking the alert, and starts a response SLA timer. The UI reflects the outcome - it doesn't produce it. Scheduled Screening - The Sanctions Screening Match rule in the prototype was static. In production, it's a nightly job that re-screens all active entities against updated OFAC, EU, and UN sanctions lists - generating new alerts if a previously clean entity now appears. The results feed back into the alert pipeline. Report Export - The dashboard's Export Report button downloaded a text file of whatever React was holding in memory. In production, report generation is an async job: the user requests the report, the job runs server-side against the live database, and a download link is returned when ready. The content is a verifiable, timestamped record - not a UI snapshot. ────────────────────────────────────────── The Audit Log: From Feed to Fact The prototype's audit log was populated by a generateAuditLog function. It looked comprehensive and immutable. It was neither. Production audit events are written by the API layer on every state-modifying operation - before the response is returned to the client. The table is append-only. No update operations are permitted on AuditEvent records. Timestamps are server-generated in UTC and stored with full precision. Actor identity comes from the authenticated session, not from a string the client sends. The audit log the interface displayed was a simulation of accountability. The production version is the accountability. ────────────────────────────────────────── Tech Stack 1. Frontend: React + Vite, React Router v6, Recharts, React Context + local state, TanStack Query 2. Backend: Node.js + TypeScript, Fastify, Prisma, PostgreSQL, Redis, BullMQ, Passport.js + express-session 3. Infrastructure: AWS ECS / Railway / Render, S3, AWS Secrets Manager / Doppler, Sentry + Datadog, GitHub Actions 4. External Integrations: OFAC / ComplyAdvantage, Refinitiv World-Check, SendGrid / SMTP, Webhooks  ────────────────────────────────────────── From Interface to System The prototype answered the right questions. It proved the workflow was sound, the information hierarchy was correct, and the alert investigation pattern worked the way compliance officers needed it to. What it couldn't answer was: what happens when two investigators open the same alert simultaneously? What happens when a rule change needs to take effect immediately across 200 pending alerts? What happens when a regulator asks for every action taken on a specific entity over the past 18 months? Those questions don't live in the interface. They live in the system. KovaRisk's interface was always strong. What it needed was the architecture to make it real - persistent, coordinated, auditable, and defensible under scrutiny. The logic existed from the beginning. We gave it somewhere to live.
2
1.9K
Cover image for KovaRisk: Turning a Risk Monitoring
KovaRisk: Turning a Risk Monitoring Prototype Into a Production-Ready Fintech Platform From Interactive Compliance Dashboard to Persistent Risk Intelligence System KovaRisk started with a clear goal: give compliance teams a centralized way to monitor financial risk, investigate alerts, manage rules, and maintain reliable audit records. The original prototype already had a strong product foundation. It included: Risk and alert monitoring dashboards Filterable alert feeds Entity-level risk profiles Historical risk trends Configurable monitoring rules Investigation workflows Audit activity Scenario-based testing The interface effectively demonstrated how a compliance team could interact with the product. The challenge was that most of the underlying functionality was still simulated. The Gap Between the Prototype and Production The frontend represented a complete risk-management workflow, but much of its state existed only inside the browser. Alerts were generated when the application started. Risk scores were simulated. Status changes were stored in component state, and audit events existed only in memory. Refreshing the application could erase an investigation update, internal note, or rule configuration. For a financial compliance platform, persistence isn't simply a technical requirement. Investigations, decisions, and user actions need to remain traceable and verifiable. The next phase was therefore focused on building the system behind the interface. Building the Production Foundation Structured Data Architecture We translated the prototype's workflows into a persistent relational data model using PostgreSQL. The architecture introduced dedicated entities for: Alerts Financial entities Monitoring rules Risk-score history Audit events Internal investigation notes Transactions Relationships between these entities allowed actions performed through the interface to become durable records rather than temporary frontend state. Rule versioning was also introduced so historical alerts could remain associated with the conditions that existed when they were generated. Real-Time Alert Generation The prototype initially generated a predefined set of alerts. We replaced this behavior with a transaction-monitoring architecture capable of evaluating incoming transactions against active compliance rules. The system could: Evaluate transactions against configured rules Calculate risk scores Consider entity and jurisdiction risk Identify threshold breaches Create persistent alert records Trigger notifications for high-risk events Rule controls in the dashboard became connected to the actual monitoring engine. Disabling a rule affected future evaluations rather than simply changing the appearance of a UI component. Asynchronous Compliance Workflows Several actions required more than a simple frontend state change. We introduced background processing for operational workflows such as: Alert Escalation Escalating an alert could initiate notifications, create a corresponding case, and begin tracking the response timeline. Scheduled Screening Entities could be periodically screened against external sanctions data, with newly identified matches feeding back into the alert workflow. Report Generation Instead of exporting whatever happened to be loaded in the browser, reports were generated server-side from the current database state and made available once processing completed. This created a more reliable separation between the user interface and the underlying business operations. Building a Reliable Audit Trail One of the most important parts of KovaRisk was transforming the audit interface from a simulated activity feed into a persistent record of system events. Audit events were generated at the API layer whenever important state changes occurred. Each event captured: Authenticated user Action performed Target entity Event type Server-generated timestamp Relevant activity context The audit records were designed to be append-only, preventing normal application workflows from modifying historical events. This gave compliance teams a much more dependable record of how alerts and investigations progressed. Technology Stack Frontend: React, Vite, React Router, Recharts, TanStack Query Backend: Node.js, TypeScript, Fastify, Prisma Database & Processing: PostgreSQL, Redis, BullMQ Authentication: Passport.js, Express Session Infrastructure: AWS ECS, Railway / Render, Amazon S3 Security & Monitoring: AWS Secrets Manager, Doppler, Sentry, Datadog Integrations: OFAC / ComplyAdvantage, Refinitiv World-Check, SendGrid / SMTP, Webhooks The Result KovaRisk evolved from an interactive compliance prototype into a structured fintech risk-monitoring platform. The interface remained focused on the workflows compliance teams needed, while the underlying architecture introduced: Persistent data Automated alert generation Configurable rule processing Background workflows External screening integrations Reliable report generation Role-aware system operations Persistent audit records The key transformation wasn't adding more screens. It was connecting every important interaction in the interface to a dependable backend process. The prototype demonstrated how compliance teams should work. The production architecture made those workflows persistent, automated, and operationally reliable.
0
65