diff --git a/Makefile b/Makefile
index 60a648e..49442f5 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
# `make ci` locally runs exactly what the pipeline runs — no drift. Until a
# self-hosted runner is registered, `make ci` is the gate (see docs/runbooks/ci.md).
-SLN := services/bff/Bff.slnx
+SLN := register-referentie.slnx
COMPOSE := infra/docker-compose.yml
HEALTH_URL := http://localhost:8080/health
OZ_COMPOSE := infra/openzaak/docker-compose.yml
diff --git a/register-referentie.slnx b/register-referentie.slnx
new file mode 100644
index 0000000..bf80fac
--- /dev/null
+++ b/register-referentie.slnx
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/acl/Acl.Application/AclService.cs b/services/acl/Acl.Application/AclService.cs
index effb09d..e285ee7 100644
--- a/services/acl/Acl.Application/AclService.cs
+++ b/services/acl/Acl.Application/AclService.cs
@@ -5,5 +5,16 @@ namespace Acl.Application;
public sealed class AclService(IZaakGateway gateway, AclDefaults defaults, IClock clock)
{
public Task OpenZaakAsync(DomainRegistration registration, CancellationToken ct = default)
- => throw new NotImplementedException();
+ {
+ ArgumentNullException.ThrowIfNull(registration);
+
+ var request = new ZaakRequest(
+ defaults.Bronorganisatie,
+ defaults.VerantwoordelijkeOrganisatie,
+ defaults.Vertrouwelijkheidaanduiding,
+ defaults.ZaaktypeUrl,
+ clock.Today);
+
+ return gateway.OpenZaakAsync(request, ct);
+ }
}
diff --git a/services/acl/Acl.Infrastructure/OpenZaakGateway.cs b/services/acl/Acl.Infrastructure/OpenZaakGateway.cs
index 3332a1e..0a6e2e4 100644
--- a/services/acl/Acl.Infrastructure/OpenZaakGateway.cs
+++ b/services/acl/Acl.Infrastructure/OpenZaakGateway.cs
@@ -1,3 +1,6 @@
+using System.Net.Http.Headers;
+using System.Net.Http.Json;
+using System.Text.Json.Serialization;
using Acl.Application;
namespace Acl.Infrastructure;
@@ -5,6 +8,41 @@ namespace Acl.Infrastructure;
/// The only code that talks to OpenZaak's Zaken API (ADR-0001).
public sealed class OpenZaakGateway(HttpClient http, OpenZaakOptions options) : IZaakGateway
{
- public Task OpenZaakAsync(ZaakRequest request, CancellationToken ct = default)
- => throw new NotImplementedException();
+ public async Task OpenZaakAsync(ZaakRequest request, CancellationToken ct = default)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+
+ using var message = new HttpRequestMessage(
+ HttpMethod.Post, new Uri(options.BaseUrl, "/zaken/api/v1/zaken"))
+ {
+ Content = JsonContent.Create(new ZaakDto(
+ request.Bronorganisatie,
+ request.Zaaktype.ToString(),
+ request.VerantwoordelijkeOrganisatie,
+ request.Startdatum.ToString("yyyy-MM-dd"),
+ request.Vertrouwelijkheidaanduiding)),
+ };
+ message.Headers.Authorization =
+ new AuthenticationHeaderValue("Bearer", ZgwToken.Mint(options.ClientId, options.Secret));
+ // ZRC is a geo API; it requires the CRS headers.
+ message.Headers.Add("Accept-Crs", "EPSG:4326");
+ message.Content.Headers.Add("Content-Crs", "EPSG:4326");
+
+ using var response = await http.SendAsync(message, ct);
+ response.EnsureSuccessStatusCode();
+
+ var created = await response.Content.ReadFromJsonAsync(ct)
+ ?? throw new InvalidOperationException("OpenZaak returned an empty zaak response");
+ return new Uri(created.Url);
+ }
+
+ private sealed record ZaakDto(
+ [property: JsonPropertyName("bronorganisatie")] string Bronorganisatie,
+ [property: JsonPropertyName("zaaktype")] string Zaaktype,
+ [property: JsonPropertyName("verantwoordelijkeOrganisatie")] string VerantwoordelijkeOrganisatie,
+ [property: JsonPropertyName("startdatum")] string Startdatum,
+ [property: JsonPropertyName("vertrouwelijkheidaanduiding")] string Vertrouwelijkheidaanduiding);
+
+ private sealed record ZaakCreatedDto(
+ [property: JsonPropertyName("url")] string Url);
}