doc clean up phase 2
This commit is contained in:
@@ -145,5 +145,136 @@ file, and a deploy question is answered by `topology.md` + `config-matrix.md` wi
|
||||
|
||||
## Handoff
|
||||
|
||||
_(filled in by the agent that runs this phase — especially: the drift list, since Phase 4 turns the
|
||||
`phantom` and `drifted` rows into backlog items)_
|
||||
> Run 2026-07-30 against commit `d3ec723`. **All verification items pass**, checked mechanically
|
||||
> (script in the session scratchpad, results reproduced below).
|
||||
|
||||
### What shipped
|
||||
|
||||
```
|
||||
docs/integration/
|
||||
index.md 153 lines — the whole seam, one screen and a half
|
||||
api-contract.md envelope · casing · status codes · auth · pagination · idempotency · money · enums · rate limits
|
||||
config-matrix.md every key in both appsettings, docker-compose, 3 .env files, the bot, Caddy, CORS
|
||||
topology.md mermaid graph + a 10-edge table + ports + startup order + the local variant
|
||||
domains/
|
||||
index.md the census, the route-shape exceptions, the enum map, what-replaced-what
|
||||
<22 files> one per client services/ domain, 1:1
|
||||
openapi/README.md updated: C-9 resolved, the servers-block provenance wrinkle recorded
|
||||
```
|
||||
|
||||
Also updated: `DEPLOY.md` (links topology + config-matrix; states there is no `appsettings.Production.json`
|
||||
so step 2 of "Going to Production" is a *create*), `docs/README.md` (integration → **written**),
|
||||
`dev/contracts/README.md` + `openapi/README.md` + `domains/messaging.md` (moved/merged banners).
|
||||
|
||||
### Verification
|
||||
|
||||
| Item | Result |
|
||||
| --- | --- |
|
||||
| Every swagger path declared in exactly one `domains/*.md` | **178/178**, 0 unreferenced, 0 duplicated |
|
||||
| Operation census adds up | 186 = 184 domain + 2 `ping` in `api-contract.md` |
|
||||
| Every phantom declared with a reason + REQ | **24/24** |
|
||||
| `config-matrix.md` accounts for every key | Diffed mechanically; 5 gaps found and written up |
|
||||
| `DEPLOY.md` no longer instructs `user-secrets` | Pass — it already documented the removal; now also links the new files |
|
||||
| `index.md` fits a screen and a half | 153 lines |
|
||||
| Every doc carries a `Last verified` stamp | 27/27 |
|
||||
| No reference file over 400 lines | Pass |
|
||||
| Relative links resolve | **216 checked, 0 broken** |
|
||||
|
||||
### Scope note
|
||||
|
||||
`api-contract.md` was **merged into `index.md`'s siblings as planned**, but the plan's `domains/` count of
|
||||
22 was met by re-cutting the file set along the **client's** domain boundaries rather than the backend
|
||||
phases the old 17 files used. That is what makes the mapping 1:1 and is why the file names changed.
|
||||
|
||||
`swagger.v1.json` was **not** re-fetched — Phase 0's 2026-07-29 snapshot is 1 day older than this run and
|
||||
the server was not booted. Everything here is derived from that snapshot plus current source.
|
||||
|
||||
---
|
||||
|
||||
### Drift list — Phase 4's input
|
||||
|
||||
**A. Phantom endpoints (24).** The client's real API clients call 24 routes the server does not expose.
|
||||
Each is declared in its domain file with its REQ. Grouped by REQ:
|
||||
|
||||
| REQ | Status | Phantoms | Domain |
|
||||
| --- | --- | --- | --- |
|
||||
| REQ-031 | deferred | 3 (`admin_roles/*`) | admin |
|
||||
| **REQ-061** | **never filed** | 2 (`admin_users/search`, `/lookup`) | admin |
|
||||
| REQ-022 | partial | 3 (`checkout_bnpl/options`, `/schedule`, `/wallet_installments`) | bnpl |
|
||||
| REQ-032 | partial | 5 (`centers/me/*`, `partner-centers/{id}/nurses`) | partner-center |
|
||||
| REQ-033 | partial | 1 (`centers/me/settlement`) | partner-center |
|
||||
| REQ-064 | open | 1 (`centers/me/bookings/{id}`) | partner-center |
|
||||
| REQ-034 | deferred | 3 (`admin_verifications` documents-url / approve / reject) | verification |
|
||||
| REQ-035 | deferred | 3 (`admin_refunds` preview / approve / reject) | refunds |
|
||||
| REQ-036 | deferred | 1 (`admin_payouts/{id}/transfer_reference`) | payouts |
|
||||
| REQ-047 | open | 1 (`bookings/payment_history`) | payment |
|
||||
| REQ-048 | open | 1 (`refunds/my`) | refunds |
|
||||
| REQ-063 | open | 1 (`tickets/{id}/assign`) | tickets |
|
||||
|
||||
**Two are live 404s** because their domain's mock is off: `bookings/payment_history` (payment) and
|
||||
`tickets/{id}/assign` (tickets). Both are guarded in the client, so neither is user-visible — but they are
|
||||
reachable, not hypothetical.
|
||||
|
||||
**B. Five REQs whose filed status is wrong or narrower than reality.** Each was checked against the
|
||||
swagger, not against another document. Phase 4 should re-triage these rather than copy the ledger.
|
||||
|
||||
| REQ | Filed as | Actually |
|
||||
| --- | --- | --- |
|
||||
| REQ-050 | open — "the list DTO carries neither field" | `BookingRequestListItemDto` **has `variantLabel`** (and `patientAge`). It lacks `variantPrice`/`variantPriceUnit` and the `status=answered` group filter. The REQ was verified against the *client type*, not the wire |
|
||||
| REQ-063 | open — "no close/reopen/assign routes yet" | `tickets/{id}/close` and `/reopen` **exist and are wired**. Only `assign` is missing. `tickets/constants.ts` carries the stale reason |
|
||||
| REQ-066 | open — needs an anonymous search read | `GET /search/nurses` **is already anonymous**. What is missing is the rate limit — `SearchController` has no `[EnableRateLimiting]` |
|
||||
| REQ-067 | open — needs an anonymous profile read | `GET /nurses/{id}/profile` **is already anonymous**. What is missing is the privacy review |
|
||||
| REQ-029 / REQ-030 | delivered | Correct — but `admin/constants.ts` still names them as reasons the admin mock is primary. The only live reasons are REQ-031 and REQ-061 |
|
||||
|
||||
**C. Client-side drifts (client work, not contract work).**
|
||||
|
||||
| # | Where | What |
|
||||
| --- | --- | --- |
|
||||
| 1 | `client/src/lib/api/types.ts` | `ApiEnvelope<T>` omits **`code`**, which the server sends and `clientFetch` already reads at runtime. Incomplete type, no defect |
|
||||
| 2 | `client/src/services/admin/apis/clientApi.ts` | `pageQuery()` sends **`page_size`**; these endpoints declare `PageSize`. Model binding is case-insensitive, **not separator-insensitive**, so it binds nothing and every admin list silently gets the default page size. Latent until `USE_ADMIN_MOCK` flips |
|
||||
| 3 | `client/src/services/bookingRequests/types.ts` | Marks `variantLabel` as client-augmented/absent; the server serves it. Widening the type would light up the redesigned inbox card today |
|
||||
| 4 | `client/src/services/payouts/apis/clientApi.ts` | Comment says `NursePayoutHistoryDto` has no `failureReason`; **the wire has it** on all three payout read models |
|
||||
| 5 | `client/src/services/tickets/constants.ts` | Says the backend has no close/reopen/assign; close and reopen exist (B, above) |
|
||||
| 6 | `client/src/services/payouts/apis/clientApi.ts` | Sends `Idempotency-Key` on `admin_payouts` process/retry, where the server never reads it. Decorative, not harmful |
|
||||
| 7 | `client/.env.sample` | Still `NEXT_PUBLIC_API_URL = https://localhost:5002` — the `https` half of **C-3**, in the file a fresh clone copies. `.env.development` is correct |
|
||||
| 8 | `client/src/services/profiles/` | `POST customer_profiles/avatar` exists and is live; the client only wires the nurse route, so a customer cannot set a photo |
|
||||
|
||||
**D. Cross-side vocabulary asymmetry (1).** The client's `TicketAuthorRole` includes **`system`**;
|
||||
`Entities/Messaging/TicketCodes.cs` defines only `customer`/`nurse`/`admin`. Safe on the reading side, but a
|
||||
reader of the client types would wrongly conclude the server emits it. All other 17 shared vocabularies
|
||||
match exactly, both directions.
|
||||
|
||||
**E. Route-shape exceptions (4).** `admin/partner-centers` (+ `/set-active`, `/sponsor-nurse`),
|
||||
`admin/tickets`, `admin/reviews/…` and `internal/bookings/…` hardcode route strings instead of using the
|
||||
`[controller]`/`[action]` tokens; three introduce hyphens, against the snake_case rule. **Because the route
|
||||
also derives the dynamic-permission key, normalising them breaks permissions as well as URLs** — recorded,
|
||||
not fixed.
|
||||
|
||||
**F. Config gaps (5).** Written up in
|
||||
[config-matrix.md § What the diff found](../integration/config-matrix.md#what-the-diff-found):
|
||||
`NEXT_PUBLIC_EVV_MOCK_GPS` and `NEXT_PUBLIC_VERSION` read but declared in no `.env`;
|
||||
`OpenTelemetry:Otlp:Endpoint`, `Search:Backend` and `Seed:Admin*` read but set nowhere (and a bad
|
||||
`Search:Backend` **throws at startup**); `.env.sample`'s stale `https`; the Telegram shared secret
|
||||
duplicated across two files with nothing keeping them equal; no `appsettings.Production.json`.
|
||||
|
||||
**G. Unfiled REQ (1).** `ui-phase-11-report.md` records "REQ-061…064 appended" to the ledger. **Only
|
||||
062/063/064 were.** Ten live client files cite REQ-061 for the admin user directory
|
||||
(`admin_users/search`, `admin_users/lookup`). Phase 4 must **file it**, not assume it is tracked.
|
||||
|
||||
### Contradictions resolved here
|
||||
|
||||
**C-6** · **C-7** · **C-8** · **C-9** closed; **C-2** closed as a documentation decision; **C-3**'s
|
||||
contract-layer half closed. Decisions recorded in
|
||||
[open-contradictions.md § Resolved](open-contradictions.md#resolved).
|
||||
|
||||
### What Phase 3 should know
|
||||
|
||||
- The seam facts it needs are settled and mechanically verified: camelCase bodies, snake_case URLs, bearer
|
||||
header (**not** cookie auth), money as a digit string outbound and an int64 inbound, `Idempotency-Key` on
|
||||
exactly two endpoints, 20 anonymous operations.
|
||||
- **`GET /api/v1/dev/last_otp/{phone}` is live on `api.balinyaar.ir`** — the deployment runs as Development
|
||||
with a capture-safe SMS provider, so both gate conditions hold. Any flow doc that describes logging in
|
||||
should say this is how you do it today, and that it is the deployment's largest exposure.
|
||||
- C-4 (the `dev-certs` step) is confirmed dead: the API binds plain HTTP locally, so there is no certificate
|
||||
to trust. C-5's two bring-up worlds are real and give **different data** — the committed dev config points
|
||||
at the same remote, already-seeded database the deployment uses.
|
||||
|
||||
Reference in New Issue
Block a user