Files
baya-monorepo/archive/docs/integration/domains/profiles.md
T
2026-08-02 20:01:31 +03:30

58 lines
3.1 KiB
Markdown

# profiles — customer and nurse profiles
> Client seam `client/src/services/profiles/` · `USE_PROFILES_MOCK = false` (**real**) · 7 server ops
> Last verified: 2026-07-30 against commit `d3ec723` and swagger.v1.json (2026-07-29).
One client domain over two server controllers, because the client's profile screens are one feature with
two actor variants. Identity and roles come from [auth.md](auth.md)'s `/me`, not from here.
## Endpoints
| Method | Path | Verdict |
| --- | --- | --- |
| GET | `/api/v1/customer_profiles/me` | wired |
| POST | `/api/v1/customer_profiles/upsert` | wired |
| POST | `/api/v1/customer_profiles/avatar` | **unwired** — the client's avatar upload calls the nurse route only |
| GET | `/api/v1/nurse_profiles/me` | wired |
| POST | `/api/v1/nurse_profiles/upsert` | wired |
| POST | `/api/v1/nurse_profiles/avatar` | wired |
| POST | `/api/v1/nurse_profiles/set_accepting_bookings` | wired |
All `[Authorize]`. No phantoms.
> **`customer_profiles/avatar` exists and is unused.** The nurse avatar upload is wired; the customer one
> is not, so a customer cannot set a photo even though the endpoint is live. A one-line client gap, not a
> contract gap.
## Shape rules the JSON does not express
- **Avatar upload is `multipart/form-data`.** This is the one place the client must **not** set
`Content-Type``clientFetch` detects a `FormData` body and lets the browser write the multipart
boundary. A manual JSON content-type there breaks the upload. See
[../api-contract.md](../api-contract.md).
- **`avatarUrl` is served by the object-storage seam.** `Seams:ObjectStorage:Provider` = `local` (default,
writes under `RootPath`) or `s3`. In the deployment `RootPath` is a **named docker volume** — without it,
uploads vanish on the next `up --build`. See [../topology.md](../topology.md).
- **`isAcceptingBookings` is a real toggle with real consequences.** It is one of the four conditions the
search index's `is_searchable` requires — flipping it off removes the nurse from discovery. See
[search.md](search.md).
- **`isVerified` on `NurseProfileDto` is derived, never writable.** It is written **only** by the
verification finalize transaction when the aggregate reaches `approved`. Never set it from a profile
write. See [verification.md](verification.md).
- **`averageRating` / `totalReviews` / `totalCompletedBookings` are recomputed from source**, not
incremented. A moderation change that hides a review recomputes the aggregate. See
[reviews.md](reviews.md).
- **`specializationsJson` is a string containing JSON**, like the other `*Json` fields on this wire.
- `preferredLanguage` on `CustomerProfileDto` (REQ-007, delivered) alongside the name update.
- `defaultEmergencyContactName`/`Phone` are the customer-level fallback used when a booking supplies none.
## Enums
None of its own. `educationLevel` and `educationField` are free strings. Gender lives on the user
(see [auth.md](auth.md)), not on the profile.
## Open REQs
None. REQ-006 (avatar/object-storage upload route) and REQ-007 (name + preferred language) were both
delivered in refinement-phase-3.