Skip to content

feat(aml): track AML decision source (automatic/GSheet/compliance)#3852

Draft
TaprootFreak wants to merge 1 commit into
developfrom
feat/aml-source-tracking
Draft

feat(aml): track AML decision source (automatic/GSheet/compliance)#3852
TaprootFreak wants to merge 1 commit into
developfrom
feat/aml-source-tracking

Conversation

@TaprootFreak

Copy link
Copy Markdown
Collaborator

Problem

Manual AML passes/fails cannot be reliably attributed to their origin. The generic compliance update endpoint records no actor at all, and amlResponsible is an inconsistent client-supplied free-string (mix of API, null, first names, typos). The GSheet admin and the human compliance tool both hit the same PUT /buyCrypto/:id (update()) with the same role, so the backend cannot tell them apart.

Change

Introduce an authoritative amlSource enum (Automatic | GSheet | Compliance), set server-side, on buy_crypto and buy_fiat.

  • AutomaticAmlHelperService.getAmlResult stamps amlSource = Automatic on every automatic decision.
  • Manualupdate() and manualPassAmlCheck() now receive the authenticated principal via @GetJwt(). When an amlCheck decision is made, the source is derived from the principal:
    • the configured GSheet technical account (AML_GS_ACCOUNT_ID) → GSheet
    • otherwise → Compliance, and the acting principal is recorded in amlResponsible when the caller didn't supply one (fills the previous null gap).
  • Reveal helperGsController.getDbData logs the first gs/db caller per principal (deduplicated, INFO). This surfaces the GSheet technical account id from the live logs so AML_GS_ACCOUNT_ID can be set.

The client-supplied responsible string is no longer the source of truth; the source is decided in the backend.

Scope

  • New enum AmlSource, nullable amlSource column on buy_crypto and buy_fiat + migration.
  • update() / manualPassAmlCheck() (BuyCrypto + BuyFiat) + their controllers pass @GetJwt().
  • No request/response contract changed (column is server-set only).

Rollout

  1. Merge + deploy. The gs/db first-access log reveals the GSheet technical account id.
  2. Set env AML_GS_ACCOUNT_ID to that account id (DEV + PRD). From then on GSheet passes are recorded as GSheet; before that they are recorded as Compliance with the acting principal captured.

Test plan

  • type-check, lint, format clean
  • build (nest build) green
  • AML / buy-crypto / buy-fiat suites green (59 tests)
  • migration PostgreSQL-compatibility spec green
  • manual: confirm amlSource is populated on automatic, compliance-tool and GSheet passes after deploy

Follow-ups

  • Expose amlSource in the relevant response DTOs / compliance UI once needed.
  • Consider a one-off backfill of amlSource for historical rows.

Add an authoritative amlSource enum (Automatic | GSheet | Compliance) to
buy_crypto and buy_fiat, set server-side, so every AML pass/fail is clearly
attributable to its origin instead of relying on the inconsistent free-string
amlResponsible.

- Automatic checks (AmlHelperService) stamp amlSource = Automatic.
- Manual decisions via the COMPLIANCE update/amlCheck endpoints derive the
  source from the authenticated principal (@GetJwt): the configured GSheet
  technical account (AML_GS_ACCOUNT_ID) maps to GSheet, otherwise Compliance,
  and the acting principal is recorded in amlResponsible when not provided.
- Log the first gs/db caller per principal to reveal the GSheet account id.

GSheet recognition activates once AML_GS_ACCOUNT_ID is set; until then manual
passes are recorded as Compliance with the acting principal captured.
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.

1 participant