namespace EventSubscriber.Application; /// /// The durable log of notifications the subscriber has accepted. It is both the idempotency /// guard (a replayed notification is recognised and dropped) and the rebuild source: the /// projection is a derived artefact (PRD §8.4) regenerated by replaying this log, so a rebuild /// needs no access to OpenZaak (CLAUDE.md §8.1). Implemented in Infrastructure over Postgres. /// public interface INotificationLog { /// /// Record a notification. Returns true if it was newly recorded, false if an /// entry with the same key already existed (a duplicate delivery). Must be atomic so that /// concurrent duplicate deliveries cannot both observe true. /// Task TryRecordAsync(RecordedNotification notification, CancellationToken ct = default); /// Every accepted notification, for rebuilding the projection. Task> AllAsync(CancellationToken ct = default); } /// A notification that has been accepted, retaining what a rebuild needs to recompute its /// projection row — the ZGW resource (zaak-create → INGEDIEND vs status-set → INGESCHREVEN) and /// the zaak reference (identificatie), so a rebuild reproduces the row without re-reading ZGW (#78). public sealed record RecordedNotification(string Key, string Actie, string ZaakId, string Resource, string? Reference); /// /// Port to the Anti-Corruption Layer. The subscriber enriches the projection with the zaak's /// public-safe reference (its identificatie) by asking the ACL — the only code that may read ZGW /// (§8.1) — rather than reading OpenZaak itself (adr-proposal #78). /// public interface IAclClient { /// The zaak's reference (identificatie) for the read projection. Task GetZaakReferenceAsync(Uri zaakUrl, CancellationToken ct = default); } /// The read projection store. Owned by the projection bounded context (ADR-0008); the /// subscriber writes to it and the projection-api reads it. public interface IProjectionStore { /// Insert or update the row for . Idempotent on the id. Task UpsertAsync(RegisterEntry entry, CancellationToken ct = default); /// Remove every row — the first step of a rebuild. Task ClearAsync(CancellationToken ct = default); /// Every projection row (used by tests and the rebuild verification). Task> AllAsync(CancellationToken ct = default); }