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>
This commit is contained in:
Siavash Sameni
2026-05-30 18:41:44 +04:00
parent eab1d77582
commit dceaf82934
153 changed files with 6276 additions and 179 deletions

View File

@@ -0,0 +1,222 @@
# 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.