FraudDesk reproduces the daily workflow of a fraud/risk/payments analyst at a bank or fintech (AIB, Revolut, Stripe, Citi) — a single running system, not a notebook. Transactions stream through Apache Kafka, get scored live by a rules engine fused with an XGBoost model, land as prioritised alerts in an analyst's case queue, get investigated against a full customer profile, actioned (block card, refund, chargeback, Claude-drafted customer SMS), tuned (a live threshold/rule Tuning Lab), reported (MI dashboards for leadership), and — where relevant — screened against sanctions lists with an auto-drafted Suspicious Activity Report. It's built for anyone hiring a fraud strategy analyst, a fraud data scientist, or a fraud engineer to be able to open it and think "this person has already done my job."
| Module | What it does | Key files |
|---|---|---|
| 1. Data platform | Synthetic Irish bank (Faker en_IE), sanctions list, 6 hand-built fraud scenarios, ETL into Postgres |
data/, db/ |
| 2. ML detection | XGBoost + SMOTE + SHAP, trained on engineered behavioural features | detection/features.py, detection/train_model.py |
| 3. Kafka streaming | Live transaction replay → rules + ML fusion → alerts, at-least-once, idempotent sink | streaming/, detection/rules_engine.py, detection/score.py |
| 4. Case management | FastAPI + Streamlit: alert queue, investigation, 4-eyes review, full audit trail | backend/routers/{alerts,cases}.py, ui/pages/1_Alert_Queue.py, ui/pages/2_Case_View.py |
| 5. Actions & comms | Block card, hold/release txn, refund, chargeback lifecycle, Claude-drafted customer SMS | actions/, backend/routers/actions.py |
| 6. Tuning Lab + MI | Live threshold/rule-weight simulation, champion/challenger, back-testing, leadership dashboards | backend/routers/{tuning,mi}.py, ui/pages/{4_Tuning_Lab,5_MI_Dashboard}.py |
| 7. Compliance | Fuzzy sanctions/PEP screening, Claude-drafted SAR narratives, EU AI Act model card | compliance/, backend/routers/compliance.py, ui/pages/6_Compliance.py |
| Layer | Tools |
|---|---|
| Streaming | Apache Kafka (KRaft mode), confluent-kafka |
| Warehouse | PostgreSQL, SQLAlchemy, pandas |
| Synthetic data | Faker (en_IE), Claude API |
| ML detection | XGBoost, scikit-learn, imbalanced-learn (SMOTE), SHAP |
| Rules engine | YAML config + Python evaluator |
| Backend / API | FastAPI, Pydantic, Uvicorn |
| UI / dashboards | Streamlit, Plotly |
| GenAI | Claude API (claude-sonnet-4-6) — SAR narratives, customer SMS |
| MLOps | MLflow (registry), Evidently (drift) |
| Compliance | rapidfuzz (fuzzy sanctions/PEP matching) |
| Deploy / CI | Docker, GitHub Actions, Render |
git clone <this-repo>
cd frauddesk
python -m venv .venv && source .venv/Scripts/activate # Windows: .venv\Scripts\activate
python run.py install
cp .env.example .env # add a real ANTHROPIC_API_KEY for SAR/SMS drafting
docker compose up -d # Kafka + Postgres
python run.py demo # seed data, create topics, start backend + UIThen open http://localhost:8501.
python run.py install (and Render's own build) only installs
requirements.txt — the slim set the app needs to run. For full local
development including Kafka streaming and drift monitoring:
pip install -r requirements-dev.txtpython run.py seed # synthetic data + public fraud dataset -> Postgres
python run.py train # train the XGBoost detection model
python run.py topics # create the 3 Kafka topics
python run.py stream # replay transactions onto Kafka (--speed configurable)
python run.py score # scoring consumer + sink consumer (needs Kafka)
python run.py demo-score # DEMO_MODE alternative — scores everything once, no Kafka needed
python run.py run # FastAPI backend (:8000) + Streamlit UI (:8501)
python run.py test # pytest suiteEvery seed run injects 6 labelled fraud stories so the Alert Queue is never
empty at demo time (transactions.scenario_tag):
| Scenario | Typology | What to look for in the Case View |
|---|---|---|
ato_new_device |
Account takeover | Device < 24h old, high-value ecom purchase |
app_scam |
Authorised push payment scam | A single transfer far above the account's normal spend |
mule_chain_inflow / mule_chain_outflow |
Money mule | Large inflow followed by rapid outflow to 3+ counterparties |
structuring |
Structuring/smurfing | 4 transfers just under the reporting threshold within 24h |
impossible_travel |
Impossible travel | Two card-present transactions ~7,500km apart, 25 minutes apart |
sanctions_near_match |
Compliance (not a fraud rule) | Customer name is a fuzzy match on the sanctions list — screen it in the Compliance page |
Rule Tuning Lab — threshold and rule-weight sliders re-simulate catch-rate
vs false-positive trade-offs live against the cached transaction set.

Why Flagged? — SHAP-explained ML signal fused with the rules that fired,
so an analyst can see exactly why a transaction was scored the way it was.

Home — the analyst's morning briefing: open alerts, SLA breaches, live
alert feed, and the recent audit trail.

Alert Queue — every open alert, prioritised and ready to investigate.

Case View — Overview — the full customer-360 profile and transaction
detail behind a case.

Actions — block card, refund, chargeback, and a Claude-drafted customer
SMS, all logged to the case's audit trail.

MI Dashboard — fraud loss trend, alert volume, typology breakdown, and
team performance for leadership reporting.

SAR Draft — a Claude-drafted Suspicious Activity Report narrative, built
from the case's evidence and ready for analyst review before filing.

python run.py test # fast suite (~5s), skips the one slow test
RUN_SLOW_TESTS=1 python run.py test # also runs the full tuning-cache simulation test (~60-90s)32 tests across rules, fused scoring, the FastAPI routers, and sanctions screening — all run against the real seeded Postgres database and the real trained model artifact, not mocks.
.github/workflows/ci.yml runs on every push to main and every PR: spins
up a Postgres service container, seeds it, trains the model, runs the full
pytest suite, and validates docker-compose.yml. Check it's green under the
repo's Actions tab on GitHub.
python monitoring/evidently_drift.py # compares last-7-days feature distributions vs older data
python monitoring/retrain.py # if drift share > 0.3, retrains and versions the modelPrimary demo (full Kafka streaming): run locally via python run.py demo,
then expose it with ngrok http 8501 for a live URL during a recorded walkthrough.
Render (always-on, free tier, CV link): Render's free tier has no Kafka
add-on, so the deployed version runs with DEMO_MODE=true — every
transaction is scored once in a batch pass (streaming/demo_mode_score.py)
instead of a live stream. Every other feature (case management, actions,
Tuning Lab, MI, compliance, SAR drafting) works identically either way, since
none of those routers touch Kafka at all.
Steps to deploy to Render:
- Push this repo to GitHub.
- In the Render dashboard: New + → Blueprint, select the repo. Render reads
render.yamland provisions the free Postgres, the API service, and the UI service. - Once the API service exists, copy its
.onrender.comURL and set it as the UI service'sAPI_BASE_URLenv var (the placeholder inrender.yamlwon't be correct until the first deploy assigns the real one). - In both services' Environment settings, set
ANTHROPIC_API_KEYto a real key (never commit it —render.yamldeliberately leaves itsync: false). - Trigger a deploy. The API service's build step seeds the database, trains the model, and batch-scores alerts — first deploy takes several minutes; watch the build logs.
- Open the UI service's URL once both services show "Live".
Built by Lookinder Kumar — MSc Big Data Management & Analytics, Dublin.

