Capstone 02 — Stateful Fraud / Risk Stream Processing (runnable Scala)

Phase: 16 — Capstone Systems | Difficulty: ⭐⭐⭐⭐⭐ | Time: 1–2 weeks

The JD's Problem 2, built as a Flink-style keyed, event-time stateful operator in Scala (P04/P05/P11) — verified with sbt test. Per-account state, a hot-swappable broadcast ruleset, three rule kinds, idempotent (deduped) alerts, and savepoint-style checkpoint/restore for stateful redeploys.

What it implements

CapabilityIn the codePhase
Keyed state per accountstate: Map[account, AccountState] (recent txns + last country)P04
Broadcast rules (hot-swap)updateRules(...) swaps the active rulesetP04
Amount rulesingle txn over a threshold
Velocity ruleN txns within a time window (event-time)P04
Impossible travelcountry switch faster than physically possibleP05 enrichment
Idempotent alertsdedup by (account, kind, eventTime) → exactly-once effectP01
Savepoint redeploysnapshotState / restoreP04
Replay validationre-run the stream → identical alert setP02/P13

Run

sbt test

Expected: 8 specs, all green — each rule fires correctly, alerts dedup, a broadcast rule update changes behavior, and the headline proofs:

  • savepoint/restore: processing [1,2,3] then snapshot→restore→process [4,5] yields the same alert set as processing [1..5] in one detector (no lost/duplicated alerts across a stateful redeploy).
  • replay: re-running the same stream produces the identical alert set.

Success criteria

  • sbt test → all 8 specs pass.
  • You can explain why alerts must be deduped (at-least-once delivery + idempotent effect = P01) and how a savepoint preserves the dedup set across a redeploy.
  • You can explain why velocity/impossible-travel are inherently event-time, not arrival-time.

How to extend toward production

  • Add watermarks + allowed lateness (Phase 04 lab-02-scala-windows) so late txns are handled, not silently misordered.
  • Enrich from the Cassandra serving layer (Capstone 03) for account risk profiles (the as-of join, P05/P11), via async lookups.
  • Emit alerts to the lakehouse (Phase 09 lab) for audit + replay, and to a low-latency sink for action.
  • Wrap the detector in an FS2 stream (P12) reading a real Kafka topic; checkpoint state to S3 (the real savepoint).