Skip to content

feat(compliance): consume ledger transactions and raise aml alerts - #280

Merged
tiana-code merged 1 commit into
mainfrom
feat/E-04-aml-consumer
Jun 19, 2026
Merged

feat(compliance): consume ledger transactions and raise aml alerts#280
tiana-code merged 1 commit into
mainfrom
feat/E-04-aml-consumer

Conversation

@tiana-code

Copy link
Copy Markdown
Owner

E-04 Compliance #267 - the AML event consumer (the first event consumer in the repo).

What

  • AmlTransactionConsumer (@KafkaListener on fincore.transaction, group compliance-aml): deserializes the envelope via a Jackson TypeReference into a compliance-owned wire DTO (LedgerTransactionPosted, @JsonIgnoreProperties - services don't share classes), filters TransactionPosted (the topic also carries reversals), and delegates. Thin, no @Transactional.
  • AmlEventHandler (@Service @Transactional): deduplicates by envelope id (IdempotentEventProcessor + JdbcProcessedEventStore, F-03.5 Idempotent consumer base class / annotation #192), maps the event to an AmlTransactionView (amount = sum of DEBIT entries as BigDecimal), evaluates with the embedded AML engine (F-04.6 AML rules engine + rolling-window aggregation #266), and persists an AmlAlert when flagged - all in one transaction, so a thrown handler rolls back the claim and the event retries (at-least-once + idempotent). No external call inside the transaction.
  • Migrations: processed_events (default schema, matching the store's unqualified table name) + subject_reference on aml_alerts (an alert now records its subject).
  • Consumer-only Kafka config; the eventbus producer auto-config stays off (fincore.eventbus.bootstrap-servers unset).

Tests

Unit: handler (dedup, DEBIT-sum, flag/clear), consumer (typed deserialization + type filtering). IT: @SpringBootTest + Testcontainers (Redpanda + Postgres) publishing via KafkaTemplate -> asserts an alert by subject, and a duplicate envelope raises only one alert (await + settle).

Notes / deferred

Rolling-window composition (no history source yet) and a DLQ/error-handler (the #193 toolkit exists) are explicit follow-ups; documented, state-safe (poison message never commits).

Gate chain

  • critic: GO-WITH-CHANGES (subject_reference column, KycApiContextIT listener auto-startup=false, processed_events schema-invariant comment, exact DEBIT toView + typed round-trip test - all applied).
  • security-auditor (opus): PASS - dedup+evaluate+persist in one tx, no external call in tx, no SQL injection (constant table + bound params), deserialization safe, §5.3 clean.
  • code-reviewer: 2 must-fix applied (removed the DEFAULT '' poison; moved producer config to the IT) + strengthened the dedup test; 1 declined with reasoning.
  • evaluator: PASS (0.918).
    All local gates green; the Redpanda+Postgres IT runs on CI.

Closes #267

Add the first event consumer: a Kafka listener on the ledger
transaction topic deserializes posted-transaction events into a local
wire view, and an idempotent handler deduplicates by envelope id,
evaluates the transaction with the embedded AML engine and persists an
alert when it is flagged, all in one transaction so a failed handler
retries safely. Alerts now record the subject they concern. The
external receive stays outside the transaction; dedup uses the shared
processed-events ledger. Rolling-window aggregation and dead-letter
handling are left for follow-ups.

Closes #267
@tiana-code tiana-code added this to the v0.3.0 milestone Jun 19, 2026
@tiana-code
tiana-code merged commit 5415433 into main Jun 19, 2026
8 checks passed
@tiana-code
tiana-code deleted the feat/E-04-aml-consumer branch June 19, 2026 11:16
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.

F-04.7 AML event consumer (ledger tx-posted -> alerts)

1 participant