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:
@@ -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.
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user