diff --git a/services/acl/Acl.Application/AclService.cs b/services/acl/Acl.Application/AclService.cs
index 4b23964..34c0ced 100644
--- a/services/acl/Acl.Application/AclService.cs
+++ b/services/acl/Acl.Application/AclService.cs
@@ -42,6 +42,12 @@ public sealed class AclService(IZaakGateway gateway, AclDefaults defaults, IZaak
await gateway.SetZaakToCancellationStatusAsync(zaakUrl, await catalog.GetZaaktypeUrlAsync(ct), clock.Today, ct);
}
+ /// The published zaaktypen, for the beheer catalogus viewer (S-15a). Read-only passthrough:
+ /// no default-fill, the ACL is simply the only code allowed to read ZGW (§8.1).
+ public Task> ListZaaktypenAsync(CancellationToken ct = default) =>
+ // ponytail: stub for the red test; real passthrough lands in the green commit.
+ Task.FromResult>([]);
+
/// The zaak's reference (its ZGW identificatie), for the read projection (#78).
public Task GetZaakReferenceAsync(Uri zaakUrl, CancellationToken ct = default)
{
diff --git a/services/acl/Acl.Application/IZaakGateway.cs b/services/acl/Acl.Application/IZaakGateway.cs
index 3848d8b..d3620ec 100644
--- a/services/acl/Acl.Application/IZaakGateway.cs
+++ b/services/acl/Acl.Application/IZaakGateway.cs
@@ -40,4 +40,8 @@ public interface IZaakGateway
/// Resolve the URL of the published informatieobjecttype with the given
/// from the Catalogi API (S-27). Throws if none matches.
Task ResolveInformatieobjecttypeUrlAsync(string omschrijving, CancellationToken ct = default);
+
+ /// List the published zaaktypen from the Catalogi API — the read-only catalogus the beheer
+ /// portal shows (S-15a). The ACL is the only code allowed to read ZGW (§8.1).
+ Task> ListZaaktypenAsync(CancellationToken ct = default);
}
diff --git a/services/acl/Acl.Application/ZaaktypeSummary.cs b/services/acl/Acl.Application/ZaaktypeSummary.cs
new file mode 100644
index 0000000..8c93d05
--- /dev/null
+++ b/services/acl/Acl.Application/ZaaktypeSummary.cs
@@ -0,0 +1,6 @@
+namespace Acl.Application;
+
+/// A published zaaktype as the beheer catalogus viewer shows it (S-15a). Public-safe: the
+/// business + human and the ZGW
+/// (the URL is the ACL's own reference, not shown to end users).
+public sealed record ZaaktypeSummary(string Identificatie, string Omschrijving, Uri Url);
diff --git a/services/acl/Acl.Infrastructure/OpenZaakGateway.cs b/services/acl/Acl.Infrastructure/OpenZaakGateway.cs
index 156b810..1978a4f 100644
--- a/services/acl/Acl.Infrastructure/OpenZaakGateway.cs
+++ b/services/acl/Acl.Infrastructure/OpenZaakGateway.cs
@@ -170,6 +170,10 @@ public sealed class OpenZaakGateway(HttpClient http, OpenZaakOptions options) :
return new Uri(match.Url);
}
+ public Task> ListZaaktypenAsync(CancellationToken ct = default) =>
+ // ponytail: stub for the red test; real Catalogi read lands in the green commit.
+ throw new NotImplementedException();
+
// GETs an absolute-by-path ZGW resource with auth (no CRS — catalogi is not a geo API).
private async Task GetAsync(string pathAndQuery, string label, CancellationToken ct)
{
diff --git a/services/acl/Acl.Tests/AclServiceTests.cs b/services/acl/Acl.Tests/AclServiceTests.cs
index 930d380..905dc9f 100644
--- a/services/acl/Acl.Tests/AclServiceTests.cs
+++ b/services/acl/Acl.Tests/AclServiceTests.cs
@@ -65,6 +65,14 @@ public class AclServiceTests
ResolvedByOmschrijving = omschrijving;
return Task.FromResult(ResolvedInformatieobjecttype);
}
+
+ public IReadOnlyList Zaaktypen { get; } =
+ [
+ new("BIG-REGISTRATIE", "BIG-registratie", new Uri("http://openzaak/catalogi/api/v1/zaaktypen/big")),
+ ];
+
+ public Task> ListZaaktypenAsync(CancellationToken ct = default) =>
+ Task.FromResult(Zaaktypen);
}
private static AclDefaults Defaults() => new()
@@ -225,4 +233,18 @@ public class AclServiceTests
await Assert.ThrowsAsync(() => service.GetZaakReferenceAsync(null!));
Assert.Null(gateway.ReadReferenceFor);
}
+
+ [Fact]
+ public async Task Listing_zaaktypen_returns_the_gateways_published_zaaktypen(/* S-15a */)
+ {
+ var gateway = new FakeGateway();
+ var service = ServiceWith(gateway, Defaults(), new DateOnly(2026, 6, 4));
+
+ var zaaktypen = await service.ListZaaktypenAsync();
+
+ var only = Assert.Single(zaaktypen);
+ Assert.Equal("BIG-REGISTRATIE", only.Identificatie);
+ Assert.Equal("BIG-registratie", only.Omschrijving);
+ Assert.Equal(new Uri("http://openzaak/catalogi/api/v1/zaaktypen/big"), only.Url);
+ }
}
diff --git a/services/acl/Acl.Tests/ZaaktypeCatalogTests.cs b/services/acl/Acl.Tests/ZaaktypeCatalogTests.cs
index 8f3f7f6..117b00c 100644
--- a/services/acl/Acl.Tests/ZaaktypeCatalogTests.cs
+++ b/services/acl/Acl.Tests/ZaaktypeCatalogTests.cs
@@ -36,6 +36,7 @@ public class ZaaktypeCatalogTests
public Task SetZaakToCancellationStatusAsync(Uri z, Uri zt, DateOnly d, CancellationToken ct = default) => throw new NotSupportedException();
public Task GetZaakIdentificatieAsync(Uri z, CancellationToken ct = default) => throw new NotSupportedException();
public Task StoreDocumentAsync(DocumentRequest r, CancellationToken ct = default) => throw new NotSupportedException();
+ public Task> ListZaaktypenAsync(CancellationToken ct = default) => throw new NotSupportedException();
}
private static AclDefaults Defaults() => new()