diff --git a/services/domain/Big.Tests/BeoordeelRegistratieTests.cs b/services/domain/Big.Tests/BeoordeelRegistratieTests.cs
new file mode 100644
index 0000000..de51af2
--- /dev/null
+++ b/services/domain/Big.Tests/BeoordeelRegistratieTests.cs
@@ -0,0 +1,142 @@
+using Big.Application;
+using Big.Domain;
+
+namespace Big.Tests;
+
+///
+/// The beoordeling use case (S-12): a behandelaar's decision on a registration. Goedkeuren sets the
+/// zaak's final status via the ACL (ยง8.1) and marks the aggregate INGESCHREVEN; Afwijzen marks it
+/// AFGEWEZEN in the domain (propagating a rejection to the zaak is a later sub-slice). Both are
+/// idempotent so a repeated or redelivered decision is a no-op.
+///
+public class BeoordeelRegistratieTests
+{
+ private static Registration WithZaak(string bsn = "123456782")
+ {
+ var registration = Registration.Submit(bsn);
+ registration.AttachZaak(FakeAclClient.DefaultZaakUrl);
+ return registration;
+ }
+
+ [Fact]
+ public async Task Goedkeuren_sets_the_zaak_status_via_the_acl_and_marks_the_registration_ingeschreven()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var registration = WithZaak();
+ store.Seed(registration);
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
+
+ var saved = await store.GetAsync(registration.Id);
+ Assert.Equal(RegistrationStatus.Ingeschreven, saved!.Status);
+ Assert.Equal(FakeAclClient.DefaultZaakUrl, acl.ApprovedZaakUrl);
+ Assert.Equal(1, acl.ApproveCallCount);
+ Assert.Equal(1, store.SaveCount);
+ }
+
+ [Fact]
+ public async Task Afwijzen_marks_the_registration_afgewezen_without_calling_the_acl()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var registration = WithZaak();
+ store.Seed(registration);
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen));
+
+ var saved = await store.GetAsync(registration.Id);
+ Assert.Equal(RegistrationStatus.Afgewezen, saved!.Status);
+ Assert.Equal(0, acl.ApproveCallCount);
+ Assert.Equal(1, store.SaveCount);
+ }
+
+ [Fact]
+ public async Task Goedkeuren_an_in_behandeling_registration_marks_it_ingeschreven()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var registration = WithZaak();
+ registration.TakeIntoBehandeling();
+ store.Seed(registration);
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
+
+ Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status);
+ }
+
+ [Fact]
+ public async Task Rejects_a_null_command_without_touching_the_store_or_acl()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ await Assert.ThrowsAsync(() => handler.HandleAsync(null!));
+ Assert.Equal(0, acl.ApproveCallCount);
+ Assert.Equal(0, store.SaveCount);
+ }
+
+ [Fact]
+ public async Task Deciding_an_unknown_registration_throws_and_does_not_call_the_acl()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ var ex = await Assert.ThrowsAsync(() =>
+ handler.HandleAsync(new BeoordeelRegistratieCommand(RegistrationId.New(), BeoordelingsBesluit.Goedkeuren)));
+ Assert.Contains("No registration", ex.Message);
+ Assert.Equal(0, acl.ApproveCallCount);
+ }
+
+ [Fact]
+ public async Task Goedkeuren_before_the_zaak_is_opened_throws_without_calling_the_acl()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var registration = Registration.Submit("123456782"); // no zaak yet
+ store.Seed(registration);
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ var ex = await Assert.ThrowsAsync(() =>
+ handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)));
+ Assert.Contains("no zaak", ex.Message);
+ Assert.Equal(0, acl.ApproveCallCount);
+ }
+
+ [Fact]
+ public async Task Re_goedkeuren_an_already_ingeschreven_registration_is_idempotent()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var registration = WithZaak();
+ store.Seed(registration);
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
+
+ Assert.Equal(1, acl.ApproveCallCount);
+ Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status);
+ }
+
+ [Fact]
+ public async Task Re_afwijzen_an_already_afgewezen_registration_is_idempotent()
+ {
+ var store = new FakeRegistrationStore();
+ var acl = new FakeAclClient();
+ var registration = WithZaak();
+ store.Seed(registration);
+ var handler = new BeoordeelRegistratie(store, acl);
+
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen));
+ await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen));
+
+ Assert.Equal(1, store.SaveCount);
+ Assert.Equal(RegistrationStatus.Afgewezen, (await store.GetAsync(registration.Id))!.Status);
+ }
+}