add build development phases

This commit is contained in:
hamid
2026-06-28 21:59:59 +03:30
parent 1df3cd9f64
commit 53a40dc51d
52 changed files with 12379 additions and 0 deletions
@@ -0,0 +1,50 @@
# API conventions (read before writing or consuming any contract)
These hold for **every** Balinyaar endpoint. Per-domain contract docs assume them and don't restate them.
## Base & versioning
- Base URL from `NEXT_PUBLIC_API_URL` (client) / `https://localhost:5002` (server default).
- Versioned routes: `api/v{version}/...` (Asp.Versioning). Default `v1`.
- **All URL segments are `snake_case`** (server `SnakeCaseParameterTransformer`). Controllers use
`[controller]`/`[action]` tokens, so `GetNurseProfile``.../get_nurse_profile`.
## Response envelope (`OperationResult` → `ApiResult`)
Every response is the server's standard envelope, not a bare body. Success and failure share the shape;
the frontend's `clientFetch`/`serverFetch` already unwrap it and throw `ApiError` on failure. Document
each endpoint's **payload** (the `data`/result) and its failure cases. The envelope carries at least:
a success flag, an HTTP-aligned status, a user-safe message, and the typed `data` (or validation errors).
The canonical shape is defined by `Baya.Application/Models/ApiResult` + `OperationResult<T>` on the
server — mirror that, don't invent a new envelope.
## Status codes
- `200` success (payload in `data`).
- `400` validation/business-rule failure (field-level errors included).
- `401` unauthenticated (missing/expired token) · `403` unauthorized (lacks permission).
- `404` not found.
- `409` conflict (idempotency / duplicate / state-machine violation) where applicable.
- `5xx` unexpected (generic safe message; details only in server logs).
## Auth
- Bearer JWE in `Authorization: Bearer <token>` (access token, ~15 min). Refresh via the refresh
endpoint; rotation + reuse-detection apply. The client attaches the header automatically in
`clientFetch`. State which policy/role each endpoint needs.
## Localisation
- The client sends the active locale (`Accept-Language` / `x-app-locale`, `fa` default). Server-produced
user-facing messages should honour it. Reference data that has `name_fa`/`name_en` returns both;
the client picks by locale.
## Pagination (mandatory on lists)
- Query params: `page` (1-based) + `page_size` (cap it server-side, e.g. ≤100). Response payload carries
`items` + `total` (+ `page`/`page_size`). Document the default and max `page_size` per endpoint.
## Idempotency (money & side-effecting POSTs)
- Where stated, the client sends an idempotency key (header or body field) and the server dedups. Webhook
endpoints dedup on the provider's `external_event_id`. Document which endpoints require a key.
## Naming
- JSON properties are the server's serialized casing (follow what NSwag/Swagger emits — typically
`snake_case` to match routing, or the project's configured policy; **derive the exact casing from the
published `swagger.json`, don't assume**). The frontend types match the wire exactly.
> When in doubt about an envelope/casing detail, the published `openapi/swagger.json` is authoritative.
@@ -0,0 +1,39 @@
# Money & shared types on the wire
## Money — IRR Rials, integer, no floats
- All monetary values are **IRR Rials as integers** (`BIGINT` server-side). There are **no floats** on
the money path anywhere — not in the DB, not in the API, not in the client.
- Because IRR amounts exceed JS's safe integer range in some aggregates and to avoid float coercion,
represent money on the wire as a **string of digits** (e.g. `"23300000"`) unless the published
`swagger.json` shows otherwise; the client parses with `BigInt`/integer-safe helpers and formats for
display. **Toman is display-only** and is converted to/from Rials **only** inside a provider adapter
at its boundary — never in shared contracts or the client's own math.
- The three booking amounts always satisfy `gross_price_irr = balinyaar_commission_irr + nurse_payout_amount`.
## Dates & times
- Timestamps are **UTC ISO-8601** (`DATETIME2(7)` server-side). Persian-calendar (Shamsi) display is a
**client** concern. The exception is bank-closure scheduling, which the server resolves via the
holiday calendar — the client never computes payout dates.
- `day_of_week` for availability uses the **Shamsi week (0 = Saturday … 6 = Friday)**, not ISO Monday-start.
## Enums (string-valued, stable codes)
Enums cross the wire as their stable string code (e.g. `male`/`female`/`any`, `per_hour`/`per_session`/
`per_half_day`/`per_day`/`per_24h`, booking/verification/payment statuses, `refund_channel` =
`psp_card`/`bnpl_revert`/`manual`). Each domain contract doc lists the exact set it uses. The frontend
mirrors them as string-literal union types and **never** hardcodes a display label off the code — labels
are i18n keys.
## Identifiers
- Entity IDs are integers/`BIGINT` (serialized per the published schema). Human-facing references
(`reference_code` on tickets, `invoice_number`) are strings shown to users — treat as opaque.
## PII & sensitive fields
- Encrypted-at-rest fields (phone, national_id, IBAN, addresses, clinical notes) are returned **only**
to authorized callers and often **masked** (e.g. last 4 of an IBAN). Contracts must state when a field
is masked vs. full, and the two-stage clinical-disclosure rule (full care instructions only after a
booking is confirmed, to the assigned nurse + admin) applies to the relevant payloads.
## Gender (load-bearing)
- `gender` (`male`/`female`) drives **same-gender caregiver matching** — a near-hard requirement. It is
present on users/patients and on the booking request as `required_caregiver_gender`
(`male`/`female`/`any`). Never default or drop it silently.