docs: align API reference and data model docs with code reality
API Reference (9 files updated): - Marketplace API: corrected offer endpoints (scoped under /purchase-requests/:id/offers), marked phantom /search /stats /seller/:sellerId /withdraw routes as NOT IMPLEMENTED, documented PUT→PATCH mismatches, removed invalid SellerOffer 'active' status - Dispute API: corrected resolve schema (action enum), categories (no 'fraud'), removed 'under_review' status, added security callouts (3 unguarded endpoints), route shadowing documented, all socket events marked as TODO stubs - Notification API: corrected mark-all-read method+path, fixed broken GET /:id, added unread-count-update event, 90-day TTL documented - Payment API: /create→/save, removed 10+ phantom endpoints, fixed release/refund paths (no /shkeeper/ segment), added 3 unauthenticated endpoint security warnings, stats undercounting documented, export privilege gap documented - Authentication API: 8-digit→6-digit code, no-complexity warning on reset-with-code, rate limiter counts all attempts, passkey stub claims removed, deleteAccount bug noted - Admin API: PUT→PATCH bug documented, wrong status values documented, hard vs soft delete clarified, scanner no-auth security bug, 3 NOT IMPLEMENTED endpoints - Chat API: file upload wrong endpoint bug, archive PUT→PATCH bug, rate limits added - Points API: corrected redeem schema, referral triggers on 'completed' only, leaderboard period ignored, removed 'refund' PointTransaction type - Socket Events: removed request-cancelled, notification-read; added unread-count-update; dispute events all stubs; referral-signup is auth-domain not points-domain Data Models (3 files updated): - SellerOffer: removed 'active' from status enum, withdrawOffer() is dead code - PurchaseRequest: added pending_payment/active statuses, added 'urgent' urgency, corrected description minimum (5 chars), removed finalized/archived - Dispute: corrected action enum, categories (no fraud), removed under_review, security callout on unguarded status/resolve endpoints Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,8 @@ aliases: [Complaint, IDispute]
|
||||
|
||||
# Dispute
|
||||
|
||||
> **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md))
|
||||
|
||||
Buyer-raised complaint tied to a [[PurchaseRequest]]. Captures the reason, priority, category, an array of evidence uploads, a chronological `timeline` of actions, an optional resolution, and SLA deadlines. An admin (`adminId`) is assigned during triage and resolves the dispute with a structured action (`refund`, `replacement`, `compensation`, `warning_seller`, `ban_seller`, or `no_action`).
|
||||
|
||||
> [!note] Implementation status
|
||||
@@ -13,6 +15,8 @@ Buyer-raised complaint tied to a [[PurchaseRequest]]. Captures the reason, prior
|
||||
>
|
||||
> Source: `backend/src/models/Dispute.ts` — schema definition and model export.
|
||||
|
||||
> ⚠️ **SECURITY** — The dispute `status` update endpoint and the `resolve` endpoint currently have **no role guards**. Any authenticated user (not just admins) can modify dispute status or submit a resolution. This is a known gap pending a role-guard audit.
|
||||
|
||||
## Schema
|
||||
|
||||
| Field | Type | Required | Default | Validation | Index | Description |
|
||||
@@ -49,6 +53,22 @@ Buyer-raised complaint tied to a [[PurchaseRequest]]. Captures the reason, prior
|
||||
| `createdAt` | Date | auto | — | — | yes (desc) | Mongoose timestamp. |
|
||||
| `updatedAt` | Date | auto | — | — | — | Mongoose timestamp. |
|
||||
|
||||
### Category enum
|
||||
|
||||
Valid values: `product_quality` · `delivery_delay` · `wrong_item` · `payment_issue` · `seller_behavior` · `other`
|
||||
|
||||
**Note:** `fraud` is **not** a valid category value. Use `seller_behavior` or `other` for fraud-related complaints.
|
||||
|
||||
### Status enum
|
||||
|
||||
Valid values: `pending` · `in_progress` · `waiting_response` · `resolved` · `rejected` · `closed`
|
||||
|
||||
**Note:** `under_review` does **not** exist in the schema. The equivalent lifecycle state is `in_progress`.
|
||||
|
||||
### Resolution action enum
|
||||
|
||||
Valid values: `refund` · `replacement` · `compensation` · `warning_seller` · `ban_seller` · `no_action`
|
||||
|
||||
> [!note] `messages` in the interface
|
||||
> The TypeScript interface mentions an optional embedded `messages[]` array, but the actual Mongoose schema does not declare it — messages live in [[Chat]] via `chatId`.
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ aliases: [Purchase Request, Buy Request, IPurchaseRequest]
|
||||
|
||||
# PurchaseRequest
|
||||
|
||||
> **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md))
|
||||
|
||||
The central buyer-side document. A `PurchaseRequest` captures what a buyer wants to acquire (physical product, digital product, service, or consultation), the budget envelope, urgency, delivery details, and the entire lifecycle from creation through payment, delivery, and completion. Sellers respond by attaching [[SellerOffer]] documents; the buyer accepts one, a [[Payment]] is opened, and delivery is verified by a 6-digit code.
|
||||
|
||||
> [!note] Source
|
||||
@@ -18,7 +20,7 @@ The central buyer-side document. A `PurchaseRequest` captures what a buyer wants
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `buyerId` | ObjectId → [[User]] | yes | — | — | yes | Buyer that owns the request. |
|
||||
| `title` | String | yes | — | trim, maxlength 200 | — | Short headline. |
|
||||
| `description` | String | yes | — | trim, maxlength 2000 | — | Long form description. |
|
||||
| `description` | String | yes | — | trim, minlength 5 (frontend), maxlength 2000 | — | Long form description. Frontend enforces a 5-character minimum; the field is optional in the raw schema but the form will reject shorter values. |
|
||||
| `categoryId` | ObjectId → [[Category]] | yes | — | — | yes | Category the request belongs to. |
|
||||
| `productType` | String | no | `physical_product` | enum: `physical_product` / `digital_product` / `service` / `consultation` | yes | What kind of fulfilment is expected. |
|
||||
| `productLink` | String | no | — | trim, must match `/^https?:\/\/.+/` | — | Reference URL for the desired product. |
|
||||
@@ -31,7 +33,7 @@ The central buyer-side document. A `PurchaseRequest` captures what a buyer wants
|
||||
| `budget.max` | Number | no | — | min 0 | — | Upper bound. |
|
||||
| `budget.currency` | String | no | `USD` | enum: `USD` / `EUR` / `IRR` | — | Budget currency. |
|
||||
| `urgency` | String | no | `medium` | enum: `low` / `medium` / `high` / `urgent` | yes | Buyer urgency. |
|
||||
| `status` | String | no | `pending` | enum (13 values, see below) | yes | Lifecycle state. |
|
||||
| `status` | String | no | `pending` | enum (13 values — see State Transitions below) | yes | Lifecycle state. |
|
||||
| `isPublic` | Boolean | no | `true` | — | — | Public marketplace listing vs. private request. |
|
||||
| `tags[]` | String[] | no | — | trim | — | Free-form tags. |
|
||||
| `specifications[].key` | String | yes | — | trim | — | Spec key. |
|
||||
@@ -84,6 +86,12 @@ The central buyer-side document. A `PurchaseRequest` captures what a buyer wants
|
||||
| `createdAt` | Date | auto | — | — | yes (desc) | Mongoose timestamp. |
|
||||
| `updatedAt` | Date | auto | — | — | — | Mongoose timestamp. |
|
||||
|
||||
### Status enum — all valid values
|
||||
|
||||
`pending_payment` · `pending` · `active` · `received_offers` · `in_negotiation` · `payment` · `processing` · `delivery` · `delivered` · `confirming` · `completed` · `seller_paid` · `cancelled`
|
||||
|
||||
**Note:** `finalized` and `archived` are **not** valid status values and do not appear in the `IPurchaseRequest` frontend type or the Mongoose schema enum. Using either would cause a validation error.
|
||||
|
||||
## Virtuals
|
||||
|
||||
None defined.
|
||||
|
||||
@@ -6,6 +6,8 @@ aliases: [Seller Offer, Bid, ISellerOffer]
|
||||
|
||||
# SellerOffer
|
||||
|
||||
> **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md))
|
||||
|
||||
A seller's bid against a [[PurchaseRequest]]. Stores the proposed price, the delivery time commitment, optional notes/attachments, and a small status machine (`pending` / `accepted` / `rejected` / `withdrawn`). The parent `PurchaseRequest` keeps the array of offer ids in `offers[]` and the chosen one in `selectedOfferId`.
|
||||
|
||||
> [!note] Source
|
||||
@@ -31,6 +33,8 @@ A seller's bid against a [[PurchaseRequest]]. Stores the proposed price, the del
|
||||
| `createdAt` | Date | auto | — | — | yes (desc) | Mongoose timestamp. |
|
||||
| `updatedAt` | Date | auto | — | — | — | Mongoose timestamp. |
|
||||
|
||||
> **Status enum note:** Valid values are `pending | accepted | rejected | withdrawn` only. `'active'` is **not** a valid status and would throw a Mongoose `ValidationError` if passed.
|
||||
|
||||
## Virtuals
|
||||
|
||||
None defined.
|
||||
@@ -56,6 +60,16 @@ None defined.
|
||||
|
||||
None defined.
|
||||
|
||||
## Service notes
|
||||
|
||||
### `createOffer` — eligible parent request statuses
|
||||
|
||||
`createOffer` in `SellerOfferService` permits offers against a `PurchaseRequest` whose status is **`pending`**, **`received_offers`**, or **`active`**. Attempts against any other status are rejected.
|
||||
|
||||
### `withdrawOffer()` — dead code
|
||||
|
||||
`SellerOfferService.withdrawOffer()` exists in the source but is **not exposed via any HTTP route**. It cannot be called through the API. Any frontend references to a withdraw endpoint will receive a `404`.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **References**: [[User]] (`sellerId`), [[PurchaseRequest]] (`purchaseRequestId`).
|
||||
|
||||
Reference in New Issue
Block a user