Finance  ·  2026

Deal Engine

Desktop underwriting for merchant cash advance and multifamily — screening, modelling and IC packet generation over one local deal store.

2 Asset classes
85 Unit tests
11 E2E tests
11 SQLite migrations

2 Asset classes

Finance

2026

Key decisions

  • Screening, modelling and the IC packet all read from one assumption set, so changing a rate moves the screen, the model and the memo together instead of drifting across three documents.
  • It is a desktop application because the inputs are confidential and arrive as files, so the vault encrypts attachments with AES-256-GCM under scrypt-derived keys and nothing transits a server.
  • Persistence runs on node:sqlite, the runtime's built-in SQLite, so an Electron upgrade never strands the app on a native module waiting for an ABI rebuild.
  • Pinned underwriting scenarios are stored as immutable, hash-stamped snapshots of the model output, so the exact numbers behind a past decision survive every later change to the model.
Schematic

Where underwriting actually leaks

The analytical work in a deal is not the hard part. The leak is everywhere else: assumptions living in one analyst’s workbook, a memo hand-copied from a model that has since changed, and no way to answer “what did we assume in March” without opening a file nobody can find.

Deal Engine 2.0 replaces two product-specific predecessors — one merchant cash advance platform, one multifamily platform — with a single modular monolith. Import adapters in src/main/importers map legacy records and stage names from both tools into one unified deal model, and a reconciliation report tracks every migrated document through attachment, extraction and dead-letter states, so the cutover itself is auditable.

Screening, modelling and the IC packet sit over one assumption set. Change a rate and the screen, the model and the memo move together, because they are three views of the same object rather than three documents.

Two asset classes, one spine

Product logic lives in the main process under src/main/products, not in React components; a thin dispatcher routes each deal to its module by productType.

Merchant cash advance — a readiness model evaluated against per-funder profiles: factor-rate yield floors, holdback tolerance and current-position (stacking) limits, with explicit reasons when a deal falls outside a funder’s envelope, plus a document-readiness signal from the vault. The submission desk gates funder submission on that readiness output.

Multifamily — pro forma through to debt: effective gross income, NOI, amortisation with interest-only periods, DSCR and break-even NOI at a 1.20x covenant, exit-cap and NOI-growth sensitivity, ranked tornado drivers, rate-stress floors, project IRR and equity multiple. A fund ledger alongside tracks LP commitments, capital calls and distributions.

Pinned scenarios are stored as immutable, hash-stamped snapshots of the module output, so the exact metrics behind a past decision survive later changes to the model — every output states which version produced it.

Why desktop

The inputs are confidential and frequently arrive as files. The document vault encrypts attachments with AES-256-GCM under scrypt-derived keys, and a durable extraction queue parses PDF (pdfjs-dist) and Excel (read-excel-file) attachments into review findings without the file transiting anyone’s server. Persistence is node:sqlite — the runtime’s built-in SQLite, so no native module ever needs an ABI rebuild — behind repository interfaces and eleven versioned migrations.

The renderer is sandboxed with contextIsolation and no Node integration; every privileged call crosses a typed, Zod-validated IPC boundary exposed through a narrow preload bridge. Playwright drives the regression suite over the real UI — pinning a scenario, transitioning a stage, surviving a restart — because an underwriting tool that silently changes a number is worse than no tool.