Skip to content

feat(aml): add configurable AML screening service with velocity checks#140

Open
Faromzy wants to merge 1 commit into
Pidoko257:mainfrom
Faromzy:feature/aml-screening-service
Open

feat(aml): add configurable AML screening service with velocity checks#140
Faromzy wants to merge 1 commit into
Pidoko257:mainfrom
Faromzy:feature/aml-screening-service

Conversation

@Faromzy

@Faromzy Faromzy commented Jun 30, 2026

Copy link
Copy Markdown

feat(aml): Configurable AML Screening Service with Velocity Checks

Summary

Implements a synchronous AML screening service that evaluates every payment transaction against
configurable rules before processing begins. Flagged transactions are automatically set to
pending_review status and cannot be processed until a compliance officer approves them.

Rules are stored in the database — no code deployment needed to tune thresholds, add
blacklisted numbers, or toggle rules on/off.

Changes

Database

  • New aml_rules table — stores rule definitions (type, JSONB config, enabled flag)
  • New aml_screening_results table — one audit row per transaction × rule evaluation, regardless
    of whether it triggered
  • Seeded 5 default rules out of the box:
    • Large transaction threshold (≥ 1,000,000 XAF)
    • Elevated amount alert (≥ 500,000 XAF)
    • Hourly velocity check (> 3 transactions from same phone in 1 hr)
    • Daily velocity check (> 10 transactions from same phone in 24 hrs)
    • Phone number blacklist

New Files

  • src/services/amlScreening.ts — core screening engine with 1-min DB rule cache, Redis velocity
    counters (time-bucketed keys shared across instances), and fail-open behavior on Redis
    unavailability
  • src/models/amlScreeningResult.ts — data access layer for aml_screening_results
  • src/services/tests/amlScreening.test.ts — 32 unit tests, all passing
  • migrations/20260630_create_aml_screening_tables.sql

Modified

  • src/controllers/transactionController.ts — screening now runs synchronously inside
    processTransactionRequest before transactionModel.create():
    • Flagged → status: review, tags [aml-screened, aml-flagged], admin note with matched rule
      names
    • Clean → status: pending, tag [aml-screened]
    • Velocity counters incremented after successful transaction commit
  • Result rows persisted with the real transaction ID (fire-and-forget, never blocks the payment
    path)

Test Coverage

32 unit tests covering:

  • All 3 rule types (amount threshold, velocity check, blacklisted phone)
  • Invalid rule configs (graceful no-trigger)
  • Redis unavailability (fail-open — transaction proceeds)
  • DB persistence failure isolation (never propagates to caller)
  • Rule cache and invalidateRuleCache()
  • Velocity counter TTL logic (set only on first increment)
  • Combined multi-rule OR semantics

Notes

Pre-commit hook failures are pre-existing environment issues on main (spdy/http_parser missing
native module, sharp binary not installed for this runtime). Unrelated to this PR.
closes #11

- Add migration for aml_rules and aml_screening_results tables
  - aml_rules: DB-backed configurable rules (no hardcoded thresholds)
  - aml_screening_results: per-transaction rule evaluation audit log
  - Seeds 5 default rules: amount thresholds (1M/500K XAF),
    velocity checks (3/hr, 10/24hr), phone blacklist

- Add AmlScreeningResultModel (src/models/amlScreeningResult.ts)
  - createBulk(), findByTransactionId(), list() with pagination

- Add AmlScreeningService (src/services/amlScreening.ts)
  - Evaluates amount_threshold, velocity_check (Redis counters),
    and blacklisted_phone rules loaded from DB (1-min cache)
  - Velocity uses time-bucketed Redis keys shared across instances
  - Fails open on Redis unavailability (never blocks transactions)
  - Persists all evaluation results fire-and-forget

- Integrate screening synchronously into processTransactionRequest
  - Runs before transaction creation; flagged txns get status=review
    and tags [aml-screened, aml-flagged]
  - Velocity counters incremented after successful commit
  - Admin notes populated with matched rule names

- Add 32 unit tests (all passing) covering all rule types, edge
  cases, Redis failure isolation, caching, and DB persistence
@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@Faromzy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement AML Transaction Screening Service

1 participant