Files
nick-doc/04 - Flows/Rating Flow.md
Siavash Sameni 7a616744f4 docs: complete code-reality alignment for remaining docs + reconcile issue set
Remaining docs updated to match code (the docs that the first pass had not covered):
- Flows: Chat, Referral, Rating, Registration, Google OAuth, Negotiation, Payout,
  Trezor Safekeeping — corrected endpoints, socket events, status enums, auth gaps
- API Reference: User API, Trezor API — admin route prefix/verb/status corrections,
  added undocumented endpoints (ton-proof challenge, profile email verify,
  GET /trezor/account, POST /trezor/verify-operation)
- Data Models: Chat, Notification, Payment, PointTransaction, User — corrected
  enums (PaymentProvider, escrowState, PointTransaction.type, User.status),
  90-day notification TTL, soft-delete semantics, wallet fields

Trezor "zero frontend" finding (audit C31/C32) corrected as STALE:
- Verified current code HAS a full frontend Trezor implementation (admin/trezor
  page, TrezorSettingsView, trezorConnector via @trezor/connect-web,
  TrezorSignDialog, actions/trezor.ts building the {message,signature} object)
- Fixed Trezor Safekeeping Flow doc (removed false "no frontend" warnings)
- Reclassified ISSUE-012 as invalid/superseded with explanation

Issue set reconciled to a single canonical numbering (ISSUE-001..054):
- Adopted the comprehensive 51-issue set (long-slug, fully indexed)
- Removed 35 superseded short-slug duplicates from the first pass
- Removed a duplicate ISSUE-046 file
- Added 3 issues the 51-set lacked: ISSUE-052 (completed-not-counted-in-stats),
  ISSUE-053 (axios 401-only interceptor), ISSUE-054 (rate limiter counts all attempts)
- Regenerated Issues Index: 53 open (14 critical, 39 major) + 1 invalid

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 15:15:02 +04:00

126 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Rating Flow
tags: [flow, rating, review, moderation]
related_models: ["[[Review]]", "[[ShopSettings]]", "[[PurchaseRequest]]"]
related_apis: ["POST /api/marketplace/reviews", "GET /api/marketplace/reviews/:subjectType/:subjectId"]
---
# Rating Flow
> **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))
> [!caution] Not deeply audited
> This flow was not deeply covered by the 2026-05-29 audit; endpoints should be verified against `reviewRoutes`/`marketplaceController` before relying on them for UAT.
After an order is `completed`, the buyer rates the seller and (optionally) leaves a review; the seller can rate the buyer in the reciprocal flow. Reviews are scoped by `subjectType` (`seller` | `template`) and constrained by the seller's `ShopSettings`.
## Actors
- **Buyer** (typical reviewer).
- **Seller** (subject; can also be a reviewer in the reciprocal direction).
- **System** — enforces uniqueness and moderation rules.
- **Backend** — `backend/src/services/marketplace/reviewRoutes.ts`.
- **MongoDB** — `reviews` collection (`backend/src/models/Review.ts`).
## Preconditions
- The associated `PurchaseRequest` is `completed` (or `finalized`).
- The reviewer is the buyer of that request (for `isVerifiedBuyer` to be `true`).
- The subject's `ShopSettings.allowSellerReviews` / `allowTemplateReviews` is not `false` (`reviewRoutes.ts:15-31`).
## Step-by-step narrative
1. From the request detail or seller profile, the buyer clicks "Leave review". The form captures `rating` (15) and `comment` (≤ 1000 chars).
2. Frontend POSTs `POST /api/marketplace/reviews` with `{ subjectType: 'seller' | 'template', subjectId, rating, comment, purchaseRequestId? }`.
3. Backend route handler:
- Validates payload.
- Calls `isReviewsAllowed(subjectType, subjectId)` — checks the seller's `ShopSettings` (for sellers, look up the seller directly; for templates, look up the template's owning seller).
- Sets `isVerifiedBuyer = true` if the user owns a `completed` purchase request from that seller.
- Defaults `status: 'published'` (no moderation queue today).
4. Inserts a `Review` document. Unique index `{ subjectType, subjectId, reviewerId }` prevents a user from reviewing the same subject twice (`Review.ts:34`).
5. Aggregated stats are recomputed on read via `computeStats` (`reviewRoutes.ts:33-62`) — count, average, per-star histogram. No denormalised counter on `User` today; everything is computed at read-time.
## Visibility
- Public — anyone hitting `GET /api/marketplace/reviews/seller/:sellerId` sees `status: 'published'` reviews paginated by 10.
- If `ShopSettings.allowSellerReviews === false` (or `allowTemplateReviews === false`), reads return `403 Reviews are disabled by seller`.
- The seller can flag a review for moderation (planned — current statuses include `pending` and `rejected`, but no UI to flip them today; admin can update via direct DB).
## Sequence diagram
```mermaid
sequenceDiagram
autonumber
actor B as Buyer
participant FE as Frontend
participant BE as Backend
participant DB as MongoDB
B->>FE: Open seller profile / request detail
B->>FE: Click "Leave review", choose stars + comment
FE->>BE: POST /api/marketplace/reviews
BE->>DB: ShopSettings.findOne({sellerId}) → allowSellerReviews?
alt allowed
BE->>DB: PurchaseRequest.exists({buyer, seller, status:"completed"})?
BE->>DB: Review.create({status:"published", isVerifiedBuyer})
BE-->>FE: 201 { review }
else disabled
BE-->>FE: 403 Reviews disabled
end
Note over FE: Public visitor:
FE->>BE: GET /api/marketplace/reviews/seller/{id}
BE->>DB: Review.find / computeStats aggregate
BE-->>FE: { items, pagination, stats:{count, avg, histogram} }
```
## API calls
| Method | Endpoint | Purpose |
|---|---|---|
| `POST` | `/api/marketplace/reviews` | Submit review |
| `GET` | `/api/marketplace/reviews/:subjectType/:subjectId` | List reviews + stats |
| `PATCH` | `/api/marketplace/reviews/:id` | Edit own review (within edit window) |
| `DELETE` | `/api/marketplace/reviews/:id` | Delete own review |
## Database writes
- **`reviews`** — insert on submission; one document per `(subjectType, subjectId, reviewerId)`.
- **`shopsettings`** — read-only here; the seller controls `allowSellerReviews` / `allowTemplateReviews` in their shop settings.
## Socket events emitted
- None today. A `new-review` event broadcast to `user-{sellerId}` would be a useful enhancement so sellers see reviews appear live.
## Side effects
- Recompute aggregate on every list call — fine for small volumes; consider caching `stats` per subject when the review count grows.
- Order rating field also stamps `metadata.rating` on the purchase request when the marketplace endpoint accepts ratings inline (see `routes.ts` references in `backend/src/services/marketplace/routes.ts`).
## Error / edge cases
- **Duplicate review** → MongoDB `E11000` from the unique index; surface as `409 Already reviewed`.
- **Subject disabled reviews** → `403`.
- **Reviewer not a verified buyer** → review is still allowed but `isVerifiedBuyer = false`. Display this in the UI.
- **Rating out of 15** → Mongoose schema validator rejects.
- **Comment > 1000 chars** → schema-level rejection.
- **Seller toggles `allowSellerReviews=false` after reviews exist** → existing reviews remain stored but become unreadable via the public GET (`reviewRoutes.ts:81-83`).
- **Spam / abuse** → no automatic moderation; admin can flip `status` to `rejected` to hide.
> [!tip] Verified-buyer badge
> The `isVerifiedBuyer` flag is the most credible signal for prospective buyers. Always render a "Verified buyer" pill next to reviews where this is `true`.
## Linked flows
- [[Purchase Request Flow]] — precursor that makes the buyer "verified".
- [[Seller Offer Flow]] — display average rating on offer cards.
- [[Dispute Flow]] — a resolved dispute could trigger a review prompt; today they are independent.
## Source files
- Backend: `backend/src/services/marketplace/reviewRoutes.ts`
- Backend: `backend/src/models/Review.ts`
- Backend: `backend/src/services/marketplace/shopSettingsController.ts` (allow flags)
- Backend: `backend/src/services/marketplace/routes.ts` (inline rating on order completion)
- Frontend: review components under `frontend/src/sections/account/` and seller profile views