# Phase 3 — The flow atlas (verified) **Depends on:** Phase 0, Phase 2 · **Blocks:** Phase 4 · **Size:** 2–4 sessions — the biggest phase ## Goal Build **the one go-to place** that answers, for every flow in the product: 1. What is it, and who does it? 2. **Is it actually implemented — really, or only mocked?** 3. What screens and endpoints does it use? 4. **How do I test it, step by step, with which account?** 5. What's known to be broken or missing? This is the phase where "verify the load-bearing claims" earns its keep. The existing [manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md) is the closest predecessor and it is already wrong about bring-up (it tells you to set `user-secrets`, which the code no longer reads). Copying it forward would reproduce the problem this chain exists to fix. **Run this phase in slices.** One session does `testing-setup.md` + 4–6 flows. Later sessions pick up the next slice. The index table tracks which flows are done. --- ## Inputs - [dev/post-phase/manual-testing-plan.md](../../dev/post-phase/manual-testing-plan.md) — flow walkthroughs, test accounts, the seeded world, the mock-vs-real map, the numbers the UI must respect - [dev/post-phase/refinement/RUNBOOK.md](../../dev/post-phase/refinement/RUNBOOK.md) — bring-up, demo accounts, login round-trip, reset, troubleshooting - [dev/shared-working-context/reports/mocks-registry.md](../../dev/shared-working-context/reports/mocks-registry.md) - `docs/integration/` — from Phase 2, the endpoint truth - `product/business/*` — the 14 requirement areas; what "correct" means - The seeder code (`DemoWorldSeeder`, `DemoLifecycleSeeder`) — **the authority on test accounts and seeded state**, over any doc - `client/src/app/[locale]/**` — 83 routes across `(customer)`, `(customer-focused)`, `nurse`, `admin`, `partner`, `(public-routes)` - `client/src/services/*/` — 22 domains, each with a mock/real flag ## Outputs ``` docs/flows/ index.md the status table — every flow, one row testing-setup.md bring-up, accounts, seeded world, OTP, reset, troubleshooting .md one per flow (see the candidate list) ``` --- ## Candidate flow list Derived from the route groups, the 22 service domains, and the 14 business areas. Confirm and adjust in the first session; the point is one file per *user-meaningful journey*, not per screen. | # | Flow | Actor | Primary routes | | --- | --- | --- | --- | | 1 | `auth-login-otp` | all | `(public-routes)/login`, `select-role` | | 2 | `public-front-door` | guest | `/`, `welcome`, `terms`, `privacy` | | 3 | `onboarding-customer` | customer | onboarding, account | | 4 | `care-circle-patients` | customer | patients / care-circle | | 5 | `addresses-and-map` | customer | addresses, Neshan pin | | 6 | `onboarding-nurse` | nurse | profile, bank account | | 7 | `nurse-service-areas` | nurse | coverage, whole-city (`districtId = null`) | | 8 | `nurse-verification` | nurse + admin | verification journey, document upload, review queue | | 9 | `nurse-catalog-and-pricing` | nurse | services, variant builder | | 10 | `search-and-discovery` | customer | C1–C3, filters, nurse profile | | 11 | `booking-request` | customer + nurse | C4/C5, nurse inbox, countdown, accept/reject | | 12 | `checkout-and-payment` | customer | C6, gateway return, confirmation, escrow | | 13 | `bnpl-installments` | customer | D1–D5 | | 14 | `booking-lifecycle-evv` | nurse + customer | check-in/out, two-stage clinical gate | | 15 | `cancellation-and-refunds` | customer + admin | cancel, policy, refund settlement | | 16 | `reviews` | customer | post-visit review, moderation | | 17 | `patient-care-records` | nurse + customer | append-only records | | 18 | `nurse-earnings-and-payouts` | nurse | earnings, weekly payout run | | 19 | `messaging-tickets` | all | threads, `is_internal` boundary | | 20 | `notifications` | all | bell, day-grouped list | | 21 | `admin-backoffice` | admin | config, holidays, audit, RBAC, queues | | 22 | `partner-center` | partner | the separately-scoped portal | | 23 | `account-and-settings` | all | profile, theme/language (settings-only since iteration 1) | --- ## Steps ### 1. Write `testing-setup.md` — and **actually boot it** Do not transcribe RUNBOOK.md. Follow it, note where it is wrong, and write what really happens. Must cover: - Prerequisites and the two-terminal run (`dotnet run` + `npm run dev`). - **Configuration** — the current, correct story: config in `appsettings.*.json` and `.env.*`; `user-secrets` **is not used and is not read** (`` was removed). The four crypto values still matter and must match whatever the target DB was encrypted under — booting with different `Seams:FieldEncryption` keys makes every phone lookup miss and every PII read throw `Padding is invalid`. Say where they live now. - **Which database.** The dev config has pointed at a *remote* SQL Server. Confirm the current target, and give the local-DB alternative. - **Test accounts** — read them out of the seeder, not the old doc. Note the phone-OTP admins (`09120000020` super_admin, `09120000021` finance) and what each demo account is set up to demonstrate. - **Getting the OTP** — server console (`MOCK SMS — OTP code …`), `GET /api/v1/dev/last_otp/{phone}`, or the Telegram relay. Note the limits: 120 s resend window, 5 wrong attempts, 60 s validity, and that the OTP endpoints are IP rate-limited (scripted logins will 429). - **The seeded world** — what `DemoLifecycleSeeder` builds (the 8-booking world), and the fact that **time-relative scenarios age out** and need a reseed. - **Reset** — the drop-and-reseed procedure, verified. - **Troubleshooting** — the failures you actually hit while doing the above. ### 2. Build the mock-vs-real map — from code The single most important input to every flow file, and the thing most likely to be stale in the docs. For each of the 22 client `services/` domains, read the code: - Is the mock flag on or off? - If real, does the whole domain hit the API, or only part of it? - Server-side: which seams are mocked (SMS, payment gateway, BNPL provider, object storage, geocoder, search) and which have a real adapter available behind config (refinement-phase-8)? Cross-check `mocks-registry.md` and **correct it** — Phase 0 already flagged that the registry has had stale rows before. Put the result in `docs/flows/index.md` as a column, and in each flow file as a header block. Known suspects from the hardening audit (2026-07-16, never ticked off — verify each against current code, do not assume): verification fully mocked while catalog/search are real; the refunds mock reading a retired store; the BNPL wizard on a disconnected store; nurse earnings fabricated despite live endpoints; `patientRecords` id-type mismatch. ### 3. Write one file per flow Template — keep each under ~200 lines: ```markdown # Flow — > Last verified: against **Actor(s):** · **Status:** built | partial | mocked | not started **Business source:** product/business/NN-….md ## What it does Two or three sentences. The user's intent, not the implementation. ## Screens | Step | Route | Component/notes | ## API | Call | Endpoint | Notes | Link to docs/integration/domains/.md — don't restate shapes here. ## Rules that must hold The load-bearing numbers and invariants, with their product/ source. (e.g. commission 0.15, VAT 0.10 on commission only; forward-only status; escrow released after confirmed check-out; whole-city = districtId NULL) ## How to test 1. Log in as (see testing-setup.md) 2. … **Expect:** … ## Known gaps - [BL-xxx] … (filled by Phase 4; leave a plain list here for now) ``` **Verification standard per flow.** For each, do at least the cheap check — trace the route → service → endpoint → handler and confirm the chain is real. For the money flows (11–15, 18) and auth (1), do the expensive check too: run the walkthrough against a booted app. If you cannot run it, mark the flow's status `UNVERIFIED` in the index and say why — an honest gap beats a confident guess. ### 4. Write `index.md` The status table, and nothing else of substance: | Flow | Actor | Status | Client | Server | Verified | File | | --- | --- | --- | --- | --- | --- | --- | | booking-request | customer + nurse | built | real | real | 2026-…-… | [link] | Statuses: `built` (end-to-end real) · `partial` (real but with gaps) · `mocked` (UI real, data fake) · `not started`. `Client`/`Server` columns say `real`/`mock` independently — a flow can have a real UI on a mocked service, which is exactly the trap the hardening audit found. --- ## Verification - [ ] `testing-setup.md` was executed, not transcribed — the agent booted the API and the client. - [ ] Every flow file has a status backed by a code trace, or an explicit `UNVERIFIED` mark. - [ ] The mock-vs-real map was derived from code and disagreements with `mocks-registry.md` are logged. - [ ] No flow file restates an API shape that `docs/integration/` already owns. - [ ] The index accounts for all 22 client service domains and all 14 business areas — anything with no flow is either intentional or a Phase 4 backlog item. - [ ] Every flow file carries a `Last verified:` line. ## Definition of done You can hand someone `docs/flows/testing-setup.md` and `docs/flows/index.md` and they can test the product without asking you a single question — and without hitting an instruction that no longer works. ## Handoff _(filled in per slice — which flows are done, which are `UNVERIFIED` and why, and the running list of gaps found, which is Phase 4's primary input)_