remove user-secrets approach & prepare a pilot deploy

This commit is contained in:
hamid
2026-07-28 23:18:54 +03:30
parent 630c7907ec
commit 5885280b49
28 changed files with 639 additions and 142 deletions
+35 -29
View File
@@ -47,24 +47,29 @@ 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)
### 3. Point the API at a database
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:
**`dotnet user-secrets` is no longer used** — the `<UserSecretsId>` was removed from
`Baya.Web.Api.csproj`, so that store isn't read at all. A leftover `secrets.json` on your machine is inert
and can be deleted. All configuration lives in
[`appsettings.Development.json`](../../../server/src/API/Baya.Web.Api/appsettings.Development.json), which
already points at the **shared remote database** the deployed demo also uses — so a fresh clone boots with
no configuration step at all.
```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;"
To work against the throwaway local container from step 2 instead, edit `ConnectionStrings:SqlServer` in
that file (the `Password` must match `MSSQL_SA_PASSWORD` in `server/docker-compose.yml`):
```jsonc
"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.
> **Env-var alternative** (CI/containers, or to avoid a local edit showing up in `git status`): set
> `ConnectionStrings__SqlServer` (double underscore = the `:` config separator) — it overrides the file.
> 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;"`
> Deploying rather than developing? See [DEPLOY.md](../../../DEPLOY.md).
---
## Run it (two terminals)
@@ -126,12 +131,10 @@ endpoint works). Use them to see the real path populated:
| `09120000030` | partner-center owner | بهنام رستگار (male) | owns مرکز پرستاری آرامش (merchant-of-record, sponsors علی کریمی). No admin/nurse role — log in, then navigate to `/partner` manually (REQ-038: no `/me` partner signal yet) |
> The old username+password `admin`/`qw123321` account is **no longer auto-seeded** (refinement-phase-5 —
> no committed credential). To bootstrap a break-glass username+password admin, set both secrets before boot,
> then log in via the API (not the web UI, which is phone-OTP only):
> ```bash
> cd server/src/API/Baya.Web.Api
> dotnet user-secrets set "Seed:AdminUsername" "admin"
> dotnet user-secrets set "Seed:AdminPassword" "<a-strong-password>"
> no committed credential). To bootstrap a break-glass username+password admin, add both keys to
> `appsettings.Development.json` before boot, then log in via the API (not the web UI, which is phone-OTP only):
> ```jsonc
> "Seed": { "AdminUsername": "admin", "AdminPassword": "<a-strong-password>" }
> ```
The **phone-OTP admins** (`09120000020` / `09120000021`, refinement-phase-2) are how you reach the `/admin`
@@ -179,11 +182,11 @@ code to every configured chat id, so it is a test-group convenience, not an SMS
`api.telegram.org` is filtered in Iran, so set `TELEGRAM_PROXY_URL` in its `.env` to your VPN/proxy
client (`http://127.0.0.1:10809`, `socks5://…`, or the proxy container on a VPS). The boot banner prints
the bot's `@username` — that line appearing means the token *and* the proxy work.
2. **Share the secret with the API** — the same value on both sides (relay `.env` `API_KEY`, API user-secret):
```bash
cd server/src/API/Baya.Web.Api
dotnet user-secrets set "Seams:Sms:Telegram:ApiKey" "<the relay's API_KEY>"
```
2. **Share the secret with the API** — the same value on both sides: the relay's `.env` `API_KEY` and
`Seams:Sms:Telegram:ApiKey` in `appsettings.Development.json`. The appsettings side is already filled
in; copy that value into your local `telegram-otp-bot/.env`. Do **not** use the one in `.env.example` —
it is published in git, so `TelegramSmsSender` rejects it with
`Seams:Sms:Telegram:ApiKey is not configured (unset, or still the published example key)`.
3. **Flip the provider** in `server/src/API/Baya.Web.Api/appsettings.Development.json`:
```jsonc
"Seams": { "Sms": { "Provider": "telegram" } } // committed default is "mock"
@@ -202,10 +205,13 @@ error) rather than pretending an undelivered code was sent.
- **The API speaks HTTP/1.1 and HTTP/2** (Kestrel `Protocols: Http1AndHttp2`, refinement-phase-5 — the
previous HTTP/2-only default broke non-TLS HTTP/1.1 hops). Over TLS the client negotiates h2 via ALPN, so
gRPC and `fetch` both work; plain-HTTP hops fall back to HTTP/1.1.
- **Secrets fail fast.** On a fresh clone with no user-secrets the API refuses to start with
`Refusing to start: required secret configuration is missing…` — set the connection-string user-secret
(step 3) and boot again. Deployed environments must additionally supply real `IdentitySettings` JWE keys
and `Seams:FieldEncryption` keys (Development uses dev-only defaults from `appsettings.Development.json`).
- **Secrets fail fast.** If `ConnectionStrings` is blank or still the base file's
`SET_VIA_USER_SECRETS_OR_ENV` placeholder, the API refuses to start with
`Refusing to start: required secret configuration is missing…`. Production/Staging must additionally supply
real `IdentitySettings` JWE keys and `Seams:FieldEncryption` keys; Development uses the dev-only ones in
`appsettings.Development.json`.
- **Never change `Seams:FieldEncryption:Key`/`:HashKey`.** They decrypt every PII column in the shared
database and derive `users.PhoneHash`, which every login looks up. Changing either locks everyone out.
- **Enable the secret-scan pre-commit hook** once per clone so a stray credential can't be committed:
`git config core.hooksPath .githooks` (see [`.githooks/README.md`](../../../.githooks/README.md)).
- **Behind a reverse proxy**, list its address in `ForwardedHeaders:KnownProxies` (or a CIDR in
@@ -243,7 +249,7 @@ world, wipe the volume (`docker compose down -v`) and boot again.
| Symptom | Fix |
| --- | --- |
| Browser: `net::ERR_CERT_AUTHORITY_INVALID` on `:5002` | Run `dotnet dev-certs https --trust` (setup step 1). |
| API startup: `Refusing to start: required secret configuration is missing…` | The connection-string user-secret isn't set (or still the placeholder). Do setup step 3. |
| 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`. |
| API startup: `Refusing to start: required secret configuration is missing…` | `ConnectionStrings:SqlServer` is blank or still a placeholder. Do setup step 3. |
| API startup: `Login failed for user 'sa'` / connect timeout | DB not up or wrong password — check `docker compose ps` and that the password in `appsettings.Development.json` 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>`). |
| `dotnet user-secrets` errors with "could not find UserSecretsId" | Expected — user-secrets was removed. Edit `appsettings.Development.json` instead. |