Files
baya-monorepo/dev/post-phase/hardening/hardening-phase-5-final-demock.md
T
2026-07-17 13:22:04 +03:30

6.2 KiB

Hardening Phase 5 — Final de-mock & partner reachability (zero mocks left)

Flip the last mocked client domains to the Phase-4 backend, reconcile the patientRecords id-type mismatch that makes its PUT write-unsafe, and make the partner portal reachable from login and actually gated. Exit criteria for the whole chain: no USE_*_MOCK = true remains anywhere. Track: frontend · Depends on: Phases 2 & 4 · Unlocks: — (chain complete) Before you start, read _shared/agent-operating-rules.md.

1. Context — where this sits

Fixes H-16b, H-17 and retires the remaining flags from issues.md. After Phase 2 the mocked surface is: refunds, bnpl, admin, partnerCenter, patientRecords, plus the admin halves of verification/payouts. Phase 4 delivered (or explicitly re-deferred) their REQs — its handoff note says exactly which flags may flip. This mirrors refinement-phase-4: a flip is never assumed to be a pure flag flip — check each clientApi.ts mapper against the delivered DTOs first (that phase's lesson: delivered fields were being null-overridden by stale mappers).

What already exists (do not rebuild): every domain's real clientApi.ts, the seam-split mechanics from Phase 2, the partner portal screens, useMyPartnerCenter's access-denied pattern, the Phase-0 auth gate.

2. Required reading (do this first)

  • Phase 4's report + handoff note (which REQs landed; which were re-deferred — a re-deferred REQ means its domain stays mocked and you record why, you don't force it).
  • issues.md H-16b/H-17; the refinement-phase-4 file + report (the mapper-fix lesson).
  • client/CLAUDE.md de-mock status block; mocks-registry.md frontend section.
  • The regenerated swagger in dev/contracts/openapi/ for every DTO you map.

3. Scope — build this

  1. H-17 — patientRecords id reconciliation, then flip. Client Medication/RoutineItem/ CareTask.id are string ('m1'/'r1'/'t1' seeds) vs the wire's long (CarePlanDtos.cs:11-15). Reconcile before flipping: existing items carry the server's numeric id (stringified is fine if the type stays string — but the PUT must send what the server accepts); new items omit the id and let the server assign. Update the mapper + useUpdateCareRecord's optimistic path; then USE_PATIENT_RECORDS_MOCK=false. The nurse visit-note half is already contract-real — don't disturb it.
  2. H-16b — partner reachability + gate.
    • Me gains administersPartnerCenterId (REQ-038); resolveRoleDestination gains the partner branch (a partner admin lands on /partner after login; add the routing unit test).
    • Gate the portal at the layout level: a PartnerAccessGuard in partner/layout.tsx resolves useMyPartnerCenter() once and renders the non-leaking access-denied state on 403/404 before any child page mounts; nurses/bookings/settlement pages stop fetching before the gate resolves.
    • Flip USE_PARTNER_MOCK=false onto the centers/me* reads (REQ-032/033).
  3. Flip the rest, mapper-checked, in dependency order: refunds (REQ-019/020/021 — retire the Phase-2 mock-side preview), bnpl (REQ-022/023/024 — restore the checkout CTA derivation to enabled-when-real; delete the dev gateway-harness page if the real provider redirect replaces it), verification admin half (REQ-034 — admin queue/case/decide/signed-URL onto real), payouts admin half (REQ-036 — batch preview/run/retry/reference onto real), admin (REQ-029/030/031 — config/ audit/alerts/holidays/RBAC grid real; the RBAC grid consumes Phase 1's RolesController).
  4. Cleanup + honesty pass. Delete now-unused mockApi modules and cross-mock helpers (mockGetBookingForRefund, mockInsertConvertedBooking, __mockApproveAll, …) unless a Testing path genuinely uses them (then say so in the registry). No dead code. Update the client/CLAUDE.md de-mock block (should read "22/22 real"), mocks-registry.md (frontend rows → 🟢), and the project-structure tree if files moved/died.

4. Mocks & seams in this phase

This phase retires the frontend mock seams. The seam pattern itself stays (it's the test/dev affordance); only the defaults flip. Any domain that must stay mocked (re-deferred REQ) keeps a registry row with the reason + pull-trigger.

5. Critical rules you must not get wrong

  • Mapper-check every flip against the real swagger — the refinement-4 lesson. A delivered field a stale mapper drops is a silent regression.
  • Money stays served IRR digit-strings; D5 wallet is provider-reported, never a Balinyaar ledger; the BNPL confirmation reuses the card confirmation (?method=bnpl).
  • Partner tenancy is server truth — the client guard is chrome; never pass a center id from the client to the me-scoped routes.
  • Published-only reviews, two-stage disclosure, nurse append-only records — unchanged invariants.
  • Per flip: run the affected screen against the live server before moving to the next flag.

6. Definition of Done

  • grep -rn "USE_.*_MOCK = true" client/src/services → empty (or each survivor justified in the registry + issues.md).
  • Journey A end-to-end on real data: login → search → request → accept → pay (card AND BNPL) → booking → cancel/refund path visible → review. Journey B: verification → publish → inbox → accept → EVV → earnings. Admin: verification decide, refund approve, payout run. Partner: login → auto-routed → own center only.
  • npm run check + npm run test:ci green; no dead mock code.

7. How to test (human)

Run the two journeys + the admin/partner spot-checks above against the RUNBOOK setup. The demo world personas: customers 0912000000x, nurses (incl. unverified 09120000003), admins 0912000002x, plus the Phase-4 partner admin seed.

8. Hand off & document

  • Tick H-16b/H-17 (and the flip checklist) in issues.md with commit hashes.
  • Final updates: client/CLAUDE.md, mocks-registry.md, for-backend.md (all REQs terminal).
  • Write dev/shared-working-context/reports/hardening-phase-5-report.md declaring the chain complete (or listing exactly what remains and why).