feat(event-subscriber): enrich the projection with the zaak reference via the ACL (refs #78)

On each notification the subscriber reads the zaak's reference (identificatie)
through the ACL — the only code allowed to talk to ZGW (§8.1) — and persists it on
the register_projection row and in the processed_notifications replay log. Storing
it in the log keeps rebuild log-only (ADR-0008): no ACL/ZGW access on rebuild.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 14:46:48 +02:00
parent 7b841d6e62
commit 566fc9bcea
19 changed files with 350 additions and 20 deletions

View File

@@ -0,0 +1,30 @@
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using EventSubscriber.Application;
namespace EventSubscriber.Api;
/// <summary>
/// HTTP client to the ACL service. The subscriber enriches the projection with the zaak's reference
/// (identificatie) by asking the ACL — the only code that may read ZGW (§8.1) — rather than reading
/// OpenZaak itself (adr-proposal #78).
/// </summary>
public sealed class AclHttpClient(HttpClient http) : IAclClient
{
public async Task<string> GetZaakReferenceAsync(Uri zaakUrl, CancellationToken ct = default)
{
ArgumentNullException.ThrowIfNull(zaakUrl);
using var response = await http.PostAsJsonAsync(
new Uri(http.BaseAddress!, "zaken/reference"), new ReferenceRequest(zaakUrl.ToString()), ct);
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadFromJsonAsync<ReferenceResponse>(ct)
?? throw new InvalidOperationException("The ACL returned an empty reference response.");
return body.Reference;
}
private sealed record ReferenceRequest([property: JsonPropertyName("zaakUrl")] string ZaakUrl);
private sealed record ReferenceResponse([property: JsonPropertyName("reference")] string Reference);
}