diff --git a/services/domain/Big.Tests/Fakes.cs b/services/domain/Big.Tests/Fakes.cs
index cf0a37d..bfd0a54 100644
--- a/services/domain/Big.Tests/Fakes.cs
+++ b/services/domain/Big.Tests/Fakes.cs
@@ -41,6 +41,29 @@ internal sealed class FakeWorkflowClient(string processInstanceId = "proc-1", Ac
}
}
+/// A fake user-task client for the werkbak/decision use cases: returns a scripted set of
+/// open beoordeling tasks and records claim/complete calls.
+internal sealed class FakeUserTaskClient(IReadOnlyList open) : IUserTaskClient
+{
+ public (string TaskId, string Behandelaar)? Claimed { get; private set; }
+ public (string TaskId, BeoordelingsBesluit Besluit)? Completed { get; private set; }
+
+ public Task> GetOpenBeoordelingenAsync(CancellationToken ct = default)
+ => Task.FromResult(open);
+
+ public Task ClaimAsync(string taskId, string behandelaar, CancellationToken ct = default)
+ {
+ Claimed = (taskId, behandelaar);
+ return Task.CompletedTask;
+ }
+
+ public Task CompleteBeoordelingAsync(string taskId, BeoordelingsBesluit besluit, CancellationToken ct = default)
+ {
+ Completed = (taskId, besluit);
+ return Task.CompletedTask;
+ }
+}
+
/// A fake ACL client that records the bsn it was asked to open a zaak for and returns a
/// fixed zaak URL.
internal sealed class FakeAclClient(Uri? zaakUrl = null) : IAclClient
diff --git a/services/domain/Big.Tests/WerkbakTests.cs b/services/domain/Big.Tests/WerkbakTests.cs
new file mode 100644
index 0000000..bfbf182
--- /dev/null
+++ b/services/domain/Big.Tests/WerkbakTests.cs
@@ -0,0 +1,49 @@
+using Big.Application;
+using Big.Domain;
+
+namespace Big.Tests;
+
+///
+/// The werkbak query (S-12c): the behandelaar's list of registrations awaiting beoordeling. It reads
+/// the open Beoordelen tasks from the workflow engine (ยง8.2) and enriches each with its registration
+/// (bsn + status) from the store. A task whose registration is unknown is skipped defensively.
+///
+public class WerkbakTests
+{
+ [Fact]
+ public async Task Lists_an_item_per_open_beoordeling_enriched_from_the_registration()
+ {
+ var store = new FakeRegistrationStore();
+ var registration = Registration.Submit("123456782");
+ registration.AttachZaak(FakeAclClient.DefaultZaakUrl);
+ registration.TakeIntoBehandeling();
+ store.Seed(registration);
+ var tasks = new FakeUserTaskClient([new BeoordelingTask("task-1", registration.Id)]);
+ var werkbak = new Werkbak(tasks, store);
+
+ var items = await werkbak.GetAsync();
+
+ var item = Assert.Single(items);
+ Assert.Equal(registration.Id.ToString(), item.RegistrationId);
+ Assert.Equal("123456782", item.Bsn);
+ Assert.Equal("InBehandeling", item.Status);
+ }
+
+ [Fact]
+ public async Task Is_empty_when_no_beoordelingen_are_open()
+ {
+ var werkbak = new Werkbak(new FakeUserTaskClient([]), new FakeRegistrationStore());
+
+ Assert.Empty(await werkbak.GetAsync());
+ }
+
+ [Fact]
+ public async Task Skips_a_task_whose_registration_is_unknown()
+ {
+ // Defensive: the werkbak never invents an item for a task the domain has no aggregate for.
+ var tasks = new FakeUserTaskClient([new BeoordelingTask("task-1", RegistrationId.New())]);
+ var werkbak = new Werkbak(tasks, new FakeRegistrationStore());
+
+ Assert.Empty(await werkbak.GetAsync());
+ }
+}