docs: sync from backend 19f7eb9, frontend 60ee6fb — Task #10 AML screening

This commit is contained in:
Siavash Sameni
2026-05-28 20:35:38 +04:00
parent fd2aa71ef4
commit ddc0434819
34 changed files with 709 additions and 453 deletions

View File

@@ -15,9 +15,9 @@ When something goes wrong (item not delivered, wrong item, fraud), either party
- **Seller** — party against whom the dispute is raised (or in rarer cases, initiator).
- **Admin / Mediator** — assigned to investigate.
- **Frontend** — buyer/seller "Report issue" buttons in the request detail view; admin dispute dashboard.
- **Backend** — `DisputeService` (`backend/src/services/dispute/DisputeService.ts` *(planned)*), `DisputeController` (`backend/src/controllers/disputeController.ts` *(planned)*), routes at `backend/src/routes/disputeRoutes.ts` *(planned)*.
> [!warning] Not implemented
> None of these files exist as of 2026-05-24. The dispute module is planned but not yet built.
- **Backend** — `DisputeService` (`backend/src/services/dispute/DisputeService.ts`), dashboard/controller routes at `backend/src/routes/disputeRoutes.ts`, and release-hold helpers in `backend/src/services/dispute/releaseHoldService.ts`.
> [!note] Alignment gap
> The module exists now, but it still uses the legacy status/action enum. [[Funds Ledger and Escrow State Machine Specification]] defines the canonical future dispute states and financial side effects.
- **MongoDB** — `disputes`, `chats`, `purchaserequests`, `payments`.
- **Socket.IO** — `new-notification`, `new-message`, `dispute-updated` (planned).
@@ -57,8 +57,8 @@ Resolution actions (from `Dispute.resolution.action` enum, see `Dispute.ts` *(in
- Persists `dispute.chatId = chat._id`.
5. Notifications (currently a `TODO` in the service — `:107-116`) should fire `new-notification` to the seller. Today the chat creation alone provides real-time presence via the `new-message` socket emit inside `Chat.create`'s lifecycle.
> [!warning] Dispute does not auto-pause escrow
> Today, opening a dispute does **not** flip `Payment.escrowState` away from `funded`. An admin could theoretically still release the escrow before resolving the dispute. Until a `disputed` flag is added to Payment, admins must check the dispute table before any release/refund action.
> [!note] Release hold behavior
> Opening a dispute now has backend release-hold support: `releaseHoldService.raiseDispute()` sets hold fields on the purchase request and related payments, and release/refund gates can consult those fields. The remaining work is to make this the single mandatory policy path for every release/refund/sweep operation and align it with the canonical `DISPUTED` escrow state.
### Phase 2 — Admin assignment
@@ -84,7 +84,7 @@ Resolution actions (from `Dispute.resolution.action` enum, see `Dispute.ts` *(in
- `dispute.closedAt = now`
- Appends `timeline` entry `dispute_resolved`.
- Saves.
13. **Financial side-effect (manual today):** depending on the action, the admin then triggers either the **payout** ([[Payout Flow]] with `kind: 'release'`) or the **refund** (`kind: 'refund'`, see [[Escrow Flow]]). The dispute service does not automatically dispatch the on-chain action.
13. **Financial side-effect (manual today):** depending on the action, the admin then triggers either the **release** ([[Payout Flow]] / [[Escrow Flow]]) or the **refund**. The dispute service records the resolution; full automatic dispatch through the release/refund policy engine is still a hardening item.
14. Both parties are notified (TODOs in code — planned: `notifyDisputeResolved`).
## Sequence diagram
@@ -179,7 +179,7 @@ All require `authenticateToken` (router-level middleware).
- **Initiator is neither buyer nor seller** → not enforced at service level — should be validated in `DisputeController` (recommended hardening).
- **Same user opens multiple disputes for the same request** → no uniqueness constraint today. Consider adding `unique on (purchaseRequestId, status:'pending'|'in_progress')` to prevent duplicates.
- **Evidence URL is hot-linked** → frontend uploads through `POST /api/files/upload` and the URL is served from `/uploads`. Ensure auth on the upload endpoint to prevent random users from polluting evidence.
- **Dispute resolved without financial follow-up** → the dispute is "resolved" in record only; the escrow stays in its previous state. Add automation that auto-fires the payout/refund when the admin selects `release` or `refund`.
- **Dispute resolved without financial follow-up** → the dispute is "resolved" in record only; the escrow stays in its previous state until the admin/custody operator completes release/refund. Add automation that dispatches the policy-checked release/refund instruction when the admin selects a financial resolution.
- **Admin resigns mid-dispute** → no transfer-of-mediator endpoint today. Add `POST /api/disputes/:id/reassign`.
> [!tip] Sort disputes by priority + age
@@ -195,12 +195,10 @@ All require `authenticateToken` (router-level middleware).
## Source files
> [!warning] Not implemented
> None of the backend files below exist as of 2026-05-24. The dispute module is planned but not yet built.
- Backend: `backend/src/services/dispute/DisputeService.ts` *(planned)*
- Backend: `backend/src/controllers/disputeController.ts` *(planned)*
- Backend: `backend/src/routes/disputeRoutes.ts` *(planned)*
- Backend: `backend/src/models/Dispute.ts` *(planned)*
- Backend: `backend/src/services/dispute/DisputeService.ts`
- Backend: `backend/src/services/dispute/releaseHoldService.ts`
- Backend: `backend/src/routes/disputeRoutes.ts`
- Backend: `backend/src/services/dispute/disputeRoutes.ts`
- Backend: `backend/src/models/Dispute.ts`
- Frontend: `frontend/src/sections/request/components/report-problem-to-admin.tsx`
- Frontend: admin dispute dashboard under `frontend/src/sections/admin/` (subject to organisation)