Cashflow Risk Intelligence
Which of a UK small business's unpaid invoices could break its cash runway, when the risk appears, and what to do this week: from an invoice CSV it forecasts a 13-week runway, ranks invoices by expected cash at risk with a plain-English reason on every score, enriches customer risk with Companies House filings, and writes the week's action brief — behind tested multi-tenant RBAC, a STRIDE threat model, and a DPIA.
Python · FastAPI · PostgreSQL · Next.js · +3
Key finding

The problem
Late payment is the classic small-business killer: the danger isn’t one bad invoice, it’s not seeing when unpaid invoices collide with the cash runway. This project models that end to end — forecast the 13-week runway, rank the invoices by expected cash at risk (late-payment probability × amount), and turn it into a deterministic weekly chase list.
Applied data science, done honestly
- Leakage-safe as-of feature store and a pinned late-payment label with censoring.
- A rolling-origin, group-aware backtest with the right metrics for a rare, ranked problem: PR-AUC against prevalence, top-decile precision, and calibration.
- A rules → logistic → gradient-boosted bake-off tracked in MLflow. On the synthetic data the fitted models tie the rules baseline, and the evaluation explains why: a latent “health-oracle” ceiling shows the predictive signal is a macro factor unobservable at prediction time without leakage. The tie is reported, not hidden.
- An anti-circular synthetic data generator (the latent mechanism the model never sees), so the demo data can’t flatter the model.
Security as a build-time requirement
Confidential financial data is treated as a first-class constraint, with several controls enforced by tests: multi-tenant isolation and RBAC with cross-tenant refusal (tested), a STRIDE threat model, a DPIA and privacy notice, PII-scrubbed error reporting (asserted by a test), CSV-injection-safe exports, an append-only audit log, retention auto-purge, and self-serve data export/delete. Raw uploads are never stored — only derived results.
Delivery
A pure-Python analytics engine behind a FastAPI service, PostgreSQL system-of-record with migrations, a Next.js dashboard, and CI running ruff, strict mypy, pytest, a migration-apply-and-drift check, and the Next build — with SHA-pinned actions.
The hosted demo was retired on 29 July 2026 and is deliberately not replaced. The free Postgres tier expired thirty days after creation, so migrations short-circuited, nothing bound the port, and the edge hung for 75–120s rather than failing. ADR 0003 records the options and the amendment that followed: a paid tier was not authorised, a SQLite fallback was rejected on sole-source-of-truth grounds with a do-not-re-propose clause, and a free non-expiring Postgres that would have worked was found late and declined on portfolio grounds rather than technical ones. The services are suspended, not deleted, so the decision is reversible. The screenshot is the console as it ran.
Honest limits
A reference project, not a commercial product: no real customer data, and the phased product roadmap and production-pivot plans are frozen as a record of the planning and threat-modelling. Model performance claims are scoped to the synthetic benchmark — that’s the point of reporting the tie.