7.8 KiB
Domain contracts
One file per client services/ domain — 22 files, 22 domains, one-to-one. Each names every server
endpoint that belongs to it, verdicted against the live swagger and the real client code.
Last verified: 2026-07-30 against commit
d3ec723and../openapi/swagger.v1.json(2026-07-29).
Read ../api-contract.md first — the envelope, casing, pagination, errors, auth,
idempotency and money rules hold everywhere and are not restated per domain.
How to read a domain file
Every endpoint carries one verdict:
| Verdict | Means |
|---|---|
| wired | In swagger and called by the domain's real apis/clientApi.ts |
| unwired | In swagger, no real client caller. Server-only, admin-only, or superseded — the reason is given |
| phantom | The client calls it; the server has no such route. It 404s. Always carries its REQ |
phantom rows are the frontend's proposed routes, filed as REQs and mocked behind the domain seam
meanwhile. They are not bugs in the client — they are the contract's open edge — but on a domain whose
mock is off they are live 404s, and that is called out where it happens.
The census
186 operations, each in exactly one file below. 184 belong to a domain; 2 (ping) are platform
endpoints and live in ../api-contract.md.
| Domain file | client/src/services/ |
Seam | Server ops | Phantom |
|---|---|---|---|---|
| addresses.md | addresses |
real | 5 | — |
| admin.md | admin |
mock | 14 | 5 |
| auth.md | auth |
real | 7 | — |
| bnpl.md | bnpl |
mock | 9 | 3 |
| booking-requests.md | bookingRequests |
real | 7 | — |
| bookings.md | bookings |
real | 16 | — |
| catalog.md | catalog |
real | 14 | — |
| geography.md | geography |
real | 13 | — |
| notifications.md | notifications |
real | 4 | — |
| nurse.md | nurse |
real | 4 | — |
| partner-center.md | partnerCenter |
mock | 9 | 6 |
| patient-records.md | patientRecords |
mock | 5 | — |
| patients.md | patients |
real | 5 | — |
| payment.md | payment |
real | 3 | 1 |
| payouts.md | payouts |
mock | 13 | 1 |
| profiles.md | profiles |
real | 7 | — |
| refunds.md | refunds |
mock | 8 | 4 |
| reviews.md | reviews |
real | 8 | — |
| search.md | search |
real | 2 | — |
| service-areas.md | serviceAreas |
real | 3 | — |
| tickets.md | tickets |
real | 11 | 1 |
| verification.md | verification |
mock | 17 | 3 |
| 184 | 24 |
"Seam" is the domain's constants.ts flag (USE_<DOMAIN>_MOCK): 15 real, 7 mock. A mocked domain
still has a complete real client — flipping the flag is one line in apis/index.ts.
Two phantoms sit on a domain whose mock is off, so they are reachable and they 404:
GET /api/v1/bookings/payment_history (payment.md, REQ-047) and
POST /api/v1/tickets/{id}/assign (tickets.md, REQ-063). Both are guarded in the client —
the first renders an empty state, the second is behind a default-off capability flag.
Route-shape exceptions
The routing convention is snake_case segments generated from [controller]/[action] tokens. Four
controllers hardcode a route string instead, and three of those introduce hyphens:
| Route | Controller | Note |
|---|---|---|
api/v1/admin/partner-centers |
AdminPartnerCentersController |
hyphens and a nested admin/ segment; children add /set-active, /sponsor-nurse |
api/v1/admin/tickets |
AdminTicketsController |
nested admin/ segment |
api/v1/admin/reviews/moderation_queue |
AdminReviewsController |
nested admin/, then snake_case |
api/v1/internal/bookings/{bookingId}/center |
InternalCentersController |
an internal/ namespace |
Every other admin controller uses a flat admin_* prefix (admin_geo, admin_catalog, admin_refunds,
…). The split is historical, not meaningful. Since the route also derives the dynamic-permission key,
normalising it is a breaking change to permissions as well as URLs — it is recorded here, not fixed.
Enum vocabularies
Swagger declares no string enums (see
../api-contract.md), so each domain file carries its own vocabulary. Every
one was cross-checked against the server's Baya.Domain code set and the client's string-literal
union. All match except one, noted in tickets.md.
| Vocabulary | Domain file | Server source |
|---|---|---|
BookingRequestStatus · RequiredCaregiverGender |
booking-requests.md | Entities/Booking/BookingRequestStatus.cs |
BookingStatus · BookingSessionStatus · VisitVerificationStatus |
bookings.md | Entities/Booking/*.cs |
PriceUnit |
catalog.md | catalog config rows |
BnplStatus · BnplEligibilityStatus · ProviderCode |
bnpl.md | Entities/Bnpl/*.cs |
PaymentTransactionStatus · MoadianStatus |
payment.md | Entities/Payments/, Entities/Invoices/ |
RefundStatus · RefundChannel · ClawbackStatus · cancellation codes |
refunds.md | Entities/Refunds/*.cs |
PayoutStatus · PayoutBatchStatus · EarningsState |
payouts.md | Entities/Payouts/*.cs |
VerificationStatus · VerificationStepStatus · StepTypeCode |
verification.md | Entities/Verification/*.cs |
ModerationStatus · ModerationAction |
reviews.md | Entities/Reviews/ReviewModerationStatus.cs |
TicketStatus · TicketCategory · TicketAuthorRole |
tickets.md | Entities/Messaging/TicketCodes.cs |
CenterOnboardingState |
partner-center.md | Entities/PartnerCenters/ |
BankAccountStatus |
nurse.md | bank-account entity |
roles · Gender |
auth.md | identity seed |
| config/audit/holiday/alert codes | admin.md | Entities/Configuration/, Audit/, Holidays/, SupportAlerts/ |
What replaced what
These files supersede archive/build-chain/contracts/domains/ — 17 hand-written files
frozen 2026-07-13, plus the two conventions/ files. Route-level content there held up well: an audit of
every route those files name found zero that the live swagger lacks. What did not hold up:
| Was | Now |
|---|---|
conventions/api-conventions.md: body casing is "typically snake_case … derive from swagger" |
camelCase, proven mechanically. ../api-contract.md |
conventions/api-conventions.md: server default https://localhost:5002 |
http://localhost:5002 — plain HTTP (contradiction C-3) |
| The envelope has 5 fields | It has 6 — code was added for machine-readable errors (REQ-003) |
| Enum vocabularies spread across 17 files and the REQ ledger | One vocabulary block per domain file, cross-checked both ways |
messaging.md (851 B, headerless) silently amending messaging-notifications-admin.md |
Merged: tickets.md + notifications.md + admin.md (contradiction C-8) |
| 17 files whose names matched backend phases | 22 files whose names match the client's domains, which is how the seam is actually consumed |
| The REQ ledger as the change log you had to read to know the current shape | Each domain file states the current shape and lists only its open REQs |