Files
baya-monorepo/archive/post-phase/hardening/hardening-phase-2-mock-integrity.md
T
2026-08-02 18:48:32 +03:30

7.7 KiB

Hardening Phase 2 — Money-path mock integrity (no fake success on real data)

Sever the dangling cross-imports the phase-4 de-mock left behind — the refunds and BNPL mocks still read retired in-memory stores keyed by REAL server ids — split the seams whose real halves are already live (verification nurse flow, nurse earnings), and stop discarding the delivered bookingId. After this phase, nothing in the money path can show a fake success against real data. Track: frontend · Depends on: Phase 0 · Unlocks: Phase 5 Before you start, read _shared/agent-operating-rules.md.

1. Context — where this sits

Fixes H-06 … H-10 from issues.md. Refinement-phase-4 flipped 14 domains to real but left 7 mocked; two of the mocked ones (refunds, bnpl) still hard-import the mock modules of now-real sibling domains (bookings, bookingRequests), whose fixture stores no longer correspond to anything — so a real customer's cancel 404s and the BNPL wizard either 404s or fabricates a client-side "booking" while the real request expires unpaid. Meanwhile two seams hold real, shipped backend halves hostage to a single flag (verification nurse flow — which silently breaks nurse discoverability because the real search gate needs the real is_verified; payouts nurse reads — REQ-025 is live).

What already exists (do not rebuild): the per-domain seam pattern (apis/index.ts selects mock/real), all the real clientApi.ts implementations named below, the b6 verification endpoints, the REQ-025 nurse payout endpoints (NursePayoutsController.cs:33-48), and the REQ-017 bookingId on BookingRequestDto.

2. Required reading (do this first)

  • issues.md H-06/H-07/H-08/H-09/H-10 — full evidence; don't re-audit.
  • client/CLAUDE.md → "The services/{domain} reference pattern" + the de-mock status block.
  • The files cited per finding (refunds/bnpl/bookings/bookingRequests mockApis + constants, checkout pages, PublishGate.tsx, MyServicesList.tsx, payment clientApi.ts/invalidations.ts, payouts/verification services).
  • dev/shared-working-context/reports/mocks-registry.md — you will update the affected rows.

3. Scope — build this

  1. H-06 — refunds mock must see real bookings. While USE_REFUNDS_MOCK=true (its REQs land in Phase 4), rewire services/refunds/apis/mockApi.ts to resolve the booking through the selected bookingsApi (the seam, real today) instead of importing mockGetBookingForRefund from the bookings mock module. The mock computes the policy preview locally off the real booking's status/sessions/amounts and simulates the cancel/refund state machine on top. A real booking id must produce a coherent preview + cancel flow (mock-side state), never a 404.
  2. H-07 — BNPL must not fake success. Two parts:
    • Derive the checkout BNPL CTA visibility instead of the bare BNPL_ENABLED=true (services/payment/constants.ts:23, used at checkout/page.tsx:214): hide the branch whenever USE_BNPL_MOCK is true while bookingRequests/payment are real (mixed state = the dangerous combination). An honest absent button beats a fabricated booking.
    • For the dev/demo path that remains reachable (both mocked, e.g. Testing), rewire services/bnpl/apis/mockApi.ts:5-8 to go through the selected bookingRequestsApi/ bookingsApi seams, never the raw mock modules.
  3. H-08 — split the verification seam; make the nurse trust flow real.
    • Split VerificationApi selection per half: nurse-facing methods (status, start, identity, Shahkar, bank, document upload, credentials, trust badge) go real now — the clientApi is already 1:1 per the mocks registry; admin-facing methods (queue, case, decideStep, signed doc URL) stay mocked until REQ-034 (Phase 4). Follow whatever per-method selection shape is cleanest under the existing seam pattern (two flags, or a composed api object) and record it in the registry.
    • Wire PublishGate.tsx to the real status (its CTA currently calls nothing — :59-68), and gate the variant-activation affordance in MyServicesList.tsx on real verification status with an honest explainer, so a nurse can no longer "publish" into invisibility. Remove/dev-gate the __mockApproveAll simulator button accordingly.
  4. H-09 — split the payouts seam. Nurse reads (earnings_balance, earnings, {id} detail, history) go real (payouts/apis/clientApi.ts:163-187 already implements them); admin batch methods stay mocked until REQ-036. Same split mechanics as verification.
  5. H-10 — stop nulling bookingId. services/payment/apis/clientApi.ts:55-75: read bookingId off the wire (drop the Omit/bookingId: null and the stale REQ-017-pending comments in clientApi.ts and types.ts:98-110); confirm invalidations.ts now receives it and the confirmation page renders the booking + invoice deep links.

4. Mocks & seams in this phase

Touches the refunds, bnpl, verification, payouts seams (splits/rewires; flags flipped only for the halves whose backend is live). Update each row in dev/shared-working-context/reports/mocks-registry.md — including correcting the stale "reads the shared f7 store" descriptions.

5. Critical rules you must not get wrong

  • A mock may only reach sibling data through the selected seam (services/{domain}/apis/index.ts), never by importing a sibling's mockApi.ts — that's the root cause you're eradicating. Grep for remaining cross-mock imports before finishing.
  • Money is served IRR digit-strings, BigInt-safe — the refunds mock's local preview must reuse the existing money utils and reconcile (refund + fee = captured), never float math.
  • Verified-only search, two-stage disclosure, and "client never computes what the server owns" invariants all still hold; the verification split must not let the client write is_verified.
  • A 409 on the money path is benign convergence, never a toast (existing rule).
  • Keep i18n complete for any new copy (both message files); npm run check owns the gate.

6. Definition of Done

  • Real journey (seeded world, real server): create booking request → accept → pay → cancel → policy preview renders with reconciling numbers (no 404).
  • BNPL CTA absent on real checkout while the domain is mocked; the D1-D5 wizard is unreachable with a real request id (and works fully in the all-mock dev mode).
  • Fresh nurse: real verification wizard drives the real b6 endpoints; variant activation is gated until the real status approves; after approval + activation the nurse appears in real search.
  • Nurse earnings screen shows real amounts from the live endpoints.
  • Payment confirmation shows working "view booking" + "download invoice" deep links after a real capture.
  • npm run check + npm run test:ci green; no services/*/apis/mockApi imports across domain boundaries (grep-proof in the report).

7. How to test (human)

  1. Full customer journey per §6 against the RUNBOOK setup; screenshot the cancel preview.
  2. grep -r "apis/mockApi" client/src/services --include=*.ts | grep -v "own domain" → empty.
  3. Nurse persona 09120000003 (unverified): services page shows the gated state; run the real verification flow; confirm search visibility flips after approval.

8. Hand off & document

  • Tick H-06…H-10 in issues.md with commit hashes.
  • Update client/CLAUDE.md de-mock status block + mocks-registry.md rows.
  • Write dev/shared-working-context/reports/hardening-phase-2-report.md; file new REQs if a split exposed a missing server read (append to for-backend.md, Phase 4 picks them up).