From 22ab38f328abe60b3ca1c40256ab7f0ec92684e3 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Tue, 30 Jun 2026 17:13:27 +0200 Subject: [PATCH] feat(domain): expose POST /registrations and the read endpoint (refs #6) The BIG Domain Service Api wires the use cases and the hosted job worker: POST /registrations creates the aggregate and starts the registratie process, returning 202 with a location; GET /registrations/{id} reads the aggregate so the eventually-opened zaak URL can be observed (ADR-0009). The Workflow Client is registered once behind both Flowable ports; the ACL client and in-memory store complete the wiring. Verified against a live flowable-rest: submit starts a parked process and the worker polls it. Co-Authored-By: Claude Opus 4.8 (1M context) --- register-referentie.slnx | 1 + services/domain/Big.Api/Big.Api.csproj | 14 ++++++ services/domain/Big.Api/Program.cs | 64 ++++++++++++++++++++++++ services/domain/Big.Api/appsettings.json | 9 ++++ services/domain/Big.slnx | 1 + 5 files changed, 89 insertions(+) create mode 100644 services/domain/Big.Api/Big.Api.csproj create mode 100644 services/domain/Big.Api/Program.cs create mode 100644 services/domain/Big.Api/appsettings.json diff --git a/register-referentie.slnx b/register-referentie.slnx index 960a92e..60bd708 100644 --- a/register-referentie.slnx +++ b/register-referentie.slnx @@ -11,6 +11,7 @@ + diff --git a/services/domain/Big.Api/Big.Api.csproj b/services/domain/Big.Api/Big.Api.csproj new file mode 100644 index 0000000..ae03b53 --- /dev/null +++ b/services/domain/Big.Api/Big.Api.csproj @@ -0,0 +1,14 @@ + + + + + + + + + net10.0 + enable + enable + + + diff --git a/services/domain/Big.Api/Program.cs b/services/domain/Big.Api/Program.cs new file mode 100644 index 0000000..6f2599d --- /dev/null +++ b/services/domain/Big.Api/Program.cs @@ -0,0 +1,64 @@ +using Big.Application; +using Big.Domain; +using Big.Infrastructure; + +var builder = WebApplication.CreateBuilder(args); + +// Options bound from configuration (compose sets Flowable__* and Acl__* env vars). +builder.Services.AddSingleton(sp => sp.GetRequiredService() + .GetSection("Flowable").Get() + ?? throw new InvalidOperationException("Missing configuration section 'Flowable'")); +builder.Services.AddSingleton(sp => sp.GetRequiredService() + .GetSection("Acl").Get() + ?? throw new InvalidOperationException("Missing configuration section 'Acl'")); + +// The in-memory registration store is shared between the submit endpoint and the worker (ADR-0009). +builder.Services.AddSingleton(); + +// The Workflow Client is one type behind two ports (start side + worker side); both resolve to the +// same HttpClient-backed implementation — the only code that talks to Flowable (§8.2). +builder.Services.AddHttpClient(); +builder.Services.AddTransient(sp => sp.GetRequiredService()); +builder.Services.AddTransient(sp => sp.GetRequiredService()); +builder.Services.AddHttpClient(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// The hosted external-task job worker polls Flowable and drives OpenZaakAanmaken to completion. +builder.Services.AddHostedService(); + +var app = builder.Build(); + +app.MapGet("/health", () => "Healthy"); + +// Submit a registration. The aggregate is created (INGEDIEND) and the registratie process started; +// the zaak is opened later, off the request path, by the worker — so this returns 202 Accepted with +// a location to read the registration's progress (ADR-0009, eventual consistency). +app.MapPost("/registrations", async (SubmitRegistrationRequest body, SubmitRegistration submit, CancellationToken ct) => +{ + var id = await submit.HandleAsync(new SubmitRegistrationCommand(body.Bsn), ct); + return Results.Accepted($"/registrations/{id}", new RegistrationResponse(id.ToString(), RegistrationStatus.Ingediend.ToString(), null)); +}); + +// Read a registration. Its zaak URL appears once the worker has opened the zaak (eventually). +app.MapGet("/registrations/{id}", async (string id, IRegistrationStore store, CancellationToken ct) => +{ + if (!Guid.TryParse(id, out var guid)) + return Results.NotFound(); + + var registration = await store.GetAsync(new RegistrationId(guid), ct); + return registration is null + ? Results.NotFound() + : Results.Ok(new RegistrationResponse( + registration.Id.ToString(), registration.Status.ToString(), registration.ZaakUrl?.ToString())); +}); + +await app.RunAsync(); + +public sealed record SubmitRegistrationRequest(string Bsn); + +public sealed record RegistrationResponse(string RegistrationId, string Status, string? ZaakUrl); + +public partial class Program; diff --git a/services/domain/Big.Api/appsettings.json b/services/domain/Big.Api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/services/domain/Big.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/services/domain/Big.slnx b/services/domain/Big.slnx index f60c02a..262d543 100644 --- a/services/domain/Big.slnx +++ b/services/domain/Big.slnx @@ -2,5 +2,6 @@ +