9.6 KiB
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:
- What is it, and who does it?
- Is it actually implemented — really, or only mocked?
- What screens and endpoints does it use?
- How do I test it, step by step, with which account?
- 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 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 — flow walkthroughs, test accounts, the seeded world, the mock-vs-real map, the numbers the UI must respect
- dev/post-phase/refinement/RUNBOOK.md — bring-up, demo accounts, login round-trip, reset, troubleshooting
- dev/shared-working-context/reports/mocks-registry.md
docs/integration/— from Phase 2, the endpoint truthproduct/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
<flow>.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.*.jsonand.env.*;user-secretsis not used and is not read (<UserSecretsId>was removed). The four crypto values still matter and must match whatever the target DB was encrypted under — booting with differentSeams:FieldEncryptionkeys makes every phone lookup miss and every PII read throwPadding 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
(
09120000020super_admin,09120000021finance) 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
DemoLifecycleSeederbuilds (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:
# Flow — <name>
> Last verified: <date> against <commit>
**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/<domain>.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 <account> (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.mdwas 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
UNVERIFIEDmark. - The mock-vs-real map was derived from code and disagreements with
mocks-registry.mdare 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)