fix: route AML check for suspicious users to GSheet review#3638
Open
TaprootFreak wants to merge 1 commit intodevelopfrom
Open
fix: route AML check for suspicious users to GSheet review#3638TaprootFreak wants to merge 1 commit intodevelopfrom
TaprootFreak wants to merge 1 commit intodevelopfrom
Conversation
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Buy/Sell-Transactions of users with
riskStatus = SUSPICIOUSare silently dropped by the AML pipeline. The transaction is created withamlCheck = null,status = Created, and never advances. There is no visibility, no audit trail, and no chargeback path — the funds sit in limbo until manual SQL intervention.Concrete incident:
buy_crypto 120973(35'000 CHF, user 383865, transaction 312001, bank_tx 197696) has been stuck since 2026-04-28 07:29 UTC. It is the only entry in the entire database withamlCheck = null AND status = Created. The user landed on the AML list (amlListAddedDate = 2026-04-27 08:49) and was flaggedSuspiciousby Compliance shortly after a successful preceding buy (120849, 50k CHF). The next buy gets caught in this gap. This needs to clear urgently — the customer is waiting on a 35k CHF deposit.Root cause
buy-crypto-preparation.service.ts:67andbuy-fiat-preparation.service.ts:60filter outSUSPICIOUSusers from the AML query:But unlike
BLOCKED(which has a corresponding rule inAmlHelperService.getAmlErrorsmapping toUSER_DATA_BLOCKED → GSHEET),SUSPICIOUShas no rule anywhere. The 14-day expired-pending reaper (aml-helper.service.ts:642) doesn't apply either — it only operates on entries that are alreadyPENDING, notnull. Result: the transaction is invisible to every job and dashboard.Fix
Treat
SUSPICIOUSexactly likeBLOCKED: surface it through the existing AML rule pipeline so it lands in the GSheet review queue with a clear reason. Compliance gets the same workflow they already use forBLOCKEDusers — review, then either setriskStatus = RELEASED(AML reruns and processes normally) or trigger a chargeback manually.Changes:
aml-error.enum.ts: addUSER_DATA_SUSPICIOUSerror mapped toCRUCIAL / GSHEET / USER_DATA_SUSPICIOUS(parallel toUSER_DATA_BLOCKED)aml-reason.enum.ts: addUSER_DATA_SUSPICIOUSreason and include it inAmlReasonWithoutReasonaml-helper.service.ts: addif (entity.userData.isSuspicious) errors.push(AmlError.USER_DATA_SUSPICIOUS);next to the existingBLOCKEDcheckbuy-crypto-preparation.service.ts/buy-fiat-preparation.service.ts: remove theriskStatus: Not(SUSPICIOUS)filter — the rule above now handles itsift.dto.ts: map toDeclineCategory.RISKY(Sift signal that the user was flagged for risk review)transaction.dto.ts: map toTransactionReason.UNKNOWN(parallel toBLOCKED)The downstream
isSuspiciousfilters inbuy-crypto-out.service.tsandbuy-crypto-batch.service.tsare intentionally left in place — they only act onamlCheck = PASSentries, so they remain a defensive guard against accidental auto-payouts to suspicious users.Test plan
buy_crypto 120973picks upamlCheck = GSHEETwithamlReason = UserDataSuspiciouson the next AML job tickUSER_DATA_BLOCKEDentriesriskStatus = NA / RELEASEDusers (default path unchanged)BLOCKEDusers still route toUSER_DATA_BLOCKEDGSheet (rule order preserved)