Files
baya-monorepo/dev/post-phase/refinement/RUNBOOK.md
T
2026-07-12 01:09:11 +03:30

141 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Run the whole app locally — Balinyaar bring-up runbook
The one copy-pasteable procedure for standing up **both** projects on one machine and watching a real,
authenticated request cross the wire. Established by **Refinement Phase 0**
([refinement-phase-0-bring-up.md](refinement-phase-0-bring-up.md)).
After this you have: the API on `https://localhost:5002` (against a local SQL Server), the web client on
`http://localhost:3000`, and a working phone-OTP login backed by the real backend. **Auth is the only real
domain** until [Refinement Phase 4](refinement-phase-4-frontend-de-mock.md) — everything else in the UI is
still an in-browser mock.
---
## Prerequisites
- **.NET 10 SDK** (`dotnet --version`) — preview is fine.
- **Node.js 20+** and **npm** (`node --version`).
- **Docker** (Desktop or engine) for the local database — or your own SQL Server on `localhost:1433`.
---
## One-time setup
### 1. Trust the ASP.NET Core HTTPS dev certificate
Without this the browser (and `fetch`) rejects `https://localhost:5002` and every call fails with an opaque
network error.
```bash
dotnet dev-certs https --trust
```
Accept the OS prompt. (macOS/Windows trust the cert; on Linux see the .NET docs for the per-distro step.)
### 2. Start a local SQL Server
From `server/`:
```bash
cd server
docker compose up -d
```
This runs SQL Server 2022 (Developer edition) on `localhost:1433` with a **dev-only** SA password
(`Balinyaar_Dev1433`, defined in `server/docker-compose.yml` — not a secret, never used in production).
Give it ~2030s on first start (`docker compose ps` shows `healthy`).
> Already have a SQL Server? Skip this and point the connection string in step 3 at it instead.
### 3. Point the API at the local database (via user-secrets — never a committed file)
The committed `appsettings*.json` carry a **placeholder** connection string on purpose. Supply the real
local one through `dotnet user-secrets` so no working credential ever lands in git. From the API project:
```bash
cd server/src/API/Baya.Web.Api
dotnet user-secrets set "ConnectionStrings:SqlServer" "Server=localhost,1433;Database=Baya;User Id=sa;Password=Balinyaar_Dev1433;TrustServerCertificate=True;Encrypt=False;"
```
The `Password` must match `MSSQL_SA_PASSWORD` in `docker-compose.yml`. User-secrets auto-load only in the
Development environment, so this never affects a deployed build.
> **Env-var alternative** (e.g. for CI/containers): set `ConnectionStrings__SqlServer` (double underscore =
> the `:` config separator) instead of using user-secrets.
> PowerShell: `$env:ConnectionStrings__SqlServer = "Server=localhost,1433;Database=Baya;User Id=sa;Password=Balinyaar_Dev1433;TrustServerCertificate=True;Encrypt=False;"`
> bash: `export ConnectionStrings__SqlServer="Server=localhost,1433;Database=Baya;User Id=sa;Password=Balinyaar_Dev1433;TrustServerCertificate=True;Encrypt=False;"`
---
## Run it (two terminals)
### Terminal 1 — backend (from `server/`)
```bash
dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj
```
On boot the API applies all EF migrations and seeds roles + an admin user + a sandbox payment gateway
against the (empty) local DB, then listens on **`https://localhost:5002`** — Swagger at
`https://localhost:5002/swagger`.
### Terminal 2 — frontend (from `client/`)
```bash
cd client
npm install # first time only
npm run dev
```
Serves **`http://localhost:3000`**. It reads the API base URL from `client/.env.development`
(`NEXT_PUBLIC_API_URL = https://localhost:5002`). If you run the API on a different port/scheme, create
`client/.env.local` with your `NEXT_PUBLIC_API_URL=…` (it overrides `.env.development`, is git-ignored).
---
## Log in (the real round-trip)
1. Open **`http://localhost:3000/fa/login`**.
2. Enter an Iranian mobile number (e.g. `09120000001`) and request the code.
3. Get the 6-digit OTP one of two ways:
- **Read the server console** (Terminal 1) — SMS is mocked, so the code is logged:
`MOCK SMS — OTP code 123456 for phone ending in 0001`.
- **Or hit the Development-only helper** (handy for scripts/e2e):
`GET https://localhost:5002/api/v1/dev/last_otp/09120000001`
`{ "data": { "phone": "09120000001", "code": "123456" }, ... }`.
This endpoint returns **404 outside Development** and is superseded by real SMS in
[Refinement Phase 8](refinement-phase-8-external-rails.md).
4. Enter the code and submit → you land on the customer home.
5. **Verify in DevTools → Network:** `POST /api/v1/auth/request_otp`, `POST /api/v1/auth/verify_otp`, and
`GET /api/v1/me` all return **200** with the `ApiResult` envelope, and there is **no CORS error** in the
console. That is the first real authenticated request between the two projects.
---
## Good to know
- **The API speaks HTTP/2** (Kestrel `Protocols: Http2`, for gRPC). Browsers negotiate h2-over-TLS
automatically, so `fetch` just works; for `curl` add `--http2`.
- **Only `auth` is real by default.** 21 of 22 client service domains default to an in-browser mock
(`USE_*_MOCK = true`); the home, search, bookings, etc. are fake in-memory data until Refinement Phase 4.
- **The DB self-migrates + self-seeds**, so pointing at an empty local instance is enough. Rich demo data
(nurses, variants, search rows) arrives in [Refinement Phase 1](refinement-phase-1-database-and-seed.md).
- **Allowed browser origins** are configuration-driven (`Cors:AllowedOrigins`), defaulting to
`http://localhost:3000` in Development. A deployed environment lists its real web origin(s).
## Stopping / resetting
```bash
docker compose down # stop the DB, keep its data
docker compose down -v # stop the DB and wipe the volume (fresh migrate + seed next run)
```
## Troubleshooting
| Symptom | Fix |
| --- | --- |
| Browser: `net::ERR_CERT_AUTHORITY_INVALID` on `:5002` | Run `dotnet dev-certs https --trust` (setup step 1). |
| API startup: `Login failed for user 'sa'` / connect timeout | DB not up or wrong password — check `docker compose ps` and that the user-secrets password matches `docker-compose.yml`. |
| Console: `...has been blocked by CORS policy` | `UseCors` missing/mis-ordered, or the browser origin isn't in `Cors:AllowedOrigins`. It must sit after `UseRouting` and before the rate limiter. |
| `dotnet user-secrets` errors with "could not find UserSecretsId" | Run it from `server/src/API/Baya.Web.Api` (the project with `<UserSecretsId>`). |