Refinement phases — making Balinyaar work as one integrated app
Created: 2026-07-10 · Scope: the whole repo (client + server) after the 16+16 phase chain completed ·
Method: a read-only audit of the live code (three parallel exploration passes over the frontend wiring, the
backend runnability/infra, and the frontend↔backend contract), cross-checked against dev/ docs.
This directory is a runnable chain of 10 refinement phases that takes the repo from "both projects build
and each runs on its own, but they aren't actually integrated" to "one working app where the logic takes
effect." Run them in order, one at a time, pointing a fresh agent at one phase file
("Execute dev/post-phase/refinement/refinement-phase-0-bring-up.md end to end").
Why this exists alongside
../server/. The existing server post-phase audit is excellent — but it audits the backend in isolation. It never covers the thing you actually hit when you ran the app: the two projects were built in parallel, decoupled lanes and never run against each other. This chain adds the missing integration + frontend track (phases 0–4) and folds the server audit's 8 buckets into the back half (phases 5–9) in the right order.
Two things that are NOT wrong (correcting the brief)
You suspected these; the audit found they're actually fine — which is good news:
- "Database migrations are behind" — they're not. There are 17 EF migrations tracking every backend
phase b0→b15; the model snapshot is in sync and the working tree is clean.
Program.csapplies them on every boot. If it felt like migrations were behind, it's because your target database was never migrated (you were running the frontend on mocks, so nothing ever touched a real DB) — not because migration files are missing. The real DB gap is no local-dev database story + no demo seed data (Phases 0–1), not drift. - "Missing services like Redis / Elasticsearch" — not needed for the MVP. The only external service the backend requires today is SQL Server. All 18 vendor/infra dependencies (cache, lock, jobs, storage, SMS, payments, KYC, geocoding, search, moderation) are in-process mocks behind DI seams — by design. Redis becomes necessary only when you run a second API instance (Phase 7); Elasticsearch is never MVP (the SQL search is real and correct). You didn't miss configuring them.
What's actually wrong (the problem inventory)
Every item below is verified in the live code (file/line evidence is in the phase files).
A. The frontend barely talks to the backend
- 21 of 22 client service domains default to an in-browser mock (
USE_*_MOCK = true, hard-coded literals in eachservices/{domain}/constants.ts). Onlyauthis real by default. So a running app shows fake in-memory data everywhere except login. → Phase 4 (flip them, in dependency order). - The backend has no CORS at all (zero
AddCors/UseCorsinserver/). Even the calls the frontend does make would be blocked by the browser once the two run on different origins. This is the #1 hard blocker. → Phase 0. - The client is correct and ready (
clientFetchreadsNEXT_PUBLIC_API_URL, unwraps theApiResultenvelope, does silent 401 refresh); each domain's realclientApialready maps the live routes 1:1. The swap is a one-line flag flip per domain — once the backend serves what that domain needs (see C).
B. "No auth / only the customer side shows"
- Auth is real and works — but a fresh phone login holds only the
customerrole, soresolveRoleDestinationsends everyone to the customer app (which lives at the root/). Nurse/admin shells are never auto-reached. - A hard-coded
DEFAULT_ROLE = customerfallback means un-hydrated or failed/merole state silently renders the customer shell — a nurse can be shown the customer app. There are no client-side role guards. - OTP delivery is a log statement (
LoggingSmsSender), so "logging in" requires reading the code from the server console — fine for dev, but there's no real SMS yet. → Phase 2 (role reachability + robust hydration + guards) and Phase 0/8 (the dev OTP bridge, then real SMS).
C. Frontend ↔ backend contract mismatches (the real "mismatch" you sensed)
- The frontend filed 37 contract requests (REQ-001…037) — all still
Status: open. They're why 21 domains are mock-primary: a DTO missing a field, or a customer read that only exists as an admin route. Almost all are additive (nullable fields, new read endpoints). → Phase 3. - Three concrete shape mismatches to reconcile before flipping the matching mock: partner-center kebab-case
routes that violate the snake_case convention; the BNPL
balinyaarprovider not in the wire enum; the client-invented cancellation-policy codes. → Phase 3, verified in Phase 4.
D. It can't start cleanly / shows nothing
- The backend only boots against a committed remote SQL Server (leaked
sacredentials); no local default, no SQLite fallback fordotnet run. → Phase 0/1 (local DB) and Phase 5 (rotate the leak). - A fresh DB seeds only lookup tables + one admin + one gateway — no nurses, variants, or search rows — so search/discovery/booking are empty even on the real path. → Phase 1 (demo seed).
E. Production-readiness gaps (from the server audit — real, but after "make it work")
- Committed secrets & dev-grade defaults (Phase 5); one genuine money hole — the unreachable BNPL/manual refund clearing (Phase 6); no unattended operation — nurses aren't paid unless an admin clicks (Phase 7); every vendor rail is mocked — SMS is launch-critical (Phase 8); metrics-only observability + doc drift (Phase 9).
The 10 refinement phases
Run top to bottom. Phases 0–4 make the app work as an integrated whole; phases 5–9 make it production-ready (and largely re-sequence the server audit).
| # | Phase | Track | Fixes (from above) | Depends on |
|---|---|---|---|---|
| 0 | Local end-to-end bring-up & the integration seam | both | CORS · local DB · dev OTP · one real round-trip | — |
| 1 | Database: local-dev story, demo seed & migration hygiene | backend | empty marketplace · local DB · (migration myth) | 0 |
| 2 | Auth & role-aware navigation | frontend (+bit of backend) | "only customer side shows" | 0, 1 |
| 3 | Backend contract batch (close the 37 REQ gaps) | backend | the mismatch — REQ-001…037 | 0 |
| 4 | Frontend de-mock (flip every domain to real) | frontend | "no API calls to backend" | 1, 2, 3 |
| 5 | Security & config hygiene | backend | leaked sa creds, keys, seeds |
— (5.1 now) |
| 6 | Money-path correctness completion | backend | unreachable refund clearing + FKs | before 8 |
| 7 | Unattended ops: scheduler, locking & multi-instance | backend | nurses not paid unattended · Redis gate | 6 |
| 8 | External rails go real (SMS → trust → money) | backend | mocks → real vendors (SMS launch-critical) | 6, 7 |
| 9 | Observability, ops hardening & scale-later | backend | tracing/health/logs · doc honesty · ES/analytics deferred | — |
Dependency & sequencing
Make it work (integration):
0 bring-up ──► 1 database/seed ──► 2 auth & role nav ─┐
└────────► 3 contract batch ────────────────────┴──► 4 frontend de-mock
(app now integrated)
Make it production-ready (server audit, re-sequenced):
5 security (5.1 rotate creds = TODAY)
6 money correctness ──► 8 money rails
7 scheduler/Redis ─────► (weekly payout trigger, Moadian poll for 8)
8 external rails (5.1 SMS = launch-critical, do first in the phase)
9 observability & scale-later (start anytime, finish before launch)
Two items that jump their slot: Phase 5 §5.1 (rotate the committed sa credentials — the leak is live
today) and Phase 8 §5.1 (real SMS — no real user can log in without it, sequence it first inside Phase 8).
Minimum path to "a working demo on real data": Phases 0 → 1 → 2 → 3 → 4. After those, the whole customer/nurse/admin funnel runs against the real backend with seeded data (payments still use the dev conversion path until Phase 8 swaps a real PSP).
How the phase files are written
Each file follows the repo's phase template: a one-paragraph mission, context (what already exists — don't rebuild), required reading, enumerated scope, the seams/mocks it touches, the invariants it must not break, a Definition of Done, concrete how-to-test steps, and a close-out (docs + memory). Phases 0–4 are written in full; phases 5–9 are concise and point into the already-detailed server audit (which has file/line evidence for every item) rather than restating it.
Related documents
- ../server/post-phase-backend-plan.md — the backend-only audit's 8 buckets (folded into Phases 5–9), with file/line evidence.
- ../server/frontend-backend-gaps.md — REQ-001…015 reconciled against shipped code (Phase 3 extends this through REQ-037).
- ../server/runtime-services.md — the 17-service deployment topology.
- ../../shared-working-context/frontend/requests/for-backend.md — the canonical REQ-001…037 tracker (Phase 3's spec).
- ../../shared-working-context/reports/mocks-registry.md — every seam + its make-it-real steps (backend seams + frontend mock flags), the checklist for Phases 4 & 8.