Files
baya-monorepo/dev/post-phase/refinement/README.md
T
2026-07-10 20:59:47 +03:30

145 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/`](../server/README.md).** The existing
> [server post-phase audit](../server/post-phase-backend-plan.md) 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 04) and folds the server audit's 8 buckets into the back half (phases 59) 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:
1. **"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.cs` applies 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 01), not drift.
2. **"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
each `services/{domain}/constants.ts`). **Only `auth` is 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`/`UseCors` in `server/`). 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 (`clientFetch` reads `NEXT_PUBLIC_API_URL`, unwraps the `ApiResult` envelope,
does silent 401 refresh); each domain's real `clientApi` already 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 `customer` role, so `resolveRoleDestination`
sends everyone to the customer app (which lives at the root `/`). Nurse/admin shells are never auto-reached.
- A hard-coded `DEFAULT_ROLE = customer` fallback means **un-hydrated or failed `/me` role 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 **`balinyaar`** provider 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 `sa` credentials); no local default,
no SQLite fallback for `dotnet 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 04 make the app **work as an integrated whole**; phases 59 make it
**production-ready** (and largely re-sequence the [server audit](../server/post-phase-backend-plan.md)).
| # | Phase | Track | Fixes (from above) | Depends on |
| --- | --- | --- | --- | --- |
| **0** | [Local end-to-end bring-up & the integration seam](refinement-phase-0-bring-up.md) | both | CORS · local DB · dev OTP · one real round-trip | — |
| **1** | [Database: local-dev story, demo seed & migration hygiene](refinement-phase-1-database-and-seed.md) | backend | empty marketplace · local DB · (migration myth) | 0 |
| **2** | [Auth & role-aware navigation](refinement-phase-2-auth-and-role-nav.md) | frontend (+bit of backend) | "only customer side shows" | 0, 1 |
| **3** | [Backend contract batch (close the 37 REQ gaps)](refinement-phase-3-contract-batch.md) | backend | the mismatch — REQ-001…037 | 0 |
| **4** | [Frontend de-mock (flip every domain to real)](refinement-phase-4-frontend-de-mock.md) | frontend | "no API calls to backend" | 1, 2, 3 |
| **5** | [Security & config hygiene](refinement-phase-5-security-hygiene.md) | backend | leaked `sa` creds, keys, seeds | — (5.1 now) |
| **6** | [Money-path correctness completion](refinement-phase-6-money-correctness.md) | backend | unreachable refund clearing + FKs | before 8 |
| **7** | [Unattended ops: scheduler, locking & multi-instance](refinement-phase-7-unattended-ops.md) | backend | nurses not paid unattended · Redis gate | 6 |
| **8** | [External rails go real (SMS → trust → money)](refinement-phase-8-external-rails.md) | backend | mocks → real vendors (SMS launch-critical) | 6, 7 |
| **9** | [Observability, ops hardening & scale-later](refinement-phase-9-observability-and-scale.md) | 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](../../phases/_shared/phase-template.md): 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 04 are written in full; phases 59 are concise and **point into the already-detailed
[server audit](../server/post-phase-backend-plan.md)** (which has file/line evidence for every item) rather than
restating it.
## Related documents
- [../server/post-phase-backend-plan.md](../server/post-phase-backend-plan.md) — the backend-only audit's 8
buckets (folded into Phases 59), with file/line evidence.
- [../server/frontend-backend-gaps.md](../server/frontend-backend-gaps.md) — REQ-001…015 reconciled against
shipped code (Phase 3 extends this through REQ-037).
- [../server/runtime-services.md](../server/runtime-services.md) — the 17-service deployment topology.
- [../../shared-working-context/frontend/requests/for-backend.md](../../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](../../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.