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 stillopen; 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 relevantproduct/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)
- REQ-019/020/021 — customer refunds (unblocks
refunds):POST bookings/{id}/cancel(customer-initiated, tenancy-checked),GET bookings/{id}/cancellation_policypreview — and define the canonicalcancellation_policy_codeset (the client inventedfree_24h/partial_under_24h/customer_no_show; decide withproduct/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. - 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-facingbookingIdon settle. - REQ-026 — reviews:
bookings/{id}/review_eligibility+ confirm/finishmy_review(verify what already shipped) + the masked-author decision. - REQ-027 leftovers — family care record: the
record_accesscheck endpoint; confirm the product decision recorded for the family-owned record (the GET/PUT already exist withlongids — the id-type reconciliation is client-side, Phase 5). StructuredtaskResultson visit notes if the REQ still asks. - 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.) - REQ-034/035/036 — the admin halves (unblock
verification/refunds/payoutsadmin 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). - REQ-032/033/038 — partner portal:
administersPartnerCenterIdonMeResult+ 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); invoicetotalIrr; 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 infor-backend.mdin 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.sln0 new warnings ·dotnet test Baya.slngreen.- Swagger regenerated; the refinement-3 §7 smoke calls for Tier B/C pass against the seeded world
(customer cancel creates a refund;
centers/meresolves 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.mdstatuses,mocks-registry.md,server/CLAUDE.mdif 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.