Files
nick-doc/PRD - AML Screening Provider Options.md
Siavash Sameni dceaf82934 audit: 2026-05-30 full-codebase audit — report, issues, docs, runbooks
Full-codebase-audit 2026-05-30 outputs:
- Audit report: 09 - Audits/Full Codebase Audit - 2026-05-30.md
- 81 issue files ISSUE-055..135 (decisions + 1 skipped no-brainer).
- Scanner docs from scratch (was zero): architecture, data model, API ref, payment
  flow, operations runbook + repo README.
- Doc-sync updates across API reference, data models, flows, design system.
- Secret Rotation Runbook (08 - Operations) for the exposed credentials.
- Reusable workflow guide (07 - Development) + .claude/workflows/full-codebase-audit.js.

Issues remain status:open intentionally — the code fixes are uncommitted-then-committed
working-tree changes per repo and aren't "resolved" until merged/deployed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 18:48:04 +04:00

223 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PRD — AML Screening Provider Options
**Status:** Draft
**Date:** 2026-05-29
**Context:** Task #10 added `ofacProvider` as the first working free AML provider. The Chainalysis free public API was ruled out (Cloudflare blocks all non-browser IPs). This document maps all options and recommends what to add next at zero cost.
---
## Current State
| What | Status |
|---|---|
| OFAC SDN provider | ✅ Live (`ofacProvider.ts`) |
| `amlScreeningService.ts` | ✅ Live — pluggable provider interface |
| `amlConfigRoutes.ts` | ✅ Admin can switch provider + force-refresh |
| Chainalysis KYT (paid) | Code ready, key required |
| Chainalysis free public API | ❌ Blocked by Cloudflare on all server IPs |
`TRANSACTION_SAFETY_AML_PROVIDER=ofac` covers the US regulatory minimum: 97 sanctioned EVM addresses (Tornado Cash, Lazarus Group, sanctioned exchanges).
---
## The Gap
OFAC alone is narrow. A buyer could be:
- On the **EU**, **UN**, or **UK** sanctions lists but not OFAC
- Flagged by on-chain intelligence (stolen funds, mixer outputs, exploit proceeds) without being formally sanctioned anywhere
- A known scammer address catalogued by community databases
For a marketplace doing cross-border escrow, the OFAC gap is meaningful and several free alternatives exist.
---
## Option Map
### Tier 1 — Free, Self-Hosted (Same Pattern as OFAC)
These are official government-issued sanctions lists available as bulk XML/CSV downloads with no API key and no IP restrictions. Identical implementation pattern to `ofacProvider.ts`.
#### 1A. EU Consolidated Sanctions List
- **Source:** European External Action Service (EEAS)
- **URL:** `https://webgate.ec.europa.eu/fsd/fsf/public/files/xmlFullSanctionsList_1_1/content`
- **Format:** XML, updated daily
- **EVM addresses:** ~4080 (growing; includes Hydra Market operators, Garantex exchange)
- **Effort:** ~2h — copy ofacProvider, change regex to match EU XML schema
- **Overlap with OFAC:** ~60% (most major entities are dual-listed)
- **Why add it:** EU operators have a compliance obligation to the EU list independently of OFAC
#### 1B. UK OFSI Consolidated List
- **Source:** UK Office of Financial Sanctions Implementation
- **URL:** `https://ofsistorage.blob.core.windows.net/publishlive/2022format/ConList.xml`
- **Format:** XML, updated daily
- **EVM addresses:** ~2040 (post-Brexit separate list; includes Garantex, some Tornado Cash)
- **Effort:** ~2h — same pattern
- **Why add it:** required for any UK-person counterparty
#### 1C. UN Security Council Consolidated List
- **Source:** UN Security Council
- **URL:** `https://scsanctions.un.org/resources/xml/en/consolidated.xml`
- **Format:** XML, updated ~weekly
- **EVM addresses:** low (~515), but includes DPRK entities (Lazarus Group basis)
- **Effort:** ~2h
- **Why add it:** many jurisdictions require UN list compliance as the baseline floor
---
### Tier 2 — Free API Tier (Rate-Limited, No IP Block)
These providers offer a free developer/community plan with meaningful rate limits.
#### 2A. GoPlus Security API
- **Endpoint:** `https://api.gopluslabs.io/api/v1/address_security/{address}?chain_id={chainId}`
- **Auth:** None for basic tier (1000 req/day free); API key for higher volume
- **Returns:** `{ malicious_address, phishing_activities, blackmail_activities, stealing_attack, fake_token, honeypot_related_address, ... }` — 15+ risk categories
- **Coverage:** On-chain intelligence across BSC, ETH, Polygon, Arbitrum, Base — exactly our 5 chains
- **IP restrictions:** None — tested from SepehrHomeserverdk ✅ (community-maintained list served normally)
- **Latency:** ~150ms average
- **Effort:** ~3h (new provider class + admin toggle)
- **Why add it:** Catches non-sanctioned but known-bad addresses (drainers, phishing deployers, stolen-fund mixers) that no government list covers
- **Limitation:** Community-sourced, not legally authoritative; use as advisory block, not hard block
#### 2B. Etherscan Address Tags (ETH only)
- **Endpoint:** `https://api.etherscan.io/api?module=account&action=txlist&address=...` + label check
- **Auth:** Free API key (no credit card, 5 req/s)
- **Returns:** Known scammer/phisher labels from Etherscan's community tag system
- **Coverage:** Ethereum mainnet only
- **Effort:** ~4h (needs scrape of label endpoint, which is unofficial)
- **Why skip for now:** Unofficial, ETH-only, limited EVM address coverage. GoPlus is strictly better.
---
### Tier 3 — Paid / Enterprise
| Provider | Model | Est. Cost | Notes |
|---|---|---|---|
| **Chainalysis KYT** | Per-request + annual | $10k+/yr | Gold standard; blocked on free tier |
| **TRM Labs** | Per-request | ~$0.050.20/check | Developer sandbox available; no IP block |
| **Elliptic** | Per-request | ~$0.100.50/check | Strong EU coverage |
| **Sardine** | Per-request | Custom | Adds fraud scoring beyond AML |
| **AMLBot** | Per-request | ~$0.10/check | Telegram-native AML bot; has API |
| **Scorechain** | Annual SaaS | ~$5k+/yr | Good EU/CIS coverage |
**TRM Labs** is the strongest paid option after Chainalysis — has a developer sandbox, no Cloudflare blocking, and competitive pricing. If a paid provider is chosen later, TRM is the recommended starting point.
---
### Tier 4 — On-Chain / Decentralized
#### 4A. Forta Network
- Decentralized threat detection; bots emit alerts for known exploiter addresses
- **Free:** Yes, public alert feed via GraphQL
- **Latency:** 15 minutes (block-based, not real-time per request)
- **Fit:** Better for monitoring than pre-payment screening; not recommended for this use case
#### 4B. Harpie Address Blocklist
- Blocklist maintained by Harpie (web3 security); some public exposure
- **Coverage:** Mostly phishing and drainer addresses on ETH
- **API:** Not public/stable
- **Verdict:** Skip — GoPlus covers the same space with a proper API
---
## Recommended Free Tier Additions
### Phase A — Sanctions breadth (1 day of work)
Add EU + UN list providers, run all three (OFAC + EU + UN) in parallel, merge results:
```
OFAC SDN → 97 EVM addresses
EU List → ~60 EVM addresses
UN SC List → ~15 EVM addresses
─────────────────────────────────
Total unique → ~140160 addresses (after dedup)
```
Implementation: add `euSanctionsProvider.ts` and `unSanctionsProvider.ts` following the exact same pattern as `ofacProvider.ts`. Add a `combinedSanctionsProvider.ts` that fans out to all three in parallel and merges results. Admin can enable `combined` as the provider.
### Phase B — On-chain intelligence (½ day of work)
Add `goplusProvider.ts`:
- Checks GoPlus free API for the 15 risk categories
- Returns `clean: false` for `malicious_address`, `phishing_activities`, `stealing_attack`, `blackmail_activities`
- Returns `clean: true` with a warning note for lower-severity flags
- Admin configurable: `advisory` (warn but allow) vs `blocking` mode
### Composite provider (final step)
A `compositeProvider.ts` that runs sanctions lists + GoPlus in parallel:
- Any sanctions hit → hard block
- GoPlus malicious hit → configurable (default: hard block)
- GoPlus advisory flag → pass with risk note in payment record
---
## Provider Interface (no changes needed)
```typescript
// Already in amlProvider.ts — all new providers just implement this
export interface AmlProvider {
name: string;
screenAddress(address: string, chainId?: number): Promise<AmlScreenResult>;
}
export interface AmlScreenResult {
clean: boolean;
verdict: 'clean' | 'sanctions' | 'high-risk' | 'unknown';
categories?: string[];
raw?: any;
error?: string;
providerUnavailable?: boolean;
provider: string;
}
```
---
## Admin Config Changes
New env vars (none required, all optional):
```bash
# Provider options (expanded):
# 'none' — disabled
# 'ofac' — OFAC SDN only (current)
# 'combined' — OFAC + EU + UN (Phase A)
# 'goplus' — GoPlus on-chain intelligence only
# 'full' — combined + goplus (Phase A + B)
# 'chainalysis' — paid KYT API
TRANSACTION_SAFETY_AML_PROVIDER=ofac
# GoPlus (Phase B)
GOPLUS_API_KEY= # optional; upgrades from 1k/day free to higher limit
GOPLUS_BLOCK_THRESHOLD=malicious # or: advisory (warns but allows)
# EU / UN list URLs (leave blank for defaults)
EU_SANCTIONS_URL=
UN_SANCTIONS_URL=
```
---
## Priority Recommendation
| Phase | Work | Benefit | Do it? |
|---|---|---|---|
| Phase A: EU + UN sanctions | ~1 day | Closes EU/UN legal gap | **Yes — do first** |
| Phase B: GoPlus | ~½ day | Catches non-sanctioned bad actors | **Yes — do second** |
| Composite provider | ~½ day | Single toggle for all | **Yes — do with Phase B** |
| TRM Labs paid | ~1 day | Full on-chain risk scoring | If/when compliance requires it |
| Chainalysis KYT | ~1 day | Gold standard + legal defensibility | If enterprise clients demand it |
Total estimated effort for Phase A + B + Composite: **~2 days**.
---
## Risk Notes
- **GoPlus community data:** community-sourced, can have false positives. Recommended to run in advisory mode first, switch to blocking after monitoring.
- **Sanctions list lag:** all three government lists are updated daily/weekly; the 24h cache is appropriate.
- **Fail-open policy:** all providers fail-open by default (payment proceeds if provider unreachable). Seller's `amlBlockOnFailure` flag overrides this per-offer.
- **Not legal advice:** this document describes technical options. Jurisdiction-specific compliance obligations (EU's AMLD6, UK's MLR 2017, US BSA) should be reviewed with legal counsel.