docs: add taskmaster prd task queue

This commit is contained in:
Siavash Sameni
2026-05-24 08:57:38 +04:00
parent 10a6c2fa53
commit 825add6487
11 changed files with 870 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
# PRD: Mermaid Diagram Rendering Stabilization
## Summary
- Scope: Documentation Mermaid diagrams in this vault.
- Discovery date: 2026-05-24.
- Total Mermaid blocks checked: `57`.
- Total failing blocks: `11`.
- Tooling used: `@mermaid-js/mermaid-cli` parse validation for each extracted block.
## Goal
Create a pass-ready task queue of Mermaid syntax/render issues so each diagram can be corrected one-by-one without guessing.
## Acceptance Criteria
- Every Mermaid block parses successfully with the same mmdc-based syntax validation.
- Diagrams render in Obsidian/markdown previews without parser errors.
- Each corrected block retains the same intent and participant names where possible.
## Task 1 - Security Architecture: Email + password sequence
- **File:** `01 - Architecture/Security Architecture.md`
- **Diagram range:** `38-57` (Authentication layers / 2.1)
- **Error:** Parse error line 12: `...nAttempts; lock at N BE-->>FE: 4`
- **Likely issue:** Sequence parser is choking around a message containing inline punctuation and line continuation (`;` and `...`), likely interpreted as malformed sequence text.
- **Fix:** Keep the message text parser-safe (single simple `:` message per line; avoid special separators like unescaped semicolons) and rerun parser.
## Task 2 - Authentication Flow: Login sequence
- **File:** `04 - Flows/Authentication Flow.md`
- **Diagram range:** `57-90` (`## Sequence diagram`)
- **Error:** Parse error line 48: `...Tokens.push(refresh) BE->>BE: ge`
- **Likely issue:** Line includes inline method-like token with parentheses-like/space patterns and tokenization ambiguity.
- **Fix:** Replace the problematic statement with plain text in message, e.g. `BE->>DB: User.refreshTokens.push(refreshToken)` as one line.
## Task 3 - Authentication Flow: Refresh token flow
- **File:** `04 - Flows/Authentication Flow.md`
- **Diagram range:** `127-143` (`## Refresh flow`)
- **Error:** Parse error line 11: `... is in user.refreshTokens BE->>BE: Genera`
- **Likely issue:** Special math-style characters and expression-like message text interrupting parser tokenization.
- **Fix:** Replace special symbols in message text with plain ASCII and split to simple message line(s).
## Task 4 - Chat Flow: typing/chat notification sequence
- **File:** `04 - Flows/Chat Flow.md`
- **Diagram range:** `91-125` (`## Sequence diagram`)
- **Error:** Parse error line 20: `...ata.lastActivity=now BE->>IO: emit c`
- **Likely issue:** Assignment-style text (`...=now`) in message and possible bare punctuation in one-line payload.
- **Fix:** Simplify message bodies around state updates to readable text only.
## Task 5 - Delivery Confirmation Flow: code verification sequence
- **File:** `04 - Flows/Delivery Confirmation Flow.md`
- **Diagram range:** `45-71` (`## Sequence diagram`)
- **Error:** Parse error line 22: `...; status="delivered" BE->>IO: emit r`
- **Likely issue:** Double status expression in message (`deliveryCodeUsed=true; status="delivered"`).
- **Fix:** Split into two explicit sequence lines or rephrase with punctuation-safe text.
## Task 6 - Dispute Flow: admin resolve sequence
- **File:** `04 - Flows/Dispute Flow.md`
- **Diagram range:** `90-134` (`## Sequence diagram`)
- **Error:** Parse error line 18: `... is dispute } FE-->>B,S: chat opens (real`
- **Likely issue:** Invalid multi-recipient send syntax `B,S` on one arrow line.
- **Fix:** Either split into two lines (`FE-->>B:` and `FE-->>S:`) or route via a shared frontend/chat intermediary.
## Task 7 - Google OAuth Flow: completion sequence
- **File:** `04 - Flows/Google OAuth Flow.md`
- **Diagram range:** `56-96` (`## Sequence diagram`)
- **Error:** Parse error line 34: `...fill avatar if blank end BE->>BE`
- **Likely issue:** `end`/branch block combined with following arrow in parser context likely due missing separation in message-heavy block.
- **Fix:** Ensure `opt ... end` block boundaries and arrows are on clean, standalone lines.
## Task 8 - Purchase Request Flow: publish sequence
- **File:** `04 - Flows/Purchase Request Flow.md`
- **Diagram range:** `94-129` (`## Sequence diagram`)
- **Error:** Parse error line 27: `...ds; compute isPublic BE->>DB: Purcha`
- **Likely issue:** Message text includes expressions (`compute isPublic`) and punctuation (`;`) that are breaking the sequence parser.
- **Fix:** Rephrase backend processing lines into simple text without `;`/embedded expressions.
## Task 9 - Referral Flow: conversion and payout sequence
- **File:** `04 - Flows/Referral Flow.md`
- **Diagram range:** `70-99` (`## Sequence diagram`)
- **Error:** Parse error line 26: `...Transaction.create; update`
- **Likely issue:** Message text around chained commands (`updateUserLevel`) appears parser-conflicting.
- **Fix:** Break chained method-like messages into one action-per-line statements.
## Task 10 - Registration Flow: email verification sequence
- **File:** `04 - Flows/Registration Flow.md`
- **Diagram range:** `87-127` (`## Sequence diagram`)
- **Error:** Parse error line 36: `...tokens.push(refresh) BE->>BE: 200`
- **Likely issue:** Message line includes token-manipulation call style in plain text causing parser confusion.
- **Fix:** Reword to plain textual action; keep method calls minimal.
## Task 11 - Seller Offer Flow: submit offer sequence
- **File:** `04 - Flows/Seller Offer Flow.md`
- **Diagram range:** `97-134` (`## Sequence diagram`)
- **Error:** Parse error line 16: `...ETA, notes; submit FE_S->>BE: POST`
- **Likely issue:** Message with `; submit` and inline comma-separated action text.
- **Fix:** Split into cleaner action lines before POST step.
## Execution Order
1. Address Task 6 first (obvious syntax violation) to quickly cut down parse noise.
2. Tackle Tasks 2, 3, 5, 8, 9, 10, 11 (message-format cleanup).
3. Validate with a full parser sweep after each batch.
4. Final sweep: re-run mmdc parse validation across all `57` Mermaid blocks and close this PRD once no errors remain.
## Current Run Status
- Execution date: 2026-05-24
- Parallel passes launched: 3
- Result: All targeted task files pass `@mermaid-js/mermaid-cli` parsing.
- Full vault sweep (all markdown Mermaid blocks): **pass**.
### Task Completion
- Task 1: Complete (Security Architecture sequence lines simplified)
- Task 2: Complete (Authentication login refresh token line split/rephrased)
- Task 3: Complete (Authentication refresh-flow syntax normalized)
- Task 4: Complete (Chat flow update-message line rewritten)
- Task 5: Complete (Delivery confirmation message split into safe lines)
- Task 6: Complete (Dispute flow multi-recipient send split into separate arrows)
- Task 7: Complete (Google OAuth flow statement ordering fixed)
- Task 8: Complete (Purchase Request preference/public logic split into separate action lines)
- Task 9: Complete (Referral flow user-points action split)
- Task 10: Complete (Registration token update line split)
- Task 11: Complete (Seller Offer flow rewritten into parser-safe sequence diagram)

View File

@@ -0,0 +1,232 @@
# PRD: Platform Audit Remediation Plan (2026-05-24)
## Scope
- Source audit: `09 - Audits/Platform Logical Audit - 2026-05-24.md`
- Target: backend hardening and consistency fixes first, then doc/runtime alignment.
- Assessed date: 2026-05-24
## Audit validity check (code-backed vs docs-only)
- **Code-confirmed valid findings**:
- Unauthenticated financial/auth-sensitive routes are exposed (`/api/payment/*`, `/api/ai/*`, legacy notification routes).
- Passkey flow uses stubbed credential handling and in-memory challenge storage.
- `PaymentCoordinator` does not currently enforce dispute holds.
- Web3 verifier relies primarily on `receipt.status`.
- Socket.IO user-room joins are client-controlled.
- Rate limiting is explicitly disabled in `backend/src/app.ts`.
- **Partially validated / inconsistent findings**:
- Dispute module appears absent in the checked backend tree (`backend/src` does not contain `services/dispute`/`routes/disputeRoutes`/`controllers/disputeController`), so many dispute-specific audit checks cannot be confirmed against code but indicate a documentation-runtime mismatch.
- The REST/API/flow docs mention endpoints that differ from available implementation in some places; these should be normalized as part of a separate alignment pass.
---
## PRD 1: Secure unauthenticated endpoints and data-owner enforcement (P0)
### Problem
- `backend/src/services/payment/decentralizedPaymentRoutes.ts` exposes mutation endpoints (`/save`, `/update`, `/verify`, `/verify-all-pending`) without auth.
- `backend/src/services/ai/aiRoutes.ts` has public generation endpoints (`/generate`, `/analyze`, `/translate`, `/assist`) with no auth.
- `backend/src/services/notification/routes.ts` lets clients specify `userId` and mutate/read without ownership checks, and routes are mounted publicly via `app.use("/api", notificationRoutes)` in `backend/src/app.ts`.
### Acceptance criteria
- Every endpoint in `decentralizedPaymentRoutes.ts`, `aiRoutes.ts`, and legacy `notificationRoutes.ts` requires:
- `authenticateToken`
- owner/admin role check where applicable
- Notification endpoints do not accept arbitrary `userId`; derive `userId` from authenticated principal.
- Payment history and mutation endpoints enforce requestor ownership or admin/authorized role.
### Risk assessment
- **Threat**: Financial/private data tampering or privacy breach by unauthenticated callers.
- **Likelihood**: High.
- **Impact**: Critical (funding fraud, PII leakage, cost abuse).
- **Mitigation**: Introduce router-level middleware and standardized auth helper.
- **Residual risk**: Medium if any integration jobs call these endpoints (document required with service tokens or service role).
### Delivery plan
1. Add route-level `authenticateToken` to all routes in files above.
2. Introduce ownership guard utilities for:
- `history/:userId` and payment listing/history filters
- notification queries/updates
3. Restrict AI calls to authenticated users with per-user rate budget.
4. Add audit logs for denied access and suspicious payloads.
5. Update API docs for auth requirements.
### Owner / dependencies
- Owner: Backend security + payments teams.
- Depends on: token standards in `backend/src/shared/middleware/auth`.
---
## PRD 2: Production-grade Passkey/WebAuthn flow (P0)
### Problem
- `backend/src/services/auth/passkeyService.ts` stores passkey challenge data in an in-memory `Map` and inserts `'simulated-public-key'` during registration.
- Refresh token is generated on authentication but never persisted to `user.refreshTokens[]`, making token rotation behavior inconsistent with the rest of auth flows.
### Acceptance criteria
- Replace stubbed registration/verification with real WebAuthn verification.
- Back challenges by shared storage (Redis or equivalent), not in-process memory.
- Persist verified refresh tokens and rotate according to normal auth policy.
- Reject reused/expired challenges and malformed assertions with deterministic errors.
### Risk assessment
- **Threat**: Credential spoofing, replay attacks, and broken session continuity.
- **Likelihood**: High.
- **Impact**: Critical (account takeover / authentication bypass).
- **Mitigation**: Add `@simplewebauthn/server` (or equivalent) + Redis-backed nonce store + strict verification.
- **Residual risk**: Medium (device/browser compatibility edge-cases).
### Delivery plan
1. Replace `verifyRegistration` and `verifyAuthentication` with attestation/assertion verification.
2. Swap `storedChallenges` map for distributed storage with TTL.
3. Add persistent refresh token append in passkey login flow.
4. Add regression tests for sign-in/sign-up and challenge expiry.
### Owner / dependencies
- Owner: Auth team.
- Depends on: Redis infra, passkey frontend challenge handling.
---
## PRD 3: Enforce dispute hold before payout/release operations (P1)
### Problem
- No dispute implementation files are present in the checked backend for enforcement paths, yet escrow release can still proceed in payment logic without a blocking hold.
- `backend/src/services/marketplace/routes.ts` release endpoint (`/purchase-requests/:id/release-payment`) executes without a dispute gate.
- `backend/src/services/payment/paymentCoordinator.ts` applies sequencing and dedupe logic but has no dispute state guard.
### Acceptance criteria
- Introduce explicit hold mechanism on `Payment` (or new `disputeStatus`/`holdReason` field).
- All release/refund flows check hold state before state mutation.
- Release endpoint returns clear 409/423 response when disputed.
- Backfill/reporting distinguishes dispute-blocked payments.
### Risk assessment
- **Threat**: Funds released before dispute resolution.
- **Likelihood**: Medium (documented behavior gap).
- **Impact**: Critical (financial loss / trust erosion).
- **Mitigation**: Centralize payout/refund state checks in coordinator and services, not UI-only logic.
- **Residual risk**: Medium (existing open disputes may need manual reconciliation).
### Delivery plan
1. Add `disputed`/`disputeHoldReason` fields (and migration plan) to `Payment`.
2. Add hold checks in:
- `backend/src/services/marketplace/routes.ts` admin release flow
- `backend/src/services/payment/shkeeper/shkeeperService.ts` and payout flows
- `backend/src/services/payment/paymentCoordinator.ts` before completion transitions.
3. Create an internal service contract for setting/releasing hold after dispute open/resolve.
4. Add guard tests for blocked release and allowed release post-override.
### Owner / dependencies
- Owner: Escrow/payment platform team.
- Depends on: dispute subsystem availability / status source-of-truth.
---
## PRD 4: Strengthen DePay/Web3 verification semantics (P1)
### Problem
- `backend/src/services/payment/decentralizedPaymentService.ts` verifies only `receipt.status === '0x1'`, without validating destination token, recipient, and amount mapping.
### Acceptance criteria
- Verification loads the transaction receipt + logs + token-decoding and validates:
- correct recipient address (`toAddress`)
- expected token contract (`token`)
- minimum amount with decimals.
- Reject/flag ambiguous payloads and store verifier evidence in `Payment.metadata`.
- Add idempotency/duplicate handling for repeated verification requests.
### Risk assessment
- **Threat**: Fraudulent transaction proofing and false-positive confirmations.
- **Likelihood**: Medium.
- **Impact**: High (unauthorized balance movement/false completion).
- **Mitigation**: Strict recipient/token/amount checks + explicit failure reason mapping.
- **Residual risk**: Medium (chain/protocol variance).
### Delivery plan
1. Extend verifier schema for expected transfer contract/address/decimals.
2. Decode ERC-20 `Transfer` event and compare against expected values.
3. Mark and persist `verificationFingerprint` to prevent replay/double-processing.
4. Return canonical failure reasons for observability.
### Owner / dependencies
- Owner: Payments + blockchain service team.
- Depends on: RPC/provider reliability and token ABI metadata.
---
## PRD 5: Lock Socket.IO user room joins to authenticated context (P2)
### Problem
- `backend/src/app.ts` allows `join-user-room`, `join-buyer-room`, and `join-seller-room` events from arbitrary input IDs with no identity binding.
### Acceptance criteria
- Server derives room membership from validated `socket` identity after token handshake.
- Reject mismatched room join attempts with server-side authorization checks.
- Preserve real-time event behavior for legitimate users.
### Risk assessment
- **Threat**: Event channel interception and privacy leakage.
- **Likelihood**: Medium.
- **Impact**: High (notifications/messages for wrong user).
- **Mitigation**: Server-authorized socket-to-user mapping and middleware verification.
- **Residual risk**: Low (requires active socket auth and client migration).
### Delivery plan
1. Add token validation middleware on socket connection.
2. Replace client-sent ID room joins with authenticated identity joins.
3. Add per-room join/emit checks in critical publishers.
4. Add monitoring for room-join failures and suspicious activity.
### Owner / dependencies
- Owner: Real-time platform team.
- Depends on: frontend socket auth handshake updates.
---
## PRD 6: Re-enable and scope rate limiting for public-sensitive paths (P2)
### Problem
- `backend/src/app.ts` has comments and code indicating rate limiting is disabled globally.
### Acceptance criteria
- Re-enable limiter at edge level with sensible defaults.
- Use stricter quotas for auth/financial/AI endpoints.
- Keep lightweight paths (public listings, static read APIs) at higher budgets.
### Risk assessment
- **Threat**: Brute-force/log abuse, AI cost exhaustion, webhook abuse.
- **Likelihood**: High.
- **Impact**: Medium-High (operational availability and cost).
- **Mitigation**: Endpoint-tiered limiter with trusted network exceptions and observability.
- **Residual risk**: Medium (false positives on legitimate spikes).
### Delivery plan
1. Restore global limiter with default relaxed values.
2. Add stricter route-level windows for `/api/auth/*`, `/api/payment/*`, `/api/ai/*`.
3. Add alerts on repeated 429s and limit misconfigurations.
### Owner / dependencies
- Owner: Platform infrastructure/security team.
---
## Documentation and API alignment follow-up (P2)
- Where docs refer to `backend/src/services/dispute/*` and `backend/src/services/dispute/disputeRoutes.ts`, either implement that module or update architecture/API/docs to current repository reality.
- Normalize enum/action naming across:
- `02 - Data Models/*`
- `03 - API Reference/*`
- `04 - Flows/*`
---
## Delivery sequencing suggestion
1. PRD 1 (security/auth)
2. PRD 6 (rate limiting)
3. PRD 2 (passkeys)
4. PRD 4 (verification trust)
5. PRD 5 (socket hardening)
6. PRD 3 (dispute hold controls)
7. Documentation/API alignment

View File

@@ -0,0 +1,333 @@
# PRD - Request Network Migration and Funds Management
Date: 2026-05-24
Status: Draft for architecture review
Owner: Platform / Payments
Codebase reviewed: `/Users/manwe/CascadeProjects/escrow`
## Executive Summary
Replacing SHKeeper with Request Network is not a provider swap. SHKeeper currently acts like a deposit-wallet and payout-task provider: the backend creates a payment intent, receives a generated wallet address, watches SHKeeper webhooks and BSC wallet balances, then optionally creates an outgoing payout task.
Request Network is request/payment-reference based. The platform creates a Request Network payment request or secure payment page, the payer pays through Request Network contracts or hosted flow, and reconciliation happens through Request Network payment events. Payouts are API-created payment requests/calldata that still require wallet execution. This means Amanat needs a first-class funds ledger and a release/refund orchestration layer, not just renamed `/payment/shkeeper/*` endpoints.
Primary recommendation: run a phased migration behind a provider adapter. Introduce Request Network for new pay-ins first using Secure Payment Pages, keep SHKeeper read-only for existing payments, then add funds ledger, release/refund gates, and Request Network payout flows.
## Source Findings
Current code:
- Backend mounts SHKeeper at `/api/payment/shkeeper` through `backend/src/services/payment/shkeeper/shkeeperRoutes.ts` and `shkeeperPayoutRoutes.ts`.
- Frontend calls SHKeeper through `frontend/src/actions/payment.ts`, `frontend/src/web3/components/shkeeper-payment.tsx`, `shkeeper-widget.tsx`, and `shkeeper-payout.tsx`.
- `Payment.provider` only allows `shkeeper` or `other`; SHKeeper-specific fields live directly under `Payment.metadata`.
- Pay-in completion is accepted from SHKeeper webhook, manual confirmation, or wallet monitor, all coordinated through `PaymentCoordinator`.
- Current payout paths mix SHKeeper payout tasks, simulated marketplace release, and direct admin wallet payout.
- There is no durable internal funds ledger that tracks available, held, releasable, disputed, released, refunded, and fee amounts per purchase request.
Request Network documentation checked:
- API v2 supports programmatic request creation, secure payment pages, payouts, webhooks, payment search, platform fees, and payee destinations: <https://docs.request.network/llms.txt>
- Secure Payment Pages are hosted payment URLs returned by `POST /v2/secure-payments`, returning `requestIds`, `token`, and `securePaymentUrl`: <https://beta.docs.request.network/api-features/secure-payment-pages>
- Secure Payment Pages validate official Request Network contracts before payer signing: <https://beta.docs.request.network/api-features/secure-payment-pages>
- Webhooks are scoped by Client ID and include `x-request-network-signature`, delivery ID, retry count, and optional test header: <https://requestnetwork.mintlify.app/api-reference/webhooks>
- Request Network webhooks retry failed deliveries up to 3 retries with short backoff windows: <https://requestnetwork.mintlify.app/api-reference/webhooks>
- Payout endpoints return unsigned transaction data that the platform/wallet must execute: <https://docs.request.network/request-network-api/recurring-payments>
- Batch payouts can return approval and batch payment transactions; the application sends those wallet transactions: <https://docs.request.network/request-network-api/batch-payments>
- Request Network protocol fee is 5 bps with stablecoin caps, and platform fees can be included through `feePercentage` and `feeAddress`: <https://docs.request.network/request-network-api/fees>
- Payment networks use payment references for detection, rather than unique deposit wallets per invoice: <https://docs.request.network/advanced/protocol-overview/how-payment-networks-work>
## Target Architecture
### Payment Provider Adapter
Create a provider-neutral payment interface:
- `createPayInIntent`
- `getPayInStatus`
- `handleProviderWebhook`
- `createHostedPaymentLink`
- `createReleaseInstruction`
- `createRefundInstruction`
- `getPayoutStatus`
- `searchProviderPayments`
Implement:
- `ShkeeperProvider` for legacy compatibility.
- `RequestNetworkProvider` for new flows.
### Funds Ledger
Add an internal ledger separate from provider metadata:
- `fundsAccount`: one per purchase request or order.
- `ledgerEntry`: immutable entries for authorization, payment detected, platform fee, provider fee, hold, release, refund, chargeback/dispute hold, adjustment.
- `fundsBalance`: derived or cached view containing `expected`, `paid`, `held`, `releasable`, `released`, `refunded`, `disputed`, `fees`, and `available`.
Ledger invariants:
- Seller payout cannot exceed paid amount minus refunds, fees, and active dispute holds.
- Release requires payment status `completed`, escrow state `releasable`, no open dispute, and a verified seller destination.
- Refund requires available held balance and must mark the purchase request/payment state consistently.
- Provider webhooks never directly mark funds as released; they create/reconcile ledger entries.
### Payment Flow
Pay-in:
1. Buyer accepts seller offer.
2. Backend creates internal payment + funds account.
3. Backend calls Request Network `POST /v2/secure-payments` or `POST /v2/request`.
4. Frontend redirects to `securePaymentUrl` or executes returned calldata in wallet.
5. Request Network webhook confirms payment.
6. Backend verifies signature, idempotency, amount, request ID, payment reference, currency, and merchant reference.
7. Ledger moves from `expected` to `held`.
8. Purchase request enters `payment` or `processing`.
Release:
1. Buyer delivery confirmation or admin release marks funds `releasable`.
2. Backend creates Request Network payout/release instruction, or admin wallet transaction instruction.
3. Admin/operator wallet signs and broadcasts transaction.
4. Backend records transaction hash as `release_pending`.
5. Webhook/search confirms settlement.
6. Ledger moves `held -> released`.
Refund:
1. Refund request validates available held balance.
2. Backend creates refund transaction instruction.
3. Admin/operator wallet executes.
4. Confirmation updates ledger `held -> refunded`.
## PRD 1 - Provider-Neutral Payment Adapter
Priority: P0
Goal: decouple checkout, webhook, and payout flows from SHKeeper-specific routes and metadata.
Scope:
- Add `paymentProvider` abstraction in backend.
- Add `provider: 'shkeeper' | 'request_network' | 'manual' | 'admin_wallet'` to payment model.
- Keep `/api/payment/shkeeper/*` operational for legacy records.
- Add `/api/payment/providers/request-network/*` or `/api/payment/request-network/*` for new Request Network flows.
- Add a feature flag: `PAYMENT_PROVIDER=request_network|shkeeper`.
Acceptance Criteria:
- New checkout can create a Request Network payment link without touching SHKeeper service code.
- Existing SHKeeper payments remain readable and can still process late webhooks.
- Frontend does not import provider-specific action names outside provider-specific components.
- Provider metadata is namespaced under `metadata.providers.requestNetwork` or a dedicated provider table.
Risk Assessment:
- Impact: High. Payment creation is core revenue flow.
- Likelihood: Medium. Existing code has many direct `shkeeper` references.
- Main risks: broken checkout, duplicate payment records, orphaned webhooks, mixed provider states.
- Mitigation: use provider feature flag, preserve SHKeeper routes, add idempotency keys, run Request Network only for new payments during rollout.
- Rollback: set `PAYMENT_PROVIDER=shkeeper`; keep Request Network records read-only.
## PRD 2 - Request Network Pay-In Integration
Priority: P0
Goal: replace generated SHKeeper wallet addresses with Request Network request/payment-reference based payment collection.
Scope:
- Store Request Network `requestId`, `paymentReference`, `securePaymentUrl`, `token`, `merchantReference`, `network`, `invoiceCurrency`, and `paymentCurrency`.
- Use Secure Payment Pages for first launch to reduce frontend wallet/calldata complexity.
- Include Amanat purchase request ID and payment ID as merchant reference or metadata.
- Validate supported networks/currencies before creating payment links.
- Remove frontend dependence on SHKeeper-generated `walletAddress` for new provider flow.
Acceptance Criteria:
- Buyer can start payment and receive a Request Network hosted payment URL.
- Backend records internal payment as `pending` with Request Network identifiers.
- Webhook `payment.confirmed` reconciles only the matching internal payment.
- Amount, currency, provider request ID, and merchant reference are verified before setting `escrowState='funded'`.
- Late or duplicate webhook deliveries are idempotent.
Risk Assessment:
- Impact: High.
- Likelihood: Medium.
- Main risks: currency/network mismatch, hosted redirect UX breakage, buyer pays wrong amount, missing webhook.
- Mitigation: backend-only creation, strict metadata correlation, periodic fallback reconciliation using Request Network payment search, idempotency by delivery ID and request ID.
- Rollback: disable Request Network provider for new payments; keep pending Request Network payments visible with manual support workflow.
## PRD 3 - Funds Ledger and Escrow State Machine
Priority: P0
Goal: introduce internal funds management so payment, hold, release, refund, dispute, and fee states are auditable and provider-independent.
Scope:
- Add `FundsAccount` model keyed by purchase request/payment.
- Add immutable `LedgerEntry` model with provider references and actor/source.
- Add derived `FundsBalance` query/service.
- Define state transitions: `expected -> held -> releasable -> releasing -> released`, plus `refunded`, `partially_refunded`, `disputed`, `failed`.
- Prevent release/refund from reading raw `Payment.status` alone.
Acceptance Criteria:
- Every successful pay-in creates a ledger entry for gross paid amount.
- Platform fee, Request Network protocol fee, and net seller amount are represented explicitly.
- Release API checks ledger invariants before creating payout/refund instructions.
- Dispute hold blocks payout until resolved.
- Admin UI/payment detail view can show gross paid, fees, held, releasable, released, refunded.
Risk Assessment:
- Impact: Very High.
- Likelihood: Medium.
- Main risks: double-release, incorrect fee accounting, drift between Payment and ledger state.
- Mitigation: immutable entries, unique idempotency keys, transaction/session writes where Mongo supports them, reconciliation job, read-only migration report before enforcing ledger.
- Rollback: keep old payment fields as source of truth until ledger backfill passes; feature flag release enforcement.
## PRD 4 - Request Network Webhook and Reconciliation Service
Priority: P1
Goal: replace SHKeeper webhook and wallet monitor semantics with signed Request Network event processing and periodic reconciliation.
Scope:
- Add `/api/payment/request-network/webhook`.
- Verify raw body using `x-request-network-signature`.
- Store delivery ID, retry count, event type, request ID, payment reference, payload hash, and processed status.
- Support test webhooks via `x-request-network-test`.
- Add scheduled reconciliation using Request Network payment search/status APIs.
- Retire SHKeeper wallet monitor for new Request Network payments.
Acceptance Criteria:
- Invalid signatures are rejected in all environments except explicit local test mode.
- Duplicate delivery IDs are acknowledged without duplicating ledger entries.
- `payment.confirmed` and partial/over/failed states map to internal status consistently.
- Reconciliation job can repair missed webhook state without relying on buyer/frontend callbacks.
Risk Assessment:
- Impact: High.
- Likelihood: Medium.
- Main risks: raw body parsing mismatch, webhook downtime, event mapping mistakes.
- Mitigation: raw-body middleware scoped to webhook route, event fixture tests, dead-letter queue/table, operator replay endpoint.
- Rollback: pause webhook processor and rely on manual/admin reconciliation for Request Network records.
## PRD 5 - Release, Refund, and Payout Orchestration
Priority: P1
Goal: replace SHKeeper payout tasks and simulated marketplace release with auditable transaction instruction and confirmation flows.
Scope:
- Define release/refund service that consumes ledger balances, not raw request status.
- Generate Request Network payout instructions or direct admin wallet transaction instructions.
- Store unsigned transaction payloads, signer, submitted tx hash, confirmation status, and provider status.
- Add batch payout support as a later optimization after single release is stable.
- Require admin/operator authorization and dispute checks before instruction creation.
Acceptance Criteria:
- Seller payout requires verified seller wallet/payee destination.
- Release cannot occur if funds are unpaid, already released, refunded, or disputed.
- Transaction hash confirmation updates ledger only once.
- Admin can see pending release instructions and retry/cancel safely.
- Existing `/purchase-requests/:id/release-payment` simulated path is removed or hidden behind dev-only mode.
Risk Assessment:
- Impact: Very High.
- Likelihood: High.
- Main risks: Request Network payouts are not custodial magic; operator wallet still signs transactions, so process failure can leave funds pending.
- Mitigation: explicit release queue, two-step admin approval, signer audit trail, reconciliation against tx hash/provider status.
- Rollback: keep direct admin wallet payout as emergency fallback with mandatory ledger entry and reason code.
## PRD 6 - Frontend Checkout and Admin Migration
Priority: P1
Goal: update buyer payment, admin release, seller payout, and payment details UI for Request Network flows.
Scope:
- Replace `ShkeeperPayment` with provider-neutral `CryptoPayment`.
- Add `RequestNetworkPayment` redirect flow for secure payment pages.
- Keep `ShkeeperPayment` available only for legacy/unpaid SHKeeper records if needed.
- Replace `ShkeeperPayout` with release queue/admin payout UI.
- Payment detail page shows provider, request ID, payment reference, hosted link, transaction hashes, ledger balances, webhook/reconciliation status.
Acceptance Criteria:
- Buyer checkout no longer expects provider-generated `walletAddress` for Request Network payments.
- Admin release UI displays available/releasable funds and blocks unsafe release states.
- Seller payout status comes from internal release instruction/ledger, not SHKeeper task polling.
- Legacy SHKeeper labels are not shown for Request Network payments.
Risk Assessment:
- Impact: Medium-High.
- Likelihood: Medium.
- Main risks: confusing redirect UX, old Persian labels referencing SHKeeper, admin accidentally using old payout button.
- Mitigation: provider-specific copy, feature flag UI sections, legacy badge, clear payment detail diagnostics.
- Rollback: route checkout back to SHKeeper component via provider flag.
## PRD 7 - Data Migration and Legacy Decommission
Priority: P2
Goal: safely migrate historical SHKeeper payment records and phase out provider-specific code.
Scope:
- Backfill provider metadata namespace for existing SHKeeper payments.
- Create ledger entries for completed SHKeeper payments from trusted records.
- Mark historical records as `legacyProvider='shkeeper'`.
- Keep SHKeeper webhook active during webhook tail period.
- Remove SHKeeper wallet monitor, simple auto webhook, test callback routes, and payout routes after cutoff.
Acceptance Criteria:
- Migration produces counts for total, migrated, skipped, ambiguous, and failed records.
- No historical completed payment loses transaction hash/provider invoice/task metadata.
- Legacy SHKeeper webhook can still reconcile existing pending records until cutoff date.
- Decommission checklist includes env vars, docs, frontend labels, backend routes, and runbooks.
Risk Assessment:
- Impact: Medium.
- Likelihood: Medium.
- Main risks: ambiguous historical records, template checkout string IDs, mixed status meanings.
- Mitigation: dry-run migration, manual review bucket, no destructive migration, keep original metadata.
- Rollback: ledger backfill is additive; old records remain intact.
## Implementation Sequence
1. Add provider adapter and Request Network config without changing default provider.
2. Add funds ledger models/services and dry-run backfill report.
3. Implement Request Network secure pay-in flow behind feature flag.
4. Implement signed webhook receiver and reconciliation job.
5. Enable Request Network for limited new checkout cohort.
6. Add release/refund orchestration using ledger gates.
7. Migrate admin/frontend views.
8. Backfill legacy records.
9. Decommission SHKeeper once no active records depend on it.
## Open Decisions
- Use Request Network Secure Payment Pages first, or execute Request Network calldata directly in the existing wallet modal?
- Keep funds in a platform-controlled escrow wallet, pay sellers via admin/operator release, or route pay-ins directly to seller with only platform fee collection?
- Which chains/currencies are required for launch: BSC USDT parity with today, or Request Network supported stablecoin routes first?
- Should platform fee be paid by buyer, seller, or absorbed by Amanat?
- Does Amanat need crypto-to-fiat/offramp later, which adds KYC/payment detail requirements?
## Recommendation
Start with Secure Payment Pages and a platform escrow/payee destination controlled by Amanat. This best matches the current escrow mental model while reducing frontend transaction-building risk. Do not route pay-ins directly to sellers until dispute handling, refund logic, and service fee economics are fully redesigned.