diff --git a/tests/acceptance/Acceptance.csproj b/tests/acceptance/Acceptance.csproj
index 7b795eb..08d182b 100644
--- a/tests/acceptance/Acceptance.csproj
+++ b/tests/acceptance/Acceptance.csproj
@@ -19,6 +19,7 @@
+
diff --git a/tests/acceptance/Features/RegistratieIndienen.feature b/tests/acceptance/Features/RegistratieIndienen.feature
new file mode 100644
index 0000000..1f78c95
--- /dev/null
+++ b/tests/acceptance/Features/RegistratieIndienen.feature
@@ -0,0 +1,18 @@
+# language: en
+# Drives S-05 (#6). A zorgprofessional submits a registration; the Domain Service starts the
+# registratie process and, via the external-task worker, opens a zaak through the ACL and records
+# it on the aggregate (ADR-0009). This scenario exercises the use cases against in-memory stand-ins
+# for the Workflow Client and the ACL; real Flowable + ACL + OpenZaak delivery is verified by the
+# live-stack check (verify-domain).
+Feature: Een registratie indienen
+ Als zorgprofessional wil ik mijn registratie indienen
+ zodat er een registratieproces start en een zaak wordt geopend.
+
+ Scenario: Indienen start het registratieproces en opent een zaak
+ Given a zorgprofessional submits a registration for BSN "123456782"
+ When the domain service handles the submission
+ Then a registratie process is started for the registration
+ And the registration has status "INGEDIEND"
+ When the OpenZaakAanmaken external task is handled for the registration
+ Then a zaak is opened via the ACL for BSN "123456782"
+ And the zaak is recorded on the registration
diff --git a/tests/acceptance/Steps/RegistratieIndienenSteps.cs b/tests/acceptance/Steps/RegistratieIndienenSteps.cs
new file mode 100644
index 0000000..a882e9e
--- /dev/null
+++ b/tests/acceptance/Steps/RegistratieIndienenSteps.cs
@@ -0,0 +1,54 @@
+using Acceptance.Support;
+using Big.Application;
+using Big.Domain;
+using Reqnroll;
+using Xunit;
+
+namespace Acceptance.Steps;
+
+/// Bindings for RegistratieIndienen.feature (S-05). Drives the SubmitRegistration
+/// and OpenZaakWorker use cases against in-memory ports; one instance per scenario.
+[Binding]
+public sealed class RegistratieIndienenSteps
+{
+ private readonly InMemoryWorkflowClient _workflow = new();
+ private readonly InMemoryAclClient _acl = new();
+ private readonly InMemoryRegistrationStore _store = new();
+ private string _bsn = "";
+ private RegistrationId _id;
+
+ [Given("a zorgprofessional submits a registration for BSN \"(.*)\"")]
+ public void GivenAZorgprofessionalSubmitsARegistration(string bsn) => _bsn = bsn;
+
+ [When("the domain service handles the submission")]
+ public async Task WhenTheDomainServiceHandlesTheSubmission()
+ => _id = await new SubmitRegistration(_store, _workflow).HandleAsync(new SubmitRegistrationCommand(_bsn));
+
+ [Then("a registratie process is started for the registration")]
+ public void ThenARegistratieProcessIsStarted()
+ => Assert.Equal(_id, _workflow.StartedFor);
+
+ [Then("the registration has status \"(.*)\"")]
+ public async Task ThenTheRegistrationHasStatus(string expected)
+ {
+ var registration = await _store.GetAsync(_id);
+ Assert.NotNull(registration);
+ Assert.Equal(expected, registration.Status.ToString().ToUpperInvariant());
+ Assert.Equal(InMemoryWorkflowClient.StartedProcessInstanceId, registration.ProcessInstanceId);
+ }
+
+ [When("the OpenZaakAanmaken external task is handled for the registration")]
+ public async Task WhenTheExternalTaskIsHandled()
+ => await new OpenZaakWorker(_store, _acl).HandleAsync(new OpenZaakJob("job-acc-1", _id));
+
+ [Then("a zaak is opened via the ACL for BSN \"(.*)\"")]
+ public void ThenAZaakIsOpenedViaTheAcl(string bsn)
+ => Assert.Equal(bsn, _acl.OpenedForBsn);
+
+ [Then("the zaak is recorded on the registration")]
+ public async Task ThenTheZaakIsRecordedOnTheRegistration()
+ {
+ var registration = await _store.GetAsync(_id);
+ Assert.Equal(InMemoryAclClient.OpenedZaakUrl, registration!.ZaakUrl);
+ }
+}
diff --git a/tests/acceptance/Support/InMemoryDomainPorts.cs b/tests/acceptance/Support/InMemoryDomainPorts.cs
new file mode 100644
index 0000000..3059aa7
--- /dev/null
+++ b/tests/acceptance/Support/InMemoryDomainPorts.cs
@@ -0,0 +1,50 @@
+using Big.Application;
+using Big.Domain;
+
+namespace Acceptance.Support;
+
+/// An in-memory Workflow Client for the domain acceptance scenario: it records which
+/// registration a process was started for and returns a fixed instance id. The acceptance test
+/// drives the use case without a running Flowable (live verification is the verify-domain check).
+public sealed class InMemoryWorkflowClient : IWorkflowClient
+{
+ public const string StartedProcessInstanceId = "proc-acc-1";
+
+ public RegistrationId? StartedFor { get; private set; }
+
+ public Task StartRegistrationProcessAsync(RegistrationId registrationId, CancellationToken ct = default)
+ {
+ StartedFor = registrationId;
+ return Task.FromResult(StartedProcessInstanceId);
+ }
+}
+
+/// An in-memory ACL stand-in: records the bsn it opened a zaak for and returns a fixed URL,
+/// so the scenario verifies the domain crosses the ACL boundary (ยง8.1) without a running OpenZaak.
+public sealed class InMemoryAclClient : IAclClient
+{
+ public static readonly Uri OpenedZaakUrl = new("http://openzaak/zaken/api/v1/zaken/acc-zaak");
+
+ public string? OpenedForBsn { get; private set; }
+
+ public Task OpenZaakAsync(string bsn, CancellationToken ct = default)
+ {
+ OpenedForBsn = bsn;
+ return Task.FromResult(OpenedZaakUrl);
+ }
+}
+
+/// An in-memory registration store for the domain acceptance scenario.
+public sealed class InMemoryRegistrationStore : IRegistrationStore
+{
+ private readonly Dictionary _byId = [];
+
+ public Task SaveAsync(Registration registration, CancellationToken ct = default)
+ {
+ _byId[registration.Id] = registration;
+ return Task.CompletedTask;
+ }
+
+ public Task GetAsync(RegistrationId id, CancellationToken ct = default)
+ => Task.FromResult(_byId.GetValueOrDefault(id));
+}