feat(backend): expand stamdata + OpenZaak-ready cases seam (WP-49)
CI / frontend (push) Successful in 2m59s
CI / backend (push) Successful in 1m27s
CI / semgrep (push) Successful in 58s
CI / e2e (push) Successful in 2m30s
CI / api-client-drift (push) Canceled after 1m14s
CI / storybook-a11y (push) Canceled after 29m8s

Stamdata: add beroepen, opleidingen (temporal), and specialismen tables to the
schema-driven catalog (zero UI code). opleidingen.beroep and specialismen.beroep
both reference beroepen.code — the first stamdata->stamdata references, enforced by
two new StamdataRef entries in the CI gate.

OpenZaak/ZGW (WP-49, slice 1 — read-only zaken): introduce IZaakSource as the cases
read seam. Default LocalZaakSource reads the local SQLite store (offline); an
OpenZaakZaakSource (Zgw/ client: HS256 per-call JWT, ZGW->existing-DTO mapper,
paginating HTTP source) is selected behind Zgw:Enabled (default false). The FE never
changes — same ApplicationSummaryDto, no api-client drift. Unit-tested with fixtures
+ a stub HttpMessageHandler; no live OpenZaak needed.

Docs: ADR-0005, reference/openzaak-integration.md, WP-49..52 roadmap, stamdata.md
update, README index rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-24 15:01:06 +02:00
co-authored by Claude Opus 4.8
parent cff711504f
commit 1c3c195d32
28 changed files with 974 additions and 8 deletions
+19 -5
View File
@@ -10,6 +10,7 @@ using BigRegister.Domain.Intake;
using BigRegister.Domain.Letters;
using BigRegister.Domain.Registrations;
using BigRegister.Domain.Submissions;
using BigRegister.Api.Zgw;
using BigRegister.Stamdata;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging.Console;
@@ -40,6 +41,22 @@ builder.Services.AddCors(o => o.AddPolicy(SpaCors, p =>
// override it (ConnectionStrings:AppDb) without touching this file.
Db.ConnectionString = builder.Configuration.GetConnectionString("AppDb") ?? Db.ConnectionString;
// WP-49: the cases (zaken) READ path goes through IZaakSource so a real ZGW backend
// (OpenZaak) can replace the local SQLite store behind the same DTO contract — the FE never
// changes (ADR-0001). Default = LocalZaakSource (offline). Zgw:Enabled=true swaps in the
// OpenZaak client (needs the base URLs + credentials in the Zgw config section).
var zgw = builder.Configuration.GetSection("Zgw").Get<ZgwOptions>() ?? new ZgwOptions();
if (zgw.Enabled)
{
builder.Services.AddSingleton(zgw);
builder.Services.AddSingleton<ZgwTokenProvider>();
builder.Services.AddHttpClient<IZaakSource, OpenZaakZaakSource>();
}
else
{
builder.Services.AddSingleton<IZaakSource, LocalZaakSource>();
}
var app = builder.Build();
// Migrate on every startup, seed nothing (WP-22): unlike SeedData's read-only
@@ -314,11 +331,8 @@ api.MapPost("/applications/{id}/submit", (string id, SubmitApplicationRequest re
.Produces(StatusCodes.Status404NotFound);
// --- Admin cases (WP-36): cross-owner list + admin delete, gated by `cases:manage`. ---
api.MapGet("/admin/cases", (HttpContext ctx) => CasesAdmin(ctx, () =>
{
var now = DateTimeOffset.UtcNow;
return Results.Ok(ApplicationStore.ListAll().Select(a => a.ToAdminSummaryDto(now)).ToList());
}))
api.MapGet("/admin/cases", (HttpContext ctx, IZaakSource zaken) => CasesAdmin(ctx, () =>
Results.Ok(zaken.ListCases(DateTimeOffset.UtcNow))))
.Produces<List<ApplicationSummaryDto>>()
.ProducesProblem(StatusCodes.Status403Forbidden);