docs: AML scope note, human-blocked items, Task #11 pre-flight inventory

- Add AML scope note to Handoff - RN Multichain Probe (sanctions-only vs full KYT)
- Add human-blocked section with 3 precise next steps for owner
- Create Task 11 Pre-flight Inventory: library choice, dev/prod flow, admin UI gaps, backend gaps, risks, acceptance criteria
This commit is contained in:
Siavash Sameni
2026-05-28 20:42:42 +04:00
parent ddc0434819
commit 81625d35d2
18 changed files with 398 additions and 113 deletions

View File

@@ -190,7 +190,7 @@ Use `src/utils/logger.ts`:
import { log, logError } from "src/utils/logger";
log(`✅ Payment ${id} confirmed`);
logError("SHKeeper webhook verification failed", err);
logError("Request Network webhook verification failed", err);
```
Never use raw `console.error` in service code — it bypasses Sentry breadcrumbs.

View File

@@ -80,36 +80,39 @@ In dev, Redis runs without a password. In production the compose entrypoint is `
---
## Payments — SHKeeper
## Payments — Request Network
SHKeeper is the crypto payment gateway. See [[Payment Flow]] and [[SHKeeper Integration]] in the architecture section.
Request Network is the current primary payment provider. See [[PRD - Request Network In-House Checkout]], [[Request Network Integration Constraints]], and [[Escrow Flow]].
| Name | Repo | Required | Default | Example | Purpose |
|------|------|----------|---------|---------|---------|
| `SHKEEPER_BASE_URL` | backend | ✅ | — | `https://shkeeper.example.com` | Base API URL |
| `SHKEEPER_API_URL` | backend | ✅ | — | `https://shkeeper.example.com/api/v1` | Versioned API URL |
| `SHKEEPER_API_KEY` | backend | ✅ | — | — | `X-Shkeeper-Api-Key` header |
| `SHKEEPER_WEBHOOK_SECRET` | backend | ✅ | — | — | HMAC secret for inbound webhook signatures |
| `SHKEEPER_CALLBACK_SECRET` | backend | ✅ | — | — | Older alias for webhook secret; some payloads still use it |
| `SHKEEPER_ALLOWED_TOKENS` | backend | optional | `USDT,USDC` | `USDT,USDC,BTC` | Comma-separated list of accepted tokens |
| `SHKEEPER_NETWORKS` | backend | optional | `bsc,polygon` | `bsc,polygon,eth` | Networks enabled in checkout |
| `SHKEEPER_ENVIRONMENT` | backend | optional | `production` | `sandbox` | Switches SHKeeper sandbox vs prod behaviour |
| `SHKEEPER_FORCE_PAYOUT_DEMO` | backend | optional | `false` | `true` | Skips real-chain payout; demo-confirms after 5s |
| `SHKEEPER_FORCE_REAL` | backend | optional | `false` | `true` | Forces real-chain even in dev/sandbox |
| `ADMIN_PAYOUT_WALLET_ADDRESS` | backend | ✅ for payouts | — | `0xAc23…` | Wallet that receives platform fees / payouts |
| `REQUEST_NETWORK_ENABLED` | backend | optional | `true` | `true` | Enables `request.network` as an available provider |
| `REQUEST_NETWORK_API_KEY` | backend | ✅ | — | `cli_...` | Request Network API credential |
| `REQUEST_NETWORK_API_BASE_URL` | backend | ✅ | `https://api.request.network` | `https://api.request.network` | Request Network API base URL |
| `REQUEST_NETWORK_ORIGIN` | backend | ✅ | `FRONTEND_URL` | `https://dev.amn.gg` | Origin sent to Request Network API |
| `REQUEST_NETWORK_MERCHANT_REFERENCE` | backend | ✅ | — | `<receiver>@eip155:56#...:<token>` | Encodes receiver, chain, payment reference, and token context |
| `REQUEST_NETWORK_NETWORK` | backend | optional | `bsc` | `bsc` | Default checkout network |
| `REQUEST_NETWORK_PAYMENT_CURRENCY` | backend | optional | `USDT` | `USDC` | Default checkout token symbol |
| `REQUEST_NETWORK_WEBHOOK_CALLBACK_URL` | backend | ✅ | — | `https://dev.amn.gg/api/payment/request-network/webhook` | Provider callback URL |
| `REQUEST_NETWORK_WEBHOOK_SECRET` | backend | ✅ | — | — | HMAC secret for inbound webhook signatures |
| `REQUEST_NETWORK_ALLOW_TEST_WEBHOOKS` | backend | optional | `false` | `false` | Allows explicit Request Network test webhooks only for controlled smoke tests |
| `ESCROW_WALLET_ADDRESS` | backend | ✅ | — | `0xa304…` | Master escrow address used by payments service |
| `RECEIVER_WALLET_ADDRESS` | backend | optional | — | `0x…` | Used by alternative payout flows |
### Historical SHKeeper keys
`SHKEEPER_*` variables may still appear in legacy migration docs or old `.env` files. They are not the current primary checkout path and should not be used for new payment work unless a deliberate legacy-record reconciliation task requires them.
---
## Payments — Provider Selection
| Name | Repo | Required | Default | Example | Purpose |
|------|------|----------|---------|---------|---------|
| `PAYMENT_PROVIDER` | backend | optional | `shkeeper` | `request.network` | Active provider for new payment intents |
| `PAYMENT_DEFAULT_PROVIDER` | backend | optional | `shkeeper` | `shkeeper` | Fallback alias when `PAYMENT_PROVIDER` is unset |
| `PAYMENT_ENABLED_PROVIDERS` | backend | optional | `shkeeper` | `shkeeper,request.network` | Comma-separated providers allowed at runtime |
| `PAYMENT_ROLLBACK_PROVIDER` | backend | optional | `shkeeper` | `shkeeper` | Provider used when selected provider is not enabled |
| `PAYMENT_PROVIDER` | backend | optional | `request.network` | `request.network` | Active provider for new payment intents |
| `PAYMENT_DEFAULT_PROVIDER` | backend | optional | `request.network` | `request.network` | Fallback alias when `PAYMENT_PROVIDER` is unset |
| `PAYMENT_ENABLED_PROVIDERS` | backend | optional | `request.network` | `request.network` | Comma-separated providers allowed at runtime |
| `PAYMENT_ROLLBACK_PROVIDER` | backend | optional | `request.network` | `request.network` | Provider used when selected provider is not enabled |
| `PAYMENT_PROVIDER_MODE` | backend | optional | `live` | `dry-run` | Provider mode: `live`, `dry-run`, or `read-only` |
| `REQUEST_NETWORK_ENABLED` | backend | optional | `false` | `true` | Adds `request.network` to enabled providers when no explicit list is set |
| `PAYMENT_REQUEST_NETWORK_COHORT_PERCENT` | backend | optional | `0` | `10` | Percent of new checkout cohort eligible for Request Network |
@@ -125,11 +128,11 @@ SHKeeper is the crypto payment gateway. See [[Payment Flow]] and [[SHKeeper Inte
---
## Payments — DePay / Web3 (frontend)
## Payments — Wallet UI (frontend)
| Name | Repo | Required | Default | Example | Purpose |
|------|------|----------|---------|---------|---------|
| `NEXT_PUBLIC_DEPAY_INTEGRATION_ID` | frontend | ✅ for DePay | — | `1330e2d3-…` | DePay widget integration ID |
| `NEXT_PUBLIC_DEPAY_INTEGRATION_ID` | frontend | legacy only | — | `1330e2d3-…` | Historical DePay widget integration ID |
| `NEXT_PUBLIC_ESCROW_WALLET_ADDRESS` | frontend | ✅ | — | `0xa304…` | Escrow address shown to buyers in the wallet flow |
| `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` | frontend | ✅ | — | `283b54dd…` | WalletConnect v2 project ID |
| `NEXT_PUBLIC_ALCHEMY_API_KEY_MAINNET` | frontend | ✅ | — | — | Alchemy RPC for mainnet |
@@ -271,20 +274,23 @@ SMTP_USER=
SMTP_PASS=
SMTP_FROM="AMN <no-reply@amn.gg>"
# SHKeeper (set when ready)
PAYMENT_PROVIDER=shkeeper
PAYMENT_ENABLED_PROVIDERS=shkeeper
PAYMENT_ROLLBACK_PROVIDER=shkeeper
REQUEST_NETWORK_ENABLED=false
PAYMENT_LEDGER_ENFORCEMENT=false
# Payments
PAYMENT_PROVIDER=request.network
PAYMENT_ENABLED_PROVIDERS=request.network
PAYMENT_ROLLBACK_PROVIDER=request.network
REQUEST_NETWORK_ENABLED=true
REQUEST_NETWORK_API_KEY=
REQUEST_NETWORK_API_BASE_URL=https://api.request.network
REQUEST_NETWORK_ORIGIN=https://dev.amn.gg
REQUEST_NETWORK_MERCHANT_REFERENCE=
REQUEST_NETWORK_NETWORK=bsc
REQUEST_NETWORK_PAYMENT_CURRENCY=USDC
REQUEST_NETWORK_WEBHOOK_CALLBACK_URL=https://dev.amn.gg/api/payment/request-network/webhook
REQUEST_NETWORK_WEBHOOK_SECRET=
REQUEST_NETWORK_ALLOW_TEST_WEBHOOKS=false
PAYMENT_LEDGER_ENFORCEMENT=true
PAYMENT_RECONCILIATION_ENABLED=false
TREZOR_SAFEKEEPING_REQUIRED=false
SHKEEPER_BASE_URL=
SHKEEPER_API_URL=
SHKEEPER_API_KEY=
SHKEEPER_WEBHOOK_SECRET=
SHKEEPER_CALLBACK_SECRET=
SHKEEPER_FORCE_PAYOUT_DEMO=true
# OpenAI (optional)
OPENAI_API_KEY=

View File

@@ -125,7 +125,7 @@ frontend/
│ ├── actions/ # Server-side / shared async API calls (axios)
│ ├── auth/ # JWT / OAuth / passkey context, guards, hooks, services
│ ├── socket/ # Socket.IO client, hooks, components, contexts
│ ├── web3/ # WalletConnect + Alchemy + DePay glue
│ ├── web3/ # WalletConnect + Alchemy + Request Network checkout glue
│ ├── routes/ # Static path constants (paths object)
│ ├── utils/ # logger, format-number, format-time, localStorage, …
│ ├── types/ # Shared TS types (mirrors backend models where useful)

View File

@@ -122,9 +122,9 @@ You must `docker login git.manko.yoga -u manawenuz` first. Pushes both tags and
### `start-ngrok.sh`
**Purpose.** Start `ngrok http` against a local port (default `8083`) and print the public URL by polling the inspector at `127.0.0.1:4040`. Lets you receive SHKeeper webhooks on your laptop.
**Purpose.** Start `ngrok http` against a local port (default `8083`) and print the public URL by polling the inspector at `127.0.0.1:4040`. Lets you receive Request Network webhooks on your laptop.
**When to run.** Local SHKeeper webhook development.
**When to run.** Local Request Network webhook development.
**Example.**
@@ -219,9 +219,9 @@ Each script takes a base URL + admin token. Inspect them before running.
### `manual-test.ts`
**Purpose.** Local sanity check for the SHKeeper service: calls `createPayInIntent` with mock data and verifies a webhook signature in dev mode.
**Purpose.** Historical sanity check for the old SHKeeper service.
**When to run.** Smoke-test after changing SHKeeper code without running the full suite.
**When to run.** Legacy-record troubleshooting only; new payment work should use the Request Network tests.
**Example.**
@@ -243,13 +243,13 @@ npm run dev &
ts-node manual-payout-test.ts
```
> [!warning] Will create a real payout record in the DB. With `SHKEEPER_FORCE_PAYOUT_DEMO=true` no on-chain transaction is sent; without that flag a real on-chain transfer can occur.
> [!warning] Will create a real payout record in the DB. Treat this as a legacy/manual helper; routine releases should go through ledger-gated release/refund orchestration.
### `fix-transaction-hashes.js`
**Purpose.** One-off backfill — walks completed Payments missing `transactionHash`, queries SHKeeper for the original invoice, extracts the confirmed transaction hash, and updates the payment document.
**Purpose.** Historical one-off backfill — walks completed legacy Payments missing `transactionHash`, queries SHKeeper for the original invoice, extracts the confirmed transaction hash, and updates the payment document.
**When to run.** Only if you see payments displayed as "completed" with a missing tx hash. Rate-limits itself with a 1s delay per record.
**When to run.** Only for old SHKeeper records. New Request Network payments should be reconciled through Request Network webhook/reconciliation tooling.
**Example.**
@@ -260,7 +260,7 @@ SHKEEPER_API_KEY=... \
node fix-transaction-hashes.js
```
> [!warning] Hits the live SHKeeper API and writes to MongoDB. Take a backup ([[Backup & Recovery]]).
> [!warning] Hits the live legacy SHKeeper API and writes to MongoDB. Take a backup ([[Backup & Recovery]]).
### `check-templates.js`, `get-admin-token.js`

View File

@@ -47,9 +47,9 @@ Both repos use **Jest** as the unit/integration runner. The frontend additionall
There are also four large aggregate suites referenced in `package.json` (some may live in branches or be reintroduced as the codebase evolves):
- `models.test.ts` — every Mongoose schema, validation, indexes, relationships
- `payment-services.test.ts` — DePay, SHKeeper, Web3, admin operations
- `request-network-adapter.test.ts`, `request-network-webhook.test.ts`, `rn-in-house-checkout.test.ts` — Request Network checkout and webhook behavior
- `payment-ledger.service.test.ts`, `payment-release-refund-orchestration.test.ts` — ledger and release/refund behavior
- `complete-backend.test.ts` — Auth, marketplace, chat, notification, address, user, file, email, AI
- `shkeeper-backend.test.ts` — Service layer + API endpoints for SHKeeper
### Commands
@@ -61,11 +61,11 @@ npm run test:watch # interactive watch mode
npm run test:coverage # also emit coverage report to ./coverage/
npm run test:all # explicit __tests__/ folder
# Focused suites (each maps to a single file):
# Focused suites:
npm run test:models # jest __tests__/models.test.ts
npm run test:payment # jest __tests__/payment-services.test.ts
npm run test:complete # jest __tests__/complete-backend.test.ts
npm run test:shkeeper # jest __tests__/shkeeper-backend.test.ts
npm run test -- --testPathPattern=request-network
npm run test -- --testPathPattern=payment-ledger
```
Pass extra Jest flags after `--`:
@@ -101,7 +101,7 @@ describe('GET /api/health', () => {
```
3. Use the in-memory DB — connections are wired in `setup.ts`. Each test starts with a clean collection.
4. Mock outbound HTTP (SHKeeper, OpenAI) with `jest.spyOn(axios, 'post')`. Never hit a real provider from tests.
4. Mock outbound HTTP (Request Network, OpenAI, AML providers) with `jest.spyOn(axios, 'post')` or a dedicated adapter mock. Never hit a real provider from tests.
> [!warning] `maxWorkers: 1` makes tests serial. Don't introduce timing-sensitive parallelism — instead, keep individual tests small and deterministic.