# Backlog — closed items

> Last verified: 2026-08-02 against commit `b876490`.

Items confirmed done during phase 4's reconciliation, with what closed them. This is what keeps
[backlog.md](backlog.md)'s open count honest — an item only leaves this file if later evidence proves it
regressed.

---

## Hardening ledger (3 of 18 items — see [backlog.md](backlog.md) for the 11 still open + 4 partially-fixed)

| Origin | Item | Closed by |
|--------|------|-----------|
| H-02 | `isTokenAlive` could never read the real token (JWE) — treated every session as dead. | `baa3cc6` ("manual improvement 1") — a well-formed 5-part JWE is now treated as alive without decoding. |
| H-03 | Anonymous visitor to a private shell hit an infinite splash screen. | `baa3cc6` — `useRoleHydration` now has an explicit `unauthenticated` status; `RoleGuard` redirects to `/login` on it. |
| H-12 | Raw stack-trace error boundary; no route-level error pages. | `370c1be` (ui-phase-1) + `d33568b` (ui-phase-12) — branded `ErrorBoundary` with retry, plus `error.tsx`/`global-error.tsx`. |

## REQ ledger — delivered (28 of 67; see [backlog.md](backlog.md) for the remaining 39 open/partial/deferred)

| REQ | Item | Evidence |
|-----|------|----------|
| REQ-001 | `ApiResult` envelope, camelCase casing, `Paginated` shape | `ApiResult.cs`, `PagedResult.cs` |
| REQ-002 | `codeLength`/`expiresInSeconds` on OTP request result | `RequestOtpResult.cs:8` |
| REQ-003 | Machine-readable OTP failure codes + `retryAfterSeconds` | `VerifyOtpCommand.Handler.cs:43,58` |
| REQ-005 | `relation`/`conditions` on `PatientDto` | `Patient.cs:28,33` |
| REQ-006 | Multipart avatar-upload endpoint (nurse + customer) | `UploadCustomerAvatarCommand.cs`, `UploadNurseAvatarCommand.cs` |
| REQ-007 | Customer name + preferred-language update | `UpsertCustomerProfileCommand.cs` |
| REQ-008 | Client map-pin lat/long on address create/update | `CreateAddressCommand.cs:21`, `UpdateAddressCommand.Handler.cs:62-71` |
| REQ-009 | `provinceId` on `CustomerAddressDto` | `CustomerAddressDto.cs:12` |
| REQ-010 | Pagination param name confirmed (`pageSize`) | `PagedResult.cs:4` |
| REQ-011 | Nurse-facing structured credential-details endpoint | `NurseVerificationController.cs:47-51` |
| REQ-012 | Search enrichment + public nurse-profile aggregate | `NurseSearchResultDto.cs:21-23`, `NursesController.cs:33-35` |
| REQ-013 | Variant price on `BookingRequestDto` | `BookingRequestDto.cs:20-21,45` |
| REQ-014 | `variantLabel`+`patientAge` on nurse-inbox list DTO | `BookingRequestListItemDto.cs:23` |
| REQ-015 | Booking/session/EVV enum wire codes confirmed | `BookingStatus.cs:11-30` |
| REQ-016 | Checkout summary read | `BookingRequestsController.cs:64-66` |
| REQ-017 | `bookingId` on converted request | `BookingRequestDto.cs:49` |
| REQ-018 | Invoice reachable right after capture (auto-issue) | `ConfirmPaymentAndPostLedgerCommand.Handler.cs:98` |
| REQ-019 | Customer-initiated cancellation + refund | `BookingsController.cs:67-71` |
| REQ-020 | Pre-cancel policy preview | `BookingsController.cs:74-77` |
| REQ-021 | Refund lookup-by-booking + fee-leg decomposition | `RefundsController.cs:29` |
| REQ-023 | BNPL eligibility accepts D3 KYC inputs | `CheckBnplEligibilityQuery.cs:21-23` |
| REQ-025 | Nurse earnings balance + list + detail + `failureReason` | `NursePayoutsController.cs:27-47` |
| REQ-026 | Review eligibility + my-review-for-booking reads | `BookingReviewsController.cs:33-41` |
| REQ-027 | Family care record + record-access reads | `PatientCareRecordsController.cs:44-59` |
| REQ-028 | Ticket inbox enrichment + message idempotency | `MessagingProjections.cs:13,16-17,62` |
| REQ-029 | `updatedAt`/`updatedBy` on `PlatformConfigDto` | `PlatformConfigDto.cs:11-12` |
| REQ-030 | Audit-trail actor/action/date-range filters | `GetAuditTrailQuery.cs:8-15` |
| REQ-037 | `tagCodes` on the moderation-queue DTO | `ReviewProjections.cs:37-48` |

**Note:** REQ-029/030's server work is closed, but `client/src/services/admin/constants.ts` still cites both
as reasons the admin mock stays primary — a small residual client cleanup, not tracked separately (fold into
whichever admin-mock item is next touched).

## REQ ledger — obsolete (1)

| REQ | Item | Reason |
|-----|------|--------|
| REQ-004 | Confirm multi-role disambiguation (`activeRole`?) on `/me` | Resolved by product decision in refinement-phase-2: the client owns active-role choice; no `MeResult` change was ever needed. |

## Manual-testing iterations 1 & 2 (19 of 20 bullets — 1 partially-fixed, see [backlog.md](backlog.md) BL-217)

| Origin | Item | Closed by |
|--------|------|-----------|
| iteration-1 #1 | Login card / all Papers had too large a border radius | `theme.ts:76-84`, `tokens.css:46-51` |
| iteration-1 #2 | Login-page options should move inside the card | `AuthCard.tsx:8-33`, `PhoneStep.tsx:100-117` |
| iteration-1 #3 | No top bar needed on the login page | `PublicLayout.tsx:8-14` |
| iteration-1 #4 | Language/theme switches should live only in Settings | `PublicLayout.tsx:11-13`, `SettingsPanel.tsx:10-16` |
| iteration-1 #5 | Icon set should be modernized with semantic mapping | `AppIcon/config.ts:1-19` — MUI Icons replaced with Lucide |
| iteration-1 #6 | Default route should resolve by role, not spin forever | `RoleGuard.tsx:34-38`, `RoleRouter.tsx:31-46` |
| iteration-1 #7 | React-child console error on phone submit | `OtpStep.tsx:104-115` + regression test `richText.test.tsx` |
| iteration-1 #8 | OTP input spacing broken in `fa` locale | `OtpInput.tsx:119-127` — `gap` not RTL-mirrored `spacing` |
| iteration-1 #9 | Nurse dashboard needed a full visual refactor | `NurseDashboardScreen.tsx:28-45` |
| iteration-1 #10 | Replace drawer nav with a bottom navbar | `NurseLayout.tsx:11-26`, `BottomBar.tsx:18-40` |
| iteration-1 #11 | Each nav group needs a summary root page | `NursePracticeScreen.tsx:13-18`, `NurseFinanceScreen.tsx:10-15` |
| iteration-1 #12 | Horizontal scroll present on nurse dashboard | `AppFrame.tsx:31-33,96-103` — structurally disabled |
| iteration-1 #13 | App should be phone-width at every viewport | `layout/config.ts:5-14` — `APP_FRAME_MAX_WIDTH=480` |
| iteration-2 #1 | Nurse greeting section useless; card borders looked bad | `NurseDashboardScreen.tsx:38-41`, `AccentCard.tsx:15-21` |
| iteration-2 #2 | Bottom nav needed a better, floating form | `BottomBar.tsx:22-34,93-101`, `layout/config.ts:37-44` |
| iteration-2 #3 | No easy way to reach the nurse requests page | `NurseLayout.tsx:16-21,39-44` — now a tab with a badge |
| iteration-2 #4 | Theme-mode toggle buttons had no gap | `ThemeModeSetting.tsx:60-75` |
| iteration-2 #5 | `/nurse/verification` and `/nurse/profile` forms were an undifferentiated list | `nurse/profile/page.tsx:68-80`, `FormSection.tsx:26-40` |
| iteration-2 #6 | `/nurse/services` had the same forms problem | `VariantBuilder.tsx:1-70` — react-hook-form + `StepperHeader` wizard |

## Report follow-ups confirmed completed by a later phase (curated — the notable ones)

Verification method: cross-referenced against the later phase's own "What was built" section, not re-traced
against current code (these predate the flow-gap sweep and were folded in only where a later report's own
claim is unambiguous). Treat as **strong evidence**, not the same rigor as the code-verified items above.

| Origin | Item | Closed by |
|--------|------|-----------|
| backend-phase-0 follow-up | Extend audit interceptor to write `audit_logs`; evolve schema; add `IHolidayCalendar` seed | backend-phase-1 |
| backend-phase-0 follow-up | `ISmsSender` seam + auth/OTP REST surface + rate-limit policies | backend-phase-2 |
| backend-phase-0 follow-up | `WebApplicationFactory` integration-test project | backend-phase-2 (`Baya.Test.Api`) |
| backend-phase-2 follow-up | Profiles/patients/addresses/nurse bank accounts; `/me` completion flags read real tables | backend-phase-3 |
| backend-phase-2 follow-up | Shahkar/KYC populate `NationalId`; `/me` surfaces real `nurseVerificationStatus` | backend-phase-6 |
| backend-phase-3 follow-up | `customer_addresses`+`nurse_service_areas` geography + geocoder | backend-phase-4 |
| backend-phase-3 follow-up | `is_verified` flip transaction; Shahkar/KYC; bank-ownership step coupling | backend-phase-6 |
| backend-phase-3 follow-up | `average_rating`/`total_reviews` aggregate recompute | backend-phase-14 (`total_completed_bookings` recompute unconfirmed — see BL-245-adjacent residue) |
| backend-phase-4 follow-up | `nurse_search_index` fan-out wired to service-area add/remove | backend-phase-7 |
| backend-phase-4 follow-up | EVV distance check consuming address lat/long | backend-phase-9 |
| backend-phase-5 follow-up | `nurse_search_index`, `INurseSearch`, search query, index fan-out | backend-phase-7 |
| backend-phase-5 follow-up | `booking_requests.variant_snapshot_json` persistence | backend-phase-9 (not b8 as originally planned) |
| backend-phase-6 follow-up | Search reads `nurse_profiles.is_verified` for `is_searchable` | backend-phase-7 |
| backend-phase-7 follow-up | Search results feed the booking flow; `required_caregiver_gender` capture | backend-phase-8 |
| backend-phase-8 follow-up | `accepted_awaiting_payment` → real `bookings` row on capture | backend-phase-9/10 |
| backend-phase-8 follow-up | Stage-2 encrypted `booking_care_instructions` | backend-phase-9 |
| backend-phase-8 follow-up | Three-amount split, snapshots, sessions, EVV, dispute window | backend-phase-9 |
| backend-phase-9 follow-up | Real card capture replacing `IPaymentCaptureSimulator` | backend-phase-10 |
| backend-phase-9 follow-up | Reviews-on-completed-booking; `partner_center_id` wiring | backend-phase-14, backend-phase-15 |
| backend-phase-11 follow-up | Real `IBnplProvider` (beyond the b11 revert-only stub) | backend-phase-12 |
| backend-phase-11 follow-up | Clawback netting/recovery + real `INursePayoutStatus` | backend-phase-13 |
| backend-phase-12 follow-up | `settled_at`-gates-payout coupling flag (`require_bnpl_settlement_for_payout`) | backend-phase-13 (shipped, default off) |
| backend-phase-14 follow-up | Ticket system + partner centers | backend-phase-15 |
| frontend-phase-5 follow-up 3 | Admin verification review queue (pass/reject, doc viewer) | frontend-phase-15 |
| frontend-phase-10 follow-up 1 | Admin refund console (`RefundPanel`) | frontend-phase-15 |
| frontend-phase-12 follow-up 2 | Admin payout console (`/admin/payouts`) | frontend-phase-15 |
| frontend-phase-13 follow-up 2 | Review moderation console (`/admin/reviews`) | frontend-phase-15 |
| frontend-phase-14 follow-up 1 | Admin global ticket queue + internal-note composer | frontend-phase-15 |
| frontend-phase-14 follow-up 2 | Support-alert worklist, partner-center console, audit viewer | frontend-phase-15 |
| ui-phase-0/1 follow-up | Core primitives (EmptyState/ErrorState/PageHeader/`<Money>`/Jalali picker) | ui-phase-1 |
| ui-phase-0/1 follow-up | App-wide motion pass consuming `--bal-motion-*` tokens | ui-phase-12 |
| ui-phase-3 follow-up | Skip-onboarding («بعداً تکمیل می‌کنم») | ui-phase-4 |
| ui-phase-4 follow-up | Public/guest storefront + landing page | ui-phase-13 |
| ui-phase-4/5 follow-up | Zero-case copy sweep; `continue_payment` CTA string sweep | ui-phase-12 |
| ui-phase-7 follow-up 1 | `DashboardActivationSlot`'s full "go live" checklist content | ui-phase-8 |
| ui-phase-8 follow-up | Coverage map visualization | ui-phase-9 |
| handoff-after-refinement-phase-0 | No `USE_*_MOCK` flag had been flipped yet | refinement-phase-4 (14 of 22 domains flipped to real) |

**Not included above** (checked and found still genuinely open, or not confirmed by a later report):
`support_alerts` FK constraints (BL-not-filed — low-priority schema hygiene, see decisions.md), region
bulk-import feed, `SuspendNurse`/`ResolveSupportAlert`/`FlagConcern` admin actions (BL-245), and everything
else already carried into [backlog.md](backlog.md)'s Deferred section.
