# Implementation Plan: MercuryPay Fraud & AML Platform

Version: 1.0 | Date: 2026-05-21 | Estimated Total: 32–40 weeks

---

## Phase 1: Foundation Infrastructure (Weeks 1–4)

Goal: Redis feature store + Redix dependency. No scoring yet, no business logic.
All existing functionality remains untouched.

Tasks:
  1.1  Add Redix ~> 1.4 and Oban ~> 2.18 to root mix.exs
  1.2  Create apps/infra_feature_store umbrella app
  1.3  Implement InfraFeatureStore.KeyBuilder (canonical key naming)
  1.4  Implement InfraFeatureStore.RedisTier (INCRBYFLOAT, ZADD, HGET, EXPIRE wrappers)
  1.5  Implement InfraFeatureStore.EtsTierCache (GenServer, LRU eviction)
  1.6  Implement InfraFeatureStore.SyncSubscriber (PubSub ETS invalidation)
  1.7  Implement InfraFeatureStore.FeatureStore (public API: get/put/hydrate)
  1.8  Implement InfraFeatureStore.TtlCounter (velocity counter ops)
  1.9  Implement InfraFeatureStore.Journal (sorted set ops)
  1.10 Implement InfraFeatureStore.PayloadLatest (hash ops)
  1.11 Add Redis to docker-compose.yml (dev environment)
  1.12 Write unit tests for all infra_feature_store modules
  1.13 Configure Oban in config.exs + add oban_jobs table migration

Deliverable: Feature store works in isolation. Tests pass. No impact on existing code.
Risk: Low. Purely additive.

---

## Phase 2: Data Model + Schema Migrations (Weeks 3–5, overlaps Phase 1)

Goal: All risk schemas in MySQL. Migration files + Ecto schemas.

Tasks:
  2.1  Create migration: risk_entity_models
  2.2  Create migration: risk_activation_rules
  2.3  Create migration: risk_scores
  2.4  Create migration: risk_labels
  2.5  Create migration: risk_cases + risk_case_events
  2.6  Create migration: risk_sanctions_list
  2.7  Create migration: risk_model_versions
  2.8  Add risk_score, risk_decision, risk_score_id to transactions table
  2.9  Create Ecto schemas for all 7 new tables (infra_repo)
  2.10 Create Ecto context modules: Risks, Cases, Labels, Models (infra_repo)
  2.11 Seed data: default activation rules for demo tenant
  2.12 Write Ecto schema tests

Deliverable: All schemas in DB. Context functions available. No app logic yet.
Risk: Low. Standard Ecto migrations.

---

## Phase 3: Rules-Only Scoring Engine (Weeks 5–9)

Goal: End-to-end scoring using rules only (no ML). Fraud decisions appear in transaction
      responses. Velocity counters update asynchronously. This is the MVP.

Tasks:
  3.1  Create apps/mw_risk umbrella app
  3.2  Implement MwRisk.FeatureHydrator (extract tx fields + read from feature store)
  3.3  Implement MwRisk.AbstractionEngine (ratio/proportion computations)
  3.4  Implement MwRisk.RuleCache (ETS-backed, reloads activation_rules from DB)
  3.5  Implement MwRisk.ActivationEngine (evaluate rules → APPROVE/REVIEW/DECLINE)
  3.6  Implement MwRisk.Explainer (fired_rules + feature_snapshot builder)
  3.7  Implement MwRisk.ScoringPipeline (orchestrates steps 3.2–3.6)
  3.8  Create MwRouter.RiskScoringPlug and insert into pipeline.ex
  3.9  Implement MwRisk.EventBroadcaster (fire-and-forget post-tx PubSub event)
  3.10 Implement MwRisk.VelocityPipeline (Broadway, 8 entity dimensions)
  3.11 Async write risk_scores to DB (via Task.start, no blocking)
  3.12 Activate VelocityPipeline in production supervision tree (env-gated)
  3.13 Integration tests: full pipeline with mock CBS adapter
  3.14 Load test: verify < 50ms P95 with 500 concurrent transactions

Deliverable: Every transaction gets a risk score and decision. Velocity counters live.
Risk: Medium. Pipeline plug change requires careful integration testing.
     Rollback: env flag RISK_SCORING_ENABLED=false disables plug instantly.

---

## Phase 4: Sanctions Screening + Case Management (Weeks 9–13)

Goal: AML sanctions screening + investigator case workflow.

Tasks:
  4.1  Implement MwRisk.SanctionsCache (ETS-backed Levenshtein distance cache)
  4.2  Implement MwRisk.SanctionsChecker (fuzzy match against risk_sanctions_list)
  4.3  Insert sanctions check into ActivationEngine (FATF grey/black list rules)
  4.4  Implement MwRisk.Workers.SanctionsLoader (Oban: reload sanctions from DB/API)
  4.5  Implement MwRisk.Workers.CasesAutomation (Oban: auto-open cases on DECLINE)
  4.6  Implement CasesContext in infra_repo (create/assign/update/close cases)
  4.7  Create gateway_web/live/fraud/fraud_dashboard_live.ex
  4.8  Create gateway_web/live/fraud/score_explorer_live.ex + score_detail_live.ex
  4.9  Create gateway_web/live/fraud/case_management_live/ (index + show)
  4.10 Create gateway_web/live/fraud/rules_builder_live/ (index + form)
  4.11 Create gateway_web/live/fraud/sanctions_live/ (index + upload)
  4.12 Add fraud_analyst, fraud_admin, compliance RBAC roles to mw_auth
  4.13 Protect all /admin/fraud/* routes with role check
  4.14 LiveView tests for all fraud pages

Deliverable: Full investigator dashboard live. Cases auto-created on DECLINE.
Risk: Medium. LiveView complexity; no impact on scoring hot path.

---

## Phase 5: ML Inference — Phase A (Weeks 13–18)

Goal: Isolation Forest unsupervised scoring available (no labels needed for cold start).

Tasks:
  5.1  Add Nx ~> 0.9, Axon ~> 0.7, EXLA ~> 0.9, Scholar ~> 0.3, Explorer ~> 0.9
  5.2  Implement MwRisk.ModelServer (Nx.Serving GenServer wrapper)
  5.3  Implement feature vector builder + normalizer (matches training)
  5.4  Implement MwRisk.Workers.ModelTrainer (Oban): Isolation Forest training path
  5.5  Implement feature extraction from risk_scores using Explorer DataFrames
  5.6  Implement model artifact serialization (Nx.serialize / write to disk or S3)
  5.7  Implement model loading on startup (query deployed model version)
  5.8  Integrate ModelServer.predict into ScoringPipeline (weighted ensemble)
  5.9  Add risk_model_versions UI: ModelTrainingLive (index + show)
  5.10 Training progress streaming (Oban worker → PubSub → LiveView)
  5.11 Model performance charts in ModelTrainingLive.Show
  5.12 Env-gate ML: RISK_MODEL_SERVING=false falls back to rules-only

Deliverable: Isolation Forest score blended with rule-based decision.
             Model training UI functional. No labeled data required.
Risk: Medium-high. First ML code. EXLA compilation on first run takes minutes.
      Mitigation: compile models at deploy time, not on first request.

---

## Phase 6: ML Inference — Phase B (Weeks 18–24)

Goal: Supervised MLP training using accumulated labeled data.

Tasks:
  6.1  Implement MwRisk.Workers.LabelIngestionWorker (Oban: TC40 matching)
  6.2  Create /api/v1/risk/labels endpoint (gateway_api) for network notifications
  6.3  Add SFTP label file ingestion (extend adapter_file)
  6.4  Implement MwRisk.Workers.ReprocessingWorker (Oban: replay history)
  6.5  Implement Axon MLP training path in ModelTrainer
  6.6  Implement "Exhaustive Adaptation": iterate topologies, pick best AUC-ROC
  6.7  Implement ensemble: α * supervised + (1-α) * unsupervised
  6.8  Add ensemble weight configuration to FraudSettingsLive
  6.9  Add ReprocessingLive UI
  6.10 Feature importance / SHAP-equivalent explainability
  6.11 Auto-retrain trigger when new label count > 500 (configurable)

Deliverable: Supervised ML in production. Self-improving model as labels accumulate.
Risk: High (ML quality). Mitigation: canary deployment — new model runs in shadow
      mode (score computed but not used for decision) for 2 weeks before going live.

---

## Phase 7: Batch Feature Calculation (Weeks 22–27)

Goal: Long-horizon features (30d, 90d, 52w) pre-calculated nightly by Oban workers.

Tasks:
  7.1  Implement MwRisk.Workers.FeaturePrecalcWorker: daily batch for 30d/90d/52w features
  7.2  Implement Oban cron schedules: daily at 02:00 UTC, weekly on Sunday 03:00 UTC
  7.3  Implement LruJournal tracking (mark hot entities for priority pre-warming)
  7.4  Implement InfraFeatureStore.PruningWorker (clean expired Journal entries)
  7.5  Implement distinct count batch rollup using HyperLogLog PFMERGE
  7.6  Add batch feature metrics to FeatureExplorerLive
  7.7  Optimize Redis memory: OBJECT ENCODING checks, ziplist vs skiplist thresholds
  7.8  Redis memory monitoring alerts (Prometheus alert rules)

Deliverable: All 665 features from fraud_rules.csv available. Long-horizon AML features live.
Risk: Medium. Batch jobs are independently testable and rollback-safe.

---

## Phase 8: Hardening, Performance, and Advanced Features (Weeks 27–32+)

Goal: Production-grade hardening, performance optimization, advanced AML features.

Tasks:
  8.1  P95 latency profiling: ensure < 50ms maintained at 2000 TPS
  8.2  Redis connection pooling (multiple Redix connections for parallel writes)
  8.3  Implement Circuit Breaker around Redis calls (fuse, already in mw_router)
  8.4  Implement Circuit Breaker around ModelServer (fallback to rules-only if ML fails)
  8.5  Chaos testing: Redis failure → ETS-only degraded mode (no crash)
  8.6  Chaos testing: MySQL write failure → score still returned (async write retry)
  8.7  Add graph-based entity linking (Card → IP → Merchant relationship scoring)
  8.8  Add network-level features (BIN velocity across all tenants — opt-in)
  8.9  Add VPN/proxy detection integration (IP reputation API)
  8.10 Add geolocation velocity ("impossible travel" feature)
  8.11 GDPR/data residency: implement risk_scores.feature_snapshot encryption at rest
  8.12 Full audit export API for compliance teams
  8.13 Penetration testing of risk API endpoints
  8.14 Performance load test: 5000 TPS sustained, verify P99 < 100ms

Deliverable: Production-ready, hardened system.
