Add the discovery layer: the denormalized nurse_search_index read model (one row per bookable variant x covered service area), maintained inline inside each source write's transaction, plus the single public search query behind the INurseSearch seam. - Entity + EF config + migration (search schema): covering search index, filtered-unique (variant_id, city_id, district_id) pair with NULL district participating, nurse_id index, soft-delete. - ISearchIndexMaintainer (write seam) + SearchIndexMaintainer: reindex variant / nurse / fan-out / remove-area / full rebuild, staged in the owning source write's unit of work; wired into the b3/b4/b5/b6 handlers. - INurseSearch (read seam) + SqlNurseSearch (real MVP backend): reads only is_searchable=1, category/city/district(NULL-aware)/gender/price filters, rating sort, pagination. Elasticsearch deferred (config Search:Backend). - SearchNursesQuery (+ validator) and RebuildSearchIndexCommand; public SearchController (GET search/nurses) + admin AdminSearchController (POST admin_search/rebuild_index). - Tests: 9 DB-backed maintainer/search + 4 WebApplicationFactory; updated affected b3/b4/b5/b6 handler tests. Build clean, 167 tests green. - Docs: server CLAUDE.md project map, contract search.md, swagger refresh, handoff, report, mocks-registry rows, STATUS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OpenAPI snapshots
The server already generates OpenAPI via NSwag (Swagger UI at /swagger, documents v1, v1.1).
This folder holds the published swagger.json snapshot(s) so the frontend can generate/verify types
without running the backend.
Backend: publish on every API-shipping phase
After adding/changing endpoints and confirming the build, export the OpenAPI document and commit it here
as swagger.v1.json (overwrite — git history is the version trail). Typical options:
- Run the API and save
GET /swagger/v1/swagger.jsontodev/contracts/openapi/swagger.v1.json, or - Use the NSwag CLI / build target the server already wires to emit the document.
Record in your handoff that the snapshot was refreshed. Keep it in sync with ../domains/*.md — the
markdown is the human contract, this JSON is the machine contract; they must agree.
Frontend: consume
Generate types from swagger.v1.json (e.g. an openapi-typescript-style step) or hand-write
src/services/{domain}/types.ts to match it. Either way, the wire shapes come from here — not from
guessing. Casing/format questions are resolved by this file.
Until the first API-shipping backend phase runs, this folder is empty by design.