add build development phases
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user