Files
baya-monorepo/dev/post-phase/hardening/hardening-phase-4-contract-completion.md
T
2026-07-17 13:22:04 +03:30

7.1 KiB

Hardening Phase 4 — Contract completion batch (close the Tier B/C REQs)

Deliver the remaining open contract requests so the last seven mocked client domains have a real backend to flip to: customer refunds, BNPL reads, review eligibility, family-record access, admin console deltas, the admin halves of verification/refunds/payouts, and the partner portal's identity signal + self-scoped reads. The sequel to refinement-phase-3 (which delivered Tier A). Track: backend · Depends on: Phase 1 (RBAC — the admin endpoints here must be gated by the now-working policy) · Unlocks: Phase 5 Before you start, read _shared/agent-operating-rules.md.

1. Context — where this sits

Fixes H-15, H-16a from issues.md. The canonical spec for every item is the REQ entry in for-backend.md plus the Tier B/C sections of refinement-phase-3 — this file sequences and annotates; it does not restate shapes. Re-check each REQ's Status: line before building — some were partially delivered (REQ-025 nurse reads are live; REQ-027's GET/PUT care_record exists; REQ-017/my_review landed earlier; Phase 1 may have delivered REQ-031; Phase 2 may have appended new REQs — pick those up too).

What already exists (do not rebuild): the b11 refund engine (fee-leg decomposition, clawback fork), the b12 BNPL machine, the b14 review/moderation + care-record entities, the b13 payout engine + nurse_payouts reads, the b6 verification pipeline + signed-URL storage seam, partner centers with kebab-case admin routes, and the refinement-phase-3 house pattern for contract deltas (migration + swagger regen + tests per REQ).

2. Required reading (do this first)

  • for-backend.md — every REQ still open; the proposed shapes there are the contract.
  • refinement-phase-3-contract-batch.md §Tier B/C
    • its "how to test" — mirror its delivery pattern.
  • server/CLAUDE.md, server/CONVENTIONS.md; the relevant product/ docs per area (refund policy, BNPL, verification, partners) — business rules are decisions, not guesses.
  • Phase 2's report + any REQs it filed.

3. Scope — build this (one commit-sized slice per bullet, in this order)

  1. REQ-019/020/021 — customer refunds (unblocks refunds): POST bookings/{id}/cancel (customer-initiated, tenancy-checked), GET bookings/{id}/cancellation_policy preview — and define the canonical cancellation_policy_code set (the client invented free_24h/partial_under_24h/customer_no_show; decide with product/ and publish the enum), GET refunds/by_booking/{id} with fee-leg decomposition. Reuse the b11 engine; a customer cancel is never a self-issued refund — it routes through the existing policy/approval model.
  2. REQ-022/023/024 — BNPL reads (unblocks bnpl): checkout_bnpl/options/{requestId}, checkout_bnpl/schedule, eligibility accepting the D3 KYC fields, wallet installments (provider-reported — D5 is NOT a Balinyaar ledger), customer-facing bookingId on settle.
  3. REQ-026 — reviews: bookings/{id}/review_eligibility + confirm/finish my_review (verify what already shipped) + the masked-author decision.
  4. REQ-027 leftovers — family care record: the record_access check endpoint; confirm the product decision recorded for the family-owned record (the GET/PUT already exist with long ids — the id-type reconciliation is client-side, Phase 5). Structured taskResults on visit notes if the REQ still asks.
  5. REQ-029/030 — admin console deltas: config updatedAt/updatedBy; audit filters (actor_id/action/from/to). (REQ-031 should be done by Phase 1 — verify, don't duplicate.)
  6. REQ-034/035/036 — the admin halves (unblock verification/refunds/payouts admin UIs): verification queue + case + per-step decide + on-demand signed doc URL; refund preview/initiate/ approve/reject (ticket-linked, reusing b11); payout batch preview/run (idempotency-keyed)/retry/ record-transfer-reference (reusing b13). All gated with the Phase-1 policy + fine-grained roles (finance vs moderation vs support scopes as seeded).
  7. REQ-032/033/038 — partner portal: administersPartnerCenterId on MeResult + a seeded demo partner admin; centers/me, centers/me/nurses, centers/me/bookings, centers/me/settlement (identity-derived tenancy — resolve the center from the caller, never from a client-sent id); invoice totalIrr; activate/suspend toggle if still open.

4. Mocks & seams in this phase

No new vendor seams. Everything reuses existing engines behind existing seams. Update mocks-registry.md rows only where a "Make it real →" step is now shorter.

5. Critical rules you must not get wrong

  • Additive only — no breaking DTO/route changes; the 14 already-real client domains must keep working untouched.
  • Money invariants: refund Σ ≤ captured (409 otherwise), fee-leg decomposition, pre/post-payout fork via INursePayoutStatus, BNPL net-of-fee model, payout invariant-to-method. All exist — wire, don't re-derive.
  • Tenancy on every new customer/nurse/partner read (owner-or-staff, 404-not-403); partner reads are identity-derived (/me-style), never id-parameterized.
  • Admin endpoints: [Authorize(ConstantPolicies.DynamicPermission)] + correct fine-grained scope — Phase 1's tests must still pass.
  • Signed URLs short-lived, fetched on demand (the b6/f15 contract). Sequential invoice numbering and Moadian states untouched.
  • Per-REQ: migration if schema changes, swagger regenerated into dev/contracts/openapi/, tests per the refinement-3 pattern, Status: updated in for-backend.md in the same change.

6. Definition of Done

  • Every REQ listed above is either delivered (status updated, tested) or explicitly re-deferred with a reason recorded in for-backend.md — no silent skips.
  • dotnet build Baya.sln 0 new warnings · dotnet test Baya.sln green.
  • Swagger regenerated; the refinement-3 §7 smoke calls for Tier B/C pass against the seeded world (customer cancel creates a refund; centers/me resolves the caller's center; admin queues/previews return their shapes under the right roles).

7. How to test (human)

Per tier, via Swagger against the demo world: cancel a paid booking as its customer (policy preview → cancel → refund visible via by_booking); fetch BNPL options for an accepted request; open the verification queue as super_admin and decide a step; preview + run a payout batch as finance; log in as the seeded partner admin → centers/me chain returns their center only.

8. Hand off & document

  • Tick H-15/H-16a in issues.md (commit hashes per REQ group is fine).
  • Update for-backend.md statuses, mocks-registry.md, server/CLAUDE.md if the project map moved.
  • Write dev/shared-working-context/reports/hardening-phase-4-report.md + a handoff note listing exactly which flags Phase 5 may now flip.