# BIG-register BFF (ASP.NET Core)

The backend that hosts the **business rules** for the BIG-register portal. The
frontend renders the decisions this service computes; it does not recompute them
(BFF-lite + decision DTOs — see `../docs/architecture/0001-bff-lite-decision-dtos.md`).

No real BRP/DUO: the reference data they'd return (registration, person, diplomas,
notes — `Data/SeedData.cs`) is in-memory and seeded, but the endpoints, DTOs,
status codes and error envelope are production-shaped.

**Applications, documents and the brief persist** to a SQLite file
(`src/BigRegister.Api/bigregister.db`, EF Core-backed — `Data/AppDbContext.cs`,
`Data/Db.cs`) created and migrated on first run; restarting the process (or
`docker compose restart api` — the existing `./backend:/src` bind mount already
covers it, see `docker-compose.yml`) does **not** lose data. Delete the file to
reset demo data back to empty, the same state a fresh clone starts from. This is
a deliberate, right-sized choice for a POC (SQLite, no external DB service) — see
`docs/backlog/WP-22-durable-persistence.md`.

## Run

### Everything (docker-compose, from repo root)

```bash
docker compose up
```

- App: <http://localhost:4200>
- Swagger UI: <http://localhost:5000/swagger>

### Backend only (local)

```bash
cd backend
dotnet run --project src/BigRegister.Api
# → http://localhost:5000/swagger
```

### Frontend against a local backend

```bash
npm start          # ng serve, proxies /api → http://localhost:5000 (proxy.conf.json)
```

### Tests

```bash
cd backend && dotnet test      # rule unit tests + endpoint integration tests
```

## API

| Method | Route | Purpose |
|---|---|---|
| GET | `/api/dashboard-view` | registration + person + computed herregistratie decision |
| GET | `/api/notes` | specialisms / aantekeningen |
| GET | `/api/brp/address` | BRP address lookup (`gevonden:false` = no address) |
| GET | `/api/duo/diplomas` | diplomas with derived profession + applicable policy questions, + manual fallback |
| GET | `/api/intake/policy` | scholing threshold (config value) |
| POST | `/api/registrations` | submit registration → reference, or 422 (manual diploma) |
| POST | `/api/herregistraties` | submit re-registration → reference, or 422 (0 hours) |
| POST | `/api/intakes` | submit intake → reference, or 422 (0 hours) |

Rejections use **ProblemDetails (RFC 7807)** with status **422**. Every request
carries an `X-Correlation-Id` (set by the FE fetch adapter); the backend echoes it
into a no-PII submit-audit log line (`kind`, `outcome`, `reference`, correlation id)
— the seam for real structured logging / an audit store.

### Versioning

Endpoints live under **`/api/v1`**. Additive changes (a new optional field) stay on
v1: the NSwag-generated client and the FE `parse*` boundary ignore unknown fields,
so old clients keep working. A breaking change (renamed/removed field, changed
semantics) is introduced as **`/api/v2`** served alongside v1 until clients migrate.

## Where the rules live (`src/BigRegister.Api/Domain/`)

- `Diplomas/DiplomaRules.cs` — profession derivation + which policy questions apply.
- `Registrations/HerregistratieRule.cs` — eligibility + reason + status invariant.
- `Intake/IntakePolicy.cs` — scholing threshold.
- `Submissions/SubmissionRules.cs` — submit rejections + reference generation.

## Typed client (NSwag)

The frontend calls this API through a generated TypeScript client. Regenerate it
from the contract after a **shape** change:

```bash
npm run gen:api    # builds backend → swagger.json → src/app/shared/infrastructure/api-client.ts
```

## Maintainability: changing a policy is one backend change

**Goal:** require every *Verpleegkundige* diploma to confirm a Dutch skills
assessment. This is a new policy question on a diploma type.

Edit **one file** — `Domain/Diplomas/DiplomaRules.cs`:

```diff
 public static IReadOnlyList<PolicyQuestion> QuestionsFor(Diploma d)
 {
     var questions = new List<PolicyQuestion>();
     if (d.Engelstalig)
         questions.Add(NlTaalEngelstalig);
+    if (d.Opleiding == "verpleegkunde")
+        questions.Add(new PolicyQuestion(
+            "bekwaamheid",
+            "Heeft u in de afgelopen vijf jaar een bekwaamheidstoets afgelegd?",
+            QuestionType.JaNee));
     return questions;
 }
```

Rebuild the backend (`docker compose up` or `dotnet run`). The new question now
appears in the registration wizard for HBO-Verpleegkunde.

- **No frontend change.** The FE renders whatever questions the API returns.
- **No client regeneration.** The wire shape (`PolicyQuestionDto`) is unchanged —
  only the data behind it. `npm run gen:api` is only needed when a DTO *shape* changes.

Add a unit test for the new rule in `tests/BigRegister.Tests/RuleTests.cs` and
you're done.
