# Handoff — after backend-phase-14 (Reviews, ratings & patient care records) **The trust loop and the continuity-of-care loop are live.** A customer leaves **one moderated review per completed booking**; an admin/moderator publishes/hides/rejects it; the nurse's public rating is recomputed **from source on every transition** (so hiding a 1-star lowers the count and re-derives the average — no inflated-after-hide drift); low ratings auto-raise an internal `support_alert`; and nurses author **encrypted, patient-scoped** clinical notes readable only under a strict clinical-access rule. ## What the frontend (f13-b14) can now build - **Leave a review** — `POST bookings/{bookingId}/review` `{ rating 1–5, body?, tagCodes? }` (customer who owns a completed booking). Returns `{ id, moderationStatus: "pending_moderation", lowRatingAlertRaised }`. The review is **not public** until an admin publishes it — build the "submitted, awaiting moderation" state. - **Public nurse reviews** — `GET nurses/{nurseProfileId}/reviews?page=&pageSize=` → `{ aggregate: { averageRating, publishedCount }, reviews: PagedResult<{ id, rating, body, tagCodes[], createdAt }> }`. **Published only.** - **Public tag rollup** — `GET nurses/{nurseProfileId}/review_tags` → `{ publishedReviewCount, tags: [{ code, labelFa, labelEn, count, percentage }] }` ("% punctual"). The seeded vocab (`punctual/professional/clean/kind/ communicative`) is always returned. - **Tag your own review** — `POST reviews/{reviewId}/tags` `{ tagCodes }` (author or moderator; replaces the set). - **Admin moderation console** — `GET admin/reviews/moderation_queue?status=&page=&pageSize=` (default `pending_moderation`; each row carries the linked `lowRatingAlertId` for triage) and `PATCH reviews/{reviewId}/status` `{ action: publish|hide|reject|unpublish, reason? }` (hide/reject need a reason). The PATCH returns the recomputed `{ averageRating, totalReviews }`. - **Patient care records** — `POST patients/{patientId}/care_records` `{ bookingId?, body }` (nurse with a confirmed booking) and `GET patients/{patientId}/care_records?page=&pageSize=` (owning customer / nurse with a confirmed booking / admin) → decrypted `{ id, patientId, bookingId, nurseProfileId, nurseName, body, recordedAt }` newest first. The history is **patient-scoped** — a new nurse taking over reads the whole history. ## Contracts - **`dev/contracts/domains/reviews-records.md`** — all 8 endpoints, the `moderationStatus`/action enums, tag codes, DTO shapes, and the care-record **access matrix**. - **`dev/contracts/openapi/swagger.v1.json`** refreshed — the 8 review/care-record paths are in the snapshot. ## What is mocked (and how it becomes real) - **`IReviewModerationService`** (new) — AI review pre-screen. `MockReviewModerationService` is a keyword filter: clean text → a human-review **Flag** by default (so the publish gate holds — reviews land `pending_moderation`); a banned-word substring → **Reject** (auto-hidden). Config `Seams:ReviewModeration:{AutoApproveClean,BannedWords}`. Make it real → a text classifier / LLM endpoint (see reports/mocks-registry.md). `ModerateReviewCommand` keeps decision authority + the human override, so the real impl never touches the handler. ## Load-bearing rules (don't regress) - **Recompute from source, not delta** — every publish/hide/reject/unpublish re-derives `average_rating`/ `total_reviews` over currently-published reviews (exclude-the-changed-review then fold in its new status), in the same transaction, then refreshes the search index. - **Publish gate** — `pending_moderation`/`hidden`/`rejected` are never in a public read and never counted. - **1:1 per completed booking** — `UNIQUE(booking_id)` + handler pre-check; cross-tenant is a 404. - **Low rating (≤ config `min_rating_for_support_alert`, default 2)** raises an internal `low_rating` alert — internal-only, never in a user response (only its id shows on the admin queue). - **Care records are patient-scoped, encrypted at rest, strict access** — a nurse without a confirmed booking for the patient is denied read + write. ## Deferred (flagged, not built) - Two-way (nurse-reviews-customer) double-blind reviews with timed reveal. - First-class `incidents` entity + ML fraud scoring (manual suspension + `support_alerts` cover it now). - The ticket system, partner centers, and the admin **support-alert worklist console** → **b15** (this phase only *raises* alerts). - `SuspendNurse` / `ResolveSupportAlert` / `FlagConcern` admin actions → b15.