Architecture, perimeter, data

Seven components, one language model (optional, not used in the prototype)

1 · Intakepdf.js text layer with positions; SheetJS for XLSX/CSV; tesseract.js (uzb + rus + eng, self-hosted) for receipt photos. Field confidences; low-confidence fields need a tap to confirm.
2 · CategoriserMultilingual keyword rules plus counterparty patterns (recurring payer → family transfer; a mask that both sends and receives → own card).
3 · Cash-flow12-month series: regulatory income (cl.18), business revenue, non-business, excluded inflows, debt service. 18 features, identical in Python and TypeScript (parity-tested).
4 · Rule engineDBR clause by clause (CBU Regulation No. 3618 for banks): 50% limit and the 15% quota bands (cl.3), cl.4 exemptions, guarantor-only-if-overdue (cl.7), 36/60/180-month spreading (cl.8), 6–12-month income with the median option (cl.13–14), account receipts as income (cl.18); maximum affordable amount back-solved; every line cites its clause.
5 · Risk modelXGBoost with monotone constraints, exported to JSON and evaluated in the browser; one-at-a-time attributions against the portfolio median.
6 · IntegrityBalance-chain reconciliation, duplicates, coverage, gaps, pre-application inflow spikes, circular transfers, cross-document holder match, stated vs implied opening balance.
7 · Memo + verifierTemplate memo from a fact table; the verifier rejects any number not in the table. Hash-chained audit log with engine versions and the officer's decision.

Nothing here is a prompt to a general-purpose model. The production design adds a local open-weight LLM for free-text narrative only, inside the same perimeter, constrained to the fact table by the same verifier.

Perimeter

The prototype is a static site: every byte of a customer document is parsed in the officer's browser and never transmitted. Production is the same bundle served from the bank's own web server (Docker, no outbound network), with the officer's identity from the bank's SSO and the audit log persisted to the bank's database instead of the browser session. Statements of MKBANK's own account holders come from the core banking system directly; uploads are only needed for other banks' statements and wallets.

Human in the loop: the engine recommends, computes the maximum affordable amount and flags; the loan officer decides, and an override requires a reason that is written into the chain.

Regulatory spine

CBU Regulation No. 3618 for banks — "on macroprudential norms set for banks and on the maximum values of payments on loans (microloans) issued by them" (Board decision 7/3 of 8 April 2025, registered 22 April 2025, in force 24 July 2025, amended by decision 31/9 of 5 December 2025; lex.uz/uz/docs/7491592): definition (cl.2), 50% limit and the two 15% quotas (cl.3), exemptions for individual entrepreneurs, family-programme and education loans (cl.4), which loans count and the 30-day guarantor rule (cl.7), 36/60/180-month spreading (cl.8), 3-working-day calculation window (cl.12), 6–12-month income averaging (cl.13) with the median option (cl.14), account receipts as income (cl.18), documented evidence (cl.19). The earlier regulation No. 3205 (lex.uz/docs/4654149) applies since 24 July 2025 to microfinance organisations and pawnshops only and is not used. Products referenced: MKBANK Ommabop 2, Express, Business Online 2, family-entrepreneurship programmes (mkbank.uz).

Personal data: processed inside the bank only, with the borrower's consent recorded in the case; the public demo deletes nothing because it stores nothing — close the tab and the case is gone unless exported.

Data sources and licences

SourceUsed forLicence / terms
Daromad synthetic generator (synth/, seed 42): 2,000 borrowers, 5.7M transactions, 60 rendered statement sets, 180 receipts, 40 tampered statementsTraining, evaluation, demo samplesMIT (this repository). Parameters declared in data/synthetic/summary.json. No real person represented.
Berka / PKDD'99 Financial data set (Czech bank, 1993–98), mirror github.com/jlacko/berka-datasetMethodology validation of cash-flow features → default on real anonymised dataAcademic challenge data; no licence stated by the original authors — used for evaluation only, not redistributed in this repo
Tesseract language data (tessdata_fast: uzb, uzb_cyrl, rus, eng)Receipt OCRApache 2.0
tesseract.js, tesseract.js-coreOCR runtimeApache 2.0
pdf.js (pdfjs-dist)PDF text extractionApache 2.0
SheetJS CE 0.20.3 (npm alias @e965/xlsx, an automated republish of the vendor build)XLSX/CSV parsingApache 2.0
XGBoost, scikit-learn, NumPy, pandas, OpenCV, Playwright, Jinja2, qrcodeTraining and synthetic renderingApache 2.0 / BSD-3 / MIT (see README)
Next.js, ReactApplicationMIT
CBU regulation texts (lex.uz)Rule engine, citationsPublic legal information
stat.uz wage releases; CBU statistics; MKBANK public pagesCalibration anchors and business casePublic information, cited in the deck