docs: sync from backend 19f7eb9, frontend 60ee6fb — Task #10 AML screening
This commit is contained in:
@@ -9,7 +9,7 @@ created: 2026-05-23
|
||||
How identity, authorization, transport, and integrity are handled across the platform.
|
||||
|
||||
> [!important]
|
||||
> Read alongside [[Authentication Flow]] (user-facing), [[Passkey (WebAuthn) Flow]], and [[Payment Flow - SHKeeper]] (webhook HMAC).
|
||||
> Read alongside [[Authentication Flow]] (user-facing), [[Passkey (WebAuthn) Flow]], [[Escrow Flow]], and [[Request Network Integration Constraints]].
|
||||
|
||||
---
|
||||
|
||||
@@ -22,7 +22,7 @@ How identity, authorization, transport, and integrity are handled across the pla
|
||||
| CSRF | JWT in `Authorization` header (not cookie), CORS allow-list |
|
||||
| XSS | Helmet CSP, React auto-escaping, sanitize HTML before storage |
|
||||
| SQL/NoSQL injection | Mongoose parameterized queries, no `$where` strings, schema validation |
|
||||
| Webhook spoofing | HMAC SHA-256 over body + secret (SHKeeper, Request Network, Telegram), constant-time compare |
|
||||
| Webhook spoofing | HMAC SHA-256 over raw body + provider secret (Request Network, Telegram), constant-time compare |
|
||||
| File upload abuse | Multer MIME validation, 5 MB cap, non-executable storage, served by Nginx not Node |
|
||||
| Replay attacks | Per-payment idempotency on `providerPaymentId`; Telegram initData in-memory replay map; per-request `X-Request-Id` |
|
||||
| Account takeover | Email verification required, password reset code expiry (1h), passkey support |
|
||||
@@ -155,34 +155,36 @@ A single User may be `buyer` and `seller` simultaneously (combined role).
|
||||
|
||||
## 5. Webhook integrity
|
||||
|
||||
### 5.1 SHKeeper
|
||||
### 5.1 Request Network
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant SHK
|
||||
participant RN
|
||||
participant WK as Durable ingress (roadmap)
|
||||
participant BE
|
||||
SHK->>BE: POST /api/payment/shkeeper/webhook<br/>X-Signature: sha256=<hmac>
|
||||
BE->>BE: hmac = HMAC_SHA256(SHKEEPER_WEBHOOK_SECRET, body)
|
||||
BE->>BE: crypto.timingSafeEqual(hmac, providedSig)
|
||||
RN->>WK: POST /api/payment/request-network/webhook<br/>x-request-network-signature
|
||||
WK->>WK: Store raw body + headers + delivery id
|
||||
WK->>BE: Forward / replay raw webhook
|
||||
BE->>BE: verifyRequestNetworkWebhookSignature(rawBody, headers)
|
||||
alt mismatch
|
||||
BE-->>SHK: 401 Unauthorized
|
||||
BE-->>WK: 401 Unauthorized
|
||||
else match
|
||||
BE->>BE: process payment update
|
||||
BE-->>SHK: 200 OK
|
||||
BE->>BE: idempotency + Transaction Safety Provider
|
||||
BE->>BE: process payment update / ledger entry
|
||||
BE-->>WK: 200 OK
|
||||
end
|
||||
```
|
||||
|
||||
- Raw body must be used for HMAC — `express.raw({ type: 'application/json' })` is mounted on this route only (before the global `express.json()` parser).
|
||||
- In dev (`NODE_ENV === 'development'`) signature verification can be bypassed for local testing — confirm this is gated and never reachable in prod.
|
||||
- Idempotency: identical webhook delivered twice should be no-op. Check by `(providerPaymentId, status)` tuple before mutating.
|
||||
|
||||
### 5.2 Request Network
|
||||
|
||||
- Webhooks arrive at `/api/payment/request-network/webhook` with an `x-request-network-signature` header.
|
||||
- The backend verifies the signature using `backend/src/services/payment/requestNetwork/signature.ts` before any state mutation.
|
||||
- The route is mounted **before** the global `express.json()` body parser so raw body bytes are available for signature computation.
|
||||
- The global rate-limit middleware is configured to skip this path to avoid blocking high-frequency payment events.
|
||||
- Reconciliation service (`requestNetworkReconciliationService.ts`) handles replayed or out-of-order webhooks idempotently.
|
||||
- Durable ingress is the target production shape: the Worker stores delivery evidence and supports replay, but the backend remains the trust oracle.
|
||||
|
||||
### 5.2 Legacy SHKeeper note
|
||||
|
||||
SHKeeper-specific webhook docs are historical migration context. The current backend payment tree uses Request Network as the primary provider; do not reintroduce SHKeeper signature bypasses or fallback webhook heuristics without a new security review.
|
||||
|
||||
### 5.3 Telegram Bot webhook
|
||||
|
||||
@@ -191,7 +193,7 @@ sequenceDiagram
|
||||
- A per-update-id in-memory replay map prevents duplicate processing within the configured window.
|
||||
- The global rate-limit middleware is configured to skip this path.
|
||||
|
||||
See [[Payment Flow - SHKeeper]] for the SHKeeper full flow.
|
||||
See [[Escrow Flow]] and [[Request Network Integration Constraints]] for the current payment path.
|
||||
|
||||
---
|
||||
|
||||
@@ -219,7 +221,7 @@ See [[Payment Flow - SHKeeper]] for the SHKeeper full flow.
|
||||
- Never log secrets — logger redaction recommended (winston/pino formatter).
|
||||
- `.env*` files in `.gitignore`. Repo includes only `.env.development` / `.env.production` templates with **public** values (NEXT_PUBLIC_*).
|
||||
- Rotate `JWT_SECRET` invalidates all existing JWTs — schedule a maintenance window.
|
||||
- Rotate `SHKEEPER_WEBHOOK_SECRET` coordinated with SHKeeper dashboard (set new → verify → remove old).
|
||||
- Rotate `REQUEST_NETWORK_WEBHOOK_SECRET` coordinated with Request Network configuration (set new → verify → remove old).
|
||||
|
||||
See [[Environment Variables]] for the catalog.
|
||||
|
||||
@@ -277,6 +279,6 @@ The codebase currently uses `morgan` (HTTP access logs) and ad-hoc `logger.info/
|
||||
|
||||
- [[Authentication Flow]] (includes Telegram first-class auth flow) · [[Google OAuth Flow]] · [[Passkey (WebAuthn) Flow]] · [[Password Reset Flow]]
|
||||
- [[Backend Architecture]] · [[Frontend Architecture]] · [[Real-time Layer]]
|
||||
- [[Payment Flow - SHKeeper]] — webhook HMAC details
|
||||
- [[Request Network Integration Constraints]] — payment webhook, checkout, and reconciliation constraints
|
||||
- [[Environment Variables]] — secret catalog
|
||||
- [[Incident Response]] — what to do when something goes wrong
|
||||
|
||||
Reference in New Issue
Block a user